aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/doc
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/doc')
-rw-r--r--sources/pyside6/doc/CMakeLists.txt173
-rw-r--r--sources/pyside6/doc/PySide6/QtAsyncio/index.rst150
-rw-r--r--sources/pyside6/doc/README.md34
-rw-r--r--sources/pyside6/doc/_static/css/qt_style.css80
-rw-r--r--sources/pyside6/doc/_static/qtforpython.icobin0 -> 766 bytes
-rw-r--r--sources/pyside6/doc/_static/qtforpython.pngbin4936 -> 4043 bytes
-rw-r--r--sources/pyside6/doc/_tags/android.rst21
-rw-r--r--sources/pyside6/doc/_tags/tagsindex.rst12
-rw-r--r--sources/pyside6/doc/_themes/pysidedocs/static/pyside.css2198
-rw-r--r--sources/pyside6/doc/_themes/pysidedocs_qthelp/static/pyside.css8
-rw-r--r--sources/pyside6/doc/additionaldocs.lst366
-rw-r--r--sources/pyside6/doc/api.rst68
-rw-r--r--sources/pyside6/doc/commercial/index.rst250
-rw-r--r--sources/pyside6/doc/commercial/products.pngbin0 -> 23289 bytes
-rw-r--r--sources/pyside6/doc/commercial/qtcreator_python.pngbin0 -> 40845 bytes
-rw-r--r--sources/pyside6/doc/commercial/versions_commercial.pngbin0 -> 34660 bytes
-rw-r--r--sources/pyside6/doc/commercial/versions_lts.pngbin0 -> 34293 bytes
-rw-r--r--sources/pyside6/doc/conf.py.in61
-rw-r--r--sources/pyside6/doc/considerations.rst239
-rw-r--r--sources/pyside6/doc/contents.rst13
-rw-r--r--sources/pyside6/doc/deployment/deployment-briefcase.rst (renamed from sources/pyside6/doc/deployment-briefcase.rst)49
-rw-r--r--sources/pyside6/doc/deployment/deployment-cxfreeze.rst (renamed from sources/pyside6/doc/deployment-cxfreeze.rst)43
-rw-r--r--sources/pyside6/doc/deployment/deployment-fbs.rst (renamed from sources/pyside6/doc/deployment-fbs.rst)24
-rw-r--r--sources/pyside6/doc/deployment/deployment-nuitka.rst (renamed from sources/pyside6/doc/deployment-nuitka.rst)38
-rw-r--r--sources/pyside6/doc/deployment/deployment-py2exe.rst (renamed from sources/pyside6/doc/deployment-py2exe.rst)10
-rw-r--r--sources/pyside6/doc/deployment/deployment-pyinstaller.rst (renamed from sources/pyside6/doc/deployment-pyinstaller.rst)63
-rw-r--r--sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst211
-rw-r--r--sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst217
-rw-r--r--sources/pyside6/doc/deployment/index.rst (renamed from sources/pyside6/doc/deployment.rst)31
-rw-r--r--sources/pyside6/doc/developer/adapt_qt.rst54
-rw-r--r--sources/pyside6/doc/developer/add_module.rst61
-rw-r--r--sources/pyside6/doc/developer/add_port_example.rst67
-rw-r--r--sources/pyside6/doc/developer/add_tool.rst51
-rw-r--r--sources/pyside6/doc/developer/documentation.rst73
-rw-r--r--sources/pyside6/doc/developer/enumfeatures_doc.rst160
-rw-r--r--sources/pyside6/doc/developer/extras.rst55
-rw-r--r--sources/pyside6/doc/developer/feature-motivation.rst (renamed from sources/pyside6/doc/feature-why.rst)26
-rw-r--r--sources/pyside6/doc/developer/index.rst35
-rw-r--r--sources/pyside6/doc/developer/limited_api.rst703
-rw-r--r--sources/pyside6/doc/developer/signature_doc.rst361
-rw-r--r--sources/pyside6/doc/extras/QtBluetooth.rst46
-rw-r--r--sources/pyside6/doc/extras/QtCharts.rst4
-rw-r--r--sources/pyside6/doc/extras/QtCore.ClassInfo.rst14
-rw-r--r--sources/pyside6/doc/extras/QtCore.Property.rst52
-rw-r--r--sources/pyside6/doc/extras/QtCore.QEnum.rst85
-rw-r--r--sources/pyside6/doc/extras/QtCore.QFlag.rst74
-rw-r--r--sources/pyside6/doc/extras/QtCore.Signal.rst23
-rw-r--r--sources/pyside6/doc/extras/QtCore.Slot.rst65
-rw-r--r--sources/pyside6/doc/extras/QtDesigner.QPyDesignerContainerExtension.rst11
-rw-r--r--sources/pyside6/doc/extras/QtDesigner.QPyDesignerCustomWidgetCollection.rst28
-rw-r--r--sources/pyside6/doc/extras/QtDesigner.QPyDesignerMemberSheetExtension.rst11
-rw-r--r--sources/pyside6/doc/extras/QtDesigner.QPyDesignerTaskMenuExtension.rst11
-rw-r--r--sources/pyside6/doc/extras/QtDesigner.rst5
-rw-r--r--sources/pyside6/doc/extras/QtMultimedia.rst55
-rw-r--r--sources/pyside6/doc/extras/QtQml.ListProperty.rst24
-rw-r--r--sources/pyside6/doc/extras/QtQml.QPyQmlParserStatus.rst9
-rw-r--r--sources/pyside6/doc/extras/QtQml.QPyQmlPropertyValueSource.rst9
-rw-r--r--sources/pyside6/doc/extras/QtQml.QmlAnonymous.rst27
-rw-r--r--sources/pyside6/doc/extras/QtQml.QmlAttached.rst5
-rw-r--r--sources/pyside6/doc/extras/QtQml.QmlElement.rst35
-rw-r--r--sources/pyside6/doc/extras/QtQml.QmlExtended.rst5
-rw-r--r--sources/pyside6/doc/extras/QtQml.QmlForeign.rst37
-rw-r--r--sources/pyside6/doc/extras/QtQml.QmlNamedElement.rst35
-rw-r--r--sources/pyside6/doc/extras/QtQml.QmlSingleton.rst22
-rw-r--r--sources/pyside6/doc/extras/QtQml.QmlUncreatable.rst7
-rw-r--r--sources/pyside6/doc/extras/QtQml.qmlRegisterSingletonInstance.rst25
-rw-r--r--sources/pyside6/doc/extras/QtQml.qmlRegisterSingletonType.rst46
-rw-r--r--sources/pyside6/doc/extras/QtQml.qmlRegisterType.rst41
-rw-r--r--sources/pyside6/doc/extras/QtQml.qmlRegisterUncreatableType.rst38
-rw-r--r--sources/pyside6/doc/extras/QtQuickTest.rst58
-rw-r--r--sources/pyside6/doc/extras/QtSerialBus.rst46
-rw-r--r--sources/pyside6/doc/extras/QtUiTools.loadUiType.rst36
-rw-r--r--sources/pyside6/doc/extras/QtUiTools.rst4
-rw-r--r--sources/pyside6/doc/extras/QtWidgets.rst2
-rw-r--r--sources/pyside6/doc/faq.rst16
-rw-r--r--sources/pyside6/doc/faq/distribution.rst (renamed from sources/pyside6/doc/tutorials/pretutorial/distribution.rst)0
-rw-r--r--sources/pyside6/doc/faq/hello_linux.png (renamed from sources/pyside6/doc/tutorials/pretutorial/hello_linux.png)bin5960 -> 5960 bytes
-rw-r--r--sources/pyside6/doc/faq/hello_macOS.png (renamed from sources/pyside6/doc/tutorials/pretutorial/hello_macOS.png)bin38777 -> 38777 bytes
-rw-r--r--sources/pyside6/doc/faq/hello_win10.jpg (renamed from sources/pyside6/doc/tutorials/pretutorial/hello_win10.jpg)bin5314 -> 5314 bytes
-rw-r--r--sources/pyside6/doc/faq/tiobe.png (renamed from sources/pyside6/doc/tutorials/pretutorial/tiobe.png)bin49961 -> 49961 bytes
-rw-r--r--sources/pyside6/doc/faq/typesoffiles.rst (renamed from sources/pyside6/doc/tutorials/pretutorial/typesoffiles.rst)16
-rw-r--r--sources/pyside6/doc/faq/whatisqt.rst (renamed from sources/pyside6/doc/tutorials/pretutorial/whatisqt.rst)6
-rw-r--r--sources/pyside6/doc/faq/whatisshiboken.rst (renamed from sources/pyside6/doc/tutorials/pretutorial/whatisshiboken.rst)6
-rw-r--r--sources/pyside6/doc/faq/whichide.rst (renamed from sources/pyside6/doc/tutorials/pretutorial/whichide.rst)16
-rw-r--r--sources/pyside6/doc/faq/whyqtforpython.rst (renamed from sources/pyside6/doc/tutorials/pretutorial/whyqtforpython.rst)19
-rw-r--r--sources/pyside6/doc/gettingstarted-linux.rst79
-rw-r--r--sources/pyside6/doc/gettingstarted/index.rst (renamed from sources/pyside6/doc/gettingstarted.rst)207
-rw-r--r--sources/pyside6/doc/gettingstarted/linux.rst115
-rw-r--r--sources/pyside6/doc/gettingstarted/macOS.rst (renamed from sources/pyside6/doc/gettingstarted-macOS.rst)33
-rw-r--r--sources/pyside6/doc/gettingstarted/package_details.rst75
-rw-r--r--sources/pyside6/doc/gettingstarted/packages.pngbin0 -> 12157 bytes
-rw-r--r--sources/pyside6/doc/gettingstarted/porting_from2.rst94
-rw-r--r--sources/pyside6/doc/gettingstarted/windows.rst (renamed from sources/pyside6/doc/gettingstarted-windows.rst)46
-rw-r--r--sources/pyside6/doc/images/Commercial.svg49
-rw-r--r--sources/pyside6/doc/images/Development.svg27
-rw-r--r--sources/pyside6/doc/images/Examples.svg58
-rw-r--r--sources/pyside6/doc/images/Tooling.svg24
-rw-r--r--sources/pyside6/doc/images/linux.svg37
-rw-r--r--sources/pyside6/doc/images/macos.svg38
-rw-r--r--sources/pyside6/doc/images/windows.svg38
-rw-r--r--sources/pyside6/doc/import_inheritance.py152
-rw-r--r--sources/pyside6/doc/index.rst285
-rw-r--r--sources/pyside6/doc/inheritance_diagram.py236
-rw-r--r--sources/pyside6/doc/inheritance_diagram.pyproject6
-rw-r--r--sources/pyside6/doc/inheritance_graph.py145
-rw-r--r--sources/pyside6/doc/json_inheritance.py74
-rw-r--r--sources/pyside6/doc/modules.rst313
-rw-r--r--sources/pyside6/doc/porting_from2.rst100
-rw-r--r--sources/pyside6/doc/pysideinclude.py19
-rw-r--r--sources/pyside6/doc/qdoc_spawner.py.in105
-rw-r--r--sources/pyside6/doc/qtattributionsscannertorst.py53
-rw-r--r--sources/pyside6/doc/qtmodules/pyside-qtdoc.qdocconf.in2
-rw-r--r--sources/pyside6/doc/qtmodules/pyside-qtpdf.qdocconf.in3
-rw-r--r--sources/pyside6/doc/qtmodules/pyside-qtquickcontrols2.qdocconf.in4
-rw-r--r--sources/pyside6/doc/qtmodules/pyside-qtquicktest.qdocconf.in3
-rw-r--r--sources/pyside6/doc/qtmodules/pyside-qtserialbus.qdocconf.in2
-rw-r--r--sources/pyside6/doc/qtmodules/pyside-qtspatialaudio.qdocconf.in3
-rw-r--r--sources/pyside6/doc/quickstart.rst219
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_0.cpp.py4
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_1.cpp.py5
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_2.cpp.py5
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_3.cpp.py5
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_4.cpp.py4
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py18
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/tutorials/modelview/1_readonly/mymodel_Quoting_ModelView_Tutorial.h.py15
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/tutorials/modelview/5_edit/mymodel_Quoting_ModelView_Tutorial.h.py27
-rw-r--r--sources/pyside6/doc/snippets/qtbase/src/gui/doc/snippets/code/src_gui_painting_qpainter_drawText.cpp.py13
-rw-r--r--sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py24
-rw-r--r--sources/pyside6/doc/tools/index.rst211
-rw-r--r--sources/pyside6/doc/tools/pyside-assistant.rst21
-rw-r--r--sources/pyside6/doc/tools/pyside-designer.rst91
-rw-r--r--sources/pyside6/doc/tools/pyside-genpyi.rst52
-rw-r--r--sources/pyside6/doc/tools/pyside-linguist.rst20
-rw-r--r--sources/pyside6/doc/tools/pyside-lrelease.rst25
-rw-r--r--sources/pyside6/doc/tools/pyside-lupdate.rst23
-rw-r--r--sources/pyside6/doc/tools/pyside-metaobjectdump.rst92
-rw-r--r--sources/pyside6/doc/tools/pyside-project.rst64
-rw-r--r--sources/pyside6/doc/tools/pyside-qml.rst84
-rw-r--r--sources/pyside6/doc/tools/pyside-qmlcachegen.rst25
-rw-r--r--sources/pyside6/doc/tools/pyside-qmllint.rst49
-rw-r--r--sources/pyside6/doc/tools/pyside-qmltyperegistrar.rst17
-rw-r--r--sources/pyside6/doc/tools/pyside-rcc.rst55
-rw-r--r--sources/pyside6/doc/tools/pyside-uic.rst59
-rw-r--r--sources/pyside6/doc/tools/pyside6-assistant_screenshot.webpbin0 -> 18474 bytes
-rw-r--r--sources/pyside6/doc/tools/pyside6-balsam.rst59
-rw-r--r--sources/pyside6/doc/tools/pyside6-balsamui.rst22
-rw-r--r--sources/pyside6/doc/tools/pyside6-balsamui_screenshot.webpbin0 -> 10190 bytes
-rw-r--r--sources/pyside6/doc/tools/pyside6-designer_base_screenshot.webpbin0 -> 9446 bytes
-rw-r--r--sources/pyside6/doc/tools/pyside6-designer_customwidgets_screenshot.webpbin0 -> 39422 bytes
-rw-r--r--sources/pyside6/doc/tools/pyside6-designer_screenshot.webpbin0 -> 61182 bytes
-rw-r--r--sources/pyside6/doc/tools/pyside6-designer_sections_screenshot.webpbin0 -> 73738 bytes
-rw-r--r--sources/pyside6/doc/tools/pyside6-linguist_screenshot.webpbin0 -> 90474 bytes
-rw-r--r--sources/pyside6/doc/tools/pyside6-qmlimportscanner.rst53
-rw-r--r--sources/pyside6/doc/tools/pyside6-qsb.rst39
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/clickablebutton.rst6
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/dialog.rst43
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/icons.zipbin0 -> 6156 bytes
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/qrcfiles.rst34
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst214
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/translations.rst168
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/treewidget.rst12
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/uifiles.rst88
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/widgetstyling.rst36
-rw-r--r--sources/pyside6/doc/tutorials/datavisualize/index.rst3
-rw-r--r--sources/pyside6/doc/tutorials/debugging/mixed_debugging.rst10
-rw-r--r--sources/pyside6/doc/tutorials/debugging/qml_debugging.rst32
-rw-r--r--sources/pyside6/doc/tutorials/debugging/qtcreator/qtcreator.rst30
-rw-r--r--sources/pyside6/doc/tutorials/debugging/vscode/python_set_interpreter.pngbin0 -> 4664 bytes
-rw-r--r--sources/pyside6/doc/tutorials/debugging/vscode/vscode.rst152
-rw-r--r--sources/pyside6/doc/tutorials/expenses/expenses.rst98
-rw-r--r--sources/pyside6/doc/tutorials/expenses/main.py79
-rw-r--r--sources/pyside6/doc/tutorials/expenses/main_snake_prop.py2
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/01-expenses.py2
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/02-expenses.py7
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/03-expenses.py13
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/04-expenses.py14
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/05-expenses.py26
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/06-expenses.py41
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/07-expenses.py49
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/08-expenses.py59
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/09-expenses.py56
-rw-r--r--sources/pyside6/doc/tutorials/expenses/steps/10-expenses.py62
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/Main.qml196
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/app.qrc16
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons.qrc15
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/app_icon.svg2
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/folder_closed.svg38
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/folder_open.svg38
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/generic_file.svg38
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/globe.svg38
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/info_sign.svg38
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/leaf.svg7
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/light_bulb.svg43
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/qt_logo.svg26
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/read.svg38
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/resize.svg6
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/About.qml93
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/ColorScheme.qml118
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Editor.qml160
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/FileSystemView.qml156
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenu.qml45
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenuBar.qml177
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/ResizeButton.qml23
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Sidebar.qml146
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/WindowDragHandler.qml16
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qmldir11
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/editormodels.py116
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.md210
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.pyproject31
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/main.py50
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/resources/Colors.qml22
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/resources/colorscheme.pngbin0 -> 27675 bytes
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.gifbin0 -> 2082470 bytes
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.webpbin0 -> 23628 bytes
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/scheme_manager.py97
-rw-r--r--sources/pyside6/doc/tutorials/extendedexplorer/schemes.json82
-rw-r--r--sources/pyside6/doc/tutorials/index.rst307
-rw-r--r--sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py137
-rw-r--r--sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py44
-rw-r--r--sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py124
-rw-r--r--sources/pyside6/doc/tutorials/portingguide/chapter1/chapter1.rst14
-rw-r--r--sources/pyside6/doc/tutorials/portingguide/chapter2/chapter2.rst8
-rw-r--r--sources/pyside6/doc/tutorials/portingguide/chapter3/chapter3.rst8
-rw-r--r--sources/pyside6/doc/tutorials/portingguide/index.rst4
-rw-r--r--sources/pyside6/doc/tutorials/qmlapp/qmlapplication.rst8
-rw-r--r--sources/pyside6/doc/tutorials/qmlintegration/qmlintegration.rst24
-rw-r--r--sources/pyside6/doc/tutorials/qmlsqlintegration/qmlsqlintegration.rst98
-rw-r--r--sources/pyside6/doc/videos.rst225
228 files changed, 9952 insertions, 5381 deletions
diff --git a/sources/pyside6/doc/CMakeLists.txt b/sources/pyside6/doc/CMakeLists.txt
index 9d4fcf144..83583756f 100644
--- a/sources/pyside6/doc/CMakeLists.txt
+++ b/sources/pyside6/doc/CMakeLists.txt
@@ -1,5 +1,8 @@
-cmake_minimum_required(VERSION 3.16)
-cmake_policy(VERSION 3.16)
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.18)
+cmake_policy(VERSION 3.18)
project(doc)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../shiboken6/cmake")
@@ -29,7 +32,7 @@ if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
return()
endif()
else()
- # We are building the docs as a standalone project, likely via setup.py build_rst_docs
+ # We are building the docs as a standalone project, likely via setup.py build_base_docs
# command. Perform stricter sanity checks.
if(NOT SPHINX_BUILD)
message(FATAL_ERROR "sphinx-build command not found. Please set the SPHINX_BUILD variable.")
@@ -48,6 +51,12 @@ else()
endif()
set(DOC_DATA_DIR "${CMAKE_CURRENT_BINARY_DIR}/qdoc-output")
+# Directory for sphinx-generated files to build the HTML website. If changed,
+# update "build_scripts/main.py" in "PysideBaseDocs" class at line:
+# self.sphinx_src = self.out_dir / "base".
+set(DOC_BASE_DIR "base")
+
+set(ENV_INHERITANCE_FILE "${CMAKE_CURRENT_BINARY_DIR}/inheritance.json")
get_filename_component(ROOT ${CMAKE_CURRENT_BINARY_DIR} DIRECTORY)
set(TS_ROOT "${ROOT}/PySide6")
@@ -55,10 +64,9 @@ set(TS_ROOT "${ROOT}/PySide6")
file(REMOVE ${CMAKE_CURRENT_LIST_DIR}/pyside.qdocconf ${CMAKE_CURRENT_LIST_DIR}/pyside.qdocconf.in)
# We need to find the interpreter when running this only
-# for a rst_build_docs case, and not a full doc build
+# for the 'build_base_docs' case, and not a full doc build
if (NOT FULLDOCSBUILD)
find_package(Python COMPONENTS Interpreter)
- set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})
endif()
if (QT_SRC_DIR)
@@ -70,13 +78,15 @@ endif()
if(PYSIDE_IS_CROSS_BUILD)
set(python_executable "${QFP_PYTHON_HOST_PATH}")
else()
- set(python_executable "${PYTHON_EXECUTABLE}")
+ set(python_executable "${Python_EXECUTABLE}")
endif()
+set(TOOLS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../tools")
+
if (FULLDOCSBUILD)
# Fetch and transform the snippets from Qt
- set(SNIPPETS_TOOL "${CMAKE_CURRENT_SOURCE_DIR}/../../../tools/snippets_translate/main.py")
- set(SNIPPETS_TARGET ${CMAKE_CURRENT_BINARY_DIR}/rst/codesnippets)
+ set(SNIPPETS_TOOL "${TOOLS_DIR}/snippets_translate/main.py")
+ set(SNIPPETS_TARGET ${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/codesnippets)
# Note QT_SRC_DIR points to 'qtbase',
# so we use the general SRC directory to copy all the other snippets
@@ -89,12 +99,12 @@ if (FULLDOCSBUILD)
endif()
# Generate example gallery
-set(EXAMPLE_TOOL_TARGET "${CMAKE_CURRENT_BINARY_DIR}/rst/examples")
-set(EXAMPLE_TOOL_OPTIONS --target "${EXAMPLE_TOOL_TARGET}")
+set(EXAMPLE_TOOL_TARGET "${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/examples")
+set(EXAMPLE_TOOL_OPTIONS --target "${EXAMPLE_TOOL_TARGET}" --qt-src-dir "${QT_SRC_DIR}")
if (QUIET_BUILD)
list(APPEND EXAMPLE_TOOL_OPTIONS "-q")
endif()
-set(EXAMPLE_TOOL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../tools/example_gallery/main.py")
+set(EXAMPLE_TOOL_DIR "${TOOLS_DIR}/example_gallery/main.py")
add_custom_target("example_gallery" DEPENDS "${EXAMPLE_TOOL_TARGET}")
add_custom_command(OUTPUT "${EXAMPLE_TOOL_TARGET}"
@@ -115,13 +125,26 @@ if (FULLDOCSBUILD)
# The last element of the include list is the mkspec directory containing qplatformdefs.h
list(GET Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS -1 mkspecInclude)
- configure_file("pyside-config.qdocconf.in" "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf" @ONLY)
+ set(config_docconf "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf")
+ configure_file("pyside-config.qdocconf.in" "${config_docconf}" @ONLY)
+ set(global_header "${pyside6_BINARY_DIR}/qdoc.h")
file(READ "${pyside6_BINARY_DIR}/pyside6_global.h" docHeaderContents)
+ file(WRITE ${global_header} "${docHeaderContents}")
+
+ set(global_typesystem "${CMAKE_CURRENT_BINARY_DIR}/typesystem_doc.xml")
file(READ "typesystem_doc.xml.in" typeSystemDocXmlContents)
+ file(WRITE ${global_typesystem} "${typeSystemDocXmlContents}")
+ execute_process(
+ COMMAND ${Python_EXECUTABLE} "${TOOLS_DIR}/doc_modules.py"
+ -t "${global_typesystem}" -g "${global_header}" -d "${config_docconf}"
+ "${QT_INCLUDE_DIR}" "${SUPPORTED_QT_VERSION}"
+ OUTPUT_VARIABLE ALL_DOC_MODULES
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ separate_arguments (ALL_DOC_MODULES UNIX_COMMAND "${ALL_DOC_MODULES}")
- foreach(moduleIn ${all_module_shortnames})
+ foreach(moduleIn ${ALL_DOC_MODULES})
string(TOLOWER "${moduleIn}" lowerModuleIn)
set(docConf "${CMAKE_CURRENT_LIST_DIR}/qtmodules/pyside-qt${lowerModuleIn}.qdocconf.in")
if(EXISTS "${docConf}")
@@ -129,46 +152,16 @@ if (FULLDOCSBUILD)
get_filename_component(BASENAME ${OUTFILE} NAME)
configure_file(${docConf} "${CMAKE_CURRENT_LIST_DIR}/qtmodules/${BASENAME}" @ONLY)
file(APPEND "pyside.qdocconf.in" "\@CMAKE_CURRENT_LIST_DIR\@/qtmodules/${BASENAME}\n")
- # Handle docconf files in Qt that contain multiple modules
- if ("${moduleIn}" STREQUAL "3DExtras")
- set(modules 3DCore 3DRender 3DInput 3DLogic 3DAnimation "${moduleIn}")
- elseif ("${moduleIn}" STREQUAL "OpenGL")
- set(modules "${moduleIn}" OpenGLWidgets)
- elseif ("${moduleIn}" STREQUAL "QuickWidgets")
- set(modules Qml Quick "${moduleIn}")
- elseif ("${moduleIn}" STREQUAL "MultimediaWidgets")
- set(modules Multimedia "${moduleIn}")
- elseif ("${moduleIn}" STREQUAL "Scxml")
- set(modules StateMachine "${moduleIn}")
- elseif ("${moduleIn}" STREQUAL "Svg")
- set(modules "${moduleIn}" SvgWidgets)
- elseif ("${moduleIn}" STREQUAL "WebEngineWidgets")
- set(modules WebEngineCore WebEngineWidgets WebEngineQuick "${moduleIn}")
- set(HAS_WEBENGINE_WIDGETS 1)
- else()
- set(modules "${moduleIn}")
- endif()
- foreach(module ${modules})
- string(TOLOWER "${module}" lowerModule)
- # -- @TODO fix this for macOS frameworks.
- file(APPEND "${CMAKE_CURRENT_LIST_DIR}/pyside-config.qdocconf"
- " -I${QT_INCLUDE_DIR}/Qt${module} \\\n"
- " -I${QT_INCLUDE_DIR}/Qt${module}/${Qt${QT_MAJOR_VERSION}Core_VERSION} \\\n"
- " -I${QT_INCLUDE_DIR}/Qt${module}/${Qt${QT_MAJOR_VERSION}Core_VERSION}/Qt${module} \\\n")
-
- set(globalHeader "Qt${module}")
- set(docHeaderContents "${docHeaderContents}\n#include <Qt${module}/${globalHeader}>")
- set(typeSystemDocXmlContents "${typeSystemDocXmlContents}\n<load-typesystem name=\"Qt${module}/typesystem_${lowerModule}.xml\" generate=\"yes\"/>")
- endforeach()
endif()
endforeach()
- set(typeSystemDocXmlContents "${typeSystemDocXmlContents}\n</typesystem>\n")
- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/typesystem_doc.xml" "${typeSystemDocXmlContents}")
+ # There is no binding for the qtdoc repository, but it has some relevant documents.
+ set(qtdoc_doc_conf "qtmodules/pyside-qtdoc.qdocconf")
+ configure_file("${qtdoc_doc_conf}.in" "${CMAKE_CURRENT_LIST_DIR}/${qtdoc_doc_conf}" @ONLY)
+ file(APPEND "pyside.qdocconf.in" "\@CMAKE_CURRENT_LIST_DIR\@/${qtdoc_doc_conf}\n")
- set(docHeader "${pyside6_BINARY_DIR}/qdoc.h")
- file(WRITE ${docHeader} "${docHeaderContents}")
configure_file("pyside.qdocconf.in" "pyside.qdocconf" @ONLY)
+ configure_file("qdoc_spawner.py.in" "qdoc_spawner.py" @ONLY)
set(QDOC_TYPESYSTEM_PATH "${pyside6_SOURCE_DIR}${PATH_SEP}${pyside6_BINARY_DIR}")
@@ -183,18 +176,25 @@ if (FULLDOCSBUILD)
add_custom_target(qdoc DEPENDS "${DOC_DATA_DIR}/webxml/qtcore-index.webxml")
add_custom_command(OUTPUT "${DOC_DATA_DIR}/webxml/qtcore-index.webxml"
- # Use dummy Qt version information, QDoc needs it but has no effect on WebXML output
- COMMAND ${CMAKE_COMMAND} -E env BUILDDIR=${CMAKE_CURRENT_LIST_DIR}/src QT_INSTALL_DOCS=${QT_SRC_DIR}/doc
- QT_VERSION=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}
- QT_VER=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}
- QT_VERSION_TAG=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}
- "${qdoc_binary}" pyside.qdocconf -single-exec
- -installdir ${DOC_DATA_DIR} -outputdir ${DOC_DATA_DIR}
+ Use dummy Qt version information, QDoc needs it but has no effect on WebXML output
+ COMMAND ${CMAKE_COMMAND} -E env ${python_executable} qdoc_spawner.py
+ --qt=${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH}
+ --doc-data-dir=${DOC_DATA_DIR}
+ --qdoc-binary=${qdoc_binary}
+ --build-dir=${CMAKE_CURRENT_LIST_DIR}/src
+ --qt-install-docs=${QT_SRC_DIR}/doc
+ --parallel="auto"
+ --verbose
COMMENT "Running qdoc against Qt source code...")
endif()
+# Avoid using 'auto' for '-j' option as it could lead to
+# crash on some systems due to out-of-memory situation. Instead
+# use a no. less than 8.
add_custom_target(apidoc
- COMMAND ${SHIBOKEN_PYTHON_INTERPRETER} ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT} ${CMAKE_CURRENT_BINARY_DIR}/rst html
+ COMMAND ${CMAKE_COMMAND} -E env INHERITANCE_FILE=${ENV_INHERITANCE_FILE}
+ ${SHIBOKEN_PYTHON_INTERPRETER} ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT}
+ -j 6 ${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR} html
COMMENT "Generating PySide htmls..."
)
@@ -207,6 +207,7 @@ if(DOC_OUTPUT_FORMAT STREQUAL "html")
${CMAKE_CURRENT_BINARY_DIR}/../../shiboken6/doc/html
${CMAKE_CURRENT_BINARY_DIR}/html/shiboken6
COMMENT "Copying Shiboken docs..."
+ DEPENDS "${DOC_DATA_DIR}/webxml/qtcore-index.webxml"
VERBATIM)
else()
if(qhelpgenerator_binary)
@@ -215,9 +216,10 @@ else()
set(PATCH_QHP_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/../../shiboken6/doc/scripts/patch_qhp.py")
file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/html/PySide.qhp QHP_FILE)
add_custom_command(TARGET apidoc POST_BUILD
- COMMAND ${python_executable} ${PATCH_QHP_SCRIPT} -f ${QHP_FILE} -v pyside6
+ COMMAND ${python_executable} ${PATCH_QHP_SCRIPT} -p -v pyside6 ${QHP_FILE}
COMMAND "${qhelpgenerator_binary}" ${QHP_FILE}
COMMENT "Generating QCH from a QHP file..."
+ DEPENDS "${DOC_DATA_DIR}/webxml/qtcore-index.webxml"
VERBATIM
)
else()
@@ -226,42 +228,53 @@ else()
endif()
# create conf.py based on conf.py.in
-configure_file("conf.py.in" "rst/conf.py" @ONLY)
-
-set(CODE_SNIPPET_ROOT "${CMAKE_CURRENT_BINARY_DIR}/rst/codesnippets")
-
-add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/rst/PySide6/QtCore/index.rst"
- COMMAND Shiboken6::shiboken6 --generator-set=qtdoc ${docHeader}
- --enable-pyside-extensions
- --include-paths="${QT_INCLUDE_DIR}${PATH_SEP}${pyside6_SOURCE_DIR}${PATH_SEP}${TS_ROOT}"
- --api-version=${SUPPORTED_QT_VERSION}
- --typesystem-paths="${QDOC_TYPESYSTEM_PATH}"
- --library-source-dir=${QT_SRC_DIR}
- --documentation-data-dir=${DOC_DATA_DIR}/webxml
- --output-directory=${CMAKE_CURRENT_BINARY_DIR}/rst
- --documentation-code-snippets-dir=${CODE_SNIPPET_ROOT}
- --snippets-path-rewrite=${QT_ROOT_PATH}:${CODE_SNIPPET_ROOT}
- --documentation-extra-sections-dir=${CMAKE_CURRENT_BINARY_DIR}/rst/extras
- --additional-documentation=${CMAKE_CURRENT_BINARY_DIR}/rst/additionaldocs.lst
- ${CMAKE_CURRENT_BINARY_DIR}/typesystem_doc.xml
+configure_file("conf.py.in" "${DOC_BASE_DIR}/conf.py" @ONLY)
+
+set(CODE_SNIPPET_ROOT "${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/codesnippets")
+
+if (FULLDOCSBUILD)
+shiboken_get_tool_shell_wrapper(shiboken tool_wrapper)
+
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/PySide6/QtCore/index.rst"
+ COMMAND
+ ${tool_wrapper}
+ $<TARGET_FILE:Shiboken6::shiboken6>
+ --generator-set=qtdoc
+ ${global_header}
+ --enable-pyside-extensions
+ --include-paths="${QT_INCLUDE_DIR}${PATH_SEP}${pyside6_SOURCE_DIR}${PATH_SEP}${TS_ROOT}"
+ --api-version=${SUPPORTED_QT_VERSION}
+ --typesystem-paths="${QDOC_TYPESYSTEM_PATH}"
+ --library-source-dir=${QT_SRC_DIR}
+ --documentation-data-dir=${DOC_DATA_DIR}/webxml
+ --output-directory=${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}
+ --documentation-code-snippets-dir=${CODE_SNIPPET_ROOT}
+ --snippets-path-rewrite=${QT_ROOT_PATH}:${CODE_SNIPPET_ROOT}
+ --documentation-extra-sections-dir=${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/extras
+ --additional-documentation=${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/additionaldocs.lst
+ --inheritance-file=${ENV_INHERITANCE_FILE}
+ ${global_typesystem}
WORKING_DIRECTORY ${${module}_SOURCE_DIR}
COMMENT "Running generator to generate documentation...")
+endif()
-add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/rst/extras"
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/rst
+add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/extras"
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}
COMMENT "Copying docs...")
add_custom_target("doc_copy"
- DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/rst/extras")
+ DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/extras")
add_custom_target("docrsts"
- DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/rst/PySide6/QtCore/index.rst")
+ DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/PySide6/QtCore/index.rst")
+set(LIBEXEC_PATH "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_LIBEXECS}")
add_custom_target("licensedocrsts"
COMMAND ${python_executable}
${CMAKE_CURRENT_LIST_DIR}/qtattributionsscannertorst.py
+ -l "${LIBEXEC_PATH}"
${CMAKE_CURRENT_LIST_DIR}/../../..
- ${CMAKE_CURRENT_BINARY_DIR}/rst/licenses.rst
+ ${CMAKE_CURRENT_BINARY_DIR}/${DOC_BASE_DIR}/licenses.rst
COMMENT "Creating 3rdparty license documentation..."
)
diff --git a/sources/pyside6/doc/PySide6/QtAsyncio/index.rst b/sources/pyside6/doc/PySide6/QtAsyncio/index.rst
new file mode 100644
index 000000000..326f6efcc
--- /dev/null
+++ b/sources/pyside6/doc/PySide6/QtAsyncio/index.rst
@@ -0,0 +1,150 @@
+.. module:: PySide6.QtAsyncio
+
+PySide6.QtAsyncio
+*****************
+
+.. note:: This module is currently in technical preview.
+
+The Qt Asyncio module is a pure Python module that allows programs to be
+written that use Qt's API in conjunction with `asyncio
+<https://docs.python.org/3/library/asyncio.html>`_. asyncio is a popular
+Python library for asynchronous programming. It is used in particular
+for programs that need to handle many I/O operations from many sources,
+such as web servers. More generally, it allows developers to work with
+`couroutines <https://docs.python.org/3/library/asyncio-task.html#coroutine>`_.
+Coroutines can be imagined as "asynchronous functions". In contrast to
+Qt's signals and slot mechanism, this allows for asynchronous programs
+that are closer in program flow to synchronous programs, as programs no
+longer have to be imagined as a series of callbacks. Instead, coroutines
+transparently resume and yield at designated spots.
+
+Consider the following simple coroutine defined with the ``async``
+keyword in front of its definition:
+
+::
+
+ async def do_something():
+ result = await do_something_asynchronously()
+ print(result)
+
+``do_something_asynchronously()`` is a coroutine itself, e.g., an
+I/O-heavy operation that would normally block the execution flow in a
+synchronous program. Instead, the ``await`` keyword is used to wait for
+the result, at which point ``do_something()`` yields and the program
+flow transparently switches to the next asynchronous task. When the
+result becomes available, the program flow is able to switch back to the
+``do_something()`` coroutine, which then resumes and prints the result.
+
+The asyncio API
+^^^^^^^^^^^^^^^
+
+asyncio and Qt are both based on an event loop. asyncio provides an API
+to replace its default event loop with a custom implementation.
+**QtAsyncio** provides such an implementation that uses Qt's event loop,
+allowing Qt and asyncio to be used together.
+
+We consider that this API consists of two levels:
+
+1. Fundamental infrastructure for event loops and asynchronous
+ operations, including `futures
+ <https://docs.python.org/3/library/asyncio-future.html#asyncio.Future>`_,
+ `tasks <https://docs.python.org/3/library/asyncio-task.html#asyncio.Task>`_,
+ `handles <https://docs.python.org/3/library/asyncio-eventloop.html#callback-handles>`_,
+ executors, and event loop management functions (see below).
+2. A user-facing API for use in applications, including transports and
+ protocols, network connections, servers, sockets, signals,
+ subprocesses.
+
+**QtAsyncio** currently covers the first level. This includes the
+following functions, for which the API is identical with QtAsyncio as
+with asyncio:
+
+* `run_until_complete() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_until_complete>`_
+* `run_forever() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_forever>`_
+* `stop() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.stop>`_
+* `is_running() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.is_running>`_
+* `is_closed() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.is_closed>`_
+* `close() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.close>`_
+* `shutdown_asyncgens() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.shutdown_asyncgens>`_
+* `shutdown_default_executor() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.shutdown_default_executor>`_
+* `call_soon() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_soon>`_
+* `call_soon_threadsafe() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_soon_threadsafe>`_
+* `call_later() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_later>`_
+* `call_at() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_at>`_
+* `time() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.time>`_
+* `create_future() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.create_future>`_
+* `create_task() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.create_task>`_
+* `set_task_factory() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.set_task_factory>`_
+* `get_task_factory() <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.get_task_factory>`_
+
+Also included is the ability to
+`run synchronous code in an executor <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor>`_
+(``ThreadPoolExecutor``).
+
+Get started with QtAsyncio
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To write a program with **QtAsyncio**, first import the module, e.g.:
+
+::
+
+ import PySide6.QtAsyncio as QtAsyncio
+
+**QtAsyncio** provides a function ``run()`` that can be used to run a
+specific coroutine until it is complete, or to start the Qt & asyncio
+event loop plainly. The former case makes sense if the program flow
+starts with said coroutine, the latter case makes sense if a coroutine
+is enqueued later in the program flow, e.g., after pressing a button in
+the UI.
+
+::
+
+ QtAsyncio.run()
+
+(see the `asyncio "minimal" example <https://doc.qt.io/qtforpython-6/examples/example_async_minimal.html>`_
+for an instance of this usage) or
+
+::
+
+ QtAsyncio.run(my_coroutine())
+
+(see the `asyncio "Eratosthenes" example <https://doc.qt.io/qtforpython-6/examples/example_async_eratosthenes.html>`_)
+or
+
+::
+
+ QtAsyncio.run(my_coroutine(), keep_running=False)
+
+to run the coroutine and then stop the event loop upon its completion.
+This latter case behaves identically to ``asyncio.run(my_coroutine())``.
+
+An additional optional argument ``quit_qapp`` can be passed to ``run()``
+to configure whether the QCoreApplication at the core of QtAsyncio
+should be shut down when asyncio finishes. A special case where one
+would want to disable this is test suites that want to reuse a single
+QCoreApplication instance across all unit tests, which would fail if
+this instance is shut down every time. The default is ``True``.
+
+Note that this argument is orthogonal to the ``keep_running`` argument.
+``keep_running`` determines if **asyncio** should keep running after the
+coroutine has finished, while ``quit_qapp`` determines if the
+QCoreApplication should be shut down after asyncio has finished. It is
+possible for asyncio to finish while the QCoreApplication is kept alive.
+
+An argument ``handle_sigint`` determines whether QtAsyncio should handle
+SIGINT (Ctrl+C) and shut down the event loop when it is received. The
+default is ``False``. Set this to ``True`` if you want QtAsyncio to take
+care of handling SIGINT instead of your program.
+
+Coroutines explained
+^^^^^^^^^^^^^^^^^^^^
+
+Coroutines are functions that can be paused (yield) and resumed. Behind
+this simple concept lies a complex mechanism that is abstracted by the
+asynchronous framework. This talk presents a diagram that attempts to
+illustrate the flow of a coroutine from the moment it's provided to the
+async framework until it's completed.
+
+.. image:: https://img.youtube.com/vi/XuqdTvisqkQ/mqdefault.jpg
+ :alt: Asynchronous programming with asyncio and Qt
+ :target: https://www.youtube.com/watch?v=XuqdTvisqkQ
diff --git a/sources/pyside6/doc/README.md b/sources/pyside6/doc/README.md
deleted file mode 100644
index 88bf3a64d..000000000
--- a/sources/pyside6/doc/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Recreating the module descriptions after a Qt major version change
-
-The source tree contains .rst files containing the module description in
-doc/extras (named for example "QtCore.rst"). They are extracted/adapted from
-the C++ module descriptions. If there is no module description file, shiboken
-will extract the module description from the webxml files generated by qdoc.
-This ends up in the build directory under doc/rst/PySide6/<module>/index.rst.
-It can be used as a starting point for a module description file. C++
-specific information like build instructions should be removed.
-
-The descriptions may link to tutorials which can be added to additionaldocs.lst
-for webxml extraction.
-
-# Maintaining additionaldocs.lst
-
-The file is a list of additional documentation files. These are basically Qt
-tutorials referenced by the documentation. They will receive some Python
-adaption by shiboken/sphinx.
-
-The list can be created by the below script and some hand-editing. It will find
-almost all documents. Quite a number of them might be unreferenced, but there
-is no good way of filtering for this.
-
- for F in *.webxml
- do
- echo "$F" | egrep '(-index)|(-module)|(-qmlmodule)\.webxml$' > /dev/null
- if [ $? -ne 0 ]
- then
- if fgrep '<para>' "$F" > /dev/null # Exclude reference only
- then
- egrep "(<class )|(<namespace )" $F > /dev/null || echo $F
- fi
- fi
- done
diff --git a/sources/pyside6/doc/_static/css/qt_style.css b/sources/pyside6/doc/_static/css/qt_style.css
index 4b9b17fe7..08c4646c6 100644
--- a/sources/pyside6/doc/_static/css/qt_style.css
+++ b/sources/pyside6/doc/_static/css/qt_style.css
@@ -1,39 +1,15 @@
-.btn-qt:hover,
-.btn-qt:active,
-.btn-qt:focus,
-.btn-qt.active {
- background: #41cd52;
- color: #fff !important;
- border-color: #fff;
+.text-center {
+ text-align: center !important;
}
-.btn-link {
- color: #41cd52 !important;
-}
-
-.btn-link:hover {
- color: #222840 !important;
- text-decoration: underline;
-}
-
-/* Using !important is not recommended, but out CSS is being added
- * to the pages before the bootstrap ones, so we cannot override them
- * without using it */
-.btn-qt {
- color: #41cd52 !important;
- border-color: #41cd52 !important;
- font-weight: bold !important;
-}
-.card-img-top-main {
+.text-center img {
padding-top: 10px;
height: 70px !important;
}
-.card-img-top {
- object-fit: contain;
- height: 120px;
- padding-top: 20px;
- transform: scale(1.3, 1.3);
+.cover-img img {
+ object-fit: cover;
+ height: 50%;
}
/* Tables */
@@ -78,3 +54,47 @@ table.docutils td ul > li {
position:relative;
overflow:visible
}
+
+/* We cannot put a :download:`....` command inside
+ * a sphinx-design button, so we add some properties from the button
+ * to the download class to mimic it */
+code.download {
+ text-align: center;
+ color: var(--color-brand-primary);
+ display: block;
+ border-color: transparent;
+ background-color: transparent;
+ border: 1px solid var(--color-brand-primary) !important;
+ border-radius: 0.25rem;
+ font-size: 1rem;
+ font-weight: 400;
+ vertical-align: middle;
+ padding: .375rem .75rem;
+ user-select: none;
+ line-height: 1.5;
+ transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
+}
+
+code.download:hover {
+ color: white;
+ background-color: var(--color-brand-primary);
+ border-color: var(--color-brand-primary);
+ text-decoration: none;
+ padding: .375rem .75rem;
+}
+
+dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple):first-child > dt {
+ font-size: +2.25rem;
+ font-weight: 700;
+ color: #ff00dd;
+}
+
+.theme-toggle svg{
+ width: +1.25rem;
+ height: +2.25rem;
+}
+
+.sd-card-title code span {
+ font-size: +1rem;
+ color: var(--color-brand-primary);
+}
diff --git a/sources/pyside6/doc/_static/qtforpython.ico b/sources/pyside6/doc/_static/qtforpython.ico
new file mode 100644
index 000000000..2f4d9e9de
--- /dev/null
+++ b/sources/pyside6/doc/_static/qtforpython.ico
Binary files differ
diff --git a/sources/pyside6/doc/_static/qtforpython.png b/sources/pyside6/doc/_static/qtforpython.png
index 3a2f2bd17..33e971022 100644
--- a/sources/pyside6/doc/_static/qtforpython.png
+++ b/sources/pyside6/doc/_static/qtforpython.png
Binary files differ
diff --git a/sources/pyside6/doc/_tags/android.rst b/sources/pyside6/doc/_tags/android.rst
new file mode 100644
index 000000000..08a30fc0f
--- /dev/null
+++ b/sources/pyside6/doc/_tags/android.rst
@@ -0,0 +1,21 @@
+My tags: Android
+################
+
+.. toctree::
+ :maxdepth: 1
+ :caption: With this tag
+
+ ../examples/example_bluetooth_heartrate_game.rst
+ ../examples/example_bluetooth_lowenergyscanner.rst
+ ../examples/example_location_mapviewer.rst
+ ../examples/example_multimedia_audiooutput.rst
+ ../examples/example_multimedia_audiosource.rst
+ ../examples/example_multimedia_camera.rst
+ ../examples/example_qml_editingmodel.rst
+ ../examples/example_qml_usingmodel.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/_tags/tagsindex.rst b/sources/pyside6/doc/_tags/tagsindex.rst
new file mode 100644
index 000000000..be29337ec
--- /dev/null
+++ b/sources/pyside6/doc/_tags/tagsindex.rst
@@ -0,0 +1,12 @@
+:orphan:
+
+.. _tagoverview:
+
+Tags overview
+#############
+
+.. toctree::
+ :caption: Tags
+ :maxdepth: 1
+
+ Android (14) <android.rst>
diff --git a/sources/pyside6/doc/_themes/pysidedocs/static/pyside.css b/sources/pyside6/doc/_themes/pysidedocs/static/pyside.css
deleted file mode 100644
index 5b4cb9d1f..000000000
--- a/sources/pyside6/doc/_themes/pysidedocs/static/pyside.css
+++ /dev/null
@@ -1,2198 +0,0 @@
-@import url('cookie-confirm.css') screen;
-
-/* -- admonitions -- */
-
-div.admonition {
- margin: 1.5em 0 1.5em;
- padding: 0;
-}
-
-div.admonition dt {
- font-weight: bold;
-}
-
-div.admonition dl {
- margin-bottom: 0;
-}
-
-p.admonition-title {
- margin: 0px 10px 5px 0px;
- font-weight: bold;
-}
-
-div.admonition code {
- font-family: inherit;
-}
-
-p.admonition-title + p {
- padding-left: 1em;
-}
-
-div.admonition a:after {
- content: ', ';
-}
-
-div.admonition a:last-child:after {
- content: '';
-}
-
-.body {
- width: 100%;
- background-color: #00FF00;
- clear: both;
- display:inline-block;
- background-color:#fff;
- padding: 25px 35px 20px 30px;
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- -ms-box-sizing:border-box;
- box-sizing:border-box;
-}
-.bodywrapper {
- position: relative;
- /*background-color: #0000ff;*/
-}
-.bodywrapper .admonition p.admonition-title {
- margin-bottom:5px
-}
-
-.bodywrapper .admonition p {
- margin:0
-}
-
-div.body p.centered {
- text-align: center;
- margin-top: 25px;
-}
-
-div.warning, div.seealso, div.note, div.important {
- padding: 6px 0px 6px 10px;
- border: none;
-}
-
-div.warning {
- background-color: #ffe4e4;
-}
-
-div.important {
- background-color: #fef9f3;
- border-left: 5px solid #feeec8;
-}
-
-div.seealso {
- background-color: #fff2d6;
-}
-
-div.note {
- background-color: #c5d3f4;
- border-left: 5px solid #7899f4;
-}
-
-table.docutils {
- margin-right: auto;
- margin-bottom: 10px;
- border: none;
- width: initial;
-}
-
-table.docutils.colwidths-given td {
- float: none;
-}
-
-table.docutils th,
-table.docutils td {
- padding-left:0;
- border: none;
-}
-
-table.docutils td ul {
- margin:0
-}
-
-table.docutils td ul > li {
- margin: 0 0 0.5em;
-}
-h2 em {
- float: right;
- font-size: 10px;
- position: relative;
- top: -20px;
-}
-
-.document {
- padding-bottom: 20px;
-}
-
-.documentwrapper {
- margin-left: 255px;
- position: relative;
-}
-@media screen and (max-width: 700px) {
- .documentwrapper {
- clear: both;
- margin-left: 0px;
- position: relative;
- }
-}
-
-.body blockquote {
- border: none;
- padding-left: 0;
- margin-bottom: 1.5em;
-}
-
-.sphinxsidebar {
- float: left;
- width: 186px;
- padding: 15px;
- text-align: left;
- background-color: #fff;
- clear: both;
-}
-
-.sphinxsidebar ul {
- padding: 0px;
- margin: 0px;
- list-style-position: inside;
-}
-
-.sphinxsidebar > ul {
- padding: 0px;
- margin: 0px;
-}
-
-.sphinxsidebar ul li li {
- margin-left: 10px;
- padding: 0px;
- font-size: 0.95em;
-}
-
-.sphinxsidebar ul a,
-.sphinxsidebar p.topless a {
- word-break: break-word;
-}
-
-.sphinxsidebar h3, .sphinxsidebar h3 a {
- color: #333;
-}
-
-.sphinxsidebar p.topless {
- margin: 1em 0 1em;
-}
-
-.pysidetoc ul {
- list-style: none;
- padding: 0px;
- margin: 0px;
-}
-
-.pysidetoc em {
- font-style: normal;
-}
-
-.pysidetoc strong {
- display: block;
- padding: 5px;
- margin: 0 10px 10px 0;
- border: none;
- background-color: #e2e2e2;
-}
-
-.section .docutils.container td {
- float:left;
-}
-
-.hide {
- display: none;
-}
-
-/* copy-notice */
-.document + p {
- margin-left: 255px;
- width: 70%;
- font-size: 0.75em;
- margin: 0 35px 15px 280px;
-}
-
-#searchbox {
- border-top: 1px solid #989898;
- padding-top: 10px;
- margin-left: -10px;
- margin-right: -10px;
- padding-left: 10px;
- padding-right: 10px;
-}
-
-#search_button {
- border: 1px solid #3A393A;
- background-color: #3A393A;
- color: white;
- cursor: pointer;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- -khtml-border-radius: 5px;
-
-}
-
-form {
- margin: 0px;
- padding: 0px;
-}
-
-#searchbox h3 {
- padding: 10px 0 0 0;
- margin-bottom: 5px;
-}
-
-/* search field */
-form #q {
- width: 136px;
- /* height: 22px; */
- /* border: none; */
- margin: 0px;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- -khtml-border-radius: 5px;
- margin-top: 2px;
- padding: 4px;
- line-height: 22px;
-}
-
-#search-results h2 {
- display: none;
-}
-
-#search-results h2 {
- display: none;
-}
-
-#search-results ul.search {
- margin: 0px;
- padding: 0px;
-}
-
-ul.search div.context {
- padding-left: 40px;
-}
-
-#installation td {
- text-align: center;
- font-weight: bold;
-}
-
-em {
- color: inherit;
- font-style:italic;
-}
-
-/******** REL bar *********/
-
-.related {
- display: inline;
-}
-
-.related h3 {
- display: none;
-}
-
-.align-center {
- text-align: center;
-}
-
-.contentstable {
- width: 100%;
-}
-
-.contentstable td {
- padding-left: 30px;
- vertical-align: top;
-}
-
-p.biglink a {
- font-size: 20px;
-}
-
-dt:target, .highlight {
- background-color: #fbe54e;
-}
-
-p.highlight-link {
- margin-top: 10px;
- font-size: 0.8em;
-}
-
-#synopsis table, table.field-list {
- margin: 1em 0 1em 0;
-}
-
-table.field-list tr {
- text-align: left;
-}
-
-tt.descname {
- font-size: 120%;
- font-weight: bold;
-}
-
-#functions ul, #virtual-functions ul, #slots ul, #signals ul, #static-functions ul {
- margin: 0;
- padding: 6px;
- border: 1px solid #ddd;
- border-radius: 0;
- background-color: #e2e2e2;
-}
-
-#functions p, #virtual-functions p, #slots p, #signals p, #static-functions p {
- margin: 0;
- padding: 0;
-}
-
-#functions li, #virtual-functions li, #slots li, #signals li, #static-functions li {
- list-style: none;
- margin: 5px;
- padding: 0;
- font-size: 90%;
-}
-
-#synopsis span.pre {
- color: #009491;
- font-weight: bolder;
-}
-
-#detailed-description .class dt,
-#detailed-description .method dt,
-#detailed-description .staticmethod dt,
-#detailed-description .attribute dt {
- margin: 0px;
- margin-bottom: 10px;
- padding: 10px;
- font-weight: bold;
- background-color: #e2e2e2;
- border: none;
- border-radius: 0;
-}
-
-#detailed-description dd > blockquote,
-#detailed-description dd > .field-list {
- font-family: 'Droid Sans Mono', monospace;
- font-size: small;
- border-left: 10px solid #e2e2e2;
- padding-left: 10px;
- margin-bottom: 1.5em;
-}
-
-#detailed-description dd > blockquote blockquote {
- border: none;
- padding: 0;
-}
-
-#detailed-description .class .field-odd,
-#detailed-description .method .field-odd,
-#detailed-description .staticmethod .field-odd,
-#detailed-description .attribute .field-odd {
- margin: 0;
- padding: 1px 0 0 0;
- background-color: #ffffff;
-
-}
-
-#detailed-description .class .field-even,
-#detailed-description .method .field-even,
-#detailed-description .staticmethod .field-even,
-#detailed-description .attribute .field-even {
- margin: 0;
- padding: 1px 0 0 0;
- background-color: #ffffff;
-}
-
-#detailed-description .class .field-odd li,
-#detailed-description .method .field-odd li,
-#detailed-description .staticmethod .field-odd li,
-#detailed-description .attribute .field-odd li {
- list-style: none;
- margin: 0;
- padding: 0;
-
-}
-
-#detailed-description .class .field-even li,
-#detailed-description .method .field-even li,
-#detailed-description .staticmethod .field-even li,
-#detailed-description .attribute .field-even li {
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-#detailed-description .class .field-odd p,
-#detailed-description .method .field-odd p,
-#detailed-description .staticmethod .field-odd p,
-#detailed-description .attribute .field-odd p{
- margin: 0;
- margin-left: 20px;
-
-}
-
-#detailed-description .class .field-even p,
-#detailed-description .method .field-even p,
-#detailed-description .staticmethod .field-even p,
-#detailed-description .attribute .field-even p{
- margin: 0;
- margin-left: 20px;
-}
-
-#detailed-description .class .field-odd p:last-child,
-#detailed-description .method .field-odd p:last-child,
-#detailed-description .staticmethod .field-odd p:last-child,
-#detailed-description .attribute .field-odd p:last-child {
- margin-bottom: 10px;
-
-}
-
-#detailed-description .class .field-even p:last-child,
-#detailed-description .method .field-even p:last-child,
-#detailed-description .staticmethod .field-even p:last-child,
-#detailed-description .attribute .field-even p:last-child{
- margin-bottom: 10px;
-}
-
-.document dl.attribute,
-.document dl.class,
-.document dl.method,
-.document dl.staticmethod {
- margin-top: 2em;
-}
-
-.document dl.attribute dd,
-.document dl.class dd,
-.document dl.method dd,
-.document dl.staticmethod dd {
- padding-left: 1em;
-}
-
-#detailed-description .attribute td:nth-child(1) {
- font-family: 'Droid Sans Mono', monospace;
-}
-
-/* Qt theme */
-#navbar {
- position:fixed;
- top:0;
- left:0;
- z-index:100;
- background:#fff;
- width:100%
-}
-#navbar .container, .fixed .container {
- max-width:1280px;
- margin:0 auto;
- padding:0 3.9%; /* 0? */
- position:relative;
- overflow:visible
-}
-#navbar .navbar-header {
- position:relative
-}
-#menuextras li a:hover span {
- color: #41cd52;
-}
-/* new header */
-#mm-wrap, #mm-wrap #mm-helper,
-#mm-wrap #mm-helper li.mm-item,
-#mm-wrap #mm-helper a.mm-link {
- -moz-transition: none;
- -o-transition: none;
- -webkit-transition: none;
- transition: none;
- -webkit-border-radius: 0 0 0 0;
- -moz-border-radius: 0 0 0 0;
- -ms-border-radius: 0 0 0 0;
- -o-border-radius: 0 0 0 0;
- border-radius: 0 0 0 0;
- -webkit-box-shadow: none;
- -moz-box-shadow: none;
- -ms-box-shadow: none;
- -o-box-shadow: none;
- box-shadow: none;
- background: none;
- border: 0;
- bottom: auto;
- box-sizing: border-box;
- clip: auto;
- color: #090e21;
- display: block;
- float: none;
- font-family: inherit;
- font-size: 14px;
- height: auto;
- left: auto;
- line-height: 1.7;
- list-style-type: none;
- margin: 0;
- min-height: 0;
- opacity: 1;
- outline: none;
- overflow: visible;
- padding: 0;
- position: relative;
- right: auto;
- text-align: left;
- text-decoration: none;
- text-transform: none;
- top: auto;
- vertical-align: baseline;
- visibility: inherit;
- width: auto;
-}
-#mm-wrap #mm-helper {
- visibility:visible;
- text-align:right;
- padding:0 0px 0 0px
-}
-#navbar #mm-wrap #mm-helper li.mm-item {
- border-right:solid #f3f3f4 1px;
- padding-right:30px;
- padding-left:30px
-}
-#navbar #mm-wrap #mm-helper li.mm-item > a:hover {
- opacity: .5
-}
-#mm-wrap #mm-helper > li.mm-item {
- margin:0 0 0 0;
- display:inline-block;
- height:auto;
- vertical-align:middle
-}
-#navbar #mm-wrap #mm-helper li.mm-item:nth-child(3) {
- border-right:0
-}
-#mm-wrap #mm-helper a.mm-link {
- cursor: pointer
-}
-@media (max-width: 1279px) {
- #navbar {
- padding:0;
- position:relative;
- }
- #navbar .container {
- max-width:100%
- }
- .container {
- padding:0 2%
- }
- .sphinxsidebar {
- top: 16px !important;
- }
-}
-#navbar .navbar-oneQt {
- display:inline;
- float:left;
- width:31px;
- color:#41cd52
-}
-#navbar .navbar-oneQt:before {
- content:attr(data-icon);
- position:absolute;
- top:14px;
- left:0;
- color:#41cd52;
- font-family:'Qt Icons';
- line-height:1;
- font-size:40px;
- transition:all 0.3s ease-in-out;
-}
-#mm-wrap {
- clear:both;
- background:rgba(255, 255, 255, 0.1);
- -webkit-border-radius:0px 0px 0px 0px;
- -moz-border-radius:0px 0px 0px 0px;
- -ms-border-radius:0px 0px 0px 0px;
- -o-border-radius:0px 0px 0px 0px;
- border-radius:0px 0px 0px 0px
-}
-#mm-wrap #mm-helper li.mm-item:last-child a {
- background:transparent url("icon_avatar.png") 50% 50% no-repeat !important;
- background-size:24px !important;
- width:24px !important;
- height:24px !important;
-}
-#navbar #mm-wrap #mm-helper li.mm-item > a {
- opacity:1;
- -webkit-transition:all 0.3s ease-in-out;
- -moz-transition:all 0.3s ease-in-out;
- -ms-transition:all 0.3s ease-in-out;
- -o-transition:all 0.3s ease-in-out;
- transition:all 0.3s ease-in-out;
-}
-#mm-wrap #mm-helper > li.mm-item > a.mm-link {
- border-top:0px solid #fff;
- border-left:0px solid #fff;
- border-right:0px solid #fff;
- border-bottom:0px solid #fff;
- outline:none;
- text-decoration:none;
- padding:0 0 0 0;
- line-height:70px;
- font-weight:normal;
- height:70px;
- vertical-align:baseline;
- text-align:left;
- width:auto;
- display:block;
- color:#090e21;
- text-transform:none;
- text-decoration:none;
- background:rgba(0, 0, 0, 0);
- -webkit-border-radius:0px 0px 0px 0px;
- -moz-border-radius:0px 0px 0px 0px;
- -ms-border-radius:0px 0px 0px 0px;
- -o-border-radius:0px 0px 0px 0px;
- border-radius:0px 0px 0px 0px;
- font-family:inherit;
- font-size:14px;
-}
-/* end new header */
-@media (min-width: 1320px) {
- .body .flowListDiv dl.flowList {
- -webkit-column-count:3;
- -moz-column-count:3;
- column-count:3
- }
-}
-@media (min-width: 1120px) {
- #navbar.fixed {
- -moz-box-shadow:0px 0px 8px rgba(0,0,0,0.23);
- -webkit-box-shadow:0px 0px 8px rgba(0,0,0,0.23);
- box-shadow:0px 0px 8px rgba(0,0,0,0.23)
- }
- #navbar.fixed #mm-wrap #mm-helper > li.mm-item > a.mm-link {
- height:50px;
- line-height:50px
- }
- #navbar.fixed .navbar-oneQt:before {
- font-size:35px;
- top:7px
- }
-
- .flowListDiv dl.flowList {
- -webkit-column-count:2;
- -moz-column-count:2;
- column-count:2
- }
-}
-@media (max-width: 1120px) {
- #navbar {
- padding:0;
- position:relative
- }
- #navbar .navbar-oneQt:before {
- left:10px
- }
- #navbar .container {
- max-width:100%;
- padding:0
- }
- #footerbar .container {
- padding:0
- }
- body .main {
- margin-top:0px
- }
- #footerbar .footer-main .footer-nav {
- padding:3.9% 0 3.9% 3%;
- border-bottom:1px solid #413d3b;
- float:none;
- display:block;
- width:auto
- }
- #footerbar .footer-main .theqtcompany {
- clear:both;
- float:left;
- margin:30px 0 8px 3%
- }
- #footerbar .footer-main .footer-social {
- float:left;
- padding:50px 0px 0px 3%
- }
- #footerbar #menu-footer-submenu {
- clear:both;
- float:none;
- display:block;
- padding:0px 0px 3.9% 3%
- }
- ul#menu-footer-submenu {
- margin-left: 0
- }
-}
-.cookies_yum {
- background-color:#cecfd5;
- display:none;
- width:100%
-}
-.cookies_yum img {
- width:25px;
- top:6px;
- display:inline-block;
- position:absolute;
- left:13px
-}
-.cookies_yum div {
- margin:0 auto;
- max-width:1280px;
- min-height:30px;
- padding:6px 0px 6px 0px;
- position:relative
-}
-.cookies_yum p {
- color:#09102b;
- margin:0px;
- font-size:0.79em;
- display:inline-block;
- line-height:1.2;
- padding:0 30px 0 50px
-}
-.cookies_yum p a {
- white-space:nowrap
-}
-.cookies_yum a:hover {
- color:#46a2da
-}
-.cookies_yum .close {
- width:15px;
- height:15px;
- background-image:url("cookiebar-x.png");
- background-size:15px 30px;
- background-position:top left;
- cursor:pointer;
- top:13px;
- right:13px;
- position:absolute;
- transition:none
-}
-.cookies_yum .close:hover {
- background-position:bottom left
-}
-#sidebar-toggle,#toc-toggle {
- width:24px;
- height:14px;
- background-size:24px 28px;
- cursor:pointer;
- background-image:url("list_expand.png");
- float:right
-}
-#sidebar-toggle.collapsed,
-#toc-toggle.collapsed {
- background-position:bottom left
-}
-#sidebar-content > h2 {
- display:none
-}
-#footerbar {
- background:#222840;
- color:#fff;
- font-size: 0.9em;
-}
-#footerbar.fixed {
- bottom:0;
- left:0;
- width:100%
-}
-#footerbar .footer-nav {
- display:inline;
- float:left
-}
-#footerbar .footer-main .footer-nav li {
- float:left;
- margin-right:1em
-}
-#footerbar .footer-main .footer-nav li a {
- display:block;
- padding:30px 0 10px 0;
- line-height:20px;
- height:20px;
- color:#fff;
- font-weight: 600;
-}
-#footerbar .footer-main .footer-nav li a:hover,#footerbar .footer-main .footer-nav li.current-menu-item a {
- color:#eee
-}
-#footerbar .footer-main .footer-nav .sub-menu {
- margin-left:0;
- margin-bottom:0
-}
-#footerbar .footer-main .footer-nav .sub-menu li {
- float:none;
- width: 100%;
-}
-#footerbar .footer-main .footer-nav .sub-menu ul {
- padding:1px 1em;
- font-size:0.786em;
- line-height:8px;
- float:none;
- color:#5d5b59;
- margin-bottom:0
-}
-#footerbar .footer-main .footer-nav .sub-menu li a {
- padding:2px 0;
- font-size:1em;
- float:none;
- color:#cecfd5;
- font-weight: 400;
-}
-#footerbar .footer-main .footer-nav .sub-menu li a:hover,#footerbar .footer-main .footer-nav .sub-menu li.current-menu-item a {
- color:#eee
-}
-#footerbar .theqtcompany {
- background:url("theqtcompany.png") no-repeat;
- background-size:100%;
- width:215px;
- height:68px;
- display:inline;
- float:right;
- margin:29px 0 28px 30px
-}
-#footerbar .footer-social {
- display:inline;
- float:right;
- width:164px
-}
-#footerbar .footer-main .footer-social>div {
- margin-left:0.1em;
- margin-bottom:10px
-}
-#footerbar .disclaimer {
- font-size:0.786em;
- line-height:2.73;
- color:#868584;
- padding-top:20px;
- padding-bottom:0.5%
-}
-#footerbar .disclaimer a {
- color:#bdbebf
-}
-#footerbar .disclaimer a:hover {
- color:#d6d6d6
-}
-#footerbar .disclaimer ul li {
- float:left;
- vertical-align:middle;
- margin-left:1.18em
-}
-#footerbar .disclaimer ul li:first-child {
- margin-left:0
-}
-#footerbar .disclaimer ul.lang-selector a {
- color:#506a34;
- color:rgba(128,195,66,0.3)
-}
-#footerbar .disclaimer ul.lang-selector a:hover {
- color:#80c342;
- color:rgba(128,195,66,0.7)
-}
-#menu-footer-menu, #menu-footer-menu ul {
- margin-left:0;
- margin-bottom:0
-}
-@font-face {
- font-family: 'Titillium Web';
- font-style: normal;
- font-weight: 400;
- src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot");
- /* IE9 Compat Modes */
- src: local("Titillium Web"), local("TitilliumWeb-Regular"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-regular.svg#TitilliumWeb") format("svg");
- /* Legacy iOS */
-}
-/* titillium-web-italic - latin_latin-ext */
-@font-face {
- font-family: 'Titillium Web';
- font-style: italic;
- font-weight: 400;
- src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.eot");
- /* IE9 Compat Modes */
- src: local("Titillium WebItalic"), local("TitilliumWeb-Italic"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-italic.svg#TitilliumWeb") format("svg");
- /* Legacy iOS */
-}
-/* titillium-web-600 - latin_latin-ext */
-@font-face {
- font-family: 'Titillium Web';
- font-style: normal;
- font-weight: 600;
- src: url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.eot");
- /* IE9 Compat Modes */
- src: local("Titillium WebSemiBold"), local("TitilliumWeb-SemiBold"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.eot?#iefix") format("embedded-opentype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.woff2") format("woff2"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.woff") format("woff"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.ttf") format("truetype"), url("//d33sqmjvzgs8hq.cloudfront.net/wp-content/themes/oneqt/assets/fonts/titillium-web-v4-latin_latin-ext-600.svg#TitilliumWeb") format("svg");
- /* Legacy iOS */
-}
-@font-face {
- font-family: 'Droid Sans Mono', monospace;
- font-style:normal;
- font-weight:400;
- src:local("Droid Sans Mono"),local("DroidSansMono"),url(//fonts.gstatic.com/s/droidsansmono/v7/ns-m2xQYezAtqh7ai59hJUYuTAAIFFn5GTWtryCmBQ4.woff) format("woff")
-}
-@font-face {
- font-family:'Qt Icons';
- src:url("../style/icomoon.eot?-tgjuoj");
- src:url("../style/icomoon.eot?#iefix-tgjuoj") format("embedded-opentype"),url("../style/icomoon.woff?-tgjuoj") format("woff"),url("../style/icomoon.ttf?-tgjuoj") format("truetype"),url("../style/icomoon.svg?-tgjuoj#icomoon") format("svg");
- font-weight:normal;
- font-style:normal
-}
-@font-face {
- font-family:'social-icons';
- src:url("../style/social-icons.eot?54625607");
- src:url("../style/social-icons.eot?54625607#iefix") format("embedded-opentype"),
- url("../style/social-icons.woff?54625607") format("woff");
- font-weight:normal;
- font-style:normal
-}
-.clearfix:before,.clearfix:after {
- content:" ";
- display:table
-}
-.clearfix:after {
- clear:both
-}
-.clearfix {
- *zoom:1
-}
-.clearfix .right {
- float:right
-}
-html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {
- margin:0;
- padding:0;
- border:0;
- font-size:100%;
- line-height: 1.4;
-}
-html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,caption,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video {
- vertical-align:baseline
-}
-h1,h2,h3,h4,h5,h6 {
- font-weight:300
-}
-.body h2,.body h3,.body h4,.body h5,.body h6 {
- margin:1.5em 0 0.75em
-}
-.body h1 {
- margin-bottom:0.75em;
- font-size:2.25em;
-}
-.body h3.fn,.body h3.flags {
- color:#26282a;
- font-size:1.46em;
- padding:15px 0 15px 0;
- border-bottom:2px #eee solid;
- word-wrap:break-word
-}
-.body .fngroup {
- border-bottom:2px #eee solid;
- padding-bottom:15px;
- margin-bottom:1.5em
-}
-.body .fngroup h3.fngroupitem {
- margin:0;
- padding-bottom:0;
- border:none
-}
-.body h3.fn .name,
-.body h3 span.type,
-.qmlname span.name {
- font-weight: 400
-}
-.qmlname {
- font-size:1.46em
-}
-.qmlproto table {
- border:none;
- border-bottom:2px #eee solid
-}
-.qmlproto table p {
- max-width:100%
-}
-.qmlproto table tr {
- background-color:#fff
-}
-.qmlname td, .qmlname th {
- border:none;
- text-align:left;
- padding:5px 0 0 0
-}
-.qmlreadonly,.qmldefault {
- padding:0 5px 0 5px;
- font-size:0.75em;
- background-color:#eee;
- float:right
-}
-.qmlreadonly {
- color:#414141
-}
-.qmldefault {
- color:#D14141
-}
-.rightAlign {
- padding:3px 5px 3px 10px;
- text-align:right
-}
-.centerAlign.functionIndex {
- text-align:center;
- font-size:150%;
- margin-bottom: 1em
-}
-article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {
- display:block
-}
-body {
- line-height:1;
- font-family:'Titillium Web', Arial, Helvetica, sans-serif;
- font-weight:400;
- transition-duration:1s;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- font-size: 16px;
- background-color:#f3f3f4;
- color:#404244;
-}
-ol,ul {
- list-style-type: square;
- color: #17a81a;
-}
-.body ol,.body ul {
- margin-top:0.75em;
- margin-left:20px
-}
-.bodywrapper ol>li {
- list-style-type:decimal;
- margin-left:15px
-}
-.bodywrapper ol.a >li {
- list-style-type:lower-alpha;
-}
-.bodywrapper ol.A >li {
- list-style-type:upper-alpha;
-}
-.bodywrapper ol.i >li {
- list-style-type:lower-roman;
-}
-.bodywrapper ol.I >li {
- list-style-type:upper-roman;
-}
-.body li p {
- margin-top:1em
-}
-blockquote,q {
- quotes:none;
- border-left:10px solid #ddd;
- padding-left:10px
-}
-blockquote:before,blockquote:after,q:before,q:after {
- content:'';
- content:none;
- width:100%
-}
-table {
- border-collapse:collapse;
- border-spacing:0;
- margin-bottom:5px;
- width:100%
-}
-a {
- color:#17a81a;
- text-decoration:none;
- transition-duration:0.3s
-}
-a:hover {
- color:#17a81a
-}
-.main,#footerbar>div {
- max-width:1280px;
- width:95%;
- margin:0 auto
-}
-.main {
- margin-top:80px
-}
-@media (max-width: 1120px) {
- .main,.navbar-header,#footerbar>div {
- width: 100%;
- margin: 0;
- }
- .main .main-rounded {
- padding: 0 15px;
- }
-}
-.main_index {
- background-color:#fff
-}
-.sectionlist {
- margin-bottom:2em
-}
-[class*="col-"] {
- letter-spacing:normal
-}
-.landing,.main_index .row {
- letter-spacing:-0.31em
-}
-.main_index .row>div {
- letter-spacing:normal
-}
-.col-1 {
- clear: both;
- display:inline-block;
- background-color:#fff;
- padding: 25px 35px 20px 30px;
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- -ms-box-sizing:border-box;
- box-sizing:border-box;
-}
-.col-1 h2 {
- font-size:1.8em;
- font-weight:300;
- line-height:1.1;
- margin-bottom:0.83em;
- margin-top:1em
-}
-.icons1of3 img {
- display:inline-block;
- float:left;
- margin-right:0.75em;
- margin-top:-5px;
- width:2.75em
-}
-div.multi-column {
- position:relative
-}
-div.multi-column div {
- display:-moz-inline-box;
- display:inline-block;
- vertical-align:top;
- margin-top:1em;
- margin-right:2em;
- width:16em
-}
-.sidebar {
- display:block;
- position:relative;
- position:sticky;
- float:left;
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- -ms-box-sizing:border-box;
- box-sizing:border-box;
- width:20%;
- padding-right:20px
-}
-.sidebar li {
- text-overflow:ellipsis;
- overflow:hidden
-}
-.toc,.sectionlist {
- padding:25px;
- background-color:#fff;
- margin-bottom:1.25em
-}
-.sidebar .sectionlist p {
- margin-bottom:0
-}
-.sectionlist.promo {
- padding:0;
- background-color:#f3f3f4
-}
-.sidebar-content:empty {
- display:none;
- visibility:hidden
-}
-.col-2 h2,.toc h3,.sidebar-content h2,
-.sidebar-content h3,.sectionlist h2,
-.sphinxsidebar {
- position: -webkit-sticky;
- position: sticky;
- top: 0px;
- width: 200px;
- overflow: scroll;
- overflow-x: hidden;
- overflow-y: hidden;
-}
-.sphinxsidebar h3 {
- font-weight: bold;
- margin-bottom:1em;
-}
-
-/* On screens that are less than 700px wide, make the sidebar into a topbar */
-@media screen and (max-width: 700px) {
- .sphinxsidebar {
- top: 64px;
- /*overflow-x: hidden;
- overflow-y: hidden;*/
- width: 100%;
- height: auto;
- position: relative;
- }
- /*.sidebar a {float: left;}*/
- div.content {margin-left: 0;}
-}
-
-/* On screens that are less than 400px, display the bar vertically, instead of horizontally
-@media screen and (max-width: 400px) {
- .sphinxsidebar a {
- text-align: center;
- float: none;
- }
-}
-*/
-
-.toc h3 a {
- color:#404244
-}
-.title {
- font-size:2.25em;
- font-weight:300;
- letter-spacing:-1px;
- line-height:1.15em;
- margin-bottom:0.5em;
- word-wrap:break-word
-}
-.navigationbar,col-1 h2 {
- font-size:0.85em
-}
-.navigationbar h1 {
- font-size:2.5em;
- margin-bottom:0.85em;
- margin-top:0.85em
-}
-.navigationbar li {
- display:inline-block;
- margin-right:5px;
- position:relative;
- padding-right:10px;
- color:#585a5c
-}
-.navigationbar ul:last-of-type li a {
- color:#404244
-}
-.sectionlist li, .sphinxsidebar li {
- padding-bottom: 10px;
- line-height: 1.75em;
-}
-.col-1 ul {
- margin-bottom:1.56em
-}
-.bodywrapper li {
- margin-top:0.5em;
- line-height:1.25em
-}
-.bodywrapper li.level2 {
- margin-left:10px;
- margin-top:0.4em;
- font-size:0.9375em;
-}
-.bodywrapper p,
-.bodywrapper dd {
- line-height:1.25em;
- margin:1em 0 1em;
- color:#404244
-}
-.bodywrapper b {
- font-weight:600
-}
-.body ul,.body ol {
- /* margin-bottom:1.5em */
-}
-.bodywrapper ul ul {
- margin-top:0.5em
-}
-.bodywrapper .naviNextPrevious {
- margin-top:25px;
- max-width:100%;
- position: relative;
-}
-.naviNextPrevious.headerNavi,
-p.naviNextPrevious + p {
- display:none
-}
-.nextPage {
- float:right
-}
-.prevPage:before {
- content:"< "
-}
-.nextPage:after {
- content:" >"
-}
-.navigationbar li a {
- color:#404244
-}
-.navigationbar li:after {
- color:#404244;
- content:"›";
- display:inline-block;
- font-size:1.5em;
- line-height:1;
- position:absolute;
- right:-2px;
- top:-4px
-}
-.sub-navigation {
- margin-top:10px
-}
-.navigationbar li:last-child:after,.sub-navigation li:after {
- content:none
-}
-.navigationbar {
- margin-bottom:10px;
- line-height:1em
-}
-#buildversion {
- margin-bottom:10px;
- font-style:italic;
- font-size:small;
- float:right
-}
-.copy-notice {
- width:75%;
- font-size:0.75em;
- margin:20px 35px 0 10px;
- line-height:1.75em;
- float:right;
- color:#585a5c
-}
-.copy-notice.index {
- margin-top:10px;
- float:none
-}
-li a.active {
- color:#585a5c
-}
-.flowList {
- padding:25px
-}
-.flowListDiv dl {
- -webkit-column-count:1;
- -moz-column-count:1;
- column-count:1
-}
-.flowList dd {
- display:inline-block;
- margin-left:10px;
- width:90%;
- line-height:1.15em;
- overflow-x:hidden;
- text-overflow:ellipsis
-}
-.alphaChar {
- font-size:2em;
- position:absolute
-}
-.flowList.odd {
- background-color:#f9f9f9
-}
-.body ul>li,.doc-column ul>li {
- list-style-image:url("list_arrow.png");
- margin-left:15px;
- color:#404244;
- margin-top:0.65em;
- line-height:1em
-}
-.bodywrapper table p {
- margin:0px;
- padding:0px
-}
-.bodywrapper table p {
- margin:0px;
- padding:0px;
- min-height:1.25em
-}
-.bodywrapper .qmldoc {
- margin-top:0.75em;
-}
-.body h2 {
- margin-top: 1.5em;
- font-size:1.75em
-}
-.body h3 {
- font-size:1.35em
-}
-.body h4 {
- font-size:1.15em
-}
-.body p img {
- margin-top:0.75em;
- max-width:100%
-}
-.body .border img {
- box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5)
-}
-.body .border .player {
- box-shadow:3px 3px 8px 3px rgba(200,200,200,0.5)
-}
-.body p.figCaption {
- transform:translateY(-30px);
- color:#606366;
- font-size:95%;
- margin-left:3px;
- font-style:italic
-}
-.body table {
- width:initial;
- vertical-align:initial
-}
-table .odd {
- background-color:#f9f9f9
-}
-table thead {
- text-align:left;
- padding-left:20px
-}
-table,table td,table th {
- border:1px solid #eee
-}
-table td,table th {
- padding:5px 20px;
- line-height:1.3
-}
-.body .fixed table td {
- min-width:50%;
- width:50%
-}
-table.alignedsummary,table.propsummary {
- width:initial
-}
-table.valuelist td.tblval {
- font-size:0.75em
-}
-div.main_index .row {
- border-bottom:10px solid #f3f3f4
-}
-div.main_index .row {
- position:relative
-}
-div.main_index .row>div {
- display:inline-block;
- width:50%;
- vertical-align:top;
- padding:2em 3em;
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- -ms-box-sizing:border-box;
- box-sizing:border-box
-}
-div.main_index h2 {
- font-size:2.1875em;
- margin-bottom:1em
-}
-#search_bar {
- width:40%;
- float:right
-}
-div.main_index .row:after {
- content:"";
- position:absolute;
- top:0;
- right:50%;
- height:100%;
- width:10px;
- background-color:#f3f3f4
-}
-div.table {
- overflow-x:auto
-}
-.body tr > td > pre {
- font-size:0.75em
-}
-p.qt_commercial {
- border:3px solid #5caa15;
- margin:0 auto;
- padding:15px;
- width:28%;
- text-align:center;
- clear:both
-}
-h1.qt_commercial {
- padding:20px;
- background-color:#5caa15;
- display:inline;
- float:right;
- font-size:1.25em;
- line-height:1.25em;
- height:1.25em;
- color:#fff
-}
-div.qt_commercial {
- border-top:5px solid #5caa15;
- margin-bottom:50px
-}
-div.pre {
- position:relative;
- height:auto
-}
-pre, .LegaleseLeft {
- background-color:#222840;
- color:#fff;
- display:block;
- font-family: 'Droid Sans Mono', monospace;
- line-height:1.5;
- overflow-x:auto;
- margin-bottom:25px;
- padding:25px;
- margin-top:0.75em;
- font-size: .8em;
-}
-.bodywrapper .LegaleseLeft p {
- color:#fff;
- white-space: pre-wrap;
-}
-pre .str,code .str {
- color:#aaaaaa
-}
-pre .kwd,code .kwd {
- color:#ffff55
-}
-pre .com,code .com {
- color:#55ffff
-}
-pre .typ,code .typ {
- color:#4f9d08
-}
-pre a .typ,code a .typ {
- color:#21be2b
-}
-pre .lit,code .lit {
- color:#ff55ff
-}
-pre .pun,code .pun {
- color:#fff
-}
-pre .pln,code .pln {
- color:#fff
-}
-@media print {
- pre {
- background-color:#eee !important
- }
- pre .str,code .str {
- color:#060
- }
- pre .kwd,code .kwd{
- color:#006;
- font-weight:bold
- }
- pre .com,code .com {
- color:#600
- }
- pre .typ,code .typ {
- color:#404;
- font-weight:bold
- }
- pre .lit,code .lit {
- color:#044
- }
- pre .pun,code .pun {
- color:#440
- }
- pre .pln,code .pln {
- color:#000
- }
-}
-pre.wrap {
- white-space:pre-wrap
-}
-pre span.wrap {
- display:none;
- background:url("wrap.png") no-repeat;
- right:0;
- top:2px;
- position:absolute;
- width:20px;
- height:14px;
- margin:4px;
- opacity:0.65
-}
-
-span.pre {
- color: black;
- font-family: monospace;
- font-weight: normal;
- background-color: #eaeaea;
- padding: 2px 4px;
- color: black;
- border-radius: 2px;
-}
-
-span.wrap:hover {
- opacity:1
-}
-span.wrap:active {
- opacity:0.75
-}
-.copy_text {
- background-color:#46a2da;
- color:#fff;
- border:2px solid #46a2da;
- padding:10px 16px;
- margin-left:-10px;
- margin-top:-50px;
- position:absolute;
- opacity:0;
- cursor:pointer;
- float:right
-}
-.copy_text:hover {
- background-color:#fff;
- color:#46a2da
-}
-code,.codelike {
- font-family: 'Droid Sans Mono', monospace;
-}
-#detailed-description .function dt > code,
-#detailed-description .function dt > em {
- font-weight:bold
-}
-h3.fn code {
- font-size:0.75em;
- float:right;
- background-color:#eee;
- padding:3px;
- margin: 3px 0 0 20px
-}
-pre:hover>.copy_text {
- display:inline-block;
- opacity:1;
- transition:0.5s ease
-}
-#main_title_bar {
- background:url("pyside-logo.png") no-repeat;
- background-size:100%;
- width:366px;
- height:86px;
- margin:15px 0 15px 0
-}
-#main_title_bar h1 {
- visibility:hidden
-}
-#main_title_bar .search_bar {
- letter-spacing:normal;
- width:50%;
- display:inline-block;
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- -ms-box-sizing:border-box;
- box-sizing:border-box;
- vertical-align:middle
-}
-#main_title_bar h1 {
- letter-spacing:normal;
- display:inline-block;
- -webkit-box-sizing:border-box;
- -moz-box-sizing:border-box;
- -ms-box-sizing:border-box;
- box-sizing:border-box;
- vertical-align:middle
-}
-#main_title_bar .search_bar * {
- letter-spacing:normal;
- padding:0;
- margin:0;
- border:none
-}
-#sidebar-toggle,#toc-toggle {
- display:none
-}
-@media (max-width: 980px) {
- body {
- font-size:calc-em(14px)
- }
- #main_title_bar>h1,#main_title_bar .search_bar {
- width:100%
- }
- #main_title_bar .search_bar {
- margin-bottom:15px
- }
- .main {
- margin-top:0px
- }
- .main_index .row {
- border:none !important
- }
- .title {
- font-size:1.5em;
- font-weight:400;
- word-wrap:break-word
- }
- .col-1,.body,.naviNextPrevious,.sidebar {
- padding:10px
- }
- .sidebar {
- position:relative;
- padding-top:0
- }
- .search .sidebar {
- display:none;
- visibility:hidden
- }
- .col-2 h2,.toc h3,.sidebar-content h2,.sidebar-content h3,.sectionlist h2 {
- text-align:center;
- margin-bottom:5px
- }
- div.main_index .row:after {
- content:none
- }
- div.main_index .row>div {
- display:block !important;
- width:100%;
- padding:15px;
- margin:0
- }
- .body,.sidebar,.col-1 {
- width:100%
- }
- .sidebar-content,.col-2,.toc {
- background-color:#fff;
- margin-bottom:1em;
- padding:20px
- }
- #sidebar-toggle,#toc-toggle {
- display:block
- }
- #sidebar-toggle.collapsed + h2 {
- display:block
- }
- .bodywrapper p {
- margin-bottom:1em;
- max-width:100%
- }
- table td,table th {
- padding:5px 5px
- }
- .sectionlist {
- padding:0
- }
- .sidebar > .sectionlist {
- padding:20px
- }
- .sectionlist.promo {
- max-width:46%;
- margin:0 auto 1em auto;
- float:left;
- padding:0 2%
- }
- .sidebar .sidebar-content {
- clear:both
- }
- .copy-notice {
- float:none;
- width:initial
- }
-}
-[id]:target > *:first-child,
-dt[id]:target {
- -webkit-animation:highlighter 3s;
- animation:highlighter 3s
-}
-@-webkit-keyframes highlighter {
- 25% {
- background-color:#d1e8f6;
- color:#444
- }
- 75% {
- background-color:#d1e8f6;
- color:#444
- }
-}
-@keyframes highlighter {
- 25% {
- background-color:#d1e8f6;
- color:#444
- }
- 75% {
- background-color:#d1e8f6;
- color:#444
- }
-}
-@-webkit-keyframes copypaste {
- 25% {
- opacity:1
- }
- 100% {
- border-radius:10px;
- margin-top:-50px;
- opacity:1
- }
-}
-@keyframes copypaste {
- 25% {
- opacity:1
- }
- 100% {
- border-radius:10px;
- margin-top:-50px;
- opacity:1
- }
-}
-#footer {
- clear:both
-}
-.footer-social i {
- font-family: "social-icons";
- font-style: normal;
- font-size:150%;
- margin: .55em;
- color: #cecfd5
-}
-.footer-social i:hover {
- color: #eee
-}
-.footer-social .icon-twitter:before {
- content: '\f099'
-}
-.footer-social .icon-facebook:before {
- content: '\f09a'
-}
-.footer-social .icon-youtube:before {
- content: '\f16a'
-}
-.menuextraslanguages {
- display:none;
- visibility:hidden
-}
-form.gsc-search-box {
- font-size: 25px !important;
- margin-top: 0 !important;
- margin-right: 0 !important;
- margin-bottom: 4px !important;
- margin-left: 0 !important;
- width: 102.5% !important;
-}
-table.gsc-search-box {
- border-style: none !important;
- border-width: 0 !important;
- border-spacing: 0 0 !important;
- width: 100% !important;
- margin-bottom: 2px !important;
-}
-
-table.gsc-search-box td {
- vertical-align: middle !important;
-}
-
-table.gsc-search-box td.gsc-input {
- padding-right: 0px !important;
-}
-table.gsc-search-box td.gsc-input input {
- background-position: 10px center !important;
-}
-
-td.gsc-search-button {
- width: 1% !important;
-}
-
-td.gsc-clear-button {
- width: 14px !important;
- visibility:hidden !important;
- display:none !important;
-}
-table.gsc-branding td,
-table.gsc-branding {
- margin: 0 0 0 0 !important;
- padding: 0 0 0 0 !important;
- border: none !important;
-}
-
-table.gsc-branding {
- border-style: none !important;
- border-width: 0 !important;
- border-spacing: 0 0 !important;
- width: 100% !important;
-}
-
-.gsc-branding-text {
- color: #676767 !important;
-}
-
-td.gsc-branding-text {
- vertical-align: top !important;
-}
-td.gsc-branding-text div.gsc-branding-text {
- padding-bottom: 2px !important;
- text-align: right !important;
- font-size: 11px !important;
- margin-right: 2px !important;
-}
-
-td.gsc-branding-img {
- width: 65px !important;
- vertical-align: bottom !important;
-}
-
-img.gsc-branding-img {
- padding-top: 1px !important;
- margin: 0 0 0 0 !important;
- padding-right: 0 !important;
- padding-left: 0 !important;
- padding-bottom: 0 !important;
- border: none !important;
- display: inline !important;
-}
-
-input.gsc-search-button {
- background-color: white !important;
- height: 35px !important;
- width: 25px !important;
- color: transparent !important;
- background-image: url("doc_search.png") !important;
- background-size: 25px auto;
- background-position: 0px 5px;
- background-repeat: no-repeat;
- margin-left: -43px !important;
- overflow: hidden;
- min-width: 20px !important;
-}
-
-input.gsc-search-button:hover {
- cursor: pointer;
-}
-
-input.gsc-search-button:focus {
- outline: none;
- box-shadow: none;
-}
-
-.gsc-search-box-tools .gsc-clear-button {
- display: none !important;
- visibility: none !important;
-}
-
-.gsc-overflow-hidden {
- overflow: hidden !important;
-}
-
-input.gsc-input {
- background-color: #fff !important;
- border: 1px solid #d6d6d6 !important;
- box-sizing: border-box !important;
- -moz-box-sizing: border-box !important;
- color: #868482 !important;
- outline: 0 none !important;
- padding: 9px 10px 10px !important;
- transition: color 0.5s ease 0s, box-shadow 0.5s ease 0s, background-color 0.5s ease 0s !important;
-}
-
-input {
- font-family: 'Titillium Web', Arial, Helvetica, sans-serif !important;
- line-height: 1.5 !important;
- font-weight: 300 !important;
- vertical-align:middle
-}
-
-input:focus {
- border-color: #46a2da;
- box-shadow: 0 0 5px #46a2da;
- color: #000;
-}
-
-.animation {
- width: 100%;
- border-style: none;
- border-width: 0
-}
-
-.player {
- width: auto;
- position: relative;
- display: table;
- margin-bottom:1.5em;
-}
-
-.playcontrol {
- display: none;
- background: url("play_icon.svg") no-repeat center,
- linear-gradient(
- rgba(0,0,0,0.15), rgba(0,0,0,0.15)
- );
- background-size: 25%;
- width: 100%;
- height: 100%;
- position: absolute;
- left: 0%;
- right: 0%;
- top: 0%;
- bottom: 0%;
- margin: auto
-}
-
-/* expand/collapse code sections */
-pre input {
- display:none;
- visibility:hidden
-}
-pre label {
- display:block;
- margin:-3px 3px 0 -16px;
- text-align:center;
- color:#21be2b;
- float:left;
-}
-pre label:hover {
- color:#fff
-}
-pre label::before {
- font-weight:600;
- font-size:16px;
- content:"+";
- display:inline-block;
- width:16px;
- height:16px
-}
-#ec_expand {
- height:16px;
- overflow:hidden;
- transition:height 0.35s;
-}
-#ec_expand::before {
- content:"...*/";
- color:#aaa;
- background-color:#3a4055;
- z-index:99 !important;
- right:25px;
- position:absolute
-}
-#ec_toggle:checked ~ #ec_expand {
- height:initial
-}
-#ec_toggle:checked ~ #ec_expand::before {
- content:""
-}
-#ec_toggle:checked ~ label::before {
- content:"-"
-}
-
-/* permalinks */
-h1:hover > .headerlink,
-h2:hover > .plink,
-h2:hover > .headerlink,
-h3:hover > .plink,
-h3:hover > .headerlink,
-h4:hover > .plink,
-h4:hover > .headerlink,
-h5:hover > .plink,
-h5:hover > .headerlink {
- opacity:1
-}
-a.plink, a.headerlink {
- opacity: 0;
- padding-left: 8px;
- font-size: 0.8em;
- font-weight: 600;
- transition: opacity 180ms ease-in-out
-}
-a.plink::before {
- content:'\00B6'
-}
-
-table.special {
- border: 3px;
- padding: 0px;
- border-collapse: separate;
- border-spacing: 20px;
- line-height: 1.5em;
- table-layout: fixed;
- width: 80%;
-}
-
-.special p {
- text-align: center;
- color: #3a4055;
-}
-
-.special a {
- display: block;
- border-bottom: 0;
- text-decoration: none;
-}
-
-.special a:hover {
- border-bottom: 0;
- text-decoration: none;
-}
-
-.special strong {
- color: #17a81a;
- font-size: 110%;
- font-weight: normal;
-}
-
-table.special th,
-table.special td {
- border: 1px solid #888;
- padding-top: 14px;
- padding-bottom: 14px;
- padding-left: 6px;
- padding-right: 5px;
- border-radius: 5px;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- -khtml-border-radius: 5px;
- overflow: hidden;
-}
-
-.special td:hover {
- padding-top: 14px;
- padding-bottom: 10px;
- border-bottom: 4px solid #41cd52;
- overflow: hidden;
-}
-
-.command {
- font-family: monospace;
- font-weight: normal;
- background-color: #9cd1a6;
- padding: 2px 4px;
- color: black;
- border-radius: 2px;
-}
-
-div.leftside {
- width: 50%;
- padding: 0px 50px 0px 0px;
- float: left;
-}
-
-div.rightside {
- margin-left: 50%;
-}
-
-.btn-qt:hover,
-.btn-qt:active,
-.btn-qt:focus,
-.btn-qt.active {
- background: #41cd52;
- color: #fff !important;
- border-color: #fff;
-}
-
-.btn-link {
- color: #41cd52 !important;
-}
-
-.btn-link:hover {
- color: #222840 !important;
- text-decoration: underline;
-}
-
-/* Using !important is not recommended, but out CSS is being added
- * to the pages before the bootstrap ones, so we cannot override them
- * without using it */
-.btn-qt {
- color: #41cd52 !important;
- border-color: #41cd52 !important;
- font-weight: bold !important;
-}
-.card-img-top-main {
- padding-top: 10px;
- height: 70px !important;
-}
-
-.card-img-top {
- object-fit: contain;
- height: 120px;
- padding-top: 20px;
- transform: scale(1.3, 1.3);
-}
diff --git a/sources/pyside6/doc/_themes/pysidedocs_qthelp/static/pyside.css b/sources/pyside6/doc/_themes/pysidedocs_qthelp/static/pyside.css
index aee5e4420..94134cacf 100644
--- a/sources/pyside6/doc/_themes/pysidedocs_qthelp/static/pyside.css
+++ b/sources/pyside6/doc/_themes/pysidedocs_qthelp/static/pyside.css
@@ -466,7 +466,7 @@ tt.descname {
position:relative
}
#menuextras li a:hover span {
- color: #41cd52;
+ color: #2cde85;
}
/* new header */
#mm-wrap, #mm-wrap #mm-helper,
@@ -557,14 +557,14 @@ tt.descname {
display:inline;
float:left;
width:31px;
- color:#41cd52
+ color:#2cde85
}
#navbar .navbar-oneQt:before {
content:attr(data-icon);
position:absolute;
top:14px;
left:0;
- color:#41cd52;
+ color:#2cde85;
font-family:'Qt Icons';
line-height:1;
font-size:40px;
@@ -1939,5 +1939,5 @@ table.special td {
.special td:hover {
padding-top: 2px;
padding-bottom: 2px;
- border-bottom: 4px solid #41cd52;
+ border-bottom: 4px solid #2cde85;
}
diff --git a/sources/pyside6/doc/additionaldocs.lst b/sources/pyside6/doc/additionaldocs.lst
index d2d91d699..81da58370 100644
--- a/sources/pyside6/doc/additionaldocs.lst
+++ b/sources/pyside6/doc/additionaldocs.lst
@@ -20,7 +20,6 @@ creating-a-sensor-plugin.webxml
custom-types.webxml
database.webxml
datastreamformat.webxml
-datavisualization-examples.webxml
dbus-changes-qt6.webxml
determining-the-default-sensor-for-a-type.webxml
dialogs.webxml
@@ -117,8 +116,6 @@ qml-tutorial1.webxml
qml-tutorial2.webxml
qml-tutorial3.webxml
qmldiskcache.webxml
-qmlexampletoggleswitch.webxml
-qmlextendingexamples.webxml
qmlreference.webxml
qndeffilter-record.webxml
qoutputrange.webxml
@@ -134,8 +131,6 @@ qsggeometry-texturedpoint2d.webxml
qsgmaterialshader-graphicspipelinestate.webxml
qsgmaterialtype.webxml
qstaticplugin.webxml
-qt3d-advancedcustommaterial-example.webxml
-qt3d-audio-visualizer-qml-example.webxml
qt3d-basicshapes-cpp-example.webxml
qt3d-changes-qt6.webxml
qt3d-cpp.webxml
@@ -143,16 +138,9 @@ qt3d-examples.webxml
qt3d-multiviewport-example.webxml
qt3d-overview.webxml
qt3d-pbr-materials-example.webxml
-qt3d-planets-qml-example.webxml
qt3d-qml.webxml
-qt3d-scene2d-example.webxml
-qt3d-scene3d-example.webxml
-qt3d-shadow-map-qml-example.webxml
-qt3d-simple-cpp-example.webxml
qt3d-simple-qml-example.webxml
qt3d-simplecustommaterial-example.webxml
-qt3d-wave-example.webxml
-qt3d-widgets-scene3d-example.webxml
qt3d-wireframe-example.webxml
qt3drender-framegraph.webxml
qt3drender-geometry.webxml
@@ -160,69 +148,39 @@ qt3drender-porting-to-rhi.webxml
qt3drender-protips.webxml
qtalgorithms.webxml
qtbluetooth-btchat-example.webxml
-qtbluetooth-btscanner-example.webxml
qtbluetooth-changes-qt6.webxml
-qtbluetooth-heartrate-game-example.webxml
-qtbluetooth-heartrate-server-example.webxml
qtbluetooth-le-overview.webxml
qtbluetooth-lowenergyscanner-example.webxml
qtbluetooth-overview.webxml
-qtbluetooth-pingpong-example.webxml
qtcborcommon.webxml
-qtcharts-areachart-example.webxml
-qtcharts-audio-example.webxml
-qtcharts-barchart-example.webxml
qtcharts-barmodelmapper-example.webxml
qtcharts-boxplotchart-example.webxml
-qtcharts-callout-example.webxml
qtcharts-candlestickchart-example.webxml
qtcharts-changes-qt6.webxml
-qtcharts-chartthemes-example.webxml
qtcharts-customchart-example.webxml
qtcharts-datetimeaxis-example.webxml
-qtcharts-donutbreakdown-example.webxml
-qtcharts-donutchart-example.webxml
-qtcharts-dynamicspline-example.webxml
qtcharts-examples.webxml
qtcharts-horizontalbarchart-example.webxml
qtcharts-horizontalpercentbarchart-example.webxml
qtcharts-horizontalstackedbarchart-example.webxml
-qtcharts-legend-example.webxml
qtcharts-legendmarkers-example.webxml
-qtcharts-lineandbar-example.webxml
-qtcharts-linechart-example.webxml
-qtcharts-logvalueaxis-example.webxml
-qtcharts-modeldata-example.webxml
qtcharts-multiaxis-example.webxml
-qtcharts-nesteddonuts-example.webxml
qtcharts-openglseries-example.webxml
qtcharts-overview.webxml
-qtcharts-percentbarchart-example.webxml
-qtcharts-piechart-example.webxml
-qtcharts-piechartcustomization-example.webxml
-qtcharts-piechartdrilldown-example.webxml
qtcharts-pointsselectionandmarkers-example.webxml
qtcharts-polarchart-example.webxml
qtcharts-qmlaxes-example.webxml
-qtcharts-qmlchart-example.webxml
qtcharts-qmlcustomizations-example.webxml
qtcharts-qmlcustomlegend-example.webxml
qtcharts-qmlf1legends-example.webxml
qtcharts-qmloscilloscope-example.webxml
-qtcharts-qmlpolarchart-example.webxml
qtcharts-qmlweather-example.webxml
qtcharts-scatterchart-example.webxml
-qtcharts-scatterinteractions-example.webxml
qtcharts-selectedbar-example.webxml
qtcharts-splinechart-example.webxml
qtcharts-stackedbarchart-example.webxml
-qtcharts-stackedbarchartdrilldown-example.webxml
-qtcharts-temperaturerecords-example.webxml
qtcharts-zoomlinechart-example.webxml
qtconcurrent-imagescaling-example.webxml
-qtconcurrent-map-example.webxml
-qtconcurrent-progressdialog-example.webxml
-qtconcurrent-runfunction-example.webxml
qtconcurrent-wordcount-example.webxml
qtconcurrentfilter.webxml
qtconcurrentmap.webxml
@@ -231,50 +189,18 @@ qtconcurrenttask.webxml
qtcore-changes-qt6.webxml
qtcore-ipc-localfortuneclient-example.webxml
qtcore-ipc-localfortuneserver-example.webxml
-qtcore-ipc-sharedmemory-example.webxml
-qtcore-mimetypes-mimetypebrowser-example.webxml
qtcore-platform-androidnotifier-example.webxml
qtcore-serialization-savegame-example.webxml
-qtcore-threads-mandelbrot-example.webxml
qtcore-threads-queuedcustomtype-example.webxml
qtcore-threads-semaphores-example.webxml
qtcore-threads-waitconditions-example.webxml
qtcore-tools-contiguouscache-example.webxml
-qtcore-tools-customtype-example.webxml
-qtdatavis3d-bars-example.webxml
-qtdatavis3d-custominput-example.webxml
-qtdatavis3d-customitems-example.webxml
-qtdatavis3d-customproxy-example.webxml
-qtdatavis3d-draggableaxes-example.webxml
-qtdatavis3d-itemmodel-example.webxml
-qtdatavis3d-qml3doscilloscope-example.webxml
-qtdatavis3d-qmlaxisdrag-example.webxml
-qtdatavis3d-qmlaxisformatter-example.webxml
-qtdatavis3d-qmlbars-example.webxml
-qtdatavis3d-qmlcustominput-example.webxml
-qtdatavis3d-qmllegend-example.webxml
-qtdatavis3d-qmlmultigraph-example.webxml
-qtdatavis3d-qmlscatter-example.webxml
-qtdatavis3d-qmlspectrogram-example.webxml
-qtdatavis3d-qmlsurface-example.webxml
-qtdatavis3d-qmlsurfacelayers-example.webxml
-qtdatavis3d-rotations-example.webxml
-qtdatavis3d-scatter-example.webxml
-qtdatavis3d-surface-example.webxml
-qtdatavis3d-texturesurface-example.webxml
-qtdatavis3d-volumetric-example.webxml
-qtdatavisualization-data-handling.webxml
-qtdatavisualization-interacting-with-data.webxml
-qtdatavisualization-known-issues.webxml
-qtdatavisualization-overview.webxml
qtdbus-chat-example.webxml
qtdbus-cmake-qt-add-dbus-adaptor.webxml
qtdbus-cmake-qt-add-dbus-interface.webxml
qtdbus-cmake-qt-add-dbus-interfaces.webxml
qtdbus-cmake-qt-generate-dbus-interface.webxml
qtdbus-complexpingpong-example.webxml
-qtdbus-listnames-example.webxml
-qtdbus-pingpong-example.webxml
qtdbus-remotecontrolledcar-example.webxml
qtdesigner-calculatorbuilder-example.webxml
qtdesigner-calculatorform-example.webxml
@@ -282,16 +208,12 @@ qtdesigner-components.webxml
qtdesigner-containerextension-example.webxml
qtdesigner-customwidgetplugin-example.webxml
qtdesigner-manual.webxml
-qtdesigner-taskmenuextension-example.webxml
-qtdesigner-worldtimeclockbuilder-example.webxml
-qtdesigner-worldtimeclockplugin-example.webxml
qtest-overview.webxml
qtest-tutorial.webxml
qtextedit-extraselection.webxml
qtextlayout-formatrange.webxml
qtextoption-tab.webxml
qtglobal.webxml
-qtgui-analogclock-example.webxml
qtgui-rasterwindow-example.webxml
qthelp-contextsensitivehelp-example.webxml
qthelp-framework.webxml
@@ -302,29 +224,9 @@ qtjavascript.webxml
qtmath.webxml
qtmultimedia-apple.webxml
qtmultimedia-changes-qt6.webxml
-qtmultimedia-multimedia-audiodevices-example.webxml
-qtmultimedia-multimedia-audiooutput-example.webxml
-qtmultimedia-multimedia-audiorecorder-example.webxml
-qtmultimedia-multimedia-audiosource-example.webxml
-qtmultimedia-multimedia-declarative-camera-example.webxml
-qtmultimedia-multimedia-spectrum-example.webxml
-qtmultimedia-multimedia-video-mediaplayer-example.webxml
-qtmultimedia-multimedia-video-qmlvideo-example.webxml
-qtmultimedia-multimedia-video-recorder-example.webxml
-qtmultimedia-multimediawidgets-camera-example.webxml
-qtmultimedia-multimediawidgets-player-example.webxml
-qtmultimedia-multimediawidgets-videographicsitem-example.webxml
-qtmultimedia-multimediawidgets-videowidget-example.webxml
-qtnetwork-blockingfortuneclient-example.webxml
qtnetwork-broadcastreceiver-example.webxml
qtnetwork-broadcastsender-example.webxml
-qtnetwork-download-example.webxml
-qtnetwork-downloadmanager-example.webxml
-qtnetwork-fortuneclient-example.webxml
-qtnetwork-fortuneserver-example.webxml
-qtnetwork-googlesuggest-example.webxml
qtnetwork-http-example.webxml
-qtnetwork-loopback-example.webxml
qtnetwork-multicastreceiver-example.webxml
qtnetwork-multicastsender-example.webxml
qtnetwork-network-chat-example.webxml
@@ -332,26 +234,19 @@ qtnetwork-programming.webxml
qtnetwork-securesocketclient-example.webxml
qtnetwork-secureudpclient-example.webxml
qtnetwork-secureudpserver-example.webxml
-qtnetwork-threadedfortuneserver-example.webxml
qtnetwork-torrent-example.webxml
-qtnetworkauth-changes-qt6.webxml
-qtnetworkauth-redditclient-example.webxml
-qtnetworkauth-twittertimeline-example.webxml
qtnfc-annotatedurl-example.webxml
qtnfc-changes-qt6.webxml
qtnfc-ndefeditor-example.webxml
qtnfc-overview.webxml
qtopengl-2dpainting-example.webxml
qtopengl-cube-example.webxml
-qtopengl-hellogl2-example.webxml
qtopengl-hellogles3-example.webxml
qtopengl-openglwindow-example.webxml
-qtopengl-textures-example.webxml
qtplugin.webxml
qtpositioning-android.webxml
qtpositioning-changes-qt6.webxml
qtpositioning-examples.webxml
-qtpositioning-geoflickr-example.webxml
qtpositioning-ios.webxml
qtpositioning-logfilepositionsource-example.webxml
qtpositioning-plugins.webxml
@@ -372,21 +267,16 @@ qtqml-javascript-imports.webxml
qtqml-javascript-qmlglobalobject.webxml
qtqml-javascript-resources.webxml
qtqml-javascript-topic.webxml
-qtqml-networkaccessmanagerfactory-example.webxml
qtqml-qml-i18n-example.webxml
-qtqml-qmlextensionplugins-example.webxml
qtqml-syntax-basics.webxml
qtqml-syntax-directoryimports.webxml
qtqml-syntax-imports.webxml
qtqml-syntax-objectattributes.webxml
qtqml-syntax-propertybinding.webxml
-qtqml-syntax-signals.webxml
-qtqml-tool-qmltc.webxml
qtqml-tutorials-extending-qml-example.webxml
qtqml-typesystem-basictypes.webxml
qtqml-typesystem-objecttypes.webxml
qtqml-typesystem-topic.webxml
-qtqml-xmlhttprequest-example.webxml
qtquick-animation-example.webxml
qtquick-bestpractices.webxml
qtquick-canvas-example.webxml
@@ -396,14 +286,11 @@ qtquick-cppextensionpoints.webxml
qtquick-customitems-dialcontrol-example.webxml
qtquick-customitems-flipable-example.webxml
qtquick-customitems-painteditem-example.webxml
-qtquick-customitems-scrollbar-example.webxml
-qtquick-customitems-tabwidget-example.webxml
qtquick-draganddrop-example.webxml
qtquick-effects-particles.webxml
qtquick-effects-sprites.webxml
qtquick-effects-topic.webxml
qtquick-effects-transformations.webxml
-qtquick-externaldraganddrop-example.webxml
qtquick-imageelements-example.webxml
qtquick-imageprovider-example.webxml
qtquick-imageresponseprovider-example.webxml
@@ -415,8 +302,6 @@ qtquick-keyinteraction-example.webxml
qtquick-layouts-example.webxml
qtquick-localstorage-example.webxml
qtquick-models-abstractitemmodel-example.webxml
-qtquick-models-objectlistmodel-example.webxml
-qtquick-models-stringlistmodel-example.webxml
qtquick-modelviewsdata-cppmodels.webxml
qtquick-modelviewsdata-modelview.webxml
qtquick-modelviewsdata-topic.webxml
@@ -433,19 +318,13 @@ qtquick-positioning-righttoleft.webxml
qtquick-positioning-topic.webxml
qtquick-quick-accessibility-example.webxml
qtquick-quickwidgets-quickwidget-example.webxml
-qtquick-rendercontrol-rendercontrol-d3d11-example.webxml
-qtquick-rendercontrol-rendercontrol-opengl-example.webxml
-qtquick-righttoleft-example.webxml
-qtquick-scenegraph-customgeometry-example.webxml
qtquick-scenegraph-custommaterial-example.webxml
qtquick-scenegraph-d3d11underqml-example.webxml
-qtquick-scenegraph-fboitem-example.webxml
qtquick-scenegraph-graph-example.webxml
qtquick-scenegraph-materials.webxml
qtquick-scenegraph-metaltextureimport-example.webxml
qtquick-scenegraph-metalunderqml-example.webxml
qtquick-scenegraph-nodes.webxml
-qtquick-scenegraph-openglunderqml-example.webxml
qtquick-scenegraph-twotextureproviders-example.webxml
qtquick-scenegraph-vulkantextureimport-example.webxml
qtquick-scenegraph-vulkanunderqml-example.webxml
@@ -458,12 +337,8 @@ qtquick-statesanimations-topic.webxml
qtquick-tableview-gameoflife-example.webxml
qtquick-tableview-pixelator-example.webxml
qtquick-text-example.webxml
-qtquick-text-validator.webxml
-qtquick-threading-example.webxml
-qtquick-threading-threadedlistmodel-example.webxml
qtquick-tool-qmllint.webxml
qtquick-tools-and-utilities.webxml
-qtquick-touchinteraction-example.webxml
qtquick-tutorials-dynamicview-dynamicview1-example.webxml
qtquick-tutorials-dynamicview-dynamicview2-example.webxml
qtquick-tutorials-dynamicview-dynamicview3-example.webxml
@@ -482,46 +357,41 @@ qtquick-visualcanvas-scenegraph.webxml
qtquick-visualcanvas-topic.webxml
qtquick-visualcanvas-visualparent.webxml
qtquick-visualtypes-topic.webxml
-qtquick-window-example.webxml
qtquickcontrols-changes-qt6.webxml
qtquickcontrols-chattutorial-example.webxml
qtquickcontrols-contactlist-example.webxml
qtquickcontrols-eventcalendar-example.webxml
qtquickcontrols-flatstyle-example.webxml
-qtquickcontrols-gallery-example.webxml
qtquickcontrols-imagine-automotive-example.webxml
-qtquickcontrols-imagine-musicplayer-example.webxml
-qtquickcontrols-sidepanel-example.webxml
-qtquickcontrols-swipetoremove-example.webxml
qtquickcontrols-texteditor-example.webxml
qtquickcontrols-wearable-example.webxml
-qtquickcontrols2-basic.webxml
-qtquickcontrols2-buttons.webxml
-qtquickcontrols2-configuration.webxml
-qtquickcontrols2-containers.webxml
-qtquickcontrols2-customize.webxml
-qtquickcontrols2-delegates.webxml
-qtquickcontrols2-deployment.webxml
-qtquickcontrols2-environment.webxml
-qtquickcontrols2-examples.webxml
-qtquickcontrols2-fileselectors.webxml
-qtquickcontrols2-focus.webxml
-qtquickcontrols2-fusion.webxml
-qtquickcontrols2-gettingstarted.webxml
-qtquickcontrols2-guidelines.webxml
-qtquickcontrols2-icons.webxml
-qtquickcontrols2-imagine.webxml
-qtquickcontrols2-indicators.webxml
-qtquickcontrols2-input.webxml
-qtquickcontrols2-macos.webxml
-qtquickcontrols2-material.webxml
-qtquickcontrols2-menus.webxml
-qtquickcontrols2-navigation.webxml
-qtquickcontrols2-popups.webxml
-qtquickcontrols2-separators.webxml
-qtquickcontrols2-styles.webxml
-qtquickcontrols2-universal.webxml
-qtquickcontrols2-windows.webxml
+qtquickcontrols-basic.webxml
+qtquickcontrols-buttons.webxml
+qtquickcontrols-configuration.webxml
+qtquickcontrols-containers.webxml
+qtquickcontrols-customize.webxml
+qtquickcontrols-delegates.webxml
+qtquickcontrols-deployment.webxml
+qtquickcontrols-environment.webxml
+qtquickcontrols-examples.webxml
+qtquickcontrols-fileselectors.webxml
+qtquickcontrols-focus.webxml
+qtquickcontrols-fusion.webxml
+qtquickcontrols-gettingstarted.webxml
+qtquickcontrols-guidelines.webxml
+qtquickcontrols-icons.webxml
+qtquickcontrols-imagine.webxml
+qtquickcontrols-indicators.webxml
+qtquickcontrols-input.webxml
+qtquickcontrols-macos.webxml
+qtquickcontrols-material.webxml
+qtquickcontrols-menus.webxml
+qtquickcontrols-navigation.webxml
+qtquickcontrols-popups.webxml
+qtquickcontrols-separators.webxml
+qtquickcontrols-styles.webxml
+qtquickcontrols-universal.webxml
+qtquickcontrols-windows.webxml
qtquicklayouts-overview.webxml
qtremoteobjects-cmake-qt-add-repc-merged.webxml
qtremoteobjects-cmake-qt-add-repc-replicas.webxml
@@ -532,10 +402,7 @@ qtremoteobjects-custom-transport.webxml
qtremoteobjects-external-schemas.webxml
qtremoteobjects-gettingstarted.webxml
qtremoteobjects-interaction.webxml
-qtremoteobjects-modelviewclient-example.webxml
-qtremoteobjects-modelviewserver-example.webxml
qtremoteobjects-node.webxml
-qtremoteobjects-qmlmodelviewclient-example.webxml
qtremoteobjects-registry.webxml
qtremoteobjects-repc.webxml
qtremoteobjects-replica.webxml
@@ -543,21 +410,11 @@ qtremoteobjects-source.webxml
qtremoteobjects-ssl-example.webxml
qtremoteobjects-troubleshooting.webxml
qtremoteobjects-websockets-example.webxml
-qtscxml-calculator-qml-example.webxml
-qtscxml-calculator-widgets-example.webxml
qtscxml-changes-qt6.webxml
qtscxml-cmake-qt-add-statecharts.webxml
qtscxml-ftpclient-example.webxml
qtscxml-instantiating-state-machines.webxml
-qtscxml-invoke-dynamic-example.webxml
-qtscxml-invoke-static-example.webxml
-qtscxml-mediaplayer-qml-cppdatamodel-example.webxml
-qtscxml-mediaplayer-qml-dynamic-example.webxml
-qtscxml-mediaplayer-qml-static-example.webxml
-qtscxml-mediaplayer-widgets-dynamic-example.webxml
-qtscxml-mediaplayer-widgets-static-example.webxml
qtscxml-overview.webxml
-qtscxml-pinball-example.webxml
qtscxml-scxml-compliance.webxml
qtscxml-sudoku-example.webxml
qtscxml-trafficlight-qml-dynamic-example.webxml
@@ -565,40 +422,24 @@ qtscxml-trafficlight-qml-simple-example.webxml
qtscxml-trafficlight-qml-static-example.webxml
qtscxml-trafficlight-widgets-dynamic-example.webxml
qtscxml-trafficlight-widgets-static-example.webxml
-qtsensors-accelbubble-example.webxml
qtsensors-changes-qt6.webxml
qtsensors-cpp.webxml
qtsensors-examples.webxml
-qtsensors-grue-example.webxml
-qtsensors-maze-example.webxml
-qtsensors-qmlqtsensors-example.webxml
-qtsensors-sensor-explorer-example.webxml
qtsensors-sensorsshowcase-example.webxml
qtserialport-blockingreceiver-example.webxml
qtserialport-blockingsender-example.webxml
-qtserialport-cenumerator-example.webxml
qtserialport-changes-qt6.webxml
-qtserialport-creaderasync-example.webxml
-qtserialport-creadersync-example.webxml
-qtserialport-cwriterasync-example.webxml
-qtserialport-cwritersync-example.webxml
-qtserialport-enumerator-example.webxml
qtserialport-examples.webxml
qtserialport-terminal-example.webxml
-qtsql-books-example.webxml
qtsql-cachedtable-example.webxml
qtsql-changes-qt6.webxml
qtsql-drilldown-example.webxml
qtsql-masterdetail-example.webxml
qtsql-querymodel-example.webxml
-qtsql-relationaltablemodel-example.webxml
qtsql-sqlbrowser-example.webxml
qtsql-sqlwidgetmapper-example.webxml
qtsql-tablemodel-example.webxml
qtsvg-changes-qt6.webxml
-qtsvg-richtext-textobject-example.webxml
-qtsvg-svggenerator-example.webxml
-qtsvg-svgviewer-example.webxml
qttest-best-practices-qdoc.webxml
qttestlib-tutorial1-example.webxml
qttestlib-tutorial2-example.webxml
@@ -606,7 +447,6 @@ qttestlib-tutorial3-example.webxml
qttestlib-tutorial4-example.webxml
qttestlib-tutorial5-example.webxml
qttestlib-tutorial6.webxml
-qtuitools-multipleinheritance-example.webxml
qtuitools-textfinder-example.webxml
qtwebchannel-changes-qt6.webxml
qtwebchannel-chatclient-html-example.webxml
@@ -614,30 +454,18 @@ qtwebchannel-chatclient-qml-example.webxml
qtwebchannel-chatserver-cpp-example.webxml
qtwebchannel-examples.webxml
qtwebchannel-javascript.webxml
-qtwebchannel-standalone-example.webxml
qtwebengine-changes-qt6.webxml
qtwebengine-features.webxml
qtwebengine-overview.webxml
qtwebengine-platform-notes.webxml
-qtwebengine-webenginequick-customdialogs-example.webxml
qtwebengine-webenginequick-lifecycle-example.webxml
-qtwebengine-webenginequick-minimal-example.webxml
-qtwebengine-webenginequick-quicknanobrowser-example.webxml
-qtwebengine-webenginequick-recipebrowser-example.webxml
-qtwebengine-webenginequick-webengineaction-example.webxml
qtwebengine-webenginewidgets-contentmanipulation-example.webxml
qtwebengine-webenginewidgets-cookiebrowser-example.webxml
qtwebengine-webenginewidgets-html2pdf-example.webxml
qtwebengine-webenginewidgets-maps-example.webxml
-qtwebengine-webenginewidgets-markdowneditor-example.webxml
-qtwebengine-webenginewidgets-minimal-example.webxml
-qtwebengine-webenginewidgets-notifications-example.webxml
qtwebengine-webenginewidgets-printme-example.webxml
-qtwebengine-webenginewidgets-simplebrowser-example.webxml
qtwebengine-webenginewidgets-spellchecker-example.webxml
-qtwebengine-webenginewidgets-stylesheetbrowser-example.webxml
qtwebengine-webenginewidgets-videoplayer-example.webxml
-qtwebengine-webenginewidgets-webui-example.webxml
qtwebenginewidgets-qtwebkitportingguide.webxml
qtwebsockets-changes-qt6.webxml
qtwebsockets-echoclient-example.webxml
@@ -649,104 +477,32 @@ qtwebsockets-simplechat-example.webxml
qtwebsockets-sslechoclient-example.webxml
qtwebsockets-sslechoserver-example.webxml
qtwebsockets-testing.webxml
-qtwidgets-animation-easing-example.webxml
-qtwidgets-desktop-screenshot-example.webxml
-qtwidgets-desktop-systray-example.webxml
-qtwidgets-dialogs-classwizard-example.webxml
-qtwidgets-dialogs-extension-example.webxml
-qtwidgets-dialogs-findfiles-example.webxml
-qtwidgets-dialogs-licensewizard-example.webxml
-qtwidgets-dialogs-standarddialogs-example.webxml
-qtwidgets-dialogs-tabdialog-example.webxml
-qtwidgets-dialogs-trivialwizard-example.webxml
-qtwidgets-draganddrop-draggableicons-example.webxml
-qtwidgets-draganddrop-draggabletext-example.webxml
-qtwidgets-draganddrop-dropsite-example.webxml
-qtwidgets-draganddrop-fridgemagnets-example.webxml
-qtwidgets-draganddrop-puzzle-example.webxml
-qtwidgets-effects-blurpicker-example.webxml
-qtwidgets-effects-fademessage-example.webxml
-qtwidgets-gallery-example.webxml
qtwidgets-gestures-imagegestures-example.webxml
-qtwidgets-graphicsview-anchorlayout-example.webxml
qtwidgets-graphicsview-basicgraphicslayouts-example.webxml
qtwidgets-graphicsview-chip-example.webxml
-qtwidgets-graphicsview-collidingmice-example.webxml
-qtwidgets-graphicsview-diagramscene-example.webxml
-qtwidgets-graphicsview-dragdroprobot-example.webxml
-qtwidgets-graphicsview-elasticnodes-example.webxml
-qtwidgets-graphicsview-embeddeddialogs-example.webxml
-qtwidgets-graphicsview-flowlayout-example.webxml
qtwidgets-graphicsview-simpleanchorlayout-example.webxml
-qtwidgets-graphicsview-weatheranchorlayout-example.webxml
-qtwidgets-itemviews-addressbook-example.webxml
-qtwidgets-itemviews-basicsortfiltermodel-example.webxml
-qtwidgets-itemviews-chart-example.webxml
qtwidgets-itemviews-coloreditorfactory-example.webxml
qtwidgets-itemviews-combowidgetmapper-example.webxml
qtwidgets-itemviews-customsortfiltermodel-example.webxml
-qtwidgets-itemviews-dirview-example.webxml
-qtwidgets-itemviews-editabletreemodel-example.webxml
-qtwidgets-itemviews-fetchmore-example.webxml
qtwidgets-itemviews-frozencolumn-example.webxml
-qtwidgets-itemviews-interview-example.webxml
-qtwidgets-itemviews-pixelator-example.webxml
-qtwidgets-itemviews-puzzle-example.webxml
-qtwidgets-itemviews-simpledommodel-example.webxml
qtwidgets-itemviews-simpletreemodel-example.webxml
-qtwidgets-itemviews-simplewidgetmapper-example.webxml
-qtwidgets-itemviews-spinboxdelegate-example.webxml
-qtwidgets-itemviews-spreadsheet-example.webxml
-qtwidgets-itemviews-stardelegate-example.webxml
-qtwidgets-layouts-basiclayouts-example.webxml
-qtwidgets-layouts-borderlayout-example.webxml
-qtwidgets-layouts-dynamiclayouts-example.webxml
-qtwidgets-layouts-flowlayout-example.webxml
-qtwidgets-mainwindows-application-example.webxml
-qtwidgets-mainwindows-dockwidgets-example.webxml
-qtwidgets-mainwindows-mainwindow-example.webxml
-qtwidgets-mainwindows-mdi-example.webxml
qtwidgets-mainwindows-menus-example.webxml
-qtwidgets-mainwindows-sdi-example.webxml
qtwidgets-painting-affine-example.webxml
-qtwidgets-painting-basicdrawing-example.webxml
qtwidgets-painting-composition-example.webxml
-qtwidgets-painting-concentriccircles-example.webxml
qtwidgets-painting-deform-example.webxml
-qtwidgets-painting-fontsampler-example.webxml
qtwidgets-painting-gradients-example.webxml
qtwidgets-painting-imagecomposition-example.webxml
qtwidgets-painting-painterpaths-example.webxml
qtwidgets-painting-pathstroke-example.webxml
qtwidgets-painting-transformations-example.webxml
-qtwidgets-richtext-calendar-example.webxml
-qtwidgets-richtext-orderform-example.webxml
-qtwidgets-richtext-syntaxhighlighter-example.webxml
-qtwidgets-richtext-textedit-example.webxml
qtwidgets-tools-completer-example.webxml
qtwidgets-tools-customcompleter-example.webxml
qtwidgets-tools-echoplugin-example.webxml
-qtwidgets-tools-i18n-example.webxml
-qtwidgets-tools-plugandpaint-app-example.webxml
-qtwidgets-tools-plugandpaint-plugins-basictools-example.webxml
-qtwidgets-tools-plugandpaint-plugins-extrafilters-example.webxml
-qtwidgets-tools-regularexpression-example.webxml
qtwidgets-tools-settingseditor-example.webxml
qtwidgets-tools-styleplugin-example.webxml
qtwidgets-tools-treemodelcompleter-example.webxml
-qtwidgets-tools-undo-example.webxml
qtwidgets-tools-undoframework-example.webxml
-qtwidgets-touch-dials-example.webxml
-qtwidgets-touch-fingerpaint-example.webxml
qtwidgets-touch-knobs-example.webxml
-qtwidgets-touch-pinchzoom-example.webxml
-qtwidgets-tutorials-addressbook-part1-example.webxml
-qtwidgets-tutorials-addressbook-part2-example.webxml
-qtwidgets-tutorials-addressbook-part3-example.webxml
-qtwidgets-tutorials-addressbook-part4-example.webxml
-qtwidgets-tutorials-addressbook-part5-example.webxml
-qtwidgets-tutorials-addressbook-part6-example.webxml
-qtwidgets-tutorials-addressbook-part7-example.webxml
qtwidgets-tutorials-notepad-example.webxml
qtwidgets-tutorials-widgets-childwidget-example.webxml
qtwidgets-tutorials-widgets-nestedlayouts-example.webxml
@@ -755,31 +511,14 @@ qtwidgets-tutorials-widgets-windowlayout-example.webxml
qtwidgets-widgets-analogclock-example.webxml
qtwidgets-widgets-calculator-example.webxml
qtwidgets-widgets-calendarwidget-example.webxml
-qtwidgets-widgets-charactermap-example.webxml
-qtwidgets-widgets-codeeditor-example.webxml
-qtwidgets-widgets-digitalclock-example.webxml
-qtwidgets-widgets-elidedlabel-example.webxml
qtwidgets-widgets-groupbox-example.webxml
-qtwidgets-widgets-icons-example.webxml
-qtwidgets-widgets-imageviewer-example.webxml
qtwidgets-widgets-lineedits-example.webxml
-qtwidgets-widgets-mousebuttons-example.webxml
-qtwidgets-widgets-movie-example.webxml
qtwidgets-widgets-scribble-example.webxml
qtwidgets-widgets-shapedclock-example.webxml
qtwidgets-widgets-sliders-example.webxml
qtwidgets-widgets-spinboxes-example.webxml
-qtwidgets-widgets-styles-example.webxml
-qtwidgets-widgets-stylesheet-example.webxml
qtwidgets-widgets-tablet-example.webxml
-qtwidgets-widgets-tetrix-example.webxml
-qtwidgets-widgets-tooltips-example.webxml
-qtwidgets-widgets-validators-example.webxml
-qtwidgets-widgets-wiggly-example.webxml
qtwidgets-widgets-windowflags-example.webxml
-qtxml-dombookmarks-example.webxml
-qtxml-streambookmarks-example.webxml
-qtxml-xmlstreamlint-example.webxml
quick-changes-qt6.webxml
qwebenginecookiestore-filterrequest.webxml
qwidget-styling.webxml
@@ -819,9 +558,7 @@ stylesheet-syntax.webxml
stylesheet.webxml
svgrendering.webxml
testlib-changes-qt6.webxml
-textedit-example.webxml
timers.webxml
-tutorials-addressbook.webxml
usingadaptors.webxml
videooverview.webxml
webengine-examples.webxml
@@ -836,3 +573,52 @@ xml-namespaces.webxml
xml-processing.webxml
xml-streaming.webxml
xml-tools.webxml
+# qtdoc repository
+accessible.webxml
+appicon.webxml
+create-your-first-applications.webxml
+deployment.webxml
+desktop-integration.webxml
+exceptionsafety.webxml
+explore-qt.webxml
+get-and-install-qt.webxml
+gettingstarted.webxml
+highdpi.webxml
+install-qt-design-studio.webxml
+ipc.webxml
+known-issues.webxml
+overviews-main.webxml
+plugins-howto.webxml
+qml-codingconventions.webxml
+qml-glossary.webxml
+qmlapplications.webxml
+qmlfirststeps.webxml
+qt-intro.webxml
+qtquick-debugging.webxml
+qtquick-performance.webxml
+qtquick-qml-runtime.webxml
+qtquick-usecase-animations.webxml
+qtquick-usecase-integratingjs.webxml
+qtquick-usecase-layouts.webxml
+qtquick-usecase-styling.webxml
+qtquick-usecase-text.webxml
+qtquick-usecase-userinput.webxml
+qtquick-usecase-visual.webxml
+qundo.webxml
+rcc.webxml
+restoring-geometry.webxml
+scalability.webxml
+session.webxml
+sharedlibrary.webxml
+solutions-for-application-development.webxml
+solutions-for-ui-design.webxml
+thread-basics.webxml
+threads.webxml
+tools-for-qt-quick-uis.webxml
+tools-for-qt-widget-based-uis.webxml
+topics-app-development.webxml
+topics-data-io.webxml
+topics-ui.webxml
+uic.webxml
+unicode.webxml
+wayland-and-qt.webxml
diff --git a/sources/pyside6/doc/api.rst b/sources/pyside6/doc/api.rst
index eac37a16c..7bbe2ce1c 100644
--- a/sources/pyside6/doc/api.rst
+++ b/sources/pyside6/doc/api.rst
@@ -1,40 +1,30 @@
.. _pyside-api:
-|project| Modules
-=================
+Modules API
+===========
Basic modules
-------------
These are the main modules that help you build a Widget-based UI.
-.. panels::
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
+.. grid:: 1 3 3 3
+ :gutter: 2
- :mod:`QtCore <PySide6.QtCore>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtCore <PySide6.QtCore>`
- Provides core non-GUI functionality, like signal and
- slots, properties, base classes of item models,
- serialization, and more.
+ Provides core non-GUI functionality, like signal and slots, properties,
+ base classes of item models, serialization, and more.
- ---
+ .. grid-item-card:: :mod:`QtGui <PySide6.QtGui>`
- :mod:`QtGui <PySide6.QtGui>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Extends QtCore with GUI functionality: Events, windows and screens,
+ OpenGL and raster-based 2D painting, as well as images.
- Extends QtCore with GUI functionality: Events, windows
- and screens, OpenGL and raster-based 2D painting, as
- well as images.
+ .. grid-item-card:: :mod:`QtWidgets <PySide6.QtWidgets>`
- ---
-
- :mod:`QtWidgets <PySide6.QtWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Provides ready to use Widgets for your application,
- including graphical elements for your UI.
+ Provides ready to use Widgets for your application, including graphical
+ elements for your UI.
QML and Qt Quick
----------------
@@ -42,31 +32,21 @@ QML and Qt Quick
Use these modules to interact with the `QML Language <https://doc.qt.io/qt-5.qmlapplications>`_,
from Python.
-.. panels::
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
-
- :mod:`QtQml <PySide6.QtQml>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. grid:: 1 3 3 3
+ :gutter: 2
- The base Python API to interact with the
- module.
+ .. grid-item-card:: :mod:`QtQml <PySide6.QtQml>`
- ---
+ The base Python API to interact with the module.
- :mod:`QtQuick <PySide6.QtQuick>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtQuick <PySide6.QtQuick>`
- Provides classes to embed Qt Quick in Qt
- applications.
+ Provides classes to embed Qt Quick in Qt applications.
- ---
+ .. grid-item-card:: :mod:`QtQuickWidgets <PySide6.QtQuickWidgets>`
- :mod:`QtQuickWidgets <PySide6.QtQuickWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Provides the QQuickWidget class to embed Qt
- Quick in widget-based applications.
+ Provides the QQuickWidget class to embed Qt Quick in widget-based
+ applications.
All the modules
---------------
@@ -74,4 +54,6 @@ All the modules
There are many other modules currently supported by |pymodname|, here you can find a complete list
of them.
- :doc:`Check all the modules <modules>`
+.. toctree::
+
+ modules.rst
diff --git a/sources/pyside6/doc/commercial/index.rst b/sources/pyside6/doc/commercial/index.rst
new file mode 100644
index 000000000..e74419d6a
--- /dev/null
+++ b/sources/pyside6/doc/commercial/index.rst
@@ -0,0 +1,250 @@
+.. _commercial-page:
+
+Commercial Use
+==============
+
+|project| follows the same licensing that Qt has, which means that there are two
+distributions, the Community Edition (LGPLv3/GPLv3) and a Commercial Edition. For
+more information, check the `Qt Licensing`_ page.
+
+As a brief description, you can get the commercial |project| packages by having
+any of the following licenses:
+
+#. Qt for Application Development Professional (ADP)
+#. Qt for Application Development Enterprise (ADE)
+#. Qt for Device Creation Professional (DCP)
+#. Qt for Device Creation Enterprise (DCE)
+
+The only difference is that the ADP license **does not** include the extra
+``Qt OPC UA``, ``Qt MQTT`` and ``Qt CoAP`` modules, which are distributed in
+a special Python wheel.
+
+|project| follows the same approach as Qt, meaning that commercial
+users will have access to both our commercial packages for any
+given version, or the special commercial LTS releases.
+
+Commercial users **should not** install the Community Edition distribution via ``pip
+install pyside6`` to avoid licensing problems, and should refer to the
+packages that can be acquired from the `Qt Account`_, the Qt Installer, or
+via the `qtpip` tool.
+
+Installation
+------------
+
+We understand that the installation of the commercial wheels will depend
+on your use cases. For this, we currently offer three
+ways to install a commercial Qt for Python release: a command line tool,
+using the Maintenance Tool, or downloading packages by hand.
+
+qtpip - a commercial wheel installer
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+`qtpip`_ is a wrapper around `pip`_ (the package installer for Python) that provides an
+integration with the detection of commercial licenses.
+
+To set up the tool, we recommend creating a virtual environment for your
+project, and then installing the tool like any other module:
+
+.. code-block:: bash
+
+ # Create and activate a virtual environment first
+ # then install 'qtpip'
+ pip install qtpip
+
+ # Now install pyside6 (or any of the Qt for Python packages)
+ qtpip install pyside6
+
+Besides the ``install`` command, you can also ``uninstall`` (like in pip) but
+you can also perform a `fulluninstall`` to fully remove all the Qt for Python
+packages. You can find more information running ``qtpip -h``::
+
+ $ qtpip -h
+ Usage: qtpip [options] install <package> fulluninstall <PySide6/shiboken6/all>
+ Qt wrapper around pip.
+ These arguments override pip's. For more, refer to pip --help
+
+ Options:
+ -f, --force Force installation if OSS wheels were already
+ installed.
+ --no-input Disable prompting for input.
+ --no-cache-dir Disable the cache.
+ --disable-pip-version-check Don't periodically check PyPI to determine
+ whether a new version of pip is available for
+ download.
+ --no-color Suppress colored output.
+ --user Install to the Python user install directory for
+ your platform.
+ --force-reinstall Reinstall all packages even if they are already
+ up-to-date.
+ -h, --help Displays help on commandline options.
+ --help-all Displays help, including generic Qt options.
+ -v, --version Displays version information.
+
+ Arguments:
+ install Installs a package, this can be any of PySide6,
+ PySide6-Essentials, PySide6-Addons, shiboken6 or
+ shiboken6-generator for the respective commercial
+ wheel, or any other wheel from PyPi.
+ fulluninstall Fully uninstalls all packages related to
+ PySide6, shiboken6, or both.
+
+.. note:: The release cycle of ``qtpip`` will be independent from the Qt for
+ Python one.
+
+
+Maintenance Tool
+^^^^^^^^^^^^^^^^
+
+As a commercial user, you are able to download the commercial set of wheels
+from the `Qt Maintenance Tool`_. The same versions that are available for
+Qt/C++ are available for the Python bindings.
+
+The wheels will be downloaded, but not installed, mainly because they should
+be installed into a virtual environment rather than the default interpreter.
+A ``requirements.txt`` file will be provided alongside the wheels, in order to
+simplify the installation step::
+
+ pip install -r /path/to/Qt/QtForPython/6.6.0/requirements.txt
+
+Complementary to the wheels, you will be able to download the sources
+as well.
+
+.. note:: Wheels installed this way will be detectable by `*Qt Creator*`_, which
+ will offer you to install them for your current Python interpreter.
+
+Using account.qt.io
+^^^^^^^^^^^^^^^^^^^
+
+Head to your `Qt Account`_ page, and select the **Download** option on the side
+menu. You will find an option to select |project| from the **Products**
+section:
+
+.. image:: products.png
+ :alt: Products screenshot
+ :align: center
+
+There are two options that will list a different set of packages:
+
+* **Qt for Python Commercial wheels** which are the non-LTS releases under
+ commercial licensing, and include commercial only features and tools.
+ Additionally, here is where you can find the *Qt for automation (M2M
+ Protocols)* packages.
+
+* **Qt for Python (Commercial LTS)** where you will find the 5.15.x LTS and 6.2.x
+ LTS releases.
+
+Once you select any of those, you will be able to select the version of the
+packages you want to download for the **Qt for Python Commercial wheels** packages:
+
+.. image:: versions_commercial.png
+ :alt: Commercial versions screenshot
+ :align: center
+
+and the **Qt for Python (Commercial LTS)** packages:
+
+.. image:: versions_lts.png
+ :alt: LTS versions screenshot
+ :align: center
+
+For any of the versions, you can download many packages depending on your
+Operating System (macOS, Windows, or Linux). To learn more about what the
+packages contain, please check the :ref:`package_details` page.
+
+Once you download the packages, you are encouraged to create a Python virtual
+environment to install them - check the ref:`quick-start` page for how to do
+it.
+With your activated environment on a terminal, run the following command (for
+macOS/Linux)::
+
+ pip install *.whl
+
+to install them all, and leave ``pip`` to resolve the dependencies among the
+packages, or for Windows do it by hand selecting the proper combination::
+
+ pip install shiboken6-... PySide6_Essentials-... PySide6-Addons... ...
+
+Alternatively for Windows, you can specify the following command which includes
+the version, and assumes that you are running it on the same directory where
+the wheels are::
+
+ pip install --no-index --find-links=. PySide6==6.4.0.commercial
+
+.. note:: As described in the :ref:`package_details` page, the dependency
+ of the packages requires you to first install the ``shiboken6``
+ package, and then ``shiboken6-generator`` in case you are interested
+ on binding generation; or ``PySide6_Essentials`` in case you want
+ to use the essential modules. After the Essentials, you can optionally
+ install the ``PySide6_Addons`` and ``PySide6_M2M`` depending on your
+ needs.
+
+Qt Creator Integration
+----------------------
+
+*Qt Creator* offers the option to create new |project| projects from the main
+wizard.
+
+To execute the projects, make sure that the proper *Python Interpreter* is
+selected, so *Qt Creator* can use the commercial modules you just installed.
+Go to *Edit -> Preferences* where you can find the *Python* option
+that will show the following:
+
+.. image:: qtcreator_python.png
+ :alt: Qt Creator Python options
+ :align: center
+
+you can add, remove and modify environments. To include a new one, make sure to
+select the main Python executable from your environment. This can be found on
+``path_to_your_env/bin/python`` (macOS and Linux), or
+``path_to_your_env\python.exe`` (Windows).
+
+As an alternative, you can launch *Qt Creator* from within the virtual
+environment, detecting your installation automatically.
+
+Migrating from other versions
+-----------------------------
+
+In case you have a virtual environment with the Open Source distribution, you
+need to first uninstall those packages with the ``pip uninstall <package>``
+command.
+
+To check if packages are installed, run ``pip list`` and look for
+``shiboken`` or ``PySide`` packages.
+
+We always recommend creating a new virtual environment, so in doubt it is
+better to just remove the old ones if you have previous installations. The
+nature of virtual environments is volatile by design.
+
+
+Python Workflow
+---------------
+
+The Qt framework is a C++ framework that we expose to Python with the help of
+Shiboken (binding generator), which allows us to create the PySide Python module.
+
+|project| tries to find a middle ground between how C++ and Python projects
+work, so there are many decisions that need to be made, one of them being that
+the distributing of the packages needs to follow the same Python workflow,
+which means creating Python packages (wheels) and distributing them in a way
+people can use the ``pip`` tool to install them.
+
+PyPi is the main platform to distribute Open Source packages, but when
+commercial packages are required the situation is different. Among all the
+alternatives we had, we initially decided to provide the packages (wheels) on
+the `Qt Account`_ platform, so people can download and install on demand, but
+we are investigating simple ways to improve this process.
+
+There have also been discussions regarding including |project| in the *Qt
+Maintenance Tool* but this creates a new level of complexity. The reasoning is
+that the tool would require people to select or create a Python virtual
+environment on a separate location for this to be installed. Additionally,
+the Python workflow considers virtual environments as very volatile. This means
+they get removed and created often, so reinstalling or updating the |project|
+packages will likely happen.
+
+.. _`Qt Licensing`: https://www.qt.io/licensing/
+.. _`Qt Account`: https://account.qt.io
+.. _`Qt Maintenance Tool`: https://doc.qt.io/qt-6/qt-online-installation.html
+.. _`Qt Creator`: https://www.qt.io/product/development-tools
+.. _`qtpip`: https://pypi.org/project/qtpip/
+.. _`pip`: https://pypi.org/project/pip/
+
diff --git a/sources/pyside6/doc/commercial/products.png b/sources/pyside6/doc/commercial/products.png
new file mode 100644
index 000000000..d78a29e47
--- /dev/null
+++ b/sources/pyside6/doc/commercial/products.png
Binary files differ
diff --git a/sources/pyside6/doc/commercial/qtcreator_python.png b/sources/pyside6/doc/commercial/qtcreator_python.png
new file mode 100644
index 000000000..067497657
--- /dev/null
+++ b/sources/pyside6/doc/commercial/qtcreator_python.png
Binary files differ
diff --git a/sources/pyside6/doc/commercial/versions_commercial.png b/sources/pyside6/doc/commercial/versions_commercial.png
new file mode 100644
index 000000000..00b4b875a
--- /dev/null
+++ b/sources/pyside6/doc/commercial/versions_commercial.png
Binary files differ
diff --git a/sources/pyside6/doc/commercial/versions_lts.png b/sources/pyside6/doc/commercial/versions_lts.png
new file mode 100644
index 000000000..36adaadca
--- /dev/null
+++ b/sources/pyside6/doc/commercial/versions_lts.png
Binary files differ
diff --git a/sources/pyside6/doc/conf.py.in b/sources/pyside6/doc/conf.py.in
index 0c2593147..e195d227f 100644
--- a/sources/pyside6/doc/conf.py.in
+++ b/sources/pyside6/doc/conf.py.in
@@ -13,7 +13,6 @@
import sys
import os
-from pathlib import Path
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@@ -27,12 +26,28 @@ if @HAS_WEBENGINE_WIDGETS@:
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-#extensions = ['sphinx.ext.todo', 'sphinx.ext.graphviz', 'inheritance_diagram', 'pysideinclude']
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.ifconfig',
'sphinx.ext.coverage', 'sphinx.ext.intersphinx', 'sphinx.ext.todo',
'sphinx.ext.graphviz', 'inheritance_diagram', 'pysideinclude',
'sphinx.ext.viewcode',
- 'sphinx_panels', 'sphinx_copybutton']
+ 'sphinx_design', 'sphinx_copybutton', 'myst_parser', 'sphinx_tags',
+ 'sphinx_toolbox.decorators']
+
+myst_enable_extensions = [
+ "amsmath",
+ "colon_fence",
+ "deflist",
+ "dollarmath",
+ "fieldlist",
+ "html_admonition",
+ "html_image",
+ "replacements",
+ "smartquotes",
+ "strikethrough",
+ "substitution",
+ "tasklist",
+]
+myst_heading_anchors = 6
output_format='@DOC_OUTPUT_FORMAT@'
@@ -48,7 +63,10 @@ rst_epilog = """
templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_templates']
# The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = {
+ '.rst': 'restructuredtext',
+ '.md': 'markdown',
+}
# The encoding of source files.
source_encoding = 'utf-8'
@@ -60,7 +78,7 @@ master_doc = 'index'
# General information about the project.
project = u'PySide'
-copyright = u'2021 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 (https://www.gnu.org/licenses/fdl.html) as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.'
+copyright = u'2024 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 (https://www.gnu.org/licenses/fdl.html) as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
@@ -87,7 +105,7 @@ release = '@BINDING_API_VERSION_FULL@'
# for source files.
exclude_patterns = ['_build',
'extras',
- ]
+ '**README.md']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
@@ -121,17 +139,22 @@ html_theme = 'furo'
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
+ # FIXME: This option is currently enable because on the 'requirements-doc.txt'
+ # We are using a fork of the theme, to include this new option.
+ # This needs to be removed once the functionality is either upstreamed,
+ # or a similar option is provided.
+ "collapse_navbar": True,
"dark_css_variables": {
- "color-brand-primary": "#66689d",
- "color-brand-content": "#66689d",
- "color-admonition-title--important": "#41cd52",
+ "color-brand-primary": "#2cde85",
+ "color-brand-content": "#2cde85",
+ "color-admonition-title--important": "#2cde85",
"color-admonition-title-background--important": "#474b53",
"font-stack": "'Titillium Web', sans-serif",
},
"light_css_variables": {
- "color-brand-primary": "#66689d",
- "color-brand-content": "#41cd52",
- "color-admonition-title--important": "#41cd52",
+ "color-brand-primary": "#27138b",
+ "color-brand-content": "#27138b",
+ "color-admonition-title--important": "#27138b",
"font-stack": "'Titillium Web', sans-serif",
},
}
@@ -141,7 +164,7 @@ html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
-html_title = u'Qt for Python'
+html_title = 'Qt for Python'
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
@@ -153,7 +176,7 @@ html_logo = "@CMAKE_CURRENT_SOURCE_DIR@/_static/qtforpython.png"
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
-#html_favicon = None
+html_favicon = "_static/qtforpython.ico"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@@ -205,7 +228,7 @@ intersphinx_mapping = {'shiboken6': ('shiboken6','@SHIBOKEN_INTERSPHINX_FILE@')}
add_module_names = False
# Skip some warnings when building the documentation with
-# 'build_rst_docs' due to the lack of qdoc generated files, in charge
+# 'build_base_docs' due to the lack of qdoc generated files, in charge
# of sphinx modules (autodoc) and references.
if @SKIP_SPHINX_WARNINGS@:
suppress_warnings = ["autodoc", "autodoc.import_object", "ref.ref"]
@@ -213,7 +236,9 @@ if @SKIP_SPHINX_WARNINGS@:
# -- Options for qthelp output ---------------------------------------------------
qthelp_theme = 'pysidedocs_qthelp'
-# Sphinx Panels color for inactive tab
-panels_css_variables = {
- "tabs-color-label-inactive": "rgba(116, 116, 116, 1.0)",
+# for example tagging based on supported platforms
+tags_create_tags = True
+tags_create_badges = True
+tags_badge_colors = {
+ "Android": "info",
}
diff --git a/sources/pyside6/doc/considerations.rst b/sources/pyside6/doc/considerations.rst
index 08e53e329..dda1d8b0d 100644
--- a/sources/pyside6/doc/considerations.rst
+++ b/sources/pyside6/doc/considerations.rst
@@ -1,7 +1,7 @@
.. _pysideapi2:
-|project| Considerations
-========================
+Considerations
+==============
API Changes
-----------
@@ -10,7 +10,7 @@ One of the goals of |pymodname| is to be API compatible with PyQt,
with certain exceptions.
The latest considerations and known issues will be also reported
-in the `wiki <https://wiki.qt.io/Qt_for_Python/Considerations>`_.
+in the :ref:`developer-notes`.
__hash__() function return value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -149,15 +149,15 @@ There was a long-standing bug in the ``tp_richcompare`` implementation of PySide
This oversight was fixed in version 5.15.1 .
-|project| Features
-==================
+Features
+--------
In |project|, we begin for the first time to support a more pythonic user interface.
With a special import statement, you can switch on features which replace certain aspects of
the Python interpreter. This is done by an import statement right after the PySide6 import.
snake_case
-----------
+~~~~~~~~~~
With the statement:
@@ -169,7 +169,7 @@ all methods in the current module are switched from ``camelCase`` to ``snake_cas
A single upper case letter is replaced by an underscore and the lower case letter.
true_property
--------------
+~~~~~~~~~~~~~
With the statement:
@@ -182,7 +182,7 @@ are replaced by Python property objects. Properties are also listed as such
in the according QMetaObject of a class.
Example for both features
--------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~
Some |project| snippet might read:
@@ -200,14 +200,14 @@ Additionally, properties can also be declared directly in Shiboken for
non Qt-libraries, see :ref:`property-declare`.
More about features
--------------------
+~~~~~~~~~~~~~~~~~~~
Detailed info about features can be found here: :ref:`feature-why`
Tools
------
+~~~~~
-|project| ships some Qt tools:
+|project| ships some Qt tools:
* ``pyside6-rcc``: Qt Resource Compiler. This is a command line tool
that compiles ``.qrc`` files containing binary data, for example images,
@@ -222,3 +222,220 @@ Tools
* ``pyside6-designer``: Qt User Interface Designer. This is a graphical tool
to create designs of Qt Widget-based forms and use custom widgets
(see :ref:`using_ui_files`, :ref:`designer_custom_widgets`).
+
+
+.. _NewEnumSystem:
+
+The New Python Enums
+--------------------
+
+The Motivation to use new Enums
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For a long time, there were just the Shiboken enums, which were modelled as exact as possible
+after the existing enums in Qt. These enums are small classes which also inherit from
+int.
+
+Meanwhile, Python enums have been developed over the years. They have become a natural
+part of modern Python. The implementation is perfectly modelled after the needs of Python
+users. It is therefore just consequent to stop having two different enum implementations
+in the same application and instead to use the new Python implementation everywhere.
+
+
+Existing Work
+~~~~~~~~~~~~~
+
+The new enums beginning with PySide 6.3, replace the Shiboken enums
+with Python variants, which harmonize the builtin enums with the already existing
+``QEnum`` "macro" shown in the :ref:`QEnum` section.
+
+
+Enums behavior in PySide
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+In ``PySide 6.3`` there was a double implementation of old and new enums, where the
+default was old enums.
+The new approach to enum is the default in ``PySide 6.4`` and becomes mandatory
+in ``PySide 6.6``. There exists the environment variable ``PYSIDE6_OPTION_PYTHON_ENUM``
+with the default value of "1". There can also variations be selected by specifying
+different flags, but the value of "0" (switching off) is no longer supported.
+
+The still available options for switching some enum features off can be found in the
+:ref:`enum-features` section.
+
+
+The Differences between old and new Enums
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Python enums and Shiboken enums are more or less compatible with each other.
+Tiny differences are in restrictions:
+
+* Python enums cannot inherit from each other, whereas Shiboken enums can
+* Python enums don't allow undefined values, Shiboken enums do
+* Python enums always need exactly one argument, Shiboken enums have a default zero value
+* Python enums rarely inherit from int, Shiboken enums always do
+
+More visible are the differences between flags, as shown in the following:
+
+The Shiboken flag constructor example has been in PySide prior to 6.3:
+
+::
+
+ flags = Qt.Alignment()
+ enum = Qt.AlignmentFlag
+
+with enum shortcuts like
+
+::
+
+ Qt.AlignLeft = Qt.AlignmentFlag.AlignLeft
+ Qt.AlignTop = Qt.AlignmentFlag.AlignTop
+
+In PySide 6.3, these shortcuts and flags no longer exist (officially).
+Instead, Python has an enum.Flags class which is a subclass of the enum.Enum class.
+But don't be too scared, here comes the good news...
+
+
+Doing a Smooth Transition from the Old Enums
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Changing all the enum code to suddenly use the new syntax is cumbersome and error-prone,
+because such necessary changes are not easy to find.
+Therefore a ``forgiveness mode`` was developed:
+
+The ``forgiveness mode`` allows you to continue using the old constructs but translates them
+silently into the new ones. If you for example write
+
+::
+
+ flags = Qt.Alignment()
+ enum = Qt.AlignLeft
+
+ item.setForeground(QColor(Qt.green))
+
+ flags_type = QPainter.RenderHints
+ flags = QPainter.RenderHints()
+
+ chart_view.setRenderHint(QPainter.Antialiasing)
+
+you get in reality a construct that mimics the following code which is the
+recommended way of writing Flags and Enums:
+
+::
+
+ flags = Qt.AlignmentFlag(0)
+ enum = Qt.AlignmentFlag.AlignLeft
+
+ item.setForeground(QColor(Qt.GlobalColor.green))
+
+ flags_type = QPainter.RenderHint
+ flags = QPainter.RenderHint(0)
+
+ chart_view.setRenderHint(QPainter.RenderHint.Antialiasing)
+
+This has the effect that you can initially ignore the difference between old and new enums,
+as long as the new enums are properties of classes. (This does not work on global enums
+which don't have a class, see ``Limitations`` below.)
+
+
+Forgiveness Mode and Type Hints
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When you inspect for instance ``QtCore.pyi``, you will only find the new enums, although
+the old ones are still allowed. Also, line completion will only work with the new constructs
+and never propose the old ones.
+
+The reason to implement ``forgiveness mode`` this way was
+
+* to make the transition as smooth as possible, but
+* to encourage people to use the new enums whenever new code is written.
+
+So you can continue to write:
+
+::
+
+ self.text.setAlignment(Qt.AlignCenter)
+
+but this construct is used and recommended for the future:
+
+::
+
+ self.text.setAlignment(Qt.AlignmentFlag.AlignCenter)
+
+
+Limitations
+~~~~~~~~~~~
+
+The forgiveness mode works very well whenever the enum class is embedded in a normal
+PySide class. But there are a few global enums, where especially the ``QtMsgType``
+is a problem:
+
+::
+
+ t = QtMsgType.QtDebugMsg
+
+cannot be written in the shortcut form
+
+::
+
+ t = QtDebugMsg
+
+because there is no surrounding PySide class that provides the forgiving mode
+implementation. Typically, the needed changes are easily found because they often occur
+in an import statement.
+
+Permission API
+--------------
+
+The cross-platform permission APIs were introduced to Qt in version 6.5 which are currently relevant
+to platforms macOS, iOS, Android and WebAssembly. With this API, your Qt application can check and
+request permission for certain features like Camera, Microphone, Location, Bluetooth, Contacts,
+Calendar. More about permission API can be read in this `Blog post`_.
+
+When a PySide6 application that uses the permission API is run in interpreted mode, i.e.,
+``python <main_file>.py``, the code implementing the permission API *will not work*. The only way
+to make your PySide6 application using permission API work is to bundle the application. For Android,
+this means using the `pyside6-android-deploy`_ tool and for macOS, this means using the
+`pyside6-deploy`_ tool.
+
+When running in interpreted mode, you can skip over the permission check/request using the following
+*if* condition
+
+::
+
+ is_deployed = "__compiled__" in globals()
+ if not is_deployed and sys.platform == "darwin":
+ # code implementing permission check and request
+
+This can also be seen in the PySide6 `Camera example`_. * __compiled__ * is a Nuitka attribute to
+check if the application is run as a standalone application or run in interpreted mode with Python.
+
+Android
+~~~~~~~~
+
+For Android, `pyside6-android-deploy`_ takes care of identifying the necessary permissions needed by
+the application and adding those permissions to the *AndroidManifest.xml* using the
+*<uses-permission>* element.
+
+macOS
+~~~~~
+
+Since the Android platform does not automatically come bundled with a Python interpreter, it is
+evident that to make a PySide6 application run on Android you have to package the PySide6
+application. This is not the case for desktop platforms like macOS where a Python interpreter and
+its packages can be installed and run quite easily.
+
+The problem for macOS is that for the permission API to work you need a macOS bundle with an
+*Info.plist* file that lists all the permissions required using the *usage description* string for
+each permission used. When Python is run in interpreted mode, i.e., when you run Python, the Qt
+permission API fetches the *Info.plist* from the Python interpreter by default which does not
+contain the *usage description* strings for the permissions required. You can certainly modify the
+*Info.plist* of the Python framework installation to make the Qt permission API work when running
+a PySide6 application from the terminal. However, this is not recommended. Therefore, the only
+viable solution is to bundle the PySide6 application as a macOS application bundle using
+`pyside6-deploy`_. This macOS application bundle will have its own Info.plist file.
+
+.. _`Blog post`: https://www.qt.io/blog/permission-apis-in-qt-6.5
+.. _`Camera Example`: https://doc.qt.io/qtforpython-6/examples/example_multimedia_camera.html#camera-example
+.. _`pyside6-android-deploy`: https://doc.qt.io/qtforpython-6/gettingstarted/package_details.html#deployment
+.. _`pyside6-deploy`: https://doc.qt.io/qtforpython-6/gettingstarted/package_details.html#deployment
diff --git a/sources/pyside6/doc/contents.rst b/sources/pyside6/doc/contents.rst
index 2dbd09997..4b6c7ffa9 100644
--- a/sources/pyside6/doc/contents.rst
+++ b/sources/pyside6/doc/contents.rst
@@ -1,19 +1,20 @@
-|project| Documentation
-***************************
+.. items for the main front page grid
.. toctree::
:maxdepth: 2
quickstart.rst
- gettingstarted.rst
- porting_from2.rst
+ commercial/index.rst
+ gettingstarted/index.rst
api.rst
+ tools/index.rst
tutorials/index.rst
examples/index.rst
videos.rst
- deployment.rst
- modules.rst
+ deployment/index.rst
considerations.rst
+ developer/index.rst
+
..
Intersphinx references in toctrees is not supported
https://github.com/sphinx-doc/sphinx/issues/1836
diff --git a/sources/pyside6/doc/deployment-briefcase.rst b/sources/pyside6/doc/deployment/deployment-briefcase.rst
index 95aee1432..e85e618a7 100644
--- a/sources/pyside6/doc/deployment-briefcase.rst
+++ b/sources/pyside6/doc/deployment/deployment-briefcase.rst
@@ -1,13 +1,16 @@
|project| & Briefcase
#######################
-`Briefcase <https://briefcase.readthedocs.io>`_ is a packaging tool that lets you create a standalone package for a Python application. It supports the following installer formats:
+`Briefcase <https://briefcase.readthedocs.io>`_ is a packaging tool that lets
+you create a standalone package for a Python application. It supports the
+following installer formats:
- * .app application bundle for macOS
- * MSI installer for Windows
- * AppImage for Linux
+* ``.app`` application bundle for macOS
+* MSI installer for Windows
+* AppImage for Linux
-For more details, see the `official documentation <https://briefcase.readthedocs.io/en/latest/index.html>`_.
+For more details, see the `official documentation
+<https://briefcase.readthedocs.io/en/latest/index.html>`_.
Status of Qt 6 Support
======================
@@ -17,15 +20,15 @@ As of March 2021, Qt 6 is not supported yet.
Preparation
===========
-Install `Briefcase` using the following **pip** command::
+Install ``Briefcase`` using the following **pip** command::
pip install briefcase
You also need : docker on linux, `WixToolset`_ on windows,
-If you're using a virtual environment, remember to activate it before installing `Briefcase`.
+If you're using a virtual environment, remember to activate it before installing ``Briefcase``.
-After installation, the `briefcase` binary is located in your virtual environment's `bin/`
+After installation, the ``briefcase`` binary is located in your virtual environment's ``bin/``
directory, or where your Python executable is located.
You can either create a brand new project using the briefcase assistant or setup your own.
@@ -39,8 +42,8 @@ Run the following command and answer the questions to get started::
briefcase new
-Ensure that `PySide6` is chosen as the `GUI toolkit choice`.
-Your PySide6 application is now configured. You can jump to `Build the package`_.
+Ensure that |pymodname| is chosen as the **GUI toolkit choice**.
+Your |pymodname| application is now configured. You can jump to `Build the package`_.
Set up your project
@@ -49,7 +52,7 @@ Set up your project
Create a pyproject.toml
-----------------------
-At the root level of your project, create a `pyproject.toml` file::
+At the root level of your project, create a ``pyproject.toml`` file::
[tool.briefcase]
project_name = "MyPySideApp"
@@ -85,7 +88,7 @@ At the root level of your project, create a `pyproject.toml` file::
Write some code
-----------------
+---------------
Let's say your project tree is like this::
@@ -103,7 +106,7 @@ Let's say your project tree is like this::
app.py
-Content of `__main__.py`::
+Content of ``__main__.py``::
import sys
from PySide6.QtWidgets import QApplication
@@ -119,7 +122,7 @@ Content of `__main__.py`::
sys.exit(app.exec())
-Content of `app.py`::
+Content of ``app.py``::
import random
from PySide6.QtWidgets import (QLabel, QPushButton,
@@ -151,10 +154,10 @@ Content of `app.py`::
Build the package
-==================
+=================
Initialize the package
-------------------------
+----------------------
Just run::
@@ -162,7 +165,8 @@ Just run::
Run the following command to initialize the building the packages for Windows, Linux, and macOS.
It creates a subdirectory each for the different platforms.
-This step takes longer as it adds the packages listed in `requires` sections in the `pyproject.toml` file.
+This step takes longer as it adds the packages listed in ``requires`` sections in the
+``pyproject.toml`` file.
Build the application
---------------------
@@ -185,20 +189,23 @@ Run the application
briefcase run
-.. note:: You can run your project in `dev` mode (your source code not packaged) with `briefcase dev`
+.. note:: You can run your project in ``dev`` mode (your source code not packaged) with
+ ``briefcase dev``
Build the installer (only Windows and macOS)
----------------------------------------------
+--------------------------------------------
macOS::
briefcase package --no-sign
-It's possible to sign, see the `documentation <https://briefcase.readthedocs.io/en/latest/how-to/code-signing/index.html>`_. You get `macOS/A Cool App-0.0.1.dmg`
+It's possible to sign, see the
+`documentation <https://briefcase.readthedocs.io/en/latest/how-to/code-signing/index.html>`_.
+You get ``macOS/A Cool App-0.0.1.dmg``
Windows::
briefcase package
-You get `windows\A_Cool_App-0.0.1.msi`
+You get ``windows\A_Cool_App-0.0.1.msi``
diff --git a/sources/pyside6/doc/deployment-cxfreeze.rst b/sources/pyside6/doc/deployment/deployment-cxfreeze.rst
index 681dcf315..46cbb142e 100644
--- a/sources/pyside6/doc/deployment-cxfreeze.rst
+++ b/sources/pyside6/doc/deployment/deployment-cxfreeze.rst
@@ -8,37 +8,38 @@ platforms are Linux, macOS, Windows, FreeBSD, among others.
You can read the `official documentation <https://cx-freeze.readthedocs.io/en/latest/index.html>`_
to clarify any further question, and remember to contribute to
-the project by `filing issues <https://sourceforge.net/projects/cx-freeze/>`_
-if you find any, or contributing to `their development <https://bitbucket.org/anthony_tuininga/cx_freeze/src>`_.
+the project by `filing issues
+<https://github.com/marcelotduarte/cx_Freeze/issues>`_
+if you find any, or contributing to `their development <https://github.com/marcelotduarte/cx_Freeze>`_.
Preparation
===========
-Installing `cx_Freeze` can be done using **pip**::
+Installing ``cx_Freeze`` can be done using **pip**::
pip install cx_freeze
If you are using a virtual environment, remember to activate it before
-installing `cx_Freeze` into it.
+installing ``cx_Freeze`` into it.
-After the installation, you will have the `cxfreeze` binary to deploy
+After the installation, you will have the ``cxfreeze`` binary to deploy
your application.
Freezing an application
=======================
-There are three options to work with `cx_Freeze`:
+There are three options to work with ``cx_Freeze``:
- 1. Using the `cxfreeze` script.
- 2. Creating `setup.py` script to build the project.
- 3. Using the module classes directly (for advanced purposes).
+1. Using the ``cxfreeze`` script.
+2. Creating ``setup.py`` script to build the project.
+3. Using the module classes directly (for advanced purposes).
The following sections cover the first two use cases.
Creating an example
-------------------
-Now, consider the following simple script, named `hello.py`::
+Now, consider the following simple script, named ``hello.py``::
import sys
import random
@@ -79,28 +80,28 @@ Now, consider the following simple script, named `hello.py`::
sys.exit(app.exec())
-Using `cxfreeze` executable
----------------------------
+Using ``cxfreeze`` executable
+-----------------------------
Now that we have an application, try freezing it with the following
command::
cxfreeze hello.py
-This command creates a `dist/` directory containing the executable.
-and a `lib/` directory containing all the shared libraries.
+This command creates a ``dist/`` directory containing the executable.
+and a ``lib/`` directory containing all the shared libraries.
-To launch the application, go to the `dist/` directory and execute
+To launch the application, go to the ``dist/`` directory and execute
the file::
cd dist/
./main
-Using a setuptools script
--------------------------
+Using a ``setuptools`` script
+-----------------------------
-For this process, you need an additional script called `setup.py`::
+For this process, you need an additional script called ``setup.py``::
import sys
from cx_Freeze import setup, Executable
@@ -114,15 +115,15 @@ Now, build the project using it::
python setup.py build
-This step creates a `build/` directory with the following structure::
+This step creates a ``build/`` directory with the following structure::
build
└── exe.linux-x86_64-3.7
└── lib
└── main
-The first directory inside `build/` depends on the platform
-you are using, in this case a `x86_64` Linux using Python 3.7.
+The first directory inside ``build/`` depends on the platform
+you are using, in this case a ``x86_64`` Linux using Python 3.7.
The structure is the same as previously described, and you can simply
enter the directory and execute the file::
diff --git a/sources/pyside6/doc/deployment-fbs.rst b/sources/pyside6/doc/deployment/deployment-fbs.rst
index c2a2397d2..459a225bf 100644
--- a/sources/pyside6/doc/deployment-fbs.rst
+++ b/sources/pyside6/doc/deployment/deployment-fbs.rst
@@ -2,7 +2,7 @@
####################
`fbs`_ provides a powerful environment for packaging, creating installers, and signing your
-application. It also lets you manage updates to your application. Since `fbs` is based on
+application. It also lets you manage updates to your application. Since `fbs`_ is based on
PyInstaller, it supports Linux, macOS, and Windows.
For more details, see the `fbs tutorial`_ and the `fbs manual`_.
@@ -32,12 +32,12 @@ command::
This command prompts you to answer a few questions to configure the details of your project, like:
- * Application name
- * Author name
- * Qt bindings (PySide6 or PyQt5)
- * Bundle indentified (for macOS)
+* Application name
+* Author name
+* Qt bindings (PySide6)
+* Bundle indentified (for macOS)
-Afterwards, you have a `src/` directory that contains the following structure::
+Afterwards, you have a ``src/`` directory that contains the following structure::
└── src
├── build
@@ -49,10 +49,10 @@ Afterwards, you have a `src/` directory that contains the following structure::
│ └── mac
└── python
-Inside the `settings` directory, there are a few JSON files that can be edited to include more
+Inside the ``settings`` directory, there are a few JSON files that can be edited to include more
information about your project.
-The `main` file is in the `python` directory, and its default content is::
+The ``main`` file is in the ``python`` directory, and its default content is::
from fbs_runtime.application_context import ApplicationContext
from PySide6.QtWidgets import QMainWindow
@@ -67,7 +67,7 @@ The `main` file is in the `python` directory, and its default content is::
exit_code = appctxt.app.exec() # 2. Invoke appctxt.app.exec()
sys.exit(exit_code)
-This example shows an empty `QMainWindow`. You can run it using the following command::
+This example shows an empty ``QMainWindow``. You can run it using the following command::
fbs run
@@ -83,15 +83,15 @@ After the process completes, you see a message stating the location of your exec
example::
Done. You can now run `target/MyApp/MyApp`. If that doesn't work, see
- https://build-system.fman.io/troubleshooting.
+ https://build-system.fman.io/troubleshooting
Now, you can try to run the application. The result is the same window as the one you saw with the
-`fbs run` command::
+``fbs run`` command::
cd target/MyApp/
./MyApp
.. note:: This is the case for Linux. For other platforms like macOS, you need to enter the
- directory: `target/MyApp.app/Contents/macOS`. For Windows, you need to find the `MyApp.exe`
+ directory: ``target/MyApp.app/Contents/macOS``. For Windows, you need to find the ``MyApp.exe``
executable.
diff --git a/sources/pyside6/doc/deployment-nuitka.rst b/sources/pyside6/doc/deployment/deployment-nuitka.rst
index 9be982a4c..8b0afa56c 100644
--- a/sources/pyside6/doc/deployment-nuitka.rst
+++ b/sources/pyside6/doc/deployment/deployment-nuitka.rst
@@ -11,11 +11,11 @@ For more details, see the `official documentation <https://nuitka.net/pages/over
Preparation
===========
-Install `Nuitka` via **pip** with the following command::
+Install ``Nuitka`` via **pip** with the following command::
- pip3 install nuitka
+ pip install nuitka
-After installation, the `nuitka3` binary is located in your virtual environment's `bin/`
+After installation, the ``nuitka3`` binary is located in your virtual environment's ``bin/``
directory, or where your Python executable is located.
Alternatively, you can also run::
@@ -26,7 +26,7 @@ to achieve the same effect.
Freeze an application
=====================
-`Nuitka` has many options that you can use. To list them all, run `nuitka3 -h`.
+``Nuitka`` has many options that you can use. To list them all, run ``nuitka3 -h``.
To simply compile a project, you can run::
@@ -34,17 +34,17 @@ To simply compile a project, you can run::
There are two main features:
- * the option to place it in a directory containing the libraries
- (`--standalone`)
- * the option to package the whole project (including shared libraries) into one executable file
- (`--onefile`)
+* the option to place it in a directory containing the libraries
+ (``--standalone``)
+* the option to package the whole project (including shared libraries) into one executable file
+ (``--onefile``)
-If you use these options, you need to specify `--plugin-enable=pyside6`.
+If you use these options, you need to specify ``--plugin-enable=pyside6``.
Run an example
--------------
-Now, consider the following script, named `hello.py`::
+Now, consider the following script, named ``hello.py``::
import sys
import random
@@ -84,13 +84,13 @@ Now, consider the following script, named `hello.py`::
sys.exit(app.exec())
-You don't have to copy this script. You find it as `examples/installer_test/hello.py`.
+You don't have to copy this script. You find it as ``examples/installer_test/hello.py``.
The command line to proceed looks like this::
nuitka3 examples/installer_test/hello.py
-This process creates an executable `hello.bin` and a directory hello.build that you
+This process creates an executable ``hello.bin`` and a directory hello.build that you
don't need. You can execute the binary directly.
In order to create a bundle which can be copied onto a machine without any pre-existing
@@ -98,23 +98,23 @@ installation, run::
nuitka3 --standalone --plugin-enable=pyside6 examples/installer_test/hello.py
-This creates an application `hello.dist/hello` that contains everything needed to run.
+This creates an application ``hello.dist/hello`` that contains everything needed to run.
-To run the application, go to `hello.dist/` and run the program::
+To run the application, go to ``hello.dist/`` and run the program::
cd hello.dist
./hello
-Use the `--onefile` option if you prefer to have everything bundled into one executable, without
+Use the ``--onefile`` option if you prefer to have everything bundled into one executable, without
the shared libraries next to it. First you need to install::
- pip3 install zstandard
+ pip install zstandard
-for data compression. Then you can run
+for data compression. Then you can run::
nuitka3 --onefile --plugin-enable=pyside6 examples/installer_test/hello.py
-This process takes a bit longer, but in the end you have one executable `hello.bin`::
+This process takes a bit longer, but in the end you have one executable ``hello.bin``::
./hello.bin
@@ -127,6 +127,6 @@ Nuitka issue on macOS
---------------------
Nuitka currently has a problem with the macOS bundle files on current macOS versions.
-That has the effect that `--standalone` and `--onefile` create a crashing application.
+That has the effect that ``--standalone`` and ``--onefile`` create a crashing application.
Older versions which don't have the recent macOS API changes from 2020 will work.
We are currently trying to fix that problem.
diff --git a/sources/pyside6/doc/deployment-py2exe.rst b/sources/pyside6/doc/deployment/deployment-py2exe.rst
index 24d260d71..6ca09a826 100644
--- a/sources/pyside6/doc/deployment-py2exe.rst
+++ b/sources/pyside6/doc/deployment/deployment-py2exe.rst
@@ -1,16 +1,16 @@
|project| & py2exe
##################
-Deploying an application using py2exe requires writing a small `setup.py` file.
+Deploying an application using py2exe requires writing a small ``setup.py`` file.
It is explained in the `Tutorial <http://www.py2exe.org/index.cgi/Tutorial>`_.
py2exe is not generally aware of Qt. It merely copies the dependent libraries
-of the application to the `dist` directory, so, the plugins, QML imports
+of the application to the ``dist`` directory, so, the plugins, QML imports
and translations of Qt are missing.
The latter need to be copied manually after running py2exe.
-This can be achieved by running the `windeployqt` tool
-from the Qt SDK on the Qt libraries present in the `dist` directory,
-for example:
+This can be achieved by running the ``windeployqt`` tool
+from the Qt SDK on the Qt libraries present in the ``dist`` directory,
+for example::
windeployqt dist\\Qt6Widgets.dll
diff --git a/sources/pyside6/doc/deployment-pyinstaller.rst b/sources/pyside6/doc/deployment/deployment-pyinstaller.rst
index eb900bd74..feb257162 100644
--- a/sources/pyside6/doc/deployment-pyinstaller.rst
+++ b/sources/pyside6/doc/deployment/deployment-pyinstaller.rst
@@ -5,21 +5,21 @@
stand-alone executable. This installer supports Linux, macOS, Windows, and more; and is also
compatible with 3rd-party Python modules, such as |pymodname|.
-For more details, see the `official documentation <https://www.pyinstaller.org/documentation.html>`_.
+For more details, see the `official documentation <https://www.pyinstaller.org>`_.
Status of Qt 6 Support
======================
As of March 2021, Qt 6 is not supported yet. PyInstaller is unable to properly
-deploy Qt; the Qt plugins are not copied. With that, using `--onefile` is not
+deploy Qt; the Qt plugins are not copied. With that, using ``--onefile`` is not
possible.
-It is possible to use PyInstaller for the non `--onefile` case though by
+It is possible to use PyInstaller for the non ``--onefile`` case though by
manually copying the Qt plugins, QML imports and translations into
the dist directory after running PyInstaller.
-On Windows, this can be achieved by running the `windeployqt` tool
-from the Qt SDK on the Qt libraries present in the `dist` directory, for
+On Windows, this can be achieved by running the ``windeployqt`` tool
+from the Qt SDK on the Qt libraries present in the ``dist`` directory, for
example:
windeployqt dist\\app\\Qt6Widgets.dll
@@ -28,15 +28,15 @@ example:
Preparation
===========
-Install the `PyInstaller` via **pip** with the following command::
+Install the ``PyInstaller`` via **pip** with the following command::
pip install pyinstaller
-If you're using a virtual environment, remember to activate it before installing `PyInstaller`.
+If you're using a virtual environment, remember to activate it before installing ``PyInstaller``.
-After installation, the `pyinstaller` binary is located in your virtual environment's `bin/`
-directory, or where your Python executable is located. If that directory isn't in your `PATH`,
-include the whole path when you run `pyinstaller`.
+After installation, the ``pyinstaller`` binary is located in your virtual environment's ``bin/``
+directory, or where your Python executable is located. If that directory isn't in your ``PATH``,
+include the whole path when you run ``pyinstaller``.
.. warning:: If you already have a PySide6 or Shiboken6 version installed in your
system path, PyInstaller uses them instead of your virtual environment version.
@@ -44,24 +44,24 @@ include the whole path when you run `pyinstaller`.
Freeze an application
=======================
-`PyInstaller` has many options that you can use. To list them all, run `pyinstaller -h`.
+``PyInstaller`` has many options that you can use. To list them all, run ``pyinstaller -h``.
There are two main features:
* the option to package the whole project (including shared libraries) into one executable file
- (`--onefile`)
+ (``--onefile``)
* the option to place it in a directory containing the libraries
-Additionally, on Windows when the command is running, you can open a console with the `-c` option
-(or `--console` or `--nowindowed` equivalent).
+Additionally, on Windows when the command is running, you can open a console with the ``-c`` option
+(or ``--console`` or ``--nowindowed`` equivalent).
-Otherwise, you can specify to not open such a console window on macOS and Windows with the `-w`
-option (or `--windowed` or `--noconsole` equivalent).
+Otherwise, you can specify to not open such a console window on macOS and Windows with the ``-w``
+option (or ``--windowed`` or ``--noconsole`` equivalent).
Create an example
-----------------
-Now, consider the following script, named `hello.py`::
+Now, consider the following script, named ``hello.py``::
import sys
import random
@@ -102,28 +102,29 @@ Now, consider the following script, named `hello.py`::
sys.exit(app.exec())
-Since it has a UI, you use the `--windowed` option.
+Since it has a UI, you use the ``--windowed`` option.
The command line to proceed looks like this::
pyinstaller --name="MyApplication" --windowed hello.py
-This process creates two directories: `dist/` and `build/`. The application executable and the
-required shared libraries are placed in `dist/MyApplication`.
+This process creates two directories: ``dist/`` and ``build/``. The application executable and the
+required shared libraries are placed in ``dist/MyApplication``.
-To run the application, go to `dist/MyApplication` and run the program::
+To run the application, go to ``dist/MyApplication`` and run the program::
cd dist/MyApplication/
./MyApplication
-.. note:: The directory inside `dist/` and the executable have the same name.
+.. note:: The directory inside ``dist/`` and the executable have the same name.
-Use the `--onefile` option if you prefer to have everything bundled into one executable, without
+Use the ``--onefile`` option if you prefer to have everything bundled into one executable, without
the shared libraries next to it::
pyinstaller --name="MyApplication" --windowed --onefile hello.py
-This process takes a bit longer, but in the end you have one executable in the `dist/` directory::
+This process takes a bit longer, but in the end you have one executable in the
+``dist/`` directory::
cd dist/
./MyApplication
@@ -136,26 +137,26 @@ Some Caveats
PyInstaller Issue
-----------------
-As mentioned before, if available, `PyInstaller` picks a system installation of PySide6 or
-Shiboken6 instead of your `virtualenv` version without notice. This is negligible if those
+As mentioned before, if available, ``PyInstaller`` picks a system installation of |pymodname| or
+Shiboken6 instead of your ``virtualenv`` version without notice. This is negligible if those
two versions are the same.
If you're working with different versions, this can result in frustrating debugging sessions
-when you think you are testing the latest version, but `PyInstaller` is working with an older
+when you think you are testing the latest version, but ``PyInstaller`` is working with an older
version.
Safety Instructions
-------------------
-- When using `PyInstaller` with `virtualenv`, make sure that there is no system
+- When using ``PyInstaller`` with ``virtualenv``, make sure that there is no system
installation of PySide6 or shiboken6.
-- Before compiling, use `pip -uninstall pyside6 shiboken6 -y` multiple times, until
- none of the programs are found anymore.
+- Before compiling, use ``pip -uninstall pyside6 pyside6_essentials pyside6_addons shiboken6 -y``
+ multiple times, until none of the programs are found anymore.
- Pip is usually a good tool. But to be 100 % sure, you should directly remove
- the PySide6 and shiboken6 folders from site-packages.
+ the PySide6 and shiboken6 folders from ``site-packages``.
- Be sure to use the right version of pip. The safest way to really run the right
pip, is to use the Python that you mean: Instead of the pip command, better use::
diff --git a/sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst b/sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst
new file mode 100644
index 000000000..53944f6ea
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-pyside6-android-deploy.rst
@@ -0,0 +1,211 @@
+.. _pyside6-android-deploy:
+
+pyside6-android-deploy: the Android deployment tool for Qt for Python
+#####################################################################
+
+``pyside6-android-deploy`` is an easy-to-use tool for deploying PySide6 applications to different
+Android architectures, namely *arm64-v8a, x86_64, x86 and armeabi-v7a*. This tool works similarly to
+the ``pyside6-deploy`` tool and uses the same configuration file ``pysidedeploy.spec`` as
+``pyside6-deploy`` to configure the deployment process. Using the deployment configuration
+options either from the command line or from ``pysidedeploy.spec``, ``pyside6-android-deploy``
+configures the deployment to be initiated and invokes `buildozer`_, a tool used for packaging Python
+applications to Android.
+
+The final output is a `.apk` or a `.aab` file created within the project's source directory. The
+`mode` option specified under the :ref:`buildozer <buildozer_key>` key in ``pysidedeploy.spec``
+determines whether a `.apk` or a `.aab` is created.
+
+.. warning:: Currently, users are required to cross-compile Qt for Python to generate the wheels
+ required for a specific Android target architecture. This requirement will disappear when
+ there are official Qt for Python Android wheels (*in progress*). Because of this
+ requirement ``pyside6-android-deploy`` will be considered in **Technical Preview**.
+ Instructions on cross-compiling Qt for Python for Android can be found
+ :ref:`here <cross_compile_android>`.
+
+.. note:: ``pyside6-android-deploy`` only works on a Linux host at the moment. This constraint
+ is also because Qt for Python cross-compilation for Android currently only works on Linux
+ systems.
+
+How to use it?
+==============
+
+Like ``pyside6-deploy``, there are :ref:`two different ways <how_pysidedeploy>` with which
+you can deploy your PySide6 application using ``pyside6-android-deploy``. The only difference is
+that for ``pyside6-android-deploy`` to work, the main Python entry point file should be named
+``main.py``.
+
+.. _pysideandroiddeploy:
+
+pysidedeploy.spec
+=================
+
+Like ``pyside6-deploy``, you can use the ``pysidedeploy.spec`` file to control the various
+parameters of the deployment process. The file has multiple sections, with each section containing
+multiple keys (parameters being controlled) assigned to a value. The advantages of such a file are
+mentioned :ref:`here <pysidedeployspec_advantages>`. The benefit of using the same
+``pysidedeploy.spec`` for both ``pyside6-deploy`` and ``pyside6-android-deploy`` is that you can
+have one single file to control deployment to all platforms.
+
+The relevant parameters for ``pyside6-android-deploy`` are:
+
+**app**
+ * ``title``: The name of the application.
+ * ``project_dir``: Project directory. The general assumption made is that the project directory
+ is the parent directory of the main Python entry point file.
+ * ``input_file``: Path to the main Python entry point file. For ``pyside6-android-deploy`` this
+ file should be named `main.py`.
+ * ``project_file``: If it exists, this points to the path to the `Qt Creator Python Project File
+ .pyproject <https://doc.qt.io/qtforpython-6/faq/typesoffiles.html
+ #qt-creator-python-project-file-pyproject>`_ file. Such a file in the project directory ensures
+ that deployment does not consider unnecessary files when bundling the executable.
+ * ``exec_directory``: The directory where the final executable is generated.
+
+**python**
+ * ``python_path``: Path to the Python executable. It is recommended to run
+ ``pyside6-android-deploy`` from a virtual environment as certain Python packages will be
+ installed onto the Python environment. However, note to keep the created virtual environment
+ outside the project directory so that ``pyside6-android-deploy`` does not try to package it
+ as well.
+ * ``android_packages``: The Python packages installed into the Python environment for deployment
+ to work. By default, the Python packages `buildozer`_ and `cpython`_ are installed.
+
+.. _qt_key:
+
+**qt**
+ * ``modules``: Comma-separated list of all the Qt modules used by the application. Just like the
+ other configuration options in ``pysidedeploy.spec``, this option is also computed automatically
+ by ``pyside6-android-deploy``. However, if you want to explicitly include certain Qt modules,
+ the module names can be appended to this list without the `Qt` prefix.
+ e.g. Network instead of QtNetwork
+ * ``plugins``: This field is *not relevant* for ``pyside6-android-deploy`` and is only specific to
+ ``pyside6-deploy``. The plugins relevant for ``pyside6-android-deploy`` are specified through
+ the ``plugins`` option under the :ref:`android <android_key>` key.
+
+.. _android_key:
+
+**android**
+ * ``wheel_pyside``: Specifies the path to the PySide6 Android wheel for a specific target
+ architecture.
+ * ``wheel_pyside``: Specifies the path to the Shiboken6 Android wheel for a specific target
+ architecture.
+ * ``plugins``: Comma-separated list of all the Qt plugins used by the application. Just like the
+ other configuration options in ``pysidedeploy.spec``, this option is also computed automatically
+ by ``pyside6-android-deploy``. However, if you want to to explicitly include certain Qt plugins,
+ the plugin names can be appended to this list. To see all the plugins bundled with PySide6, see
+ the `plugins` folder in the ``site-packages`` on your Python where PySide6 is installed. The
+ plugin name corresponds to their folder name. This field can be confused with the ``plugins``
+ option under :ref:`qt <qt_key>` key. In the future, they will be merged into one single option.
+
+.. _buildozer_key:
+
+**buildozer**
+ * ``mode``: Specifies one of the two modes - `release` and `debug`, to run `buildozer`_. The
+ `release` mode creates an *aab* while the `debug` mode creates an apk. The default mode is
+ `debug`.
+ * ``recipe_dir``: Specifies the path to the directory containing `python-for-android`_ recipes.
+ This option is automatically computed by ``pyside6-android-deploy`` during deployment. Without
+ the :ref:`--keep-deployment-files <keep_deployment_files>` option of ``pyside6-android-deploy``,
+ the `recipe_dir` will point to a temporary directory that is deleted after the final Android
+ application package is created.
+ * ``jars_dir``: Specifies the path to the Qt Android `.jar` files that are relevant for
+ creating the Android application package. This option is automatically computed by
+ ``pyside6-android-deploy`` during deployment. Just like ``recipe_dir``, this field is also
+ *not relevant* unless used with the :ref:`--keep-deployment-files <keep_deployment_files>`
+ option of ``pyside6-android-deploy``.
+ * ``ndk_path``: Specifies the path to the Android NDK used for packaging the application.
+ * ``sdk_path``: Specifies the path to the Android SDK used for packaging the application.
+ * ``local_libs``: Specifies non-Qt plugins or other libraries compatible with the Android target
+ to be loaded by the Android runtime on startup.
+ * ``sdk_path``: Specifies the path to the Android SDK used for packaging the application.
+ * ``arch``: Specifies the target architecture's instruction set. This option take one of the four
+ values - *aarch64, armv7a, i686, x86_64*.
+
+Command Line Options
+====================
+
+Here are all the command line options of ``pyside6-android-deploy``:
+
+* **-c/--config-file**: This option is used to specify the path to ``pysidedeploy.spec`` explicitly.
+
+* **--init**: Used to only create the ``pysidedeploy.spec`` file.
+ Usage::
+
+ pyside6-android-deploy --init
+
+* **-v/--verbose**: Runs ``pyside6-android-deploy`` in verbose mode.
+
+* **--dry-run**: Displays the commands being run to produce the Android application package.
+
+.. _keep_deployment_files:
+
+* **--keep-deployment-files**: When this option is added, it retains the build folders created by
+ `buildozer`_ during the deployment process. This includes the folder storing the
+ `python-for-android`_ recipes, relevant `.jar` files and even the Android Gradle project for the
+ application.
+
+* **-f/--force**: When this option is used, it assumes ``yes`` to all prompts and runs
+ ``pyside6-android-deploy`` non-interactively. ``pyside6-android-deploy`` prompts the user to
+ create a Python virtual environment, if not already in one. With this option, the current Python
+ environment is used irrespective of whether the current Python environment is a virtual
+ environment or not.
+
+* **--name**: Application name.
+
+* **--wheel-pyside**: Path to the PySide6 Android wheel for a specific target architecture.
+
+* **--wheel-shiboken**: Path to the Shiboken6 Android wheel for a specific target architecture.
+
+* **--ndk-path**: Path to the Android NDK used for packaging the application.
+
+* **--sdk-path**: Path to the Android SDK used for packaging the application.
+
+* **--extra-ignore-dirs**: Comma-separated directory names inside the project directory. These
+ directories will be skipped when searching for Python files relevant to the project.
+
+* **--extra-modules**: Comma-separated list of Qt modules to be added to the application,
+ in case they are not found automatically. The module name can either be specified
+ by omitting the prefix of Qt or including it eg: both Network and QtNetwork works.
+
+.. _cross_compile_android:
+
+Cross-compile Qt for Python wheels for Android
+==============================================
+
+The cross-compilation of Qt for Python wheel for a specific Android target architecture needs to be
+done only once per Qt version, irrespective of the number of applications you are deploying.
+Currently, cross-compiling Qt for Python wheels only works with a Linux host. Follow these steps
+to cross-compile Qt for Python Android wheels.
+
+#. `Download <qt_download>`_ and install Qt version for which you would like to create Qt for Python
+ wheels.
+
+#. Cloning the Qt for Python repository::
+
+ git clone https://code.qt.io/pyside/pyside-setup
+
+#. Check out the version that you want to build, for example 6.7. The version checked out has
+ to correspond to the Qt version downloaded in Step 1::
+
+ cd pyside-setup && git checkout 6.7
+
+#. Installing the dependencies::
+
+ pip install -r requirements.txt
+ pip install -r tools/cross_compile_android/requirements.txt
+
+#. Run the cross-compilation Python script.::
+
+ python tools/cross_compile_android/main.py --plat-name=aarch64 --qt-install-path=/opt/Qt/6.7.0
+ --auto-accept-license --skip-update
+
+ *--qt-install-path* refers to the path where Qt 6.7.0 is installed. *--auto-accept-license* and
+ *--skip-update* are required for downloading and installing Android NDK and SDK if not already
+ specified through command line options or if they don't already exist in the
+ ``pyside6-android-deploy`` cache. Use --help to see all the other available options::
+
+ python tools/cross_compile_android/main.py --help
+
+.. _`buildozer`: https://buildozer.readthedocs.io/en/latest/
+.. _`python-for-android`: https://python-for-android.readthedocs.io/en/latest/
+.. _`qt_download`: https://www.qt.io/download
+.. _`cpython`: https://pypi.org/project/Cython/
diff --git a/sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst b/sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst
new file mode 100644
index 000000000..980fe2dd1
--- /dev/null
+++ b/sources/pyside6/doc/deployment/deployment-pyside6-deploy.rst
@@ -0,0 +1,217 @@
+.. _pyside6-deploy:
+
+pyside6-deploy: the deployment tool for Qt for Python
+#####################################################
+
+``pyside6-deploy`` is an easy to use tool for deploying PySide6 applications to different
+platforms. It is a wrapper around `Nuitka <https://nuitka.net/>`_, a Python compiler that
+compiles your Python code to C code, and links with libpython to produce the final executable.
+
+The final executable produced has a ``.exe`` suffix on Windows, ``.bin`` on Linux and ``.app`` on
+macOS.
+
+.. note:: Although using a virtual environment for Python is recommended for ``pyside6-deploy``, do
+ not add the virtual environment to the application directory you are trying to deploy.
+ ``pyside6-deploy`` will try to package this venv folder and will eventually fail.
+
+.. _how_pysidedeploy:
+
+How to use it?
+==============
+
+There are 2 different ways with which you can deploy your PySide6 application using
+``pyside6-deploy``:
+
+Approach 1: Using the main python entry point file
+--------------------------------------------------
+
+In this approach, you point ``pyside6-deploy`` to the file containing the main Python entry point
+file of the project i.e. the file containing ``if __name__ == "__main__":``.
+The command looks like this::
+
+ pyside6-deploy /path/to/main_file.py
+
+On running the command, ``pyside6-deploy`` installs all the dependencies required for deployment
+into the Python environment.
+
+If your main Python entry point file is named ``main.py``, then you don't have to point it to the
+filename. You can run ``pyside6-deploy`` without any options, and it will work.
+
+.. note:: If your project contains a ``pysidedeploy.spec`` file, which is generated on the first
+ run of ``pyside6-deploy`` on the project directory, then for any subsequent runs of
+ ``pyside6-deploy`` you can run ``pyside6-deploy`` without specifying the main Python entry
+ point file. It would take the path to the main file from the ``pysidedeploy.spec`` file.
+ To know more about what deployment parameters are controlled by ``pysidedeploy.spec`` file,
+ read `pysidedeploy`_.
+
+.. _approach_two:
+
+Approach 2: Using pysidedeploy.spec config file
+------------------------------------------------
+
+When you run ``pyside6-deploy`` for the first time, it creates a file called ``pysidedeploy.spec``
+in the project directory. This file controls various :ref:`parameters <pysidedeploy>` that influence
+the deployment process. Any subsequent runs of ``pyside6-deploy`` on the project directory, would
+not require additional parameters like the main Python entry point file. You can also point
+``pyside6-deploy`` to the path of the ``pysidedeploy.spec`` file (in case it is not in the same
+directory), to take the parameters from that file. This can be done with the following command::
+
+ pyside6-deploy -c /path/to/pysidedeploy.spec
+
+.. _pysidedeploy:
+
+pysidedeploy.spec
+=================
+
+As mentioned in the `Approach 2 <approach_two>`_ above, you can use this file to control the various
+parameters of the deployment process. The file has multiple sections, with each section containing
+multiple keys (parameters being controlled) assigned to a value. The advantages of such a file are
+two folds:
+
+.. _pysidedeployspec_advantages:
+
+#. Using the command line, you can control the deployment parameters without specifying them each
+ time. It is saved permanently in a file, and any subsequent runs much later in time
+ would enable the user to be aware of their last deployment parameters.
+
+#. Since these parameters are saved into a file, they can be checked into version control. This
+ gives the user more control of the deployment process. For example, when you decide to exclude
+ more QML plugins, or want to include more Nuitka options into your executable.
+
+This file is also used by the ``pyside6-android-deploy`` tool as a configuration file. The advantage
+here is that you can have one single file to control deployment to all platforms.
+
+The relevant parameters for ``pyside6-deploy`` are:
+
+**app**
+ * ``title``: The name of the application
+ * ``project_dir``: Project directory. The general assumption made is that the project directory
+ is the parent directory of the main Python entry point file
+ * ``input_file``: Path to the main Python entry point file
+ * ``project_file``: If it exists, this points to the path to the `Qt Creator Python Project File
+ .pyproject <https://doc.qt.io/qtforpython-6/faq/typesoffiles.html
+ #qt-creator-python-project-file-pyproject>`_ file. Such a file makes sure that the deployment
+ process never considers unnecessary files when bundling the executable.
+ * ``exec_directory``: The directory where the final executable is generated.
+ * ``icon``: The icon used for the application. For Windows, the icon image should be of ``.ico``
+ format, for macOS it should be of ``.icns`` format, and for linux all standard image formats
+ are accepted.
+
+**python**
+ * ``python_path``: Path to the Python executable. It is recommended to run the deployment
+ process inside a virtual environment as certain python packages will be installed onto the
+ Python environment.
+ * ``packages``: The Python packages installed into the Python environment for deployment to
+ work. By default, the Python packages `nuitka <https://pypi.org/project/Nuitka/>`__,
+ `ordered_set <https://pypi.org/project/ordered-set/>`_ and `zstandard
+ <https://pypi.org/project/zstandard/>`_ are installed. If the deployment platform is
+ Linux-based, then `patchelf <https://pypi.org/project/patchelf/>`_ is also installed
+
+**qt**
+ * ``qml_files``: Comma-separated paths to all the QML files bundled with the executable
+ * ``excluded_qml_plugins``: The problem with using Nuitka for QML deployment is that all the QML
+ plugins are also bundled with the executable. When the plugins are bundled, the binaries of
+ the plugin's Qt module are also packaged. For example, size heavy module like QtWebEngine
+ also gets added to your executable, even when you do not use it in your code. The
+ ``excluded_qml_plugins`` parameter helps you to explicitly specify which all QML plugins are
+ excluded. ``pyside6-deploy`` automatically checks the QML files against the various QML
+ plugins and excludes the following Qt modules if they don't exist::
+
+ QtQuick, QtQuick3D, QtCharts, QtWebEngine, QtTest, QtSensors
+
+ The reason why only the presence of the above 6 Qt modules is searched for is because they
+ have the most size heavy binaries among all the Qt modules. With this, you can drastically
+ reduce the size of your executables.
+ * ``modules``: Comma-separated list of all the Qt modules used by the application. Just like the
+ other configuration options in `pysidedeploy.spec`, this option is also computed automatically
+ by ``pyside6-deploy``. However, if the user wants to explicitly include certain Qt modules, the
+ module names can be appended to this list without the `Qt` prefix.
+ e.g. Network instead of QtNetwork
+ * ``plugins``: Comma-separated list of all the Qt plugins used by the application. Just like the
+ other configuration options in `pysidedeploy.spec`, this option is also computed automatically
+ by ``pyside6-deploy``. However, if the user wants to explicitly include certain Qt plugins,
+ the plugin names can be appended to this list. To see all the plugins bundled with PySide6,
+ see the `plugins` folder in the `site-packages` on your Python where PySide6 is installed. The
+ plugin name correspond to their folder name.
+
+**nuitka**
+ * ``macos.permissions``: Only relevant for macOS. This option lists the permissions used by the
+ macOS application, as found in the ``Info.plist`` file of the macOS application bundle, using
+ the so-called UsageDescription strings. The permissions are normally automatically found by
+ ``pyside6-deploy``. However the user can also explicitly specify them using the format
+ `<UsageDescriptionKey>:<Short Description>`. For example, the Camera permission is specified
+ as::
+
+ NSCameraUsageDescription:CameraAccess
+
+ * ``extra_args``: Any extra Nuitka arguments specified. It is specified as space-separated
+ command line arguments i.e. just like how you would specify it when you use Nuitka through
+ the command line. By default, it contains the following arguments::
+
+ --quiet --noinclude-qt-translations=True
+
+Command Line Options
+====================
+
+The most important command line options are the path to the main Python entry point file and the
+``pysidedeploy.spec`` file. If neither of these files exists or their command line options are
+given, then ``pyside6-deploy`` assumes that your current working directory does not contain a
+PySide6 project.
+
+Here are all the command line options of ``pyside6-deploy``:
+
+* **main entry point file**: This option does not have a name or a flag and is not restricted by it.
+ This enables ``pyside6-deploy`` to be used like::
+
+ pyside6-deploy /path/to/main_file.py
+
+* **-c/--config-file**: This option is used to specify the path to ``pysidedeploy.spec`` explicitly
+
+* **--init**: Used to only create the ``pysidedeploy.spec`` file
+ Usage::
+
+ pyside6-deploy /path/to/main --init
+
+
+* **-v/--verbose**: Runs ``pyside6-deploy`` in verbose mode.
+
+* **--dry-run**: Displays the final Nuitka command being run.
+
+* **--keep-deployment-files**: When this option is added, it retains the build folders created by
+ Nuitka during the deployment process.
+
+* **-f/--force**: When this option is used, it forces through all the input prompts.
+ ``pyside6-deploy`` prompts the user to create a Python virtual environment, if not already in one.
+ With this option, the current Python environment is used irrespective of whether the current
+ Python environment is a virtual environment or not.
+
+* **--name**: Application name.
+
+* **--extra-ignore-dirs**: Comma-separated directory names inside the project directory. These
+ directories will be skipped when searching for Python files relevant to the project.
+
+* **--extra-modules**: Comma-separated list of Qt modules to be added to the application,
+ in case they are not found automatically. The module name can either be specified
+ by omitting the prefix of Qt or including it eg: both Network and QtNetwork works.
+
+Considerations
+===============
+
+For deployment to work efficiently by bundling only the necessary plugins, the following utilities
+are required to be installed on the system:
+
+.. list-table::
+ :header-rows: 1
+
+ * - OS
+ - Dependencies
+ - Installation
+ * - Windows
+ - dumpbin
+ - Shipped with MSVC. Run `vcvarsall.bat` to add it to PATH
+ * - Linux
+ - readelf
+ - Available by default
+ * - macOS
+ - dyld_info
+ - Available by default from macOS 12 and upwards
diff --git a/sources/pyside6/doc/deployment.rst b/sources/pyside6/doc/deployment/index.rst
index 69b4b7d96..36e677566 100644
--- a/sources/pyside6/doc/deployment.rst
+++ b/sources/pyside6/doc/deployment/index.rst
@@ -1,7 +1,7 @@
.. _deployment-guides:
-|project| Deployment
-====================
+Deployment
+==========
Deploying or freezing an application is an important part of a Python project,
this means to bundle all required resources so that the application finds everything it needs to
@@ -15,13 +15,18 @@ Here are a few distribution options that you can use:
3. Freeze the application into a single binary file or directory.
4. Provide native installer (msi, dmg)
-If you choose Option 3, consider using one of these tools:
- * `fbs`_
- * `PyInstaller`_
- * `cx_Freeze`_
- * `py2exe`_
- * `py2app`_
- * `briefcase`_
+If you are considering Option 3, then starting with 6.4, we ship a new tool called `pyside6-deploy`
+that deploys your PySide6 application to all desktop platforms - Windows, Linux, and macOS. To know
+more about how to use the tool see :ref:`pyside6-deploy`. For Android deployment, see
+:ref:`pyside6-android-deploy`. Additionally, you can also use other popular deployment tools shown
+below:
+
+* `fbs`_
+* `PyInstaller`_
+* `cx_Freeze`_
+* `py2exe`_
+* `py2app`_
+* `briefcase`_
.. _fbs: https://build-system.fman.io/
.. _PyInstaller: https://www.pyinstaller.org/
@@ -30,8 +35,10 @@ If you choose Option 3, consider using one of these tools:
.. _py2app: https://py2app.readthedocs.io/en/latest/
.. _briefcase: https://briefcase.readthedocs.io
-Since |project| is a cross-platform framework, we focus on solutions for the three major
-platforms that Qt supports: Windows, Linux, and macOS.
+Although you can deploy PySide6 application using these tools, it is recommended to use
+`pyside6-deploy` as it is easier to use and also to get the most optimized executable. Since
+|project| is a cross-platform framework, we focus on solutions for the three major platforms that
+Qt supports: Windows, Linux, and macOS.
The following table summarizes the platform support for those packaging tools:
@@ -138,6 +145,8 @@ Here's a set of tutorials on how to use these tools:
:name: mastertoc
:maxdepth: 2
+ deployment-pyside6-deploy.rst
+ deployment-pyside6-android-deploy.rst
deployment-fbs.rst
deployment-pyinstaller.rst
deployment-cxfreeze.rst
diff --git a/sources/pyside6/doc/developer/adapt_qt.rst b/sources/pyside6/doc/developer/adapt_qt.rst
new file mode 100644
index 000000000..aec81fb0f
--- /dev/null
+++ b/sources/pyside6/doc/developer/adapt_qt.rst
@@ -0,0 +1,54 @@
+.. _developer-adapt-qt:
+
+Adapt to new Qt versions
+========================
+
+Adapting to source changes
+--------------------------
+
+The dev branch of PySide is switched to a new Qt minor version
+after its API review is finished and the API is stable.
+
+Until that happens, a patch should be continuously developed
+to adapt to this version.
+
+The `new classes page <https://doc-snapshots.qt.io/qt6-6.7/newclasses67.html>`_
+is a good source of information for new API.
+
+New classes and should be added to the type system file (using
+a ``since`` attribute) and ``CMakeList.txt`` file of the respective module.
+
+Should the class not be available on all platforms, the respective
+``QT_CONFIG`` macro needs to be specified in the type system file and
+feature checks need to be added to ``CMakeList.txt`` (see for example
+``QPermission``).
+
+The process consists of running a build and evaluating the log file.
+The script
+`shiboken2tasks.py <https://code.qt.io/cgit/qt-creator/qt-creator.git/tree/scripts/shiboken2tasks.py>`_
+from the *Qt Creator* repository can be used to convert the shiboken warnings
+into a `task file <https://doc.qt.io/qtcreator/creator-task-lists.html>`_
+for display in the build issues pane of *Qt Creator*.
+
+Warnings about new enumerations will be shown there; they should be added
+to type system file using a ``since`` attribute.
+
+Warnings about not finding a function signature for modification
+also need to be handled; mostly this is a sign of a function parameter
+being changed from ``int`` to ``qsizetype`` or similar.
+
+If the build succeeds, a test run should be done.
+
+The Qt source code should be checked for new overloads
+(indicated by ``QT6_DECL_NEW_OVERLOAD_TAIL`` starting from 6.7).
+The resolution needs to be decided for each individual case,
+mostly by removing old functions and using ``<declare-function>``
+to declare new API.
+
+Bumping the version
+-------------------
+
+To instruct ``COIN`` to use the next version of Qt, adapt the files
+``coin/dependencies.yaml`` and/or ``product_dependencies.yaml`` accordingly.
+Next, the wheel names should be changed by adapting
+``sources/shiboken6/.cmake.conf`` and ``sources/pyside6/.cmake.conf``.
diff --git a/sources/pyside6/doc/developer/add_module.rst b/sources/pyside6/doc/developer/add_module.rst
new file mode 100644
index 000000000..2eb962207
--- /dev/null
+++ b/sources/pyside6/doc/developer/add_module.rst
@@ -0,0 +1,61 @@
+.. _developer-add-module:
+
+Add a new module
+================
+
+New modules can be added for many reasons, the most important
+one is when Qt enables or includes a new one for a new release.
+
+Adding the bindings, and documentation are the essentials
+to include new modules, but adding tests and examples is ideal.
+
+Add bindings
+------------
+
+- Find the correct name (look at the include path of Qt).
+- Add the module to the ``coin/dependencies.yaml`` file.
+- Add it to ``sources/pyside6/cmake/PySideHelpers.cmake``.
+- Add it to ``build_scripts/wheel_files.py`` (plugins, translations).
+- Copy an existing module to ``sources/pyside6/PySide6/<name>``.
+- Adapt the ``typesystem.xml`` and ``CMakeList.txt`` (using for example
+ *Qt Creator*'s case-preserving replace function).
+- Make sure the dependencies are correct.
+- Find the exported public classes, add them to the ``typesystem.xml`` file,
+ checking whether they are ``value-type`` or ``object-type``. Add their enums
+ and flags.
+- Add the wrapper files to ``CMakeList.txt``.
+- Create a test dir under ``sources/pyside6/tests`` with an empty
+ ``CMakeList.txt``.
+- Try to build with the module added to the ``--module-subset`` option of
+ ``setup.py``.
+- Watch out for shiboken warnings in the log.
+- Be aware that ``ninja`` mixes stdout and stderr, so, the first warning is
+ typically hidden behind a progress message.
+- A convenient way of doing this is using
+ ``qt-creator/scripts/shiboken2tasks.py`` from the
+ `*Qt Creator* repository <https://code.qt.io/cgit/qt-creator/qt-creator.git>`_
+ converting them to a ``.tasks`` file which can be loaded into *Qt Creator*'s
+ issue pane.
+- Link errors may manifest when ``generate_pyi`` imports the module trying
+ to create signatures. They indicate a missing source file entry
+ or a bug in the module itself.
+
+.. note:: For the build to succeed, the module must follow the Qt convention
+ of using ``#include <QtModule/header.h>`` since module include paths
+ are not passed in PySide.
+
+Distribution
+------------
+
+- Determine to which wheel the module belongs according to
+ `Qt Modules <https://doc.qt.io/qt-6/qtmodules.html>`_.
+- Add the module to ``build_scripts/wheel_files.py`` for use by
+ ``create_wheels.py``.
+- Add the module to one of the ``README.pyside6_*.md`` files.
+
+Add documentation
+-----------------
+
+- Add entry to ``sources/pyside6/doc/modules.rst``.
+- Add a .qdocconf.in file in ``sources/pyside6/doc/qtmodules``.
+- Add module description ``.rst`` file in ``sources/pyside6/doc/extras``.
diff --git a/sources/pyside6/doc/developer/add_port_example.rst b/sources/pyside6/doc/developer/add_port_example.rst
new file mode 100644
index 000000000..b99641f45
--- /dev/null
+++ b/sources/pyside6/doc/developer/add_port_example.rst
@@ -0,0 +1,67 @@
+.. _developer-add-port-example:
+
+Add a new example or port one
+=============================
+
+Adding examples is a good exercise for people wanting to become familiar with
+the modules and its functionality.
+
+You can either design an example from scratch or inspired in another
+application, or simply you can port an existing Qt example that does not have
+a Python counterpart.
+
+Example code should be free of `flake8 <https://pypi.org/project/flake8/>`_
+warnings; this is enforced by a bot. A configuration file is provided
+at the root of the repository. Offending lines can be excluded by a
+``noqa`` directive if there is a good reason to do so.
+
+Keep in mind we do allow 100 columns for line length.
+
+Additionally, please use `isort <https://pypi.org/project/isort/>`_ to keep the
+imports ordered and consistent with other examples.
+
+For example:
+
+.. code-block:: bash
+
+ $ flake8 --config pyside-setup/.flake8 your_file.py
+ $ isort your_file.py
+
+
+
+Add a new example
+-----------------
+
+- Check if the topic your example covers is not in an existing example already.
+- Create a new directory inside the ``examples/<module>`` you think
+ is more relevant.
+- Inside, place the code of the example, and also a ``.pyproject``
+ file listing the files the example needs.
+- If you want the example to be automatically displayed on the
+ example gallery, include a ``doc`` directory that contains a ``rst``
+ file and a screenshot. Check other examples for formatting questions.
+- When writing the ``rst`` file, you can include code snippets using
+ the ``literalinclude`` directive specifying the relative path
+ as listed in the ``.pyproject`` file. The `example_gallery` tool will
+ expand this (see the `pointconfiguration` example).
+- For the code displayed in the tabs, you can create ``rstinc`` files
+ in the ``doc`` directory containing some description explaining them
+ (see the `samplebinding` example).
+
+Port a Qt example
+-----------------
+
+- Quickly check the C++ example, fix outdated code.
+- Port the sources using ``tools/tools/qtcpp2py.py`` (front-end for
+ ``snippets-translate``).
+- Note that our examples need to have unique names due to the doc build.
+- Verify that all slots are decorated using ``@Slot``.
+- Add a ``.pyproject`` file (verify later on that docs build).
+- Add a ``doc`` directory and descriptive ``.rst`` file,
+ and a screenshot if suitable (use ``optipng`` to reduce file size).
+- Add the ``"""Port of the ... example from Qt 6"""`` doc string.
+- Try to port variable and function names to snake case convention.
+- Remove C++ documentation from ``sources/pyside6/doc/additionaldocs.lst``.
+
+.. note:: Example screenshots in ``.png`` should be optimized by
+ running ``optipng -o 7 -strip all``. Alternatively, the ``.webp`` format can be used.
diff --git a/sources/pyside6/doc/developer/add_tool.rst b/sources/pyside6/doc/developer/add_tool.rst
new file mode 100644
index 000000000..732e6b915
--- /dev/null
+++ b/sources/pyside6/doc/developer/add_tool.rst
@@ -0,0 +1,51 @@
+.. _developer-add-tool:
+
+Add a new tool or a Qt tool wrapper
+===================================
+
+Tooling is essential to |project|, for that reason you can find many ad-hoc
+tools in the repository, which include wrappers of Qt tools or newly developed
+tools to solve issues, or improve some project workflows.
+
+Add a new tool
+--------------
+
+Tools not available to end users
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This depicts the tools that are not shipped with Qt for Python wheels and are used to aid
+Qt for Python development
+
+- Place your tool in the ``tools`` directory.
+- If your project has more than one file, create a directory.
+- Create a ``.pyproject`` file including all the relevant files
+ for your tool.
+
+Tools available to end users
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+- Place your tool in the ``sources/pyside-tools`` directory.
+- If your project has more than one file, create a directory.
+- Create a ``.pyproject`` file including all the relevant files
+ for your tool.
+- Add the relevant files in ``sources/pyside-tools/CMakeLists.txt``.
+- Add the tool in ``sources/pyside-tools/pyside_tool.py``.
+- Add the tool in ``build_scripts/__init__.py`` to create the setuptools entry points
+ i.e. this enable using the tool from the console as "pyside6-<tool_name>"
+- Add an entry to ``sources/pyside6/doc/gettingstarted/package_details.rst``.
+- Include the necessary Qt binaries explicitly on ``build_scripts/wheel_files.py``
+- Build with ``--standalone``, verify it is working.
+
+
+Add a Qt tool wrapper
+---------------------
+
+- Add the relevant files in ``sources/pyside-tools/CMakeLists.txt``.
+- Add the tool in ``sources/pyside-tools/pyside_tool.py``.
+- Add the tool in ``build_scripts/__init__.py`` to create the setuptools entry points
+ i.e. this enable using the tool from the console as "pyside6-<tool_name>"
+- Add an entry to ``sources/pyside6/doc/tools/index.rst`` and the detailed
+ documentation to ``sources/pyside6/doc/tools/<tool_name>.rst``.
+- Include the necessary Qt binaries explicitly on ``build_scripts/wheel_files.py``
+- Add the necessary files to ``build_scripts/wheel_files.py``.
+- Build with ``--standalone``, verify it is working. Also, check if the wheel bundles the tool.
diff --git a/sources/pyside6/doc/developer/documentation.rst b/sources/pyside6/doc/developer/documentation.rst
new file mode 100644
index 000000000..517bd46f1
--- /dev/null
+++ b/sources/pyside6/doc/developer/documentation.rst
@@ -0,0 +1,73 @@
+.. _developer-documentation:
+
+Fixing Documentation issues
+===========================
+
+Fixing texts
+------------
+
+Shiboken's ``<inject-documentation>`` element can be used to add texts.
+It's ``"replace"`` mode is currently not implemented, though.
+
+Fixing snippets
+---------------
+
+Snippets can replaced by placing a Python equivalent under ``sources/pyside6/doc/snippets``.
+The directory structure matches that of Qt. To replace a snippet with the id `0` in
+``qtbase/examples/foo/snippet.cpp``, place a file ``qtbase/examples/foo/snippet_0.cpp.py``
+under that directory (one snippet per file with the snippet id appended to the base name).
+
+More complicated mappings can be added to ``tools/snippets_translate/override.py``.
+
+# Recreating the module descriptions after a Qt major version change
+
+The source tree contains .rst files containing the module description in
+doc/extras (named for example "QtCore.rst"). They are extracted/adapted from
+the C++ module descriptions. If there is no module description file, shiboken
+will extract the module description from the webxml files generated by qdoc.
+This ends up in the build directory under doc/rst/PySide6/&lt;module&gt;/index.rst.
+It can be used as a starting point for a module description file. C++
+specific information like build instructions should be removed.
+
+The descriptions may link to tutorials which can be added to additionaldocs.lst
+for webxml extraction.
+
+Maintaining additionaldocs.lst
+------------------------------
+
+The file is a list of additional documentation files. These are basically Qt
+tutorials referenced by the documentation. They will receive some Python
+adaption by shiboken/sphinx.
+
+The list can be created by the below script and some hand-editing. It will find
+almost all documents. Quite a number of them might be unreferenced, but there
+is no good way of filtering for this.
+Pages of examples that exist in Python should be removed.
+
+.. code-block:: bash
+
+ for F in *.webxml
+ do
+ echo "$F" | egrep '(-index)|(-module)|(-qmlmodule)\.webxml$' > /dev/null
+ if [ $? -ne 0 ]
+ then
+ if fgrep '<para>' "$F" > /dev/null # Exclude reference only
+ then
+ egrep "(<class )|(<namespace )" $F > /dev/null || echo $F
+ fi
+ fi
+ done
+
+Inheritance graphs
+------------------
+
+``inheritance_diagram.pyproject`` lists the script involved in inheritance
+graph generation, ``inheritance_diagram.py`` being the main one used by sphinx.
+The others have main-test drivers for checking.
+
+There are 2 scripts used for determining the inheritance:
+* ``json_inheritance.py`` (env var ``INHERITANCE_FILE``) reads a
+ inheritance.json file containing the class hierarchy generated by
+ shiboken's doc generator.
+
+* ``import_inheritance.py`` actually tries to import the class (legacy)
diff --git a/sources/pyside6/doc/developer/enumfeatures_doc.rst b/sources/pyside6/doc/developer/enumfeatures_doc.rst
new file mode 100644
index 000000000..91b7b6346
--- /dev/null
+++ b/sources/pyside6/doc/developer/enumfeatures_doc.rst
@@ -0,0 +1,160 @@
+.. _enum-features:
+
+The Set of Enum Features
+========================
+
+The development of the new Python enums took the form of a series of patches.
+While we put a lot of effort into supporting the old Enums (without promoting
+them), it is still possible that someone has a case where they cannot use
+the Python enums as they are now. To avoid people setting the environment
+flag to disable this completely, we implemented a way to select each
+combination of enum functions step by step with a specific set of flags.
+
+
+The Possible Enum Flags
+-----------------------
+
+This is the table of all flags used to control the creation of Python enums.
+
+====================== ===== ======================================================
+Flag Name Value
+====================== ===== ======================================================
+ENOPT_OLD_ENUM 0x00 (False) No longer possible since PySide 6.6
+ENOPT_NEW_ENUM 0x01 (True) The default for PySide 6.4, full implementation
+ENOPT_INHERIT_INT 0x02 Turn all Enum into IntEnum and Flag into IntFlag
+ENOPT_GLOBAL_SHORTCUT 0x04 Re-add shortcuts for global enums
+ENOPT_SCOPED_SHORTCUT 0x08 Re-add shortcuts for scoped enums
+ENOPT_NO_FAKESHORTCUT 0x10 Don't fake rename (forgiveness mode)
+ENOPT_NO_FAKERENAMES 0x20 Don't fake shortcuts (forgiveness mode)
+ENOPT_NO_ZERODEFAULT 0x40 Don't use zero default (forgiveness mode)
+ENOPT_NO_MISSING 0x80 Don't allow missing values in Enum
+====================== ===== ======================================================
+
+Such a set of flags can be defined either by the environment variable
+``PYSIDE6_OPTION_PYTHON_ENUM`` or set by the Python variable
+``sys.pyside6_option_python_enum`` before PySide6 is imported.
+The environment variable also supports arbitrary integer expressions
+by using ``ast.literal_eval``.
+
+
+ENOPT_OLD_ENUM (0x00)
+~~~~~~~~~~~~~~~~~~~~~
+
+This option completely disables the new enum implementation.
+Even though this is a valid option, we want to avoid it if possible.
+The goal is to eventually remove the old implementation. To make this
+possible, we have made the individual features of the enum implementation
+accessible as flags. This way, if users report problems, we may be able
+to provide a temporary solution before extending enum support accordingly.
+
+
+ENOPT_NEW_ENUM (0x01)
+~~~~~~~~~~~~~~~~~~~~~
+
+In a perfect world, no one would choose anything other than this default
+setting. Unfortunately, reality is not always like that. That is why
+there are the following flags.
+
+
+The most likely flags needed
+----------------------------
+
+If there are errors, they are likely to be the following: Either implicit
+assumptions are there that require IntEnum, or global enums are used that
+unfortunately cannot be replaced with tricks.
+
+
+ENOPT_INHERIT_INT (0x02)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+When this flag is set, all ``enum.Enum/enum.Flag`` classes are converted to
+``enum.IntEnum/enum.IntFlag``. This solves the most likely compatibility
+problem when switching to Python enums. The old Shiboken enums always
+inherit from int, but most Python enums do not.
+
+It was a decision of Python developers not to let enums inherit from int by
+default, since no order should be implied. In most cases, inheritance from
+int can be avoided, either by using the value property or better by
+uplifting: instead of using ``AnEnum.AnInstance.value`` in a function that
+expects an int argument, you can also convert the integer to an enumeration
+instance after the call by ``AnEnum(int_arg)`` and use that in comparisons.
+
+However, there are cases where this is not possible, and explicit support in
+PySide is simply not available. In those cases, you can use this flag as a
+workaround until we have implemented alternatives.
+
+
+ENOPT_GLOBAL_SHORTCUT (0x04)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+At the beginning of the Python enum implementation, we continued to support
+the shortcut behavior of Shiboken enums: the enum constants were mirrored
+into the enclosing scope.
+This was later emulated in the course of forgiveness mode. For enum classes
+in a PySide class this works fine, but for enum classes directly on the module
+level there is no good way to implement forgiveness.
+
+It is unlikely that errors are hidden for global enums, because they should
+already produce an error during import. But for cases without access to
+the source code, you can help yourself with this flag.
+
+A flag value of 0x6 is likely to solve the majority of problems.
+
+
+Flags for completeness
+----------------------
+
+The following flags complement the description of Python Enums.
+They essentially serve the better understanding of the
+implementation and make it fully transparent and customizable.
+
+
+ENOPT_SCOPED_SHORTCUT (0x08)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For completeness, we also supported mirroring scoped enums, although this
+has since been replaced by forgiveness mode. If you want to try this,
+please also use the ENOPT_NO_FAKESHORTCUT flag (0x10), otherwise the
+effect of this flag will remain invisible.
+
+
+ENOPT_NO_FAKERENAMES (0x10)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Forgiveness mode emulates renaming ``Enum.Flag`` classes back to Shiboken
+QFlags structures, which have slightly different names.
+So when such a defunct name is used, the system replaces it internally
+with the new ``enum.Flag`` structure. Unless special boundary problems
+are provoked, this replacement should work.
+
+To see the effect of this renaming, you can turn it off with this flag.
+
+
+ENOPT_NO_ZERODEFAULT (0x40)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As part of the forgiveness mode, Python enums can be created by a
+parameterless call, although Python enums actually force a parameter
+when called.
+
+The effect can be examined if this flag is set to disable it.
+
+
+ENOPT_NO_MISSING (0x80)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+There are a few cases where Shiboken enums use missing values. In
+``enum.Flag`` structures, this is allowed anyway because we have set the
+``FlagBoundary.KEEP`` flag (see ``enum.py``).
+
+Normal ``enum.Enum`` structures don't have this provision, but the
+``enum`` module allows to pass a ``_missing_`` function for customization.
+
+Our way of dealing with this situation is to create a new fake
+``enum.Enum`` class with the same name and a nameless instance, and
+pretend with an attribute setting that it has the same type.
+The additional instances created in this way are recorded in a class dict
+``_sbk_missing_`` in order to preserve their identity.
+
+You will see the effect of not defining a ``_missing_`` function if you
+set this flag.
diff --git a/sources/pyside6/doc/developer/extras.rst b/sources/pyside6/doc/developer/extras.rst
new file mode 100644
index 000000000..9788b539d
--- /dev/null
+++ b/sources/pyside6/doc/developer/extras.rst
@@ -0,0 +1,55 @@
+Test a wheel
+============
+
+There is a tool that you can use to test a set of wheels called 'testwheel' but
+it's currently in a different repository (``qt/qtqa``):
+
+- Use ``scripts/packagetesting/testwheel.py`` from the
+ `qtqa repository <https://code.qt.io/cgit/qt/qtqa.git>`_.
+
+To test the wheels:
+
+- Create a virtual environment and activate it.
+- Install the dependencies listed on the ``requirements.txt`` file.
+- Install all the wheels: ``shiboken6``, ``shiboken6-generator``,
+ and ``PySide6-Essentials``.
+- Run the ``testwheel`` tool.
+- Install ``PySide6-Addons`` wheels.
+- Run again the ``testwheel`` tool.
+- In case you have access to commercial wheels, don't forget the
+ ``PySide6-M2M`` as well, and re-run the ``testwheel`` tool.
+
+Build on the command line
+=========================
+
+- Consider using ``build_scripts/qp5_tool.py``.
+
+Build with address sanitizer (Linux)
+====================================
+
+ASAN needs to be told to not exit on memory leaks and its library
+needs to be pre-loaded. Assuming the library is found
+at ``/usr/lib/gcc/x86_64-linux-gnu/11``:
+
+.. code-block:: bash
+
+ export ASAN_OPTIONS=detect_leaks=0
+ export LD_PRELOAD=/usr/lib/gcc/x86_64-linux-gnu/11/libasan.so
+ python setup.py build [...] --sanitize-address
+
+De-Virtualize the Python Files
+==============================
+
+The Python files in the Shiboken module are completely virtual, i.E.
+they are nowhere existent in the file system for security reasons.
+
+For debugging purposes or to change something, it might be desirable
+to move these files into the normal file system, again.
+
+- Setting the environment variable "SBK_EMBED" once to false unpacks these
+ files when PySide6 or shiboken6 are imported. The files are written
+ into "side-packages/shiboken6/files.dir" and are used from then on.
+
+- Setting the variable to true removes "files.dir".
+
+- Without the "SBK_EMBED" variable, the embedding status remains sticky.
diff --git a/sources/pyside6/doc/feature-why.rst b/sources/pyside6/doc/developer/feature-motivation.rst
index a795e640c..1509ea724 100644
--- a/sources/pyside6/doc/feature-why.rst
+++ b/sources/pyside6/doc/developer/feature-motivation.rst
@@ -1,4 +1,4 @@
-.. _features-why:
+.. _feature-why:
Why do we have a __feature__?
=============================
@@ -84,12 +84,11 @@ all methods of all classes used in this module are changing their name.
The algorithm to change names is this:
- * if the name has less than 3 chars, or
- * if two upper chars are adjacent, or
- * if the name starts with ``gl`` (which marks OpenGL),
- * the name is returned unchanged. Otherwise
-
- * a single upper char ``C`` is replaced by ``_c``
+* if the name has less than 3 chars, or
+* if two upper chars are adjacent, or
+* if the name starts with ``gl`` (which marks OpenGL),
+* the name is returned unchanged. Otherwise
+* a single upper char ``C`` is replaced by ``_c``
The true_property feature
@@ -231,8 +230,9 @@ Example:
.. code-block:: python
>>> from PySide6 import *
+ >>> from PySide6.support.signature import get_signature
>>> import pprint
- >>> pprint.pprint(QtCore.QTimer.singleShot.__signature__)
+ >>> pprint.pprint(get_signature(QtCore.QTimer.singleShot))
[<Signature (arg__1: int, arg__2: Callable) -> None>,
<Signature (msec: int, receiver: PySide6.QtCore.QObject, member: bytes) -> None>,
<Signature (msec: int, timerType: PySide6.QtCore.Qt.TimerType,
@@ -284,7 +284,11 @@ a ``QtCore.pyi`` file next to ``QtCore.abi3.so`` or ``QtCore.pyd`` on Windows.
When using ``__feature__`` often with common IDEs, you may want to provide
a feature-aware version of ``.pyi`` files to get a correct display. The simplest
-way to change them all in-place is the command
+way to change them all in-place is the command:
+
+.. code-block:: bash
+
+ pyside6-genpyi all --feature snake_case true_property
Using __feature__ with UIC files
@@ -295,9 +299,5 @@ are _not_ converted, intentionally. Mixing them with feature selections in other
Python modules should always work, because switching will happen as needed, selected
by the currently active module. (Please report to us if this fails for an example)
-.. code-block:: python
-
- pyside6-genpyi all --feature snake_case true_property
-
.. _`Import-Hooks`: https://docs.python.org/3/reference/import.html#import-hooks
diff --git a/sources/pyside6/doc/developer/index.rst b/sources/pyside6/doc/developer/index.rst
new file mode 100644
index 000000000..92c84259d
--- /dev/null
+++ b/sources/pyside6/doc/developer/index.rst
@@ -0,0 +1,35 @@
+.. _developer-notes:
+
+Developer Notes
+===============
+
+Developing |project| requires people to understand different processes
+and steps that need to be taken into account when dealing with topics
+related to modules, bindings, examples, and more.
+
+Development Topics
+------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ add_module.rst
+ add_port_example.rst
+ add_tool.rst
+ documentation.rst
+ adapt_qt.rst
+ extras.rst
+
+Implementation details
+----------------------
+
+Complementary, here you can find the reasoning and motivation for the
+many features and implementation details that the project has:
+
+.. toctree::
+ :maxdepth: 2
+
+ enumfeatures_doc.rst
+ limited_api.rst
+ signature_doc.rst
+ feature-motivation.rst
diff --git a/sources/pyside6/doc/developer/limited_api.rst b/sources/pyside6/doc/developer/limited_api.rst
new file mode 100644
index 000000000..44d3faad2
--- /dev/null
+++ b/sources/pyside6/doc/developer/limited_api.rst
@@ -0,0 +1,703 @@
+The Transition To The Limited Python API (PEP384)
+=================================================
+
+
+Foreword
+--------
+
+Python supports a limited API that restricts access to certain structures.
+Besides eliminating whole modules and all functions and macros which names
+start with an
+underscore, the most drastic restriction is the removal of normal type object
+declarations.
+
+For details about the eliminated modules and functions, please see the
+`PEP 384`_ page for reference.
+
+
+.. _`PEP 384`: https://www.python.org/dev/peps/pep-0384/
+
+
+
+Changed Modules
+---------------
+
+All changed module's include files are listed with the changed functions here.
+As a general rule, it was tried to keep the changes to a minimum diff.
+Macros which are not available were changed to functions with the same name
+if possible. Completely removed names ``Py{name}`` were re-implemented as ``Pep{name}``.
+
+
+memoryobject.h
+~~~~~~~~~~~~~~
+
+The buffer protocol was completely removed. We redefined all the structures
+and methods, because PySide uses that. This is an exception to the limited API
+that we have to check ourselves. The code is extracted in bufferprocs_py37.h .
+This is related to the following:
+
+
+abstract.h
+~~~~~~~~~~
+
+This belongs to the buffer protocol like memoryobject.h .
+As replacement for ``Py_buffer`` we defined ``Pep_buffer`` and several other
+internal macros.
+
+The version is checked by hand, and the version number must be updated only
+if the implementation does not change. Otherwise, we need to write version
+dependent code paths.
+
+It is questionable if it is worthwhile to continue using the buffer protocol
+or if we should try to get rid of ``Pep_buffer``, completely.
+
+
+pydebug.h
+~~~~~~~~~
+
+We have no direct access to ``Py_VerboseFlag`` because debugging is not
+supported. We redefined it as macro ``Py_VerboseFlag`` which calls ``Pep_VerboseFlag``.
+
+
+unicodeobject.h
+~~~~~~~~~~~~~~~
+
+The macro ``PyUnicode_GET_SIZE`` was removed and replaced by ``PepUnicode_GetLength``
+which evaluates to ``PyUnicode_GetSize`` for Python 2 and ``PyUnicode_GetLength`` for Python 3.
+Since Python 3.3, ``PyUnicode_GetSize`` would have the bad side effect of requiring the GIL!
+
+Function ``_PyUnicode_AsString`` is unavailable and was replaced by a macro
+that calls ``_PepUnicode_AsString``. The implementation was a bit involved,
+and it would be better to change the code and replace this function.
+
+
+bytesobject.h
+~~~~~~~~~~~~~
+
+The macros ``PyBytes_AS_STRING`` and ``PyBytes_GET_SIZE`` were redefined to call
+the according functions.
+
+
+floatobject.h
+~~~~~~~~~~~~~
+
+``PyFloat_AS_DOUBLE`` now calls ``PyFloat_AsDouble``.
+
+
+tupleobject.h
+~~~~~~~~~~~~~
+
+``PyTuple_GET_ITEM``, ``PyTuple_SET_ITEM`` and ``PyTuple_GET_SIZE`` were redefined as
+function calls.
+
+
+listobject.h
+~~~~~~~~~~~~
+
+``PyList_GET_ITEM``, ``PyList_SET_ITEM`` and ``PyList_GET_SIZE`` were redefined as
+function calls.
+
+
+dictobject.h
+~~~~~~~~~~~~
+
+``PyDict_GetItem`` also exists in a ``PyDict_GetItemWithError`` version that does
+not suppress errors. This suppression has the side effect of touching global
+structures. This function exists in Python 2 only since Python 2.7.12 and has
+a different name. We simply implemented the function.
+Needed to avoid the GIL when accessing dictionaries.
+
+
+methodobject.h
+~~~~~~~~~~~~~~
+
+``PyCFunction_GET_FUNCTION``, ``PyCFunction_GET_SELF`` and ``PyCFunction_GET_FLAGS``
+were redefined as function calls.
+
+Direct access to the methoddef structure is not available, and we defined
+``PepCFunction_GET_NAMESTR`` as accessor for name strings.
+
+
+pythonrun.h
+~~~~~~~~~~~
+
+The simple function ``PyRun_String`` is not available. It was re-implemented
+in a simplified version for the signature module.
+
+
+funcobject.h
+~~~~~~~~~~~~
+
+The definitions of funcobject.h are completely missing, although there
+are extra ``#ifdef`` conditional defines inside, too. This suggests that the exclusion
+was unintended.
+
+We therefore redefined ``PyFunctionObject`` as an opaque type.
+
+The missing macro ``PyFunction_Check`` was defined, and the macro
+``PyFunction_GET_CODE`` calls the according function.
+
+There is no equivalent for function name access, therefore we introduced
+``PepFunction_GetName`` either as a function or as a macro.
+
+*TODO: We should fix funcobject.h*
+
+
+classobject.h
+~~~~~~~~~~~~~
+
+Classobject is also completely not imported, instead of defining an opaque type.
+
+We defined the missing functions ``PyMethod_New``, ``PyMethod_Function`` and
+``PyMethod_Self`` and also redefined ``PyMethod_GET_SELF`` and
+``PyMethod_GET_FUNCTION`` as calls to these functions.
+
+*TODO: We should fix classobject.h*
+
+
+code.h
+~~~~~~
+
+The whole code.c code is gone, although it may make sense to
+define some minimum accessibility. This will be clarified on
+`Python-Dev`_. We needed access to code objects and defined the missing
+PepCode_GET_FLAGS and PepCode_GET_ARGCOUNT either as function or macro.
+We further added the missing flags, although few are used:
+
+``CO_OPTIMIZED`` ``CO_NEWLOCALS`` ``CO_VARARGS`` ``CO_VARKEYWORDS`` ``CO_NESTED``
+``CO_GENERATOR``
+
+*TODO: We should maybe fix code.h*
+
+.. _`Python-Dev`: https://mail.python.org/mailman/listinfo/python-dev
+
+datetime.h
+~~~~~~~~~~
+
+The DateTime module is explicitly not included in the limited API.
+We defined all the needed functions but called them via Python instead
+of direct call macros. This has a slight performance impact.
+
+The performance could be easily improved by providing an interface
+that fetches all attributes at once, instead of going through the object
+protocol every time.
+
+The re-defined macros and methods are::
+
+ PyDateTime_GET_YEAR
+ PyDateTime_GET_MONTH
+ PyDateTime_GET_DAY
+ PyDateTime_DATE_GET_HOUR
+ PyDateTime_DATE_GET_MINUTE
+ PyDateTime_DATE_GET_SECOND
+ PyDateTime_DATE_GET_MICROSECOND
+ PyDateTime_DATE_GET_FOLD
+ PyDateTime_TIME_GET_HOUR
+ PyDateTime_TIME_GET_MINUTE
+ PyDateTime_TIME_GET_SECOND
+ PyDateTime_TIME_GET_MICROSECOND
+ PyDateTime_TIME_GET_FOLD
+
+ PyDate_Check
+ PyDateTime_Check
+ PyTime_Check
+
+ PyDate_FromDate
+ PyDateTime_FromDateAndTime
+ PyTime_FromTime
+
+*XXX: We should maybe provide an optimized interface to datetime*
+
+
+object.h
+~~~~~~~~
+
+The file object.h contains the ``PyTypeObject`` structure, which is supposed
+to be completely opaque. All access to types should be done through
+``PyType_GetSlot`` calls. Due to bugs and deficiencies in the limited API
+implementation, it was not possible to do that. Instead, we have defined
+a simplified structure for ``PyTypeObject`` that has only the fields that
+are used in PySide.
+
+We will explain later why and how this was done. Here is the reduced
+structure::
+
+ typedef struct _typeobject {
+ PyVarObject ob_base;
+ const char *tp_name;
+ Py_ssize_t tp_basicsize;
+ void *X03; // Py_ssize_t tp_itemsize;
+ void *X04; // destructor tp_dealloc;
+ void *X05; // printfunc tp_print;
+ void *X06; // getattrfunc tp_getattr;
+ void *X07; // setattrfunc tp_setattr;
+ void *X08; // PyAsyncMethods *tp_as_async;
+ void *X09; // reprfunc tp_repr;
+ void *X10; // PyNumberMethods *tp_as_number;
+ void *X11; // PySequenceMethods *tp_as_sequence;
+ void *X12; // PyMappingMethods *tp_as_mapping;
+ void *X13; // hashfunc tp_hash;
+ ternaryfunc tp_call;
+ reprfunc tp_str;
+ void *X16; // getattrofunc tp_getattro;
+ void *X17; // setattrofunc tp_setattro;
+ void *X18; // PyBufferProcs *tp_as_buffer;
+ void *X19; // unsigned long tp_flags;
+ void *X20; // const char *tp_doc;
+ traverseproc tp_traverse;
+ inquiry tp_clear;
+ void *X23; // richcmpfunc tp_richcompare;
+ Py_ssize_t tp_weaklistoffset;
+ void *X25; // getiterfunc tp_iter;
+ void *X26; // iternextfunc tp_iternext;
+ struct PyMethodDef *tp_methods;
+ void *X28; // struct PyMemberDef *tp_members;
+ void *X29; // struct PyGetSetDef *tp_getset;
+ struct _typeobject *tp_base;
+ PyObject *tp_dict;
+ descrgetfunc tp_descr_get;
+ void *X33; // descrsetfunc tp_descr_set;
+ Py_ssize_t tp_dictoffset;
+ initproc tp_init;
+ allocfunc tp_alloc;
+ newfunc tp_new;
+ freefunc tp_free;
+ inquiry tp_is_gc; /* For PyObject_IS_GC */
+ PyObject *tp_bases;
+ PyObject *tp_mro; /* method resolution order */
+ } PyTypeObject;
+
+Function ``PyIndex_Check`` had to be defined in an unwanted way due to
+a Python issue. See file pep384_issue33738.cpp .
+
+There are extension structures which have been isolated as special macros that
+dynamically compute the right offsets of the extended type structures:
+
+* ``PepType_SOTP`` for ``SbkObjectTypePrivate``
+* ``PepType_SETP`` for ``SbkEnumTypePrivate``
+* ``PepType_PFTP`` for ``PySideQFlagsTypePrivate``
+
+How these extension structures are used can best be seen by searching
+``PepType_{four}`` in the source.
+
+Due to the new heaptype interface, the names of certain types contain
+now the module name in the ``tp_name`` field. To have a compatible way
+to access simple type names as C string, ``PepType_GetNameStr`` has been
+written that skips over dotted name parts.
+
+Finally, the function ``_PyObject_Dump`` was excluded from the limited API.
+This is a useful debugging aid that we always want to have available,
+so it is added back, again. Anyway, we did not reimplement it, and so
+Windows is not supported.
+Therefore, a forgotten debugging call of this functions will break COIN. :-)
+
+
+Using The New Type API
+----------------------
+
+After converting everything but the object.h file, we were a little
+bit shocked: it suddenly was clear that we would have no more
+access to type objects, and even more scary that all types which we
+use have to be heap types, only!
+
+For PySide with its intense use of heap type extensions in various
+flavors, the situation looked quite unsolvable. In the end, it was
+nicely solved, but it took almost 3.5 months to get that right.
+
+Before we see how this is done, we will explain the differences
+between the APIs and their consequences.
+
+
+The Interface
+~~~~~~~~~~~~~
+
+The old type API of Python knows static types and heap types.
+Static types are written down as a declaration of a ``PyTypeObject``
+structure with all its fields filled in. Here is for example
+the definition of the Python type ``object`` (Python 3.6)::
+
+ PyTypeObject PyBaseObject_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "object", /* tp_name */
+ sizeof(PyObject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ object_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ object_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ (hashfunc)_Py_HashPointer, /* tp_hash */
+ 0, /* tp_call */
+ object_str, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ PyDoc_STR("object()\n--\n\nThe most base type"), /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ object_richcompare, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ object_methods, /* tp_methods */
+ 0, /* tp_members */
+ object_getsets, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ object_init, /* tp_init */
+ PyType_GenericAlloc, /* tp_alloc */
+ object_new, /* tp_new */
+ PyObject_Del, /* tp_free */
+ };
+
+We can write the same structure in form of a ``PyType_Spec`` structure,
+and there is even an incomplete tool *abitype.py* that does this conversion
+for us. With a few corrections, the result looks like this::
+
+ static PyType_Slot PyBaseObject_Type_slots[] = {
+ {Py_tp_dealloc, (void *)object_dealloc},
+ {Py_tp_repr, (void *)object_repr},
+ {Py_tp_hash, (void *)_Py_HashPointer},
+ {Py_tp_str, (void *)object_str},
+ {Py_tp_getattro, (void *)PyObject_GenericGetAttr},
+ {Py_tp_setattro, (void *)PyObject_GenericSetAttr},
+ {Py_tp_richcompare, (void *)object_richcompare},
+ {Py_tp_methods, (void *)object_methods},
+ {Py_tp_getset, (void *)object_getsets},
+ {Py_tp_init, (void *)object_init},
+ {Py_tp_alloc, (void *)PyType_GenericAlloc},
+ {Py_tp_new, (void *)object_new},
+ {Py_tp_free, (void *)PyObject_Del},
+ {0, 0},
+ };
+ static PyType_Spec PyBaseObject_Type_spec = {
+ "object",
+ sizeof(PyObject),
+ 0,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+ PyBaseObject_Type_slots,
+ };
+
+This new structure is almost compatible with the old one, but there
+are some subtle differences.
+
+* The new types are generated in one step
+
+This seems to be no problem, but it was very much, due to the way the
+types were built in PySide. Types were assembled piece by piece, and
+finally the ``PyType_Ready`` function was called.
+
+With the new API, ``PyType_Ready`` is called already at the end of
+``PyType_FromSpec``, and that meant that the logic of type creation became
+completely turned upside down.
+
+* The new types are always heaptypes
+
+With the new type creation functions, it is no longer possible to
+create "normal" types. Instead, they all have to be allocated on the
+heap and garbage collected. The user should normally not recognize this.
+But type creation is more constrained, and you cannot create a subtype
+if the ``Py_TPFLAGS_BASETYPE`` is not set. This constraint was already
+violated by PySide and needed a quite profound fix.
+
+* The new types always need a module
+
+While this is not a problem per se, the above new type spec will not create
+a usable new type, but complain with::
+
+ DeprecationWarning: builtin type object has no __module__ attribute
+
+But there are more problems:
+
+* The new types have unexpected defaults
+
+When fields are empty, you would usually assume that they stay empty.
+There are just a few corrections that ``PyType_Ready`` will do to a type.
+
+But there is the following clause in ``PyType_FromSpec`` that can give you
+many headaches::
+
+ if (type->tp_dealloc == NULL) {
+ /* It's a heap type, so needs the heap types' dealloc.
+ subtype_dealloc will call the base type's tp_dealloc, if
+ necessary. */
+ type->tp_dealloc = subtype_dealloc;
+ }
+
+In fact, before the move to the new API, the ``PyType_Ready`` function
+filled empty ``tp_dealloc`` fields with ``object_dealloc``. And the code
+that has been written with that in mind now becomes pretty wrong if suddenly
+``subtype_dealloc`` is used.
+
+The way out was to explicitly provide an ``object_dealloc`` function.
+This would then again impose a problem, because ``object_dealloc`` is not
+public. Writing our own version is easy, but it again needs access to
+type objects. But fortunately, we have broken this rule, already...
+
+
+* The new types are only partially allocated
+
+The structures used in ``PyType_FromSpec`` are almost all allocated,
+only the name field is static. This is no problem for types which are
+statically created once. But if you want to parameterize things and
+create multiple types with a single slots and spec definition, the name
+field that is used for tp_name must be allocated dynamically.
+This is misleading, since all the slots already are copies.
+
+* The new types don't support special offsets
+
+The special fields ``tp_weaklistoffset`` and ``tp_dictoffset`` are not supported
+by ``PyType_FromSpec``. Unfortunately the documentation does not tell you
+if you are allowed to set these fields manually after creating the type or not.
+We finally did it and it worked, but we are not sure about correctness.
+
+See basewrapper.cpp function ``SbkObject_TypeF()`` as the only reference to
+these fields in PySide. This single reference is absolutely necessary and
+very important, since all derived types invisibly inherit these two fields.
+
+
+Future Versions Of The Limited API
+----------------------------------
+
+As we have seen, the current version of the limited API does a bit of
+cheating, because it uses parts of the data structure that should be
+an opaque type. At the moment, this works fine because the data is
+still way more compatible as it could be.
+
+But what if this is changed in the future?
+
+We know that the data structures are stable until Python 3.8 comes out.
+Until then, the small bugs and omissions will hopefully all be solved.
+Then it will be possible to replace the current small tricks by calls
+to ``PyType_GetSlot`` in the way things should be.
+
+At the very moment when the current assumptions about the data structure
+are no longer true, we will rewrite the direct attribute access with
+calls to ``PyType_GetSlot``. After that, no more changes will be necessary.
+
+
+Appendix A: The Transition To Simpler Types
+-------------------------------------------
+
+After all code had been converted to the limited API, there was a
+remaining problem with the ``PyHeapTypeObject``.
+
+Why a problem? Well, all the type structures in shiboken use
+special extra fields at the end of the heap type object. This
+currently enforces extra knowledge at compile time about how large the
+heap type object is. In a clean implementation, we would only use
+the ``PyTypeObject`` itself and access the fields *behind* the type
+by a pointer that is computed at runtime.
+
+
+Restricted PyTypeObject
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Before we are going into details, let us motivate the existence of
+the restricted ``PyTypeObject``:
+
+Originally, we wanted to use ``PyTypeObject`` as an opaque type and
+restrict ourselves to only use the access function ``PyType_GetSlot``.
+This function allows access to all fields which are supported by
+the limited API.
+
+But this is a restriction, because we get no access to ``tp_dict``,
+which we need to support the signature extension. But we can work
+around that.
+
+The real restriction is that ``PyType_GetSlot`` only works for heap
+types. This makes the function quite useless, because we have
+no access to ``PyType_Type``, which is the most important type ``type``
+in Python. We need that for instance to compute the size of
+``PyHeapTypeObject`` dynamically.
+
+With much effort, it is possible to clone ``PyType_Type`` as a heap
+type. But due to a bug in the Pep 384 support, we need
+access to the ``nb_index`` field of a normal type. Cloning does not
+help because ``PyNumberMethods`` fields are *not* inherited.
+
+After we realized this dead end, we changed concept and did not
+use ``PyType_GetSlot`` at all (except in function ``copyNumberMethods``),
+but created a restricted ``PyTypeObject`` with only those fields
+defined that are needed in PySide.
+
+Is this breakage of the limited API? I don't think so. A special
+function runs on program startup that checks the correct position
+of the fields of ``PyTypeObject``, although a change in those fields is
+more than unlikely.
+The really crucial thing is to no longer use ``PyHeapTypeObject``
+explicitly because that *does* change its layout over time.
+
+
+Diversification
+~~~~~~~~~~~~~~~
+
+There were multiple ``Sbk{something}`` structures which all used a "d" field
+for their private data. This made it not easy to find the right
+fields when switching between objects and types::
+
+ struct LIBSHIBOKEN_API SbkObject
+ {
+ PyObject_HEAD
+ PyObject *ob_dict;
+ PyObject *weakreflist;
+ SbkObjectPrivate *d;
+ };
+
+ struct LIBSHIBOKEN_API SbkObjectType
+ {
+ PyHeapTypeObject super;
+ SbkObjectTypePrivate *d;
+ };
+
+The first step was to rename the SbkObjectTypePrivate part from "d" to
+"sotp". It was chosen to be short but easy to remember as abbreviation
+of "SbkObjectTypePrivate", leading to::
+
+ struct LIBSHIBOKEN_API SbkObjectType
+ {
+ PyHeapTypeObject super;
+ SbkObjectTypePrivate *sotp;
+ };
+
+After renaming, it was easier to do the following transformations.
+
+
+Abstraction
+~~~~~~~~~~~
+
+After renaming the type extension pointers to ``sotp``, I replaced
+them by function-like macros which did the special access *behind*
+the types, instead of those explicit fields. For instance, the
+expression::
+
+ type->sotp->converter
+
+became::
+
+ PepType_SOTP(type)->converter
+
+The macro expansion can be seen here::
+
+ #define PepHeapType_SIZE \
+ (reinterpret_cast<PyTypeObject *>(&PyType_Type)->tp_basicsize)
+
+ #define _genericTypeExtender(etype) \
+ (reinterpret_cast<char *>(etype) + PepHeapType_SIZE)
+
+ #define PepType_SOTP(etype) \
+ (*reinterpret_cast<SbkObjectTypePrivate **>(_genericTypeExtender(etype)))
+
+This looks complicated, but in the end there is only a single new
+indirection via ``PyType_Type``, which happens at runtime. This is the
+key to fulfil what Pep 384 wants to achieve: *No more version-dependent fields*.
+
+
+Simplification
+~~~~~~~~~~~~~~
+
+After all type extension fields were replaced by macro calls, we
+could remove the following version dependent re-definition of ``PyHeapTypeObject``
+::
+
+ typedef struct _pyheaptypeobject {
+ union {
+ PyTypeObject ht_type;
+ void *opaque[PY_HEAPTYPE_SIZE];
+ };
+ } PyHeapTypeObject;
+
+, and the version dependent structure::
+
+ struct LIBSHIBOKEN_API SbkObjectType
+ {
+ PyHeapTypeObject super;
+ SbkObjectTypePrivate *sotp;
+ };
+
+could be removed. SbkObjectType remains as a (deprecated)
+type alias to PyTypeObject.
+
+
+Appendix B: Verification Of PyTypeObject
+----------------------------------------
+
+We have introduced a limited PyTypeObject in the same place
+as the original PyTypeObject, and now we need to prove that
+we are allowed to do so.
+
+When using the limited API as intended, then types are completely
+opaque, and access is only through ``PyType_FromSpec`` and (from
+version 3.5 upwards) through ``PyType_GetSlot``.
+
+Python then uses all the slot definitions in the type description
+and produces a regular heap type object.
+
+
+Unused Information
+~~~~~~~~~~~~~~~~~~
+
+We know many things about types that are not explicitly said,
+but they are inherently clear:
+
+(a) The basic structure of a type is always the same, regardless
+ if it is a static type or a heap type.
+
+(b) types are evolving very slowly, and a field is never replaced
+ by another field with different semantics.
+
+Inherent rule (a) gives us the following information: If we calculate
+the offsets of the basic fields, then this info is also usable for non-heap
+types.
+
+The validation checks if rule (b) is still valid.
+
+
+How it Works
+~~~~~~~~~~~~
+
+The basic idea of the validation is to produce a new type using
+``PyType_FromSpec`` and to see where in the type structure these fields
+show up. So we build a ``PyType_Slot`` structure with all the fields we
+are using and make sure that these values are all unique in the
+type.
+
+Most fields are not interrogated by ``PyType_FromSpec``, and so we
+simply used some numeric value. Some fields are interpreted, like
+``tp_members``. This field must really be a ``PyMemberDef``. And there are
+``tp_base`` and ``tp_bases`` which have to be type objects and lists
+thereof. It was easiest to not produce these fields from scratch
+but use them from the ``type`` object ``PyType_Type``.
+
+Then one would think to write a function that searches the known
+values in the opaque type structure.
+
+But we can do better and use optimistically the observation (b):
+We simply use the restricted ``PyTypeObject`` structure and assume that
+every field lands exactly where we are awaiting it.
+
+And that is the whole proof: If we find all the disjoint values at
+the places where we expect them, then verification is done.
+
+
+About ``tp_dict``
+~~~~~~~~~~~~~~~~~
+
+One word about the ``tp_dict`` field: This field is a bit special in
+the proof, since it does not appear in the spec and cannot easily
+be checked by ``type.__dict__`` because that creates a *dictproxy*
+object. So how do we prove that is really the right dict?
+
+We have to create that ``PyMethodDef`` structure anyway, and instead of
+leaving it empty, we insert a dummy function. Then we ask the
+``tp_dict`` field if it has the awaited object in it, and that's it!
+
+#EOT
diff --git a/sources/pyside6/doc/developer/signature_doc.rst b/sources/pyside6/doc/developer/signature_doc.rst
new file mode 100644
index 000000000..a6c703dab
--- /dev/null
+++ b/sources/pyside6/doc/developer/signature_doc.rst
@@ -0,0 +1,361 @@
+.. _signature-extension:
+
+The signature C extension
+=========================
+
+This module is a C extension for CPython 3.5 and up, and CPython 2.7.
+Its purpose is to provide support for the ``__signature__`` attribute
+of builtin PyCFunction objects.
+
+
+Short Introduction to the Topic
+-------------------------------
+
+Beginning with CPython 3.5, Python functions began to grow a ``__signature__``
+attribute for normal Python functions. This is totally optional and just
+a nice-to-have feature in Python.
+
+PySide, on the other hand, could use ``__signature__`` very much, because the
+typing info for the 15000+ PySide functions is really missing, and it
+would be nice to have this info directly available.
+
+
+The Idea to Support Signatures
+------------------------------
+
+We want to have an additional ``__signature__`` attribute in all PySide
+methods, without changing lots of generated code.
+Therefore, we did not change any of the existing data structures,
+but supported the new attribute by a global dictionary.
+
+When the ``__signature__`` property is requested, a method is called that
+does a lookup in the global dict. This is a flexible approach with little impact
+to the rest of the project. It has very limited overhead compared to direct
+attribute access, but for the need of a signature access from time to time,
+this is an adequate compromise.
+
+
+How this Code Works
+~~~~~~~~~~~~~~~~~~~
+
+Signatures are supported for regular Python functions, only. Creating signatures
+for ``PyCFunction`` objects would require quite some extra effort in Python.
+
+Fortunately, we found this special *stealth* technique, that saves us most of the
+needed effort:
+
+The basic idea is to create a dummy Python function with **varnames**, **defaults**
+and **annotations** properties, and then to use the inspect
+module to create a signature object. This object is returned as the computed
+result of the ``__signature__`` attribute of the real ``PyCFunction`` object.
+
+There is one thing that really changes Python a bit:
+
+* We added the ``__signature__`` attribute to every function.
+
+That is a little change to Python that does not harm, but it saves us
+tons of code, that was needed in the early versions of the module.
+
+The internal work is done in two steps:
+
+* All functions of a class get the *signature text* when the module is imported.
+ This is only a very small overhead added to the startup time. It is a single
+ string for each whole class.
+* The actual signature object is created later, when the attribute is really
+ requested. Signatures are cached and only created on first access.
+
+Example:
+
+The ``PyCFunction`` ``QtWidgets.QApplication.palette`` is interrogated for its
+signature. That means ``pyside_sm_get___signature__()`` is called.
+It calls ``GetSignature_Function`` which returns the signature if it is found.
+
+
+Why this Code is Fast
+~~~~~~~~~~~~~~~~~~~~~
+
+It costs a little time (maybe 6 seconds) to run through every single signature
+object, since these are more than 25000 Python objects. But all the signature
+objects will be rarely accessed but in special applications.
+The normal case are only a few accesses, and these are working pretty fast.
+
+The key to make this signature module fast is to avoid computation as much as
+possible. When no signature objects are used, then almost no time is lost in
+initialization. Only the above mentioned strings and some support modules are
+additionally loaded on ``import PySide6``.
+When it comes to signature usage, then late initialization is used and cached.
+This technique is also known as *full laziness* in haskell.
+
+There are actually two locations where late initialization occurs:
+
+* ``dict`` can be no dict but a tuple. That is the initial argument tuple that
+ was saved by ``PySide_BuildSignatureArgs`` at module load time.
+ If so, then ``pyside_type_init`` in parser.py will be called,
+ which parses the string and creates the dict.
+* ``props`` can be empty. Then ``create_signature`` in loader.py
+ is called, which uses a dummy function to produce a signature instance
+ with the inspect module.
+
+The initialization that is always done is just two dictionary writes
+per class, and we have about 1000 classes.
+To measure the additional overhead, we have simulated what happens
+when ``from PySide6 import *`` is performed.
+It turned out that the overhead is below 0.5 ms.
+
+
+The Signature Package Structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The C++ code involved with the signature module is completely in the file
+shiboken6/libshiboken/signature.cpp . All other functionality is implemented in
+the ``signature`` Python package. It has the following structure::
+
+ sources/shiboken6/shibokenmodule/files.dir/shibokensupport
+ ├── __init__.py
+ ├── feature.py
+ ├── fix-complaints.py
+ ├── shibokensupport.pyproject
+ └── signature
+ ├── PSF-3.7.0.txt
+ ├── __init__.py
+ ├── errorhandler.py
+ ├── importhandler.py
+ ├── layout.py
+ ├── lib
+ │   ├── __init__.py
+ │   ├── enum_sig.py
+ │   ├── pyi_generator.py
+ │   └── tool.py
+ ├── loader.py
+ ├── mapping.py
+ ├── parser.py
+ └── qt_attribution.json
+
+Really important are the **parser**, **mapping**, **errorhandler**, **enum_sig**,
+**layout** and **loader** modules. The rest is needed to create Python 2 compatibility
+or be compatible with embedding and installers.
+
+
+**loader.py**
+ This module assembles and imports the ``inspect`` module, and then exports the
+ ``create_signature`` function. This function takes a fake function and some
+ attributes and builds a ``__signature__`` object with the inspect module.
+
+
+**parser.py**
+ This module takes a class signatures string from C++ and parses it into the
+ needed properties for the ``create_signature`` function. Its entry point is the
+ ``pyside_type_init`` function, which is called from the C module via ``loader.py``.
+
+
+**mapping.py**
+ The purpose of the mapping module is maintaining a list of replacement strings
+ that map from the *signature text* in C to the property strings that Python
+ needs. A lot of mappings are resolved by rather complex expressions in ``parser.py``,
+ but a few hundred cases are better to spell explicitly, here.
+
+**errorhandler.py**
+ Since ``Qt For Python 5.12``, we no longer use the builtin type error messages from C++.
+ Instead, we get much better results with the signature module. At the same time,
+ this enforced supporting shiboken as well, and the signature module was no longer
+ optional.
+
+**enum_sig.py**
+ The diverse applications of the signature module all needed to iterate over modules,
+ classes and functions. In order to centralize this enumeration, the process has
+ been factored out as a context manager. The user has only to supply functions
+ that do the actual formatting.
+
+ See for example the .pyi generator ``pyside6/PySide6/support/generate_pyi.py``.
+
+**layout.py**
+ As more applications used the signature module, different formatting of signatures
+ was needed. To support that, we created the function ``create_signature``, which
+ has a parameter to choose from some predefined layouts.
+
+
+**typing27.py**
+ Python 2 has no typing module at all. This is a backport of the minimum that is needed.
+
+
+**backport_inspect.py**
+ Python 2 has an inspect module, but lacks the signature functions, completely.
+ This module adds the missing functionality, which is merged at runtime into
+ the inspect module.
+
+
+Multiple Arities
+~~~~~~~~~~~~~~~~
+
+One aspect that was ignored so far was *multiple arities*: How to handle it when
+a function has more than one signature?
+
+I did not find any note on how multiple signatures should be treated in Python,
+but this simple rules seem to work well:
+
+* If there is a list, then it is a multi-signature.
+* Otherwise, it is a simple signature.
+
+
+Impacts of The Signature Module
+-------------------------------
+
+The signature module has a number of impacts to other PySide modules, which were
+created as a consequence of its existence, and there will be a few more in the
+future:
+
+
+existence_test.py
+~~~~~~~~~~~~~~~~~
+
+The file ``pyside6/tests/registry/existence_test.py`` was written using the
+signatures from the signatures module. The idea is that there are some 15000
+functions with a certain signature.
+
+These functions should not get lost by some bad check-in. Therefore, a list
+of all existing signatures is kept as a module that assembles a
+dictionary. The function existence is checked, and also the exact arity.
+
+This module exists for every PySide release and every platform. The initial
+module is generated once and saved as ``exists_{plat}_{version}.py``.
+
+An error is normally only reported as a warning, but:
+
+
+Interaction With The Coin Module
+++++++++++++++++++++++++++++++++
+
+When this test program is run in COIN, then the warnings are turned into
+errors. The reason is that only in COIN, we have a stable configuration
+of PySide modules that can reliably be compared.
+
+These modules have the name ``exists_{platf}_{version}_ci.py``, and as a big
+exception for generated code, these files are *intentionally* checked in.
+
+
+What Happens When a List is Missing?
+++++++++++++++++++++++++++++++++++++
+
+When a new version of PySide gets created, then the existence test files
+initially do not exist.
+
+When a COIN test is run, then it will complain about the error and create
+the missing module on standard output.
+But since COIN tests are run multiple times, the output that was generated
+by the first test will still exist at the subsequent runs.
+(If COIN was properly implemented, we could not take that advantage and
+would need to implement that as an extra exception.)
+
+As a result, a missing module will be reported as a test which partially
+succeeded (called "FLAKY"). To avoid further flaky tests and to activate as a real test,
+we can now capture the error output of COIN and check the generated module
+in.
+
+
+Explicitly Enforcing Recreation
++++++++++++++++++++++++++++++++
+
+The former way to regenerate the registry files was to remove the files
+and check that in. This has the desired effect, but creates huge deltas.
+As a more efficient way, we have prepared a comment in the first line
+that contains the word "recreate".
+By uncommenting this line, a NameError is triggered, which has the same
+effect.
+
+
+init_platform.py
+++++++++++++++++
+
+For generating the ``exists_{platf}_{version}`` modules, the module
+``pyside6/tests/registry/init_platform.py`` was written. It can be used
+standalone from the commandline, to check the compatibility of some
+changes, directly.
+
+
+scrape_testresults.py
+~~~~~~~~~~~~~~~~~~~~~
+
+To simplify and automate the process of extracting the ``exists_{platf}_{version}_ci.py``
+files, the script ``pyside6/tests/registry/scrape_testresults.py`` has been written.
+
+This script scans the whole testresults website for PySide, that is::
+
+ https://testresults.qt.io/coin/api/results/pyside/pyside-setup/
+
+On the first scan, the script runs less than 30 minutes. After that, a cache
+is generated and the scan works *much* faster. The test results are placed
+into the folder ``pyside6/tests/registry/testresults/embedded/`` with a
+unique name that allows for easy sorting. Example::
+
+ testresults/embedded/2018_09_10_10_40_34-test_1536891759-exists_linux_5_11_2_ci.py
+
+These files are created only once. If they already exist, they are not touched, again.
+The file `pyside6/tests/registry/known_urls.json`` holds all scanned URLs after
+a successful scan. The ``testresults/embedded`` folder can be kept for reference
+or can be removed. Important is only the json file.
+
+The result of a scan is then directly placed into the ``pyside6/tests/registry/``
+folder. It should be reviewed and then eventually checked in.
+
+
+generate_pyi.py
+~~~~~~~~~~~~~~~
+
+``pyside6/PySide6/support/generate_pyi.py`` is still under development.
+This module generates so-called hinting stubs for integration of PySide
+with diverse *Python IDEs*.
+
+Although this module creates the stubs as an add-on, the
+impact on the quality of the signature module is considerable:
+
+The module must create syntactically correct ``.pyi`` files which contain
+not only signatures but also constants and enums of all PySide modules.
+This serves as an extra challenge that has a very positive effect on
+the completeness and correctness of signatures.
+
+The module has a ``--feature`` option to generate modified .pyi files.
+A shortcut for this command is ``pyside6-genpyi``.
+
+A useful command to change all .pyi files to use all features is
+
+.. code-block:: bash
+
+ pyside6-genpyi all --feature snake_case true_property
+
+
+pyi_generator.py
+~~~~~~~~~~~~~~~~
+
+``shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py``
+has been extracted from ``generate_pyi.py``. It allows the generation of ``.pyi``
+files from arbitrary extension modules created with shiboken.
+
+A shortcut for this command is ``shiboken6-genpyi``.
+
+
+Current Extensions
+~~~~~~~~~~~~~~~~~~
+
+Before the signature module was written, there already existed the concept of
+signatures, but in a more C++ - centric way. From that time, there existed
+the error messages, which are created when a function gets wrong argument types.
+
+These error messages were replaced by text generated on demand by
+the signature module, in order to be more consistent and correct.
+This was implemented in ``Qt For Python 5.12.0``.
+
+Additionally, the ``__doc__`` attribute of PySide methods was not set.
+It was easy to get a nice ``help()`` feature by creating signatures
+as default content for docstrings.
+This was implemented in ``Qt For Python 5.12.1``.
+
+
+Literature
+----------
+
+* `PEP 362 – Function Signature Object <https://www.python.org/dev/peps/pep-0362/>`__
+* `PEP 484 – Type Hints <https://www.python.org/dev/peps/pep-0484/>`__
+* `PEP 3107 – Function Annotations <https://www.python.org/dev/peps/pep-3107/>`__
+
+
+*Personal Remark: This module is dedicated to our lovebird "Püppi", who died on 2017-09-15.*
diff --git a/sources/pyside6/doc/extras/QtBluetooth.rst b/sources/pyside6/doc/extras/QtBluetooth.rst
index dda05f20b..965896752 100644
--- a/sources/pyside6/doc/extras/QtBluetooth.rst
+++ b/sources/pyside6/doc/extras/QtBluetooth.rst
@@ -56,7 +56,7 @@ the environment variable ``QT_EVENT_DISPATCHER_CORE_FOUNDATION=1`` to
circumvent this issue.
Applications that don't use Classic Bluetooth will find a subset of
-`QtBluetooth <https://doc.qt.io/qt-6/qtbluetooth-module.html>`_ is available,
+`QtBluetooth`_ is available,
as CoreBluetooth (Bluetooth LE) do not require either of
:class:`QApplication<PySide6.QtWidgets.QApplication>` or
:class:`QGuiApplication<PySide6.QtGui.QGuiApplication>` .
@@ -71,32 +71,32 @@ Guides
Logging Categories
^^^^^^^^^^^^^^^^^^
-The `QtBluetooth <https://doc.qt.io/qt-6/qtbluetooth-module.html>`_ module
+The `QtBluetooth`_ module
exports the following :class:`logging categories<~.Configuring Categories>` :
- +--------------------+--------------------------------------------------------------------------------------------------------------+
- |Logging Category |Description |
- +--------------------+--------------------------------------------------------------------------------------------------------------+
- |qt.bluetooth |Enables logging of cross platform code path in `QtBluetooth <https://doc.qt.io/qt-6/qtbluetooth-module.html>`_|
- +--------------------+--------------------------------------------------------------------------------------------------------------+
- |qt.bluetooth.android|Enables logging of the Android implementation |
- +--------------------+--------------------------------------------------------------------------------------------------------------+
- |qt.bluetooth.bluez |Enables logging of the BLuez/Linux implementation |
- +--------------------+--------------------------------------------------------------------------------------------------------------+
- |qt.bluetooth.ios |Enables logging of the iOS implementation |
- +--------------------+--------------------------------------------------------------------------------------------------------------+
- |qt.bluetooth.osx |Enables logging of the macOS implementation |
- +--------------------+--------------------------------------------------------------------------------------------------------------+
- |qt.bluetooth.windows|Enables logging of the Qt for Windows implementation |
- +--------------------+--------------------------------------------------------------------------------------------------------------+
+ +--------------------+-------------------------------------------------------------+
+ |Logging Category |Description |
+ +--------------------+-------------------------------------------------------------+
+ |qt.bluetooth |Enables logging of cross platform code path in `QtBluetooth`_|
+ +--------------------+-------------------------------------------------------------+
+ |qt.bluetooth.android|Enables logging of the Android implementation |
+ +--------------------+-------------------------------------------------------------+
+ |qt.bluetooth.bluez |Enables logging of the BLuez/Linux implementation |
+ +--------------------+-------------------------------------------------------------+
+ |qt.bluetooth.ios |Enables logging of the iOS implementation |
+ +--------------------+-------------------------------------------------------------+
+ |qt.bluetooth.osx |Enables logging of the macOS implementation |
+ +--------------------+-------------------------------------------------------------+
+ |qt.bluetooth.windows|Enables logging of the Qt for Windows implementation |
+ +--------------------+-------------------------------------------------------------+
Logging categories can be used to enable additional warning and debug output
-for `QtBluetooth <https://doc.qt.io/qt-6/qtbluetooth-module.html>`_ . More
-detailed information about logging can be found in
+for `QtBluetooth`_ . More detailed information about logging can be found in
:class:`QLoggingCategory<~.QLoggingCategory>` . A quick way to enable all
-`QtBluetooth <https://doc.qt.io/qt-6/qtbluetooth-module.html>`_ logging is to
-add the following line to the ``main()`` function:
+`QtBluetooth`_ logging is to add the following line to the ``main()``
+function::
- ::
+ QLoggingCategory.setFilterRules("qt.bluetooth* = true")
- QLoggingCategory.setFilterRules("qt.bluetooth* = true")
+
+.. _QtBluetooth: https://doc.qt.io/qt-6/qtbluetooth-module.html
diff --git a/sources/pyside6/doc/extras/QtCharts.rst b/sources/pyside6/doc/extras/QtCharts.rst
index 8ff2a0386..8f2d768bf 100644
--- a/sources/pyside6/doc/extras/QtCharts.rst
+++ b/sources/pyside6/doc/extras/QtCharts.rst
@@ -15,3 +15,7 @@ directive:
from PySide6 import QtCharts
The module also provides `QML types <https://doc.qt.io/qt-6/qtcharts-qmlmodule.html>`_ .
+
+.. note:: An instance of QApplication is required for the QML types as the
+ module depends on Qt's \l{Graphics View Framework} for rendering.
+ QGuiApplication is not sufficient.
diff --git a/sources/pyside6/doc/extras/QtCore.ClassInfo.rst b/sources/pyside6/doc/extras/QtCore.ClassInfo.rst
index 0cb6d32ed..75445e1fc 100644
--- a/sources/pyside6/doc/extras/QtCore.ClassInfo.rst
+++ b/sources/pyside6/doc/extras/QtCore.ClassInfo.rst
@@ -1,11 +1,9 @@
.. currentmodule:: PySide6.QtCore
-.. _ClassInfo:
+.. py:decorator:: ClassInfo
-ClassInfo
-*********
-
-This class is used to associate extra information to the class, which is available
-using QObject.metaObject(). Qt and PySide doesn't use this information.
+This decorator is used to associate extra information to the class, which is available
+using ``QObject.metaObject()``. This information is used by the
+*Qt D-Bus* and *Qt Qml* modules.
The extra information takes the form of a dictionary with key and value in a literal string.
@@ -16,13 +14,13 @@ If the key needs to contain special characters (spaces, commas, '::', start with
it is also possible to pass a python dictionary with arbitrary strings for both the key and
value and enabling special characters in the key.
-.. note:: This Class is a implementation of Q_CLASSINFO macro.
+.. note:: This decorator is a implementation of the Q_CLASSINFO macro.
Example
-------
-::
+.. code-block:: python
# Recommended syntax
@ClassInfo(Author='PySide Team', URL='http://www.pyside.org')
diff --git a/sources/pyside6/doc/extras/QtCore.Property.rst b/sources/pyside6/doc/extras/QtCore.Property.rst
index 1912b8d23..9ed7de427 100644
--- a/sources/pyside6/doc/extras/QtCore.Property.rst
+++ b/sources/pyside6/doc/extras/QtCore.Property.rst
@@ -1,8 +1,5 @@
.. currentmodule:: PySide6.QtCore
-.. _Property:
-
-Property
-********
+.. py:class:: Property
Detailed Description
--------------------
@@ -16,7 +13,7 @@ They are equivalent to the ``Q_PROPERTY`` macro in the `Qt Docs`_.
Here is an example that illustrates how to use this
function:
-.. code-block::
+.. code-block:: python
:linenos:
from PySide6.QtCore import QObject, Property
@@ -40,20 +37,20 @@ function:
The full options for ``QtCore.Property`` can be found with ``QtCore.Property.__doc__``:
-.. code-block::
-
- Property(self, type: type,
- fget: Optional[Callable] = None,
- fset: Optional[Callable] = None,
- freset: Optional[Callable] = None,
- fdel: Optional[Callable] = None,
- doc: str = '',
- notify: Optional[Callable] = None,
- designable: bool = True,
- scriptable: bool = True,
- stored: bool = True, user: bool = False,
- constant: bool = False,
- final: bool = False) -> PySide6.QtCore.Property
+.. code-block:: python
+
+ Property(self, type: type,
+ fget: Optional[Callable] = None,
+ fset: Optional[Callable] = None,
+ freset: Optional[Callable] = None,
+ fdel: Optional[Callable] = None,
+ doc: str = '',
+ notify: Optional[Callable] = None,
+ designable: bool = True,
+ scriptable: bool = True,
+ stored: bool = True, user: bool = False,
+ constant: bool = False,
+ final: bool = False) -> PySide6.QtCore.Property
Normally, only ``type``, ``fget``and ``fset`` are used.
@@ -68,16 +65,16 @@ requires a ``type`` parameter.
In the above example, the following lines would be equivalent properties:
-.. code-block::
+.. code-block:: python
- pp = QtCore.Property(int, readPP, setPP) # PySide version
- pp = property(readPP, setPP) # Python version
+ pp = QtCore.Property(int, readPP, setPP) # PySide version
+ pp = property(readPP, setPP) # Python version
As you know from the `Python Docs`_, ``Python`` allows to break the property
creation into multiple steps, using the decorator syntax. We can do this in
``PySide`` as well:
-.. code-block::
+.. code-block:: python
:linenos:
from PySide6.QtCore import QObject, Property
@@ -110,12 +107,15 @@ If you are using properties of your objects in QML expressions,
QML requires that the property changes are notified. Here is an
example illustrating how to do this:
-.. code-block::
+.. code-block:: python
:linenos:
from PySide6.QtCore import QObject, Signal, Property
class Person(QObject):
+
+ name_changed = Signal()
+
def __init__(self, name):
QObject.__init__(self)
self._person_name = name
@@ -123,10 +123,6 @@ example illustrating how to do this:
def _name(self):
return self._person_name
- @Signal
- def name_changed(self):
- pass
-
name = Property(str, _name, notify=name_changed)
.. _`Python Docs`: https://docs.python.org/3/library/functions.html?highlight=property#property
diff --git a/sources/pyside6/doc/extras/QtCore.QEnum.rst b/sources/pyside6/doc/extras/QtCore.QEnum.rst
index d33134264..7ea35d8af 100644
--- a/sources/pyside6/doc/extras/QtCore.QEnum.rst
+++ b/sources/pyside6/doc/extras/QtCore.QEnum.rst
@@ -1,23 +1,19 @@
.. currentmodule:: PySide6.QtCore
-.. _QEnum:
-
-QEnum/QFlag
-***********
-
-This class decorator is equivalent to the `Q_ENUM` macro from Qt.
-The decorator is used to register an Enum to the meta-object system,
-which is available via `QObject.staticMetaObject`.
-The enumerator must be in a QObject derived class to be registered.
+.. py:decorator:: QEnum
+This class decorator is equivalent to the `Q_ENUM` macro from Qt. The decorator
+is used to register a Python Enum derived class to the meta-object system,
+which is available via `QObject.staticMetaObject`. The enumerator must be in a
+QObject derived class to be registered.
Example
-------
::
- from enum import Enum, Flag, auto
+ from enum import Enum, auto
- from PySide6.QtCore import QEnum, QFlag, QObject
+ from PySide6.QtCore import QEnum, QObject
class Demo(QObject):
@@ -25,68 +21,7 @@ Example
class Orientation(Enum):
North, East, South, West = range(4)
- class Color(Flag):
- RED = auto()
- BLUE = auto()
- GREEN = auto()
- WHITE = RED | BLUE | GREEN
-
- QFlag(Color) # identical to @QFlag usage
-
-
-Caution:
---------
-
-QEnum registers a Python Enum derived class.
-QFlag treats a variation of the Python Enum, the Flag class.
-
-Please do not confuse that with the Qt QFlags concept. Python does
-not use that concept, it has its own class hierarchy, instead.
-For more details, see the `Python enum documentation <https://docs.python.org/3/library/enum.html>`_.
-
-
-Details about Qt Flags:
------------------------
-
-There are some small differences between Qt flags and Python flags.
-In Qt, we have for instance these declarations:
-
-::
-
- enum QtGui::RenderHint { Antialiasing, TextAntialiasing, SmoothPixmapTransform,
- HighQualityAntialiasing, NonCosmeticDefaultPen }
- flags QtGui::RenderHints
-
-The equivalent Python notation would look like this:
-
-::
-
- @QFlag
- class RenderHints(enum.Flag)
- Antialiasing = auto()
- TextAntialiasing = auto()
- SmoothPixmapTransform = auto()
- HighQualityAntialiasing = auto()
- NonCosmeticDefaultPen = auto()
-
-
-As another example, the Qt::AlignmentFlag flag has 'AlignmentFlag' as the enum
-name, but 'Alignment' as the type name. Non flag enums have the same type and
-enum names.
-
-::
-
- enum Qt::AlignmentFlag
- flags Qt::Alignment
-
-The Python way to specify this would be
-
-::
-
- @QFlag
- class Alignment(enum.Flag):
- ...
-
-We are considering to map all builtin enums and flags to Python enums as well
-in a later release.
+See :deco:`QFlag` for registering Python Flag derived classes.
+Meanwhile all enums and flags have been converted to Python Enums
+(default since ``PySide 6.4``), see the :ref:`NewEnumSystem` section.
diff --git a/sources/pyside6/doc/extras/QtCore.QFlag.rst b/sources/pyside6/doc/extras/QtCore.QFlag.rst
new file mode 100644
index 000000000..dd4f02800
--- /dev/null
+++ b/sources/pyside6/doc/extras/QtCore.QFlag.rst
@@ -0,0 +1,74 @@
+.. currentmodule:: PySide6.QtCore
+.. py:decorator:: QFlag
+
+QFlag handles a variation of the Python Enum, the Flag class.
+
+Please do not confuse that with the Qt QFlags concept. Python does
+not use that concept, it has its own class hierarchy, instead.
+For more details, see the `Python enum documentation <https://docs.python.org/3/library/enum.html>`_.
+
+Example
+-------
+
+::
+
+ from enum import Flag, auto
+
+ from PySide6.QtCore import QFlag, QObject
+
+ class Demo(QObject):
+
+ @QFlag
+ class Color(Flag):
+ RED = auto()
+ BLUE = auto()
+ GREEN = auto()
+ WHITE = RED | BLUE | GREEN
+
+
+Details about Qt Flags:
+-----------------------
+
+There are some small differences between Qt flags and Python flags.
+In Qt, we have for instance these declarations:
+
+::
+
+ enum QtGui::RenderHint { Antialiasing, TextAntialiasing, SmoothPixmapTransform,
+ HighQualityAntialiasing, NonCosmeticDefaultPen }
+ flags QtGui::RenderHints
+
+The equivalent Python notation would look like this:
+
+::
+
+ @QFlag
+ class RenderHints(enum.Flag)
+ Antialiasing = auto()
+ TextAntialiasing = auto()
+ SmoothPixmapTransform = auto()
+ HighQualityAntialiasing = auto()
+ NonCosmeticDefaultPen = auto()
+
+
+As another example, the Qt::AlignmentFlag flag has 'AlignmentFlag' as the enum
+name, but 'Alignment' as the type name. Non flag enums have the same type and
+enum names.
+
+::
+
+ enum Qt::AlignmentFlag
+ flags Qt::Alignment
+
+The Python way to specify this would be
+
+::
+
+ @QFlag
+ class Alignment(enum.Flag):
+ ...
+
+See :deco:`QEnum` for registering Python Enum derived classes.
+
+Meanwhile all enums and flags have been converted to Python Enums
+(default since ``PySide 6.4``), see the :ref:`NewEnumSystem` section.
diff --git a/sources/pyside6/doc/extras/QtCore.Signal.rst b/sources/pyside6/doc/extras/QtCore.Signal.rst
index b50c34148..c83a76a83 100644
--- a/sources/pyside6/doc/extras/QtCore.Signal.rst
+++ b/sources/pyside6/doc/extras/QtCore.Signal.rst
@@ -1,8 +1,5 @@
.. currentmodule:: PySide6.QtCore
-.. _Signal:
-
-Signal
-******
+.. py:class:: Signal
Synopsis
--------
@@ -10,19 +7,19 @@ Synopsis
Functions
^^^^^^^^^
-+---------------------------------------------------------------------------------------------+
-|def :meth:`connect<Signal.connect>` (receiver) |
-+---------------------------------------------------------------------------------------------+
-|def :meth:`disconnect<Signal.disconnect>` (receiver) |
-+---------------------------------------------------------------------------------------------+
-|def :meth:`emit<Signal.disconnect>` (\*args) |
-+---------------------------------------------------------------------------------------------+
++-----------------------------------------------------+
+|def :meth:`connect<Signal.connect>` (receiver) |
++-----------------------------------------------------+
+|def :meth:`disconnect<Signal.disconnect>` (receiver) |
++-----------------------------------------------------+
+|def :meth:`emit<Signal.disconnect>` (\*args) |
++-----------------------------------------------------+
Detailed Description
--------------------
- The :class:`~.Signal` class provides a way to declare and connect Qt
- signals in a pythonic way.
+The :class:`~.Signal` class provides a way to declare and connect Qt
+signals in a pythonic way.
.. class:: PySide6.QtCore.Signal([type1 [, type2...]] [, name="" [, arguments=[]]])
diff --git a/sources/pyside6/doc/extras/QtCore.Slot.rst b/sources/pyside6/doc/extras/QtCore.Slot.rst
index 55c3d9fb7..98a1d465b 100644
--- a/sources/pyside6/doc/extras/QtCore.Slot.rst
+++ b/sources/pyside6/doc/extras/QtCore.Slot.rst
@@ -1,53 +1,42 @@
.. currentmodule:: PySide6.QtCore
-.. _Slot:
+.. py:decorator:: Slot([type1 [, type2...]] [, name="" [, result=None, [tag=""]]])
-Slot
-****
+ :param name: str
+ :param result: type
+ :param tag: str
-Detailed Description
---------------------
+``Slot`` takes a list of Python types of the arguments.
- PySide6 adopt PyQt's new signal and slot syntax as-is. The PySide6
- implementation is functionally compatible with the PyQt one, with the
- exceptions listed below.
+The optional named argument ``name`` defines the slot name. If nothing is
+passed, the slot name will be the decorated function name.
- PyQt's new signal and slot style utilizes method and decorator names
- specific to their implementation. These will be generalized according to
- the table below:
+The optional named argument ``result`` specifies the return type.
- ======= ======================= =============
- Module PyQt factory function PySide class
- ======= ======================= =============
- QtCore pyqtSignal Signal
- QtCore pyqtSlot Slot
- ======= ======================= =============
+The optional named argument ``tag`` specifies a value to be returned
+by ``QMetaMethod.tag()``.
- .. class:: PySide6.QtCore.Slot([type1 [, type2...]] [, name="" [, result=None]])
+This implementation is functionally compatible with the PyQt one.
- :param name: str
- :param result: type
+======= =========== ======
+Module PyQt PySide
+======= =========== ======
+QtCore pyqtSignal Signal
+QtCore pyqtSlot Slot
+======= =========== ======
- ``Slot`` takes a list of Python types of the arguments.
-
- The optional named argument ``name`` defines the slot name. If nothing is
- passed, the slot name will be the decorated function name.
-
- The optional named argument ``result`` specifies the return type.
-
- .. seealso:: :ref:`signals-and-slots`
+.. seealso:: :ref:`signals-and-slots`
Q_INVOKABLE
-----------
- There is no equivalent of the Q_INVOKABLE macro of Qt
- since PySide6 slots can actually have return values.
- If you need to create a invokable method that returns some value,
- declare it as a slot, e.g.:
-
- ::
+There is no equivalent of the Q_INVOKABLE macro of Qt
+since PySide6 slots can actually have return values.
+If you need to create a invokable method that returns some value,
+declare it as a slot, e.g.:
- class Foo(QObject):
+::
- @Slot(float, result=int)
- def getFloatReturnInt(self, f):
- return int(f)
+ class Foo(QObject):
+ @Slot(float, result=int)
+ def getFloatReturnInt(self, f):
+ return int(f)
diff --git a/sources/pyside6/doc/extras/QtDesigner.QPyDesignerContainerExtension.rst b/sources/pyside6/doc/extras/QtDesigner.QPyDesignerContainerExtension.rst
index 1baa9e369..a3e5ef511 100644
--- a/sources/pyside6/doc/extras/QtDesigner.QPyDesignerContainerExtension.rst
+++ b/sources/pyside6/doc/extras/QtDesigner.QPyDesignerContainerExtension.rst
@@ -1,10 +1,9 @@
.. currentmodule:: PySide6.QtDesigner
-.. _QPyDesignerContainerExtension:
-
-QPyDesignerContainerExtension
-*****************************
+.. py:class:: QPyDesignerContainerExtension
QPyDesignerContainerExtension is the base class for implementing
-`QDesignerContainerExtension <https://doc.qt.io/qt-6/qdesignercontainerextension.html>`_
-for a Qt Designer custom widget plugin in Python.
+`QDesignerContainerExtension class`_
+for a *Qt Widgets Designer* custom widget plugin in Python.
It provides the required inheritance from **QObject**.
+
+.. _QDesignerContainerExtension class: https://doc.qt.io/qt-6/qdesignercontainerextension.html
diff --git a/sources/pyside6/doc/extras/QtDesigner.QPyDesignerCustomWidgetCollection.rst b/sources/pyside6/doc/extras/QtDesigner.QPyDesignerCustomWidgetCollection.rst
index 00260860b..615ca4eec 100644
--- a/sources/pyside6/doc/extras/QtDesigner.QPyDesignerCustomWidgetCollection.rst
+++ b/sources/pyside6/doc/extras/QtDesigner.QPyDesignerCustomWidgetCollection.rst
@@ -1,8 +1,5 @@
.. currentmodule:: PySide6.QtDesigner
-.. _QPyDesignerCustomWidgetCollection:
-
-QPyDesignerCustomWidgetCollection
-*********************************
+.. py:class:: QPyDesignerCustomWidgetCollection
Synopsis
--------
@@ -19,20 +16,21 @@ Functions
Detailed Description
--------------------
- The :class:`~.QPyDesignerCustomWidgetCollection` implements
- `QDesignerCustomWidgetCollectionInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetcollectioninterface.html>`_
- and provides static helper functions for registering custom widgets by
- type or by implementing
- `QDesignerCustomWidgetInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetinterface.html>`_ .
+The :class:`~.QPyDesignerCustomWidgetCollection` implements
+`QDesignerCustomWidgetCollectionInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetcollectioninterface.html>`_
+and provides static helper functions for registering custom widgets by
+type or by implementing
+`QDesignerCustomWidgetInterface`_ .
- The usage is explained in :ref:`designer_custom_widgets`.
+The usage is explained in :ref:`designer_custom_widgets`.
.. py:staticmethod:: QPyDesignerCustomWidgetCollection.registerCustomWidget(type[, xml=""[, tool_tip=""[, icon=""[, group=""[container=False]]]]])
- Registers an instance of a Python-implemented QWidget by type with Qt Designer.
+ Registers an instance of a Python-implemented QWidget by type with
+ *Qt Widgets Designer*.
The optional keyword arguments correspond to the getters of
- `QDesignerCustomWidgetInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetinterface.html>`_ :
+ `QDesignerCustomWidgetInterface`_ :
:param str xml: A snippet of XML code in ``.ui`` format that specifies how the widget is created and sets initial property values.
:param str tool_tip: Tool tip to be shown in the widget box.
@@ -46,7 +44,9 @@ Detailed Description
.. py:staticmethod:: QPyDesignerCustomWidgetCollection.addCustomWidget(custom_widget)
Adds a custom widget (implementation of
- `QDesignerCustomWidgetInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetinterface.html>`_)
- with Qt Designer.
+ `QDesignerCustomWidgetInterface`_)
+ with *Qt Widgets Designer*.
:param QDesignerCustomWidgetInterface custom_widget: Custom widget instance
+
+.. _QDesignerCustomWidgetInterface: https://doc.qt.io/qt-6/qdesignercustomwidgetinterface.html
diff --git a/sources/pyside6/doc/extras/QtDesigner.QPyDesignerMemberSheetExtension.rst b/sources/pyside6/doc/extras/QtDesigner.QPyDesignerMemberSheetExtension.rst
index c52aafdf5..ef2356221 100644
--- a/sources/pyside6/doc/extras/QtDesigner.QPyDesignerMemberSheetExtension.rst
+++ b/sources/pyside6/doc/extras/QtDesigner.QPyDesignerMemberSheetExtension.rst
@@ -1,10 +1,9 @@
.. currentmodule:: PySide6.QtDesigner
-.. _QPyDesignerMemberSheetExtension:
-
-QPyDesignerMemberSheetExtension
-*******************************
+.. py:class:: QPyDesignerMemberSheetExtension
QPyDesignerMemberSheetExtension is the base class for implementing
-`QDesignerMemberSheetExtension <https://doc.qt.io/qt-6/qdesignermembersheetextension.html>`_
-for a Qt Designer custom widget plugin in Python.
+`QDesignerMemberSheetExtension class`_
+for a *Qt Widgets Designer* custom widget plugin in Python.
It provides the required inheritance from **QObject**.
+
+.. _QDesignerMemberSheetExtension class: https://doc.qt.io/qt-6/qdesignermembersheetextension.html
diff --git a/sources/pyside6/doc/extras/QtDesigner.QPyDesignerTaskMenuExtension.rst b/sources/pyside6/doc/extras/QtDesigner.QPyDesignerTaskMenuExtension.rst
index 004c94693..e5e13122d 100644
--- a/sources/pyside6/doc/extras/QtDesigner.QPyDesignerTaskMenuExtension.rst
+++ b/sources/pyside6/doc/extras/QtDesigner.QPyDesignerTaskMenuExtension.rst
@@ -1,10 +1,9 @@
.. currentmodule:: PySide6.QtDesigner
-.. _QPyDesignerTaskMenuExtension:
-
-QPyDesignerTaskMenuExtension
-****************************
+.. py:class:: QPyDesignerTaskMenuExtension
QPyDesignerTaskMenuExtension is the base class for implementing
-`QDesignerTaskMenuExtension <https://doc.qt.io/qt-6/qdesignertaskmenuextension.html>`_
-for a Qt Designer custom widget plugin in Python.
+`QDesignerTaskMenuExtension class`_
+for a *Qt Widgets Designer* custom widget plugin in Python.
It provides the required inheritance from **QObject**.
+
+.. _QDesignerTaskMenuExtension class: https://doc.qt.io/qt-6/qdesignertaskmenuextension.html
diff --git a/sources/pyside6/doc/extras/QtDesigner.rst b/sources/pyside6/doc/extras/QtDesigner.rst
index c232128dd..844f25b7b 100644
--- a/sources/pyside6/doc/extras/QtDesigner.rst
+++ b/sources/pyside6/doc/extras/QtDesigner.rst
@@ -1,5 +1,6 @@
-Provides classes to create your own custom widget plugins for Qt Designer and
-classes to access Qt Designer components.
+Provides classes to create your own custom widget plugins for
+*Qt Widgets Designer* and classes to access *Qt Widgets Designer*
+components.
In addition, the :class:`QFormBuilder<PySide6.QtDesigner.QFormBuilder>` class
provides the possibility of constructing user interfaces from UI files at
diff --git a/sources/pyside6/doc/extras/QtMultimedia.rst b/sources/pyside6/doc/extras/QtMultimedia.rst
index f495ddc4e..527c2427b 100644
--- a/sources/pyside6/doc/extras/QtMultimedia.rst
+++ b/sources/pyside6/doc/extras/QtMultimedia.rst
@@ -29,7 +29,7 @@ directive:
import PySide6.QtMultimedia
-The module also provides `QML types <https://doc.qt.io/qt-6/qtmultimedia-qmlmodule.html>`_ .
+The module also provides QML `types <https://doc.qt.io/qt-6/qtmultimedia-qmlmodule.html>`_ .
Overviews and Important Topics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -46,27 +46,38 @@ QML Types
The following table outlines some important QML types.
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |Type |Description |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`MediaPlayer <https://doc.qt.io/qt-6/qml-qtmultimedia-mediaplayer.html>`_ |Add audio/video playback functionality to a scene. |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`CaptureSession <https://doc.qt.io/qt-6/qml-qtmultimedia-capturesession.html>`_|Create a session for capturing audio/video. |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`Camera <https://doc.qt.io/qt-6/qml-qtmultimedia-camera.html>`_ |Access a camera connected to the system. |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`AudioInput <https://doc.qt.io/qt-6/qml-qtmultimedia-audioinput.html>`_ |Access an audio input (microphone) connected to the system. |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`AudioOutput <https://doc.qt.io/qt-6/qml-qtmultimedia-audiooutput.html>`_ |Access an audio output (speaker, headphone) connected to the system. |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`VideoOutput <https://doc.qt.io/qt-6/qml-qtmultimedia-videooutput.html>`_ |Display video content. |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`MediaRecorder <https://doc.qt.io/qt-6/qml-qtmultimedia-mediarecorder.html>`_ |Record audio/video from the `CaptureSession <https://doc.qt.io/qt-6/qml-qtmultimedia-capturesession.html>`_ . |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`ImageCapture <https://doc.qt.io/qt-6/qml-qtmultimedia-imagecapture.html>`_ |Capture still images from the Camera. |
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
- |`Video <https://doc.qt.io/qt-6/qml-qtmultimedia-video.html>`_ |Add Video playback functionality to a scene. Uses `MediaPlayer <https://doc.qt.io/qt-6/qml-qtmultimedia-mediaplayer.html>`_ and `VideoOutput <https://doc.qt.io/qt-6/qml-qtmultimedia-videooutput.html>`_ types to provide video playback functionality.|
- +-------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ +------------------+---------------------------------------------------------------------+
+ |Type |Description |
+ +------------------+---------------------------------------------------------------------+
+ |`MediaPlayer`_ |Add audio/video playback functionality to a scene. |
+ +------------------+---------------------------------------------------------------------+
+ |`CaptureSession`_ |Create a session for capturing audio/video. |
+ +------------------+---------------------------------------------------------------------+
+ |`Camera`_ |Access a camera connected to the system. |
+ +------------------+---------------------------------------------------------------------+
+ |`AudioInput`_ |Access an audio input (microphone) connected to the system. |
+ +------------------+---------------------------------------------------------------------+
+ |`AudioOutput`_ |Access an audio output (speaker, headphone) connected to the system. |
+ +------------------+---------------------------------------------------------------------+
+ |`VideoOutput`_ |Display video content. |
+ +------------------+---------------------------------------------------------------------+
+ |`MediaRecorder`_ |Record audio/video from the `CaptureSession`_ . |
+ +------------------+---------------------------------------------------------------------+
+ |`ImageCapture`_ |Capture still images from the Camera. |
+ +------------------+---------------------------------------------------------------------+
+ |`Video`_ |Add Video playback functionality to a scene. Uses `MediaPlayer`_ and |
+ | |`VideoOutput`_ types to provide video playback functionality. |
+ +------------------+---------------------------------------------------------------------+
+
+.. _MediaPlayer: https://doc.qt.io/qt-6/qml-qtmultimedia-mediaplayer.html
+.. _CaptureSession: https://doc.qt.io/qt-6/qml-qtmultimedia-capturesession.html
+.. _Camera: https://doc.qt.io/qt-6/qml-qtmultimedia-camera.html
+.. _AudioInput: https://doc.qt.io/qt-6/qml-qtmultimedia-audioinput.html
+.. _AudioOutput: https://doc.qt.io/qt-6/qml-qtmultimedia-audiooutput.html
+.. _VideoOutput: https://doc.qt.io/qt-6/qml-qtmultimedia-videooutput.html
+.. _MediaRecorder: https://doc.qt.io/qt-6/qml-qtmultimedia-mediarecorder.html
+.. _ImageCapture: https://doc.qt.io/qt-6/qml-qtmultimedia-imagecapture.html
+.. _Video: https://doc.qt.io/qt-6/qml-qtmultimedia-video.html
C++ Classes
^^^^^^^^^^^
diff --git a/sources/pyside6/doc/extras/QtQml.ListProperty.rst b/sources/pyside6/doc/extras/QtQml.ListProperty.rst
new file mode 100644
index 000000000..eaa580c68
--- /dev/null
+++ b/sources/pyside6/doc/extras/QtQml.ListProperty.rst
@@ -0,0 +1,24 @@
+.. currentmodule:: PySide6.QtQml
+.. py:class:: ListProperty
+
+ The ``ListProperty`` class allows applications to expose list-like properties of
+ :class:`~PySide6.QtCore.QObject`-derived classes to QML.
+ The usage is shown in the :ref:`qml-object-and-list-property-types-example`
+ and the :ref:`qml-chapter5-listproperties` example.
+
+ .. py:method:: __init__(type, append, count=None, at=None, clear=None, removeLast=None, doc="", notify=None, designable=True, scriptable=True, stored=True, user=False, constant=False, final=False)
+
+ :param type type: Element type
+ :param callable append: A function to append an item
+ :param callable count: A function returning the list count
+ :param callable at: A function returning the item at an index
+ :param callable clear: A function to clear the list
+ :param removeLast: A function to remove the last item
+ :param str doc: Doc string
+ :param Signal notify: A signal emitted when a change occurs
+ :param bool designable: Not used in QML
+ :param bool scriptable: Not used in QML
+ :param bool stored: Whether the property is stored
+ :param bool user: Not used in QML
+ :param bool constant: Whether the property is constant
+ :param bool final: Whether the property is final
diff --git a/sources/pyside6/doc/extras/QtQml.QPyQmlParserStatus.rst b/sources/pyside6/doc/extras/QtQml.QPyQmlParserStatus.rst
index 58f609b03..10dde6b9a 100644
--- a/sources/pyside6/doc/extras/QtQml.QPyQmlParserStatus.rst
+++ b/sources/pyside6/doc/extras/QtQml.QPyQmlParserStatus.rst
@@ -1,10 +1,9 @@
.. currentmodule:: PySide6.QtQml
-.. _QPyQmlParserStatus:
-
-QPyQmlParserStatus
-******************
+.. py:class:: QPyQmlParserStatus
QPyQmlParserStatus is the base class for implementing
-`QQmlParserStatus <https://doc.qt.io/qt-6/qqmlparserstatus.html>`_
+`QQmlParserStatus class`_ .
It provides the required inheritance from **QObject**.
+
+.. _QQmlParserStatus class: https://doc.qt.io/qt-6/qqmlparserstatus.html
diff --git a/sources/pyside6/doc/extras/QtQml.QPyQmlPropertyValueSource.rst b/sources/pyside6/doc/extras/QtQml.QPyQmlPropertyValueSource.rst
index 576b8baa0..bf7f8e98f 100644
--- a/sources/pyside6/doc/extras/QtQml.QPyQmlPropertyValueSource.rst
+++ b/sources/pyside6/doc/extras/QtQml.QPyQmlPropertyValueSource.rst
@@ -1,10 +1,9 @@
.. currentmodule:: PySide6.QtQml
-.. _QPyQmlPropertyValueSource:
-
-QPyQmlPropertyValueSource
-*************************
+.. py:class:: QPyQmlPropertyValueSource
QPyQmlPropertyValueSource is the base class for implementing
-`QQmlPropertyValueSource <https://doc.qt.io/qt-6/qqmlpropertyvaluesource.html>`_
+`QQmlPropertyValueSource class`_ .
It provides the required inheritance from **QObject**.
+
+.. _QQmlPropertyValueSource class: https://doc.qt.io/qt-6/qqmlpropertyvaluesource.html
diff --git a/sources/pyside6/doc/extras/QtQml.QmlAnonymous.rst b/sources/pyside6/doc/extras/QtQml.QmlAnonymous.rst
index a805b0763..44aa0ea21 100644
--- a/sources/pyside6/doc/extras/QtQml.QmlAnonymous.rst
+++ b/sources/pyside6/doc/extras/QtQml.QmlAnonymous.rst
@@ -1,22 +1,17 @@
.. currentmodule:: PySide6.QtQml
-.. _QmlAnonymous:
-
-QmlAnonymous
-************
-
.. py:decorator:: QmlAnonymous
- Declares the enclosing type to be available, but anonymous in QML. The type
- cannot be created or used to declare properties in QML, but when passed from
- C++, it is recognized. In QML, you can use properties of this type if they
- are declared in C++.
+Declares the enclosing type to be available, but anonymous in QML. The type
+cannot be created or used to declare properties in QML, but when passed from
+C++, it is recognized. In QML, you can use properties of this type if they
+are declared in C++.
- .. code-block:: python
+.. code-block:: python
- QML_IMPORT_NAME = "com.library.name"
- QML_IMPORT_MAJOR_VERSION = 1
- QML_IMPORT_MINOR_VERSION = 0 # Optional
+ QML_IMPORT_NAME = "com.library.name"
+ QML_IMPORT_MAJOR_VERSION = 1
+ QML_IMPORT_MINOR_VERSION = 0 # Optional
- @QmlAnonymous
- class ClassForQml(QObject):
- # ...
+ @QmlAnonymous
+ class ClassForQml(QObject):
+ # ...
diff --git a/sources/pyside6/doc/extras/QtQml.QmlAttached.rst b/sources/pyside6/doc/extras/QtQml.QmlAttached.rst
index e3fefb6b2..4331b03f9 100644
--- a/sources/pyside6/doc/extras/QtQml.QmlAttached.rst
+++ b/sources/pyside6/doc/extras/QtQml.QmlAttached.rst
@@ -1,9 +1,4 @@
.. currentmodule:: PySide6.QtQml
-.. _QmlAttached:
-
-QmlAttached
-***********
-
.. py:decorator:: QmlAttached
This decorator declares that the enclosing type attaches the type passed as
diff --git a/sources/pyside6/doc/extras/QtQml.QmlElement.rst b/sources/pyside6/doc/extras/QtQml.QmlElement.rst
index 2746fbc0b..66397b2d9 100644
--- a/sources/pyside6/doc/extras/QtQml.QmlElement.rst
+++ b/sources/pyside6/doc/extras/QtQml.QmlElement.rst
@@ -1,30 +1,25 @@
.. currentmodule:: PySide6.QtQml
-.. _QmlElement:
-
-QmlElement
-**********
-
.. py:decorator:: QmlElement
- This decorator registers a class it is attached to for use in QML, using
- global variables to specify the import name and version.
+This decorator registers a class it is attached to for use in QML, using
+global variables to specify the import name and version.
- .. code-block:: python
+.. code-block:: python
- QML_IMPORT_NAME = "com.library.name"
- QML_IMPORT_MAJOR_VERSION = 1
- QML_IMPORT_MINOR_VERSION = 0 # Optional
+ QML_IMPORT_NAME = "com.library.name"
+ QML_IMPORT_MAJOR_VERSION = 1
+ QML_IMPORT_MINOR_VERSION = 0 # Optional
- @QmlElement
- class ClassForQml(QObject):
- # ...
+ @QmlElement
+ class ClassForQml(QObject):
+ # ...
- Afterwards the class may be used in QML:
+Afterwards the class may be used in QML:
- .. code-block:: python
+.. code-block:: python
- import com.library.name 1.0
+ import com.library.name 1.0
- ClassForQml {
- // ...
- }
+ ClassForQml {
+ // ...
+ }
diff --git a/sources/pyside6/doc/extras/QtQml.QmlExtended.rst b/sources/pyside6/doc/extras/QtQml.QmlExtended.rst
index f9ed5a106..af113a9c8 100644
--- a/sources/pyside6/doc/extras/QtQml.QmlExtended.rst
+++ b/sources/pyside6/doc/extras/QtQml.QmlExtended.rst
@@ -1,9 +1,4 @@
.. currentmodule:: PySide6.QtQml
-.. _QmlExtended:
-
-QmlExtended
-***********
-
.. py:decorator:: QmlExtended
Declares that the enclosing type uses the type passed as an extension to
diff --git a/sources/pyside6/doc/extras/QtQml.QmlForeign.rst b/sources/pyside6/doc/extras/QtQml.QmlForeign.rst
index c58be3cb9..90b821e9b 100644
--- a/sources/pyside6/doc/extras/QtQml.QmlForeign.rst
+++ b/sources/pyside6/doc/extras/QtQml.QmlForeign.rst
@@ -1,33 +1,28 @@
.. currentmodule:: PySide6.QtQml
-.. _QmlForeign:
-
-QmlForeign
-**********
-
.. py:decorator:: QmlForeign
- This decorator can be used to change the type that is created by QML.
+This decorator can be used to change the type that is created by QML.
- This is useful for registering types that cannot be amended by adding the
- QmlElement decorator, for example because they belong to 3rdparty libraries.
+This is useful for registering types that cannot be amended by adding the
+QmlElement decorator, for example because they belong to 3rdparty libraries.
- .. code-block:: python
+.. code-block:: python
- QML_IMPORT_NAME = "com.library.name"
- QML_IMPORT_MAJOR_VERSION = 1
- QML_IMPORT_MINOR_VERSION = 0 # Optional
+ QML_IMPORT_NAME = "com.library.name"
+ QML_IMPORT_MAJOR_VERSION = 1
+ QML_IMPORT_MINOR_VERSION = 0 # Optional
- @QmlNamedElement("QWidget")
- @QmlForeign(QWidget)
- class ForeignWidgetHelperClass(QObject):
+ @QmlNamedElement("QWidget")
+ @QmlForeign(QWidget)
+ class ForeignWidgetHelperClass(QObject):
...
- Afterwards the class may be used in QML:
+Afterwards the class may be used in QML:
- .. code-block:: javascript
+.. code-block:: javascript
- import com.library.name 1.0
+ import com.library.name 1.0
- QWidget {
- // ...
- }
+ QWidget {
+ // ...
+ }
diff --git a/sources/pyside6/doc/extras/QtQml.QmlNamedElement.rst b/sources/pyside6/doc/extras/QtQml.QmlNamedElement.rst
index d603e2e83..79eb9d7ad 100644
--- a/sources/pyside6/doc/extras/QtQml.QmlNamedElement.rst
+++ b/sources/pyside6/doc/extras/QtQml.QmlNamedElement.rst
@@ -1,31 +1,26 @@
.. currentmodule:: PySide6.QtQml
-.. _QmlNamedElement:
-
-QmlNamedElement
-***************
-
.. py:decorator:: QmlNamedElement
- This decorator registers a class it is attached to for use in QML under
- a name different from the class name, using global variables to specify
- the import name and version.
+This decorator registers a class it is attached to for use in QML under
+a name different from the class name, using global variables to specify
+the import name and version.
- .. code-block:: python
+.. code-block:: python
- QML_IMPORT_NAME = "com.library.name"
- QML_IMPORT_MAJOR_VERSION = 1
- QML_IMPORT_MINOR_VERSION = 0 # Optional
+ QML_IMPORT_NAME = "com.library.name"
+ QML_IMPORT_MAJOR_VERSION = 1
+ QML_IMPORT_MINOR_VERSION = 0 # Optional
- @QmlNamedElement("ClassForQml")
- class ClassWithSomeName(QObject):
+ @QmlNamedElement("ClassForQml")
+ class ClassWithSomeName(QObject):
...
- Afterwards the class may be used in QML:
+Afterwards the class may be used in QML:
- .. code-block:: javascript
+.. code-block:: javascript
- import com.library.name 1.0
+ import com.library.name 1.0
- ClassForQml {
- // ...
- }
+ ClassForQml {
+ // ...
+ }
diff --git a/sources/pyside6/doc/extras/QtQml.QmlSingleton.rst b/sources/pyside6/doc/extras/QtQml.QmlSingleton.rst
index d3d3bf4a7..402c18d55 100644
--- a/sources/pyside6/doc/extras/QtQml.QmlSingleton.rst
+++ b/sources/pyside6/doc/extras/QtQml.QmlSingleton.rst
@@ -1,13 +1,8 @@
.. currentmodule:: PySide6.QtQml
-.. _QmlSingleton:
-
-QmlSingleton
-************
-
.. py:decorator:: QmlSingleton
Declares the decorated type to be a singleton in QML. This only takes effect if
-the type is a Q_OBJECT and is available in QML (by having a QmlElement decorator).
+the type is a QObject and is available in QML (by having a QmlElement decorator).
The QQmlEngine will try to create a singleton instance using the type's default
constructor.
@@ -20,6 +15,19 @@ constructor.
@QmlElement
@QmlSingleton
class ClassForQml(QObject):
- # ...
+ ...
+
+It is also possible to use a static ``create()`` method which receives
+the engine as a parameter:
+
+.. code-block:: python
+
+ @QmlElement
+ @QmlSingleton
+ class ClassForQml(QObject):
+
+ @staticmethod
+ def create(engine):
+ ...
.. note:: The order of the decorators matters; ``QmlSingleton`` needs to be preceded by ``QmlElement``.
diff --git a/sources/pyside6/doc/extras/QtQml.QmlUncreatable.rst b/sources/pyside6/doc/extras/QtQml.QmlUncreatable.rst
index 72fde741d..b7a28801f 100644
--- a/sources/pyside6/doc/extras/QtQml.QmlUncreatable.rst
+++ b/sources/pyside6/doc/extras/QtQml.QmlUncreatable.rst
@@ -1,9 +1,4 @@
.. currentmodule:: PySide6.QtQml
-.. _QmlUncreatable:
-
-QmlUncreatable
-**************
-
.. py:decorator:: QmlUncreatable
Declares that the decorated type shall not be creatable from QML. This takes
@@ -26,6 +21,6 @@ Passing None or no argument will cause a standard message to be used instead.
@QmlElement
@QmlUncreatable("BaseClassForQml is an abstract base class")
class BaseClassForQml(QObject):
- # ...
+ ...
.. note:: The order of the decorators matters; ``QmlUncreatable`` needs to be preceded by ``QmlElement``.
diff --git a/sources/pyside6/doc/extras/QtQml.qmlRegisterSingletonInstance.rst b/sources/pyside6/doc/extras/QtQml.qmlRegisterSingletonInstance.rst
deleted file mode 100644
index 19d59893e..000000000
--- a/sources/pyside6/doc/extras/QtQml.qmlRegisterSingletonInstance.rst
+++ /dev/null
@@ -1,25 +0,0 @@
-.. currentmodule:: PySide6.QtQml
-.. _qmlRegisterSingletonInstance:
-
-qmlRegisterSingletonInstance
-****************************
-
-.. py:function:: qmlRegisterSingletonInstance(pytype: type,\
- uri: str,\
- versionMajor: int,\
- versionMinor: int,\
- typeName: str,\
- instanceObject: object) -> int
-
- :param type pytype: Python class
- :param str uri: uri to use while importing the component in QML
- :param int versionMajor: major version
- :param int versionMinor: minor version
- :param str typeName: name exposed to QML
- :param object instanceObject: singleton object to be registered
- :return: int (the QML type id)
-
- This function registers a singleton Python object *instanceObject*, with a particular *uri* and
- *typeName*. Its version is a combination of *versionMajor* and *versionMinor*.
-
- Use this function to register an object of the given type *pytype* as a singleton type.
diff --git a/sources/pyside6/doc/extras/QtQml.qmlRegisterSingletonType.rst b/sources/pyside6/doc/extras/QtQml.qmlRegisterSingletonType.rst
deleted file mode 100644
index 32231a391..000000000
--- a/sources/pyside6/doc/extras/QtQml.qmlRegisterSingletonType.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-.. currentmodule:: PySide6.QtQml
-.. _qmlRegisterSingletonType:
-
-qmlRegisterSingletonType
-************************
-
-.. py:function:: qmlRegisterSingletonType(pytype: type, uri: str, versionMajor: int, versionMinor: int, typeName: str) -> int
-
- :param type pytype: Python class
- :param str uri: uri to use while importing the component in QML
- :param int versionMajor: major version
- :param int versionMinor: minor version
- :param str typeName: name exposed to QML
- :return: int (the QML type id)
-
- This function registers a Python type as a singleton in the QML system.
-
- Alternatively, the :ref:`QmlSingleton` decorator can be used.
-
-.. py:function:: qmlRegisterSingletonType(pytype: type, uri: str, versionMajor: int, versionMinor: int, typeName: str, callback: object) -> int
-
- :param type pytype: Python class
- :param str uri: uri to use while importing the component in QML
- :param int versionMajor: major version
- :param int versionMinor: minor version
- :param str typeName: name exposed to QML
- :param object callback: Python callable (to handle Python type)
- :return: int (the QML type id)
-
- This function registers a Python type as a singleton in the QML system using
- the provided callback (which gets a QQmlEngine as a parameter) to generate
- the singleton.
-
-
-.. py:function:: qmlRegisterSingletonType(uri: str, versionMajor: int, versionMinor: int, typeName: str, callback: object) -> int
-
- :param str uri: uri to use while importing the component in QML
- :param int versionMajor: major version
- :param int versionMinor: minor version
- :param str typeName: name exposed to QML
- :param object callback: Python callable (to handle QJSValue)
- :return: int (the QML type id)
-
- This function registers a QJSValue as a singleton in the QML system using
- the provided callback (which gets a QQmlEngine as a parameter) to
- generate the singleton.
diff --git a/sources/pyside6/doc/extras/QtQml.qmlRegisterType.rst b/sources/pyside6/doc/extras/QtQml.qmlRegisterType.rst
deleted file mode 100644
index 079e15bf1..000000000
--- a/sources/pyside6/doc/extras/QtQml.qmlRegisterType.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-.. currentmodule:: PySide6.QtQml
-.. _qmlRegisterType:
-
-qmlRegisterType
-***************
-
-.. py:function:: qmlRegisterType(pytype: type, uri: str, versionMajor: int, versionMinor: int, qmlName: str) -> int
-
- :param type pytype: Python class
- :param str uri: uri to use while importing the component in QML
- :param int versionMajor: major version
- :param int versionMinor: minor version
- :param str qmlName: name exposed to QML
- :return: int (the QML type id)
-
- This function registers the Python *type* in the QML system with the
- name *qmlName*, in the library imported from *uri* having the
- version number composed from *versionMajor* and *versionMinor*.
-
- For example, this registers a Python class 'MySliderItem' as a QML
- type named 'Slider' for version '1.0' of a module called
- 'com.mycompany.qmlcomponents':
-
- ::
-
- qmlRegisterType(MySliderItem, "com.mycompany.qmlcomponents", 1, 0, "Slider")
-
- Once this is registered, the type can be used in QML by importing
- the specified module name and version number:
-
- ::
-
- import com.mycompany.qmlcomponents 1.0
-
- Slider { ... }
-
- Note that it's perfectly reasonable for a library to register types
- to older versions than the actual version of the library.
- Indeed, it is normal for the new library to allow QML written to
- previous versions to continue to work, even if more advanced
- versions of some of its types are available.
diff --git a/sources/pyside6/doc/extras/QtQml.qmlRegisterUncreatableType.rst b/sources/pyside6/doc/extras/QtQml.qmlRegisterUncreatableType.rst
deleted file mode 100644
index be25f5f1e..000000000
--- a/sources/pyside6/doc/extras/QtQml.qmlRegisterUncreatableType.rst
+++ /dev/null
@@ -1,38 +0,0 @@
-.. currentmodule:: PySide6.QtQml
-.. _qmlRegisterUncreatableType:
-
-
-qmlRegisterUncreatableType
-**************************
-
-
-.. py:function:: qmlRegisterUncreatableType(pytype: type, uri: str, versionMajor: int, versionMinor: int, qmlName: str, noCreationReason: str) -> int
-
-
- :param type pytype: Python class
- :param str uri: uri to use while importing the component in QML
- :param int versionMajor: major version
- :param int versionMinor: minor version
- :param str qmlName: name exposed to QML
- :param str noCreationReason: Error message shown when trying to create the QML type
- :return: int (the QML type id)
-
- This function registers the Python *type* in the QML system as an uncreatable type with the
- name *qmlName*, in the library imported from *uri* having the
- version number composed from *versionMajor* and *versionMinor*,
- showing *noCreationReason* as an error message when creating the type is attempted.
-
- For example, this registers a Python class 'MySliderItem' as a QML
- type named 'Slider' for version '1.0' of a module called
- 'com.mycompany.qmlcomponents':
-
- ::
- qmlRegisterUncreatableType(MySliderItem, "com.mycompany.qmlcomponents", 1, 0, "Slider", "Slider cannot be created.")
-
- Note that it's perfectly reasonable for a library to register types
- to older versions than the actual version of the library.
- Indeed, it is normal for the new library to allow QML written to
- previous versions to continue to work, even if more advanced
- versions of some of its types are available.
-
- Alternatively, the :ref:`QmlUncreatable` decorator can be used.
diff --git a/sources/pyside6/doc/extras/QtQuickTest.rst b/sources/pyside6/doc/extras/QtQuickTest.rst
new file mode 100644
index 000000000..52f13590b
--- /dev/null
+++ b/sources/pyside6/doc/extras/QtQuickTest.rst
@@ -0,0 +1,58 @@
+ Qt Quick Test is a unit test framework for QML applications. Test cases are
+ written as JavaScript functions within a QML TestCase type:
+
+.. code-block:: JavaScript
+
+ import QtQuick
+ import QtTest
+
+ TestCase {
+ name: "MathTests"
+
+ function test_math() {
+ compare(2 + 2, 4, "2 + 2 = 4")
+ }
+
+ function test_fail() {
+ compare(2 + 2, 5, "2 + 2 = 5")
+ }
+ }
+
+Functions whose names start with ``test_`` are treated as test cases to be
+executed.
+
+QML API
+^^^^^^^
+
+The `QML types <https://doc.qt.io/qt-6/qttest-qmlmodule.html>`_
+in Qt Quick Test are available through the ``QtTest`` import.
+To use the types, add the following import statement to your ``.qml`` file:
+
+.. code-block:: JavaScript
+
+ import QtTest
+
+Running Tests
+^^^^^^^^^^^^^
+
+Test cases are launched by a harness that consists of the following code:
+
+.. code-block:: Python
+
+ import sys
+ from PySide6.QtQuickTest import QUICK_TEST_MAIN
+
+ QUICK_TEST_MAIN("example", sys.argv)
+
+Where "example" is the identifier to use to uniquely identify this set of
+tests.
+
+Test execution can be controlled by a number of command line options (pass
+``-h`` for help).
+
+Executing Code Before QML Tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To execute code before any of the QML tests are run, the
+:py:func:`QUICK_TEST_MAIN_WITH_SETUP` function can be used. This can be useful
+for setting context properties on the QML engine, amongst other things.
diff --git a/sources/pyside6/doc/extras/QtSerialBus.rst b/sources/pyside6/doc/extras/QtSerialBus.rst
new file mode 100644
index 000000000..a6493a2ae
--- /dev/null
+++ b/sources/pyside6/doc/extras/QtSerialBus.rst
@@ -0,0 +1,46 @@
+The Qt Serial Bus API provides classes and functions to access the various
+industrial serial buses and protocols, such as CAN, ModBus, and others.
+
+Getting Started
+^^^^^^^^^^^^^^^
+
+To include the definitions of modules classes, use the following
+directive:
+
+::
+
+ import PySide6.QtSerialBus
+
+Supported Buses and Protocols
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ * Qt CAN Bus
+ * Qt Modbus
+
+Logging Categories
+^^^^^^^^^^^^^^^^^^
+
+The QtSerialBus module exports the following logging categories:
+
+.. list-table::
+ :header-rows: 1
+
+ * - Logging Category
+ - Description
+ * - qt.canbus
+ - Enables standard logging inside the Qt CAN Bus classes
+ * - qt.canbus.plugins
+ - Enables low level logging inside the Qt CAN Bus plugin classes. To set logging for a specific plugin, use ``qt.canbus.plugins.pluginname``, e.g. ``qt.canbus.plugins.socketcan``. ``qt.canbus.plugins*`` affects all plugins.
+ * - qt.modbus
+ - Enables standard logging inside the Qt Modbus classes
+ * - qt.modbus.lowlevel
+ - Enables low level logging including individual packet content inside the Qt Modbus classes
+
+Logging categories can be used to enable additional warning and debug output
+for QtSerialBus.
+
+A quick way to enable all Qt Modbus logging is to add the following line:
+
+.. code-block:: python
+
+ QLoggingCategory.setFilterRules("qt.modbus* = true")
diff --git a/sources/pyside6/doc/extras/QtUiTools.loadUiType.rst b/sources/pyside6/doc/extras/QtUiTools.loadUiType.rst
deleted file mode 100644
index 8a8c4bef0..000000000
--- a/sources/pyside6/doc/extras/QtUiTools.loadUiType.rst
+++ /dev/null
@@ -1,36 +0,0 @@
-.. currentmodule:: PySide6.QtUiTools
-.. _loadUiType:
-
-loadUiType
-***********
-
-.. py:function:: loadUiType(uifile: str) -> tuple(object, object)
-
- :param str uifile: The name of the `.ui` file
- :return: tuple(object, object)
-
- This function generates and loads a `.ui` file at runtime, and it returns
- a `tuple` containing the reference to the Python class, and the base class.
-
- We recommend not to use this approach as the workflow should be to generate a Python file
- from the `.ui` file, and then import and load it to use it, but we do understand that
- there are some corner cases when such functionality is required.
-
- The internal process relies on `uic` being in the PATH.
- The `pyside6-uic` wrapper uses a shipped `uic` that is located in the
- `site-packages/PySide6/uic`, so PATH needs to be updated to use that if there
- is no `uic` in the system.
-
- A simple use case is::
-
- from PySide6.QtUiTools import loadUiType
-
- generated_class, base_class = loadUiType("themewidget.ui")
- # the values will be:
- # (<class '__main__.Ui_ThemeWidgetForm'>, <class 'PySide6.QtWidgets.QWidget'>)
-
- widget = base_class()
- form = generated_class()
- form.setupUi(widget)
- # form.a_widget_member.a_method_of_member()
- widget.show()
diff --git a/sources/pyside6/doc/extras/QtUiTools.rst b/sources/pyside6/doc/extras/QtUiTools.rst
index 6861605bb..e83aa0357 100644
--- a/sources/pyside6/doc/extras/QtUiTools.rst
+++ b/sources/pyside6/doc/extras/QtUiTools.rst
@@ -1,5 +1,5 @@
-Qt Designer forms are processed at run-time to produce
-dynamically-generated user interfaces. In order to generate a form at
+*Qt Widgets Designer* forms are processed at run-time to produce
+dynamically-generated user interfaces. In order to generate a form at
run-time, a resource file containing a UI file is needed.
A form loader object, provided by the ``QUiLoader`` class, is used to
diff --git a/sources/pyside6/doc/extras/QtWidgets.rst b/sources/pyside6/doc/extras/QtWidgets.rst
index 8c91d3e31..784421aac 100644
--- a/sources/pyside6/doc/extras/QtWidgets.rst
+++ b/sources/pyside6/doc/extras/QtWidgets.rst
@@ -52,7 +52,7 @@ widget reports its size requirements to the layout through the
:meth:`sizePolicy<PySide6.QtWidgets.QWidget.sizePolicy>` properties,
and the layout distributes the available space accordingly.
-:ref:`Qt Designer<using_ui_files>` is a powerful tool for interactively
+:ref:`Qt Widgets Designer<using_ui_files>` is a powerful tool for interactively
creating and arranging widgets in layouts.
Model/View Classes
diff --git a/sources/pyside6/doc/faq.rst b/sources/pyside6/doc/faq.rst
index c1a27b3c2..4171df947 100644
--- a/sources/pyside6/doc/faq.rst
+++ b/sources/pyside6/doc/faq.rst
@@ -23,14 +23,14 @@ Frequently Asked Questions
Before the official release, everything was in one big wheel, so it made sense to split these
into separate wheels, each for the major projects currently in development:
- * **pyside6**: contains all the PySide6 modules to use the Qt framework; also depends on the
- shiboken6 module.
- * **shiboken6**: contains the shiboken6 module with helper functions for PySide6.
- * **shiboken6_generator**: contains the generator binary that can work with a C++ project and a
- typesystem to generate Python bindings.
- If you want to generate bindings for a Qt/C++ project, there won't be any linking to the Qt
- shared libraries; you need to do this by hand. We recommend building PySide6 from scratch
- to have everything properly linked.
+ * **pyside6**: contains all the PySide6 modules to use the Qt framework; also depends on the
+ shiboken6 module.
+ * **shiboken6**: contains the shiboken6 module with helper functions for PySide6.
+ * **shiboken6_generator**: contains the generator binary that can work with a C++ project and a
+ typesystem to generate Python bindings.
+ If you want to generate bindings for a Qt/C++ project, there won't be any linking to the Qt
+ shared libraries; you need to do this by hand. We recommend building PySide6 from scratch
+ to have everything properly linked.
**Why is the shiboken6_generator not installed automatically?**
It's not necessary to install the shiboken6_generator to use PySide6. The package is a result of
diff --git a/sources/pyside6/doc/tutorials/pretutorial/distribution.rst b/sources/pyside6/doc/faq/distribution.rst
index fea588153..fea588153 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/distribution.rst
+++ b/sources/pyside6/doc/faq/distribution.rst
diff --git a/sources/pyside6/doc/tutorials/pretutorial/hello_linux.png b/sources/pyside6/doc/faq/hello_linux.png
index f335a234d..f335a234d 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/hello_linux.png
+++ b/sources/pyside6/doc/faq/hello_linux.png
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/pretutorial/hello_macOS.png b/sources/pyside6/doc/faq/hello_macOS.png
index 863149399..863149399 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/hello_macOS.png
+++ b/sources/pyside6/doc/faq/hello_macOS.png
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/pretutorial/hello_win10.jpg b/sources/pyside6/doc/faq/hello_win10.jpg
index 78dcf8ab5..78dcf8ab5 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/hello_win10.jpg
+++ b/sources/pyside6/doc/faq/hello_win10.jpg
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/pretutorial/tiobe.png b/sources/pyside6/doc/faq/tiobe.png
index 87647d1c2..87647d1c2 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/tiobe.png
+++ b/sources/pyside6/doc/faq/tiobe.png
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/pretutorial/typesoffiles.rst b/sources/pyside6/doc/faq/typesoffiles.rst
index 71d38f809..3155b24fc 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/typesoffiles.rst
+++ b/sources/pyside6/doc/faq/typesoffiles.rst
@@ -36,9 +36,10 @@ functionality to your applications.
User Interface Definition File ``.ui``
--------------------------------------
-When using Qt Designer, you can create user interfaces using Qt Widgets with
-the WYSIWYG form editor, this interface is represented as a widget tree using
-XML. Here is an extract of the beginning of a ``.ui`` file:
+When using *Qt Widgets Designer*, you can create user interfaces using
+Qt Widgets with the WYSIWYG form editor, this interface is represented
+as a widget tree using XML. Here is an extract of the beginning of a
+``.ui`` file:
.. code-block:: xml
@@ -58,7 +59,6 @@ XML. Here is an extract of the beginning of a ``.ui`` file:
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
- ...
The `pyside6-uic` tool generates Python code from these `.ui` files,
which you can import from your main files, so it is not necessary
@@ -97,8 +97,8 @@ the QML file, and optionally, elements defined in Python that are exposed
to QML to be used.
You can write ``.qml`` files by hand, but also you can use tools like the
-QML Designer that is embedded in Qt Creator. Additionally, there are commercial
-tools like Qt Design Studio that allow you to load designs from other design
+*QML Designer* that is embedded in *Qt Creator*. Additionally, there are commercial
+tools like *Qt Design Studio* that allow you to load designs from other design
applications.
Here you can find an example of how a ``.qml`` file looks like.
@@ -128,11 +128,11 @@ message on it.
Qt Creator Python Project File ``.pyproject``
---------------------------------------------
-For Qt Creator to load and handle Python based projects, a special file is
+For *Qt Creator* to load and handle Python based projects, a special file is
needed, because C++ based projects could be handle from ``.qmake`` or
``CMakeLists.txt`` file, which are not used with Python-based projects.
-Old versions of Qt Creator, provided a simple format with the ``.pyqtc``
+Old versions of *Qt Creator*, provided a simple format with the ``.pyqtc``
extension, which were plain-text files with one-file-per-line::
library/server.py
diff --git a/sources/pyside6/doc/tutorials/pretutorial/whatisqt.rst b/sources/pyside6/doc/faq/whatisqt.rst
index 2dee661a7..3b42a9403 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/whatisqt.rst
+++ b/sources/pyside6/doc/faq/whatisqt.rst
@@ -25,7 +25,7 @@ As a framework, Qt has many components, which are distributed by components
and modules, for example, `qtbase <https://code.qt.io/cgit/qt/qtbase.git/>`_
is the base component that holds many modules, like: ``QtCore``, ``QtGui``,
``QtWidgets``, ``QtNetwork``, etc.
-All those modules contains many classes that you can directly use, like the
+All those modules contains many classes that you can directly use, like the
case of the `Classes of QtCore <https://doc.qt.io/qt-6/qtcore-module.html>`_
from which you can find classes like ``QFile``, ``QTime``, ``QByteArray``, etc.
@@ -65,8 +65,8 @@ is not to affect the user experience compared to other included applications.
.. note:: You can adapt these applications to use your self-made style, but
you need to be aware that the goal of Widgets is to respect the system
- style, be careful when changing colors. Check this `simple tutorial
- <widgetstyling>`_ on how to do so.
+ style, be careful when changing colors. Check this
+ :ref:`simple tutorial <widgetstyling>` on how to do so.
QML
---
diff --git a/sources/pyside6/doc/tutorials/pretutorial/whatisshiboken.rst b/sources/pyside6/doc/faq/whatisshiboken.rst
index e867fadd4..bf6d19ab3 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/whatisshiboken.rst
+++ b/sources/pyside6/doc/faq/whatisshiboken.rst
@@ -4,11 +4,9 @@ Binding Generation: What Is Shiboken?
=====================================
When you install ``PySide6`` you might have notice that also ``Shiboken6``
-is installed as a dependency:
+is installed as a dependency::
-.. code-block:: bash
-
- (env) [qt ~]$ pip install pyside6
+ $ pip install pyside6
Collecting pyside6
Downloading PySide6-6.0.0-6.0.0-cp36.cp37.cp38.cp39-abi3-manylinux1_x86_64.whl (170.5 MB)
|████████████████████████████████| 170.5 MB 42 kB/s
diff --git a/sources/pyside6/doc/tutorials/pretutorial/whichide.rst b/sources/pyside6/doc/faq/whichide.rst
index ec005a188..3afa79b7f 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/whichide.rst
+++ b/sources/pyside6/doc/faq/whichide.rst
@@ -4,7 +4,7 @@ Which IDEs Are Compatible?
==========================
|project|, as any other Python module, can be used in any Python-compatible
-IDE, but not all of them will provide extra functionality like Qt Creator does.
+IDE, but not all of them will provide extra functionality like *Qt Creator* does.
Besides writing files, there are some external steps you might want to perform
in order to help the development of your applications:
@@ -15,8 +15,8 @@ From a terminal:
:command:`pyside6-uic -i form.ui -o ui_form.py`
* Generating a Python file from a ``.qrc`` file:
:command:`pyside6-rcc -i resources.qrc -o rc_resources.py`
-* Opening Qt Designer with the command :command:`pyside6-designer` to
- edit/create ``.ui`` files.
+* Opening *Qt Widgets Designer* with the command :command:`pyside6-designer`
+ to edit/create ``.ui`` files.
External add-ons/plugins from your favorite IDE might include configuration
steps to run these commands, or open external tools like Designer and
@@ -47,8 +47,10 @@ that you can install from VS Code while writing the following on the Quick Open
PyCharm
-------
-You can configure PyCharm to enable external tools, in |project| terms, Qt Designer, and
-Qt Creator. Go to ``File > Settings > tools > PyCharm External Tools``, and include the following
+You can configure PyCharm to enable external tools, in |project| terms,
+*Qt Widgets Designer*, and *Qt Creator*. Go to
+``File > Settings > tools > PyCharm External Tools``, and include the following
information to add them to your project.
-Later, you will be able to right click a ``.ui`` file, and select ``Qt Designer``,
-``pyside6-uic``, or any tool that you configured this way.
+Later, you will be able to right click a ``.ui`` file, and select
+``Qt Widgets Designer``, ``pyside6-uic``, or any tool that you configured this
+way.
diff --git a/sources/pyside6/doc/tutorials/pretutorial/whyqtforpython.rst b/sources/pyside6/doc/faq/whyqtforpython.rst
index 6046249b9..0f0ab9aaf 100644
--- a/sources/pyside6/doc/tutorials/pretutorial/whyqtforpython.rst
+++ b/sources/pyside6/doc/faq/whyqtforpython.rst
@@ -10,7 +10,7 @@ Why Qt for Python?
<div style="float: right; padding-left: 20px; max-width: 30%;
background-color: #e9eff5; padding-top: 5px;">
- <img src="../../_images/tiobe.png"
+ <img src="../_images/tiobe.png"
style="width: 90%;"
alt="TIOBE index for Python" />
<p style="font-size: 80%;">
@@ -67,13 +67,9 @@ Creating Qt applications in Python requires only a few lines of code,
and not much configuration is required to execute it. As an /unfair/
example, let's check the code of a simple hello world application:
+.. tab-set::
-.. panels::
- :container: container-lg
-
- :column: col-lg-6 p-2
-
- .. tabbed:: C++ Header
+ .. tab-item:: C++ Header
.. code-block:: cpp
@@ -96,7 +92,7 @@ example, let's check the code of a simple hello world application:
#endif // MAINWINDOW_H
- .. tabbed:: C++ Implementation
+ .. tab-item:: C++ Implementation
.. code-block:: cpp
@@ -115,7 +111,7 @@ example, let's check the code of a simple hello world application:
m_button->setText("Ready");
}
- .. tabbed:: C++ Main
+ .. tab-item:: C++ Main
.. code-block:: cpp
@@ -130,10 +126,9 @@ example, let's check the code of a simple hello world application:
return app.exec(d);
}
- ---
- :column: col-lg-6 p-2
+.. tab-set::
- .. tabbed:: Python
+ .. tab-item:: Python
.. code-block:: python
diff --git a/sources/pyside6/doc/gettingstarted-linux.rst b/sources/pyside6/doc/gettingstarted-linux.rst
deleted file mode 100644
index 1f8ed9bcc..000000000
--- a/sources/pyside6/doc/gettingstarted-linux.rst
+++ /dev/null
@@ -1,79 +0,0 @@
-Getting Started on Linux
-==========================
-
-Requirements
-------------
-
- * GCC
- * ``sphinx`` package for the documentation (optional).
- * Depending on your linux distribution, the following dependencies might also be required:
-
- * ``libgl-dev``, ``python-dev``, ``python-distutils``, and ``python-setuptools``.
-
-Building from source
---------------------
-
-Creating a virtual environment
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The ``venv`` module allows you to create a local, user-writeable copy of a python environment into
-which arbitrary modules can be installed and which can be removed after use::
-
- python -m venv testenv
- source testenv/bin/activate
- pip install -r requirements.txt # General dependencies, documentation, and examples.
-
-will create and use a new virtual environment, which is indicated by the command prompt changing.
-
-Setting up CLANG
-~~~~~~~~~~~~~~~~
-
-If you don't have libclang already in your system, you can download from the Qt servers::
-
- wget https://download.qt.io/development_releases/prebuilt/libclang/libclang-release_100-based-linux-Rhel7.6-gcc5.3-x86_64.7z
-
-Extract the files, and leave it on any desired path, and set the environment
-variable required::
-
- 7z x libclang-release_100-based-linux-Rhel7.6-gcc5.3-x86_64.7z
- export LLVM_INSTALL_DIR=$PWD/libclang
-
-Getting PySide
-~~~~~~~~~~~~~~
-
-Cloning the official repository can be done by::
-
- git clone --recursive https://code.qt.io/pyside/pyside-setup
-
-Checking out the version that we want to build, for example 6.0::
-
- cd pyside-setup && git checkout 6.0
-
-.. note:: Keep in mind you need to use the same version as your Qt installation.
- Additionally, :command:`git checkout -b 6.0 --track origin/6.0` could be a better option
- in case you want to work on it.
-
-Building PySide
-~~~~~~~~~~~~~~~
-
-Check your Qt installation path, to specifically use that version of qtpaths to build PySide.
-for example, :command:`/opt/Qt/6.0.0/gcc_64/bin/qtpaths`.
-
-Build can take a few minutes, so it is recommended to use more than one CPU core::
-
- python setup.py build --qtpaths=/opt/Qt/6.0.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
-
-Installing PySide
-~~~~~~~~~~~~~~~~~
-
-To install on the current directory, just run::
-
- python setup.py install --qtpaths=/opt/Qt/6.0.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
-
-Test installation
-~~~~~~~~~~~~~~~~~
-
-You can execute one of the examples to verify the process is properly working.
-Remember to properly set the environment variables for Qt and PySide::
-
- python examples/widgets/widgets/tetrix.py
diff --git a/sources/pyside6/doc/gettingstarted.rst b/sources/pyside6/doc/gettingstarted/index.rst
index 1a465b79c..9d36061ad 100644
--- a/sources/pyside6/doc/gettingstarted.rst
+++ b/sources/pyside6/doc/gettingstarted/index.rst
@@ -1,10 +1,10 @@
-|project| Getting Started
-==========================
+Getting Started
+===============
.. important:: This page is focused on building |project| **from source**.
If you just want to install |pymodname|, you need to run: :command:`pip install pyside6`.
- For more details, refer to our `Quick Start`_ guide. Additionally, you can check the
+ For more details, refer to our :ref:`quick-start` guide. Additionally, you can check the
:ref:`FAQ <faq>` related to the project.
.. _Quick Start: quickstart.html
@@ -17,39 +17,74 @@ On **Linux** you might get them with your operating system package manager, on *
you might get them with ``brew``, and on **Windows** you can download the installer from each
website.
- * **Python**: 3.6+ `[official Python website] <https://www.python.org/downloads/>`_
- * **Qt:** 6.0+ `[online installer] <https://download.qt.io/official_releases/online_installers/>`_
- * **CMake:** 3.18+ `[official CMake website] <https://cmake.org/download/>`_
- * **Git:** 2.0+. `[official Git website] <https://git-scm.com/downloads>`_
- * **libclang:** The libclang library, recommended: version 10 for 6.0+.
- Prebuilt versions for each OS can be `downloaded here`_.
+* **Python**: 3.9+ `[official Python website] <https://www.python.org/downloads/>`_
+* **Qt:** 6.4+ `[online installer] <https://download.qt.io/official_releases/online_installers/>`_
+* **CMake:** 3.18+ `[official CMake website] <https://cmake.org/download/>`_
+* **Git:** 2.0+. `[official Git website] <https://git-scm.com/downloads>`_
+* **libclang:** The libclang library, recommended: version 10 for 6.0+.
+ Prebuilt versions for each OS can be `downloaded here`_.
+* Check the `Supported Platforms of Qt`_
.. _downloaded here: https://download.qt.io/development_releases/prebuilt/libclang/
+.. _`Supported Platforms of Qt` : https://doc.qt.io/qt-6/supported-platforms.html
Guides per platform
-------------------
+.. toctree::
+ :maxdepth: 1
+ :hidden:
+
+ linux.rst
+ macOS.rst
+ windows.rst
+ package_details.rst
+ porting_from2.rst
+
You can refer to the following pages for platform specific instructions:
-.. raw:: html
-
- <table class="special">
- <colgroup>
- <col style="width: 200px" />
- <col style="width: 200px" />
- <col style="width: 200px" />
- </colgroup>
- <tr>
- <td><a href="gettingstarted-windows.html"><p><strong>Windows</strong></p></a></td>
- <td><a href="gettingstarted-macOS.html"><p><strong>macOS</strong></p></a></td>
- <td><a href="gettingstarted-linux.html"><p><strong>Linux</strong></p></a></td>
- </tr>
- </table>
+.. grid:: 1 3 3 3
+ :gutter: 2
-.. important:: |project| does not yet support WebAssembly and the mobile operating systems (Android or iOS).
+ .. grid-item-card::
+ :img-top: ../images/windows.svg
+ :class-item: text-center
+
+ +++
+ .. button-ref:: windows
+ :color: primary
+ :outline:
+ :expand:
+
+ Windows
+
+ .. grid-item-card::
+ :img-top: ../images/macos.svg
+ :class-item: text-center
+
+ +++
+ .. button-ref:: macOS
+ :color: primary
+ :outline:
+ :expand:
-Most Linux-based embedded OS provide PySide with their official
-package manager (for example, `Raspbian`_ and `ArchlinuxARM`_).
+ macOS
+
+ .. grid-item-card::
+ :img-top: ../images/linux.svg
+ :class-item: text-center
+
+ +++
+ .. button-ref:: linux
+ :color: primary
+ :outline:
+ :expand:
+
+ Linux
+
+.. important:: |project| does not yet support WebAssembly and the mobile operating systems (Android or iOS).
+ Most Linux-based embedded OS provide PySide with their official
+ package manager (for example, `Raspbian`_ and `ArchlinuxARM`_).
.. _Raspbian: https://www.raspbian.org/
.. _ArchlinuxARM: https://archlinuxarm.org/
@@ -67,7 +102,9 @@ A normal building command will look like this::
Which will build and install the project with **debug** symbols, including the **tests**,
using **ninja** (instead of make), and considering only the **module subset** of
:mod:`QtCore <PySide6.QtCore>`, :mod:`QtGui <PySide6.QtGui>`, and
-:mod:`QtWidgets <PySide6.QtWidgets`.
+:mod:`QtWidgets <PySide6.QtWidgets>`.
+
+`CMake Unity Build Mode`_ is used by default for speed-up.
Other important options to consider are:
* ``--cmake``, to specify the path to the cmake binary,
@@ -94,7 +131,7 @@ Using the ``--build-tests`` option will enable us to run all the auto tests insi
python testrunner.py test > testlog.txt
.. note:: On Windows, don't forget to have qtpaths in your path
- (:command:`set PATH=E:\\\Path\\\to\\\Qt\\\6.0.0\\\msvc2019_64\\\bin;%PATH%`)
+ (:command:`set PATH=C:\\\Path\\\to\\\Qt\\\6.4.0\\\msvc2019_64\\\bin;%PATH%`)
You can also run a specific test (for example ``qpainter_test``) by running::
@@ -106,7 +143,7 @@ Cross Compilation
-----------------
Starting from 6.3, it is possible to cross-compile Shiboken (module), and
-PySide. This functionality is still in Technical Preview, which means it could
+PySide. This functionality is still in Technical Preview, which means it could
change in the future releases.
.. important:: The only supported configuration is using a host Linux
@@ -133,12 +170,14 @@ on both the host, and the target. The used Qt versions on both platforms
should have the same minor version. That is, Qt 6.3 (host)
cannot be used with a Qt 6.2 (target), or the other way around.
+.. note:: It is recommended to use the same version of Qt on both host and target to avoid possible
+ unconventional errors.
Prerequisites
~~~~~~~~~~~~~
First and foremost, you need to have access to the target device because you
-need to copy several system files (sysroot). We recommend a Linux OS that has
+need to copy several system files (sysroot). We recommend a Linux OS that has
the latest Qt versions, like `Manjaro ARM`_ or `Archlinux ARM`_.
* (target) Install Qt 6.3+ on the system using the package manager.
@@ -151,7 +190,7 @@ the latest Qt versions, like `Manjaro ARM`_ or `Archlinux ARM`_.
After installing these prerequisites, copy the ``target`` sysroot to your
``host`` computer. This process is tricky, because copying system files from
-another computer might cause problems with the symbolic links. Here you
+another computer might cause problems with the symbolic links. Here you
have two options to achieve that.
Option A: Copying the files
@@ -185,6 +224,9 @@ Copy the package from the target to your host:
Once you have the tar file, unpack it inside a ``rpi-sysroot`` directory.
+Fix Symlinks
+************
+
It is recommended to run the following script to fix
most of the issues you would find with symbolic links:
@@ -233,7 +275,7 @@ and unpacked it.
With those compilers, now you need a CMake toolchain file. This is
a configuration file to set the compilers and sysroot information, together
-with extra options like compilation flags, and other details. You can use the
+with extra options like compilation flags, and other details. You can use the
following file as an example, but keep in mind they might vary:
.. code-block:: cmake
@@ -316,11 +358,15 @@ An example of the ``setup.py`` invocation might look like the following:
--parallel=8 --ignore-git --reuse-build --standalone --limited-api=yes \
--cmake-toolchain-file=/opt/toolchain-aarch64.cmake \
--qt-host-path=/opt/Qt/6.3.0/gcc_64 \
- --plat-name=linux_aarch64 \
+ --plat-name=linux_aarch64
Depending on the target platform, you could use ``linux_armv7``,
``linux_aarch64``, etc.
+For embedded platforms, which typically do not have Qt and its tools fully
+built, the option ``--no-qt-tools`` can be used to prevent the bundling of the
+tools.
+
If the process succeeds, you will find the target wheels in your ``dist/``
directory, for example:
@@ -361,20 +407,28 @@ Starting from 6.3, the documentation is not being built by default.
When using the second option described in this section, make sure to use the
``--build-docs`` option.
+Install the specific documentation requirements in your Python virtual
+environment::
+
+ pip install -r requirements-doc.txt
+
+You can find the ``requirements-doc.txt`` file in the root of the repository.
+
Starting from 5.15, there are two options to build the documentation:
-1. Building rst-only documentation (no API)
+1. Building the base documentation (no API)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The process of parsing Qt headers to generate the PySide API documentation can take several
-minutes, this means that modifying a specific section of the rst files we currently have, might
-become a hard task.
+minutes, this means that modifying a specific section of the documentation we currently have, might
+become a hard task. You may only care about the base documentation, which comprises all the
+documentation except for the API documentation.
-For this, you can install :command:`sphinx` on a virtual environment, and execute the following command::
+To generate this, execute the following command::
- python setup.py build_rst_docs
+ python setup.py build_base_docs
-which will generate a ``html/`` directory with the following structure::
+This will generate an ``html/`` directory with the following structure::
html
└── pyside6
@@ -390,34 +444,41 @@ files.
This is useful when updating the general sections of the documentation, adding tutorials,
modifying the build instructions, and more.
-2. Building the documentation (rst + API)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. note:: In case you are interested in only generating the Example Gallery,
+ you would need to run ``python tools/example_gallery/main.py`` to
+ generate the examples ``documentation`` for the gallery. This will
+ also be used internally by the ``build_base_docs`` target
+
+
+2. Building the documentation (Base + API)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The documentation is being generated using **qdoc** to get the API information, and also **sphinx**
for the local Python related notes.
-The system required ``libxml2`` and ``libxslt``, also on the Python environment, ``sphinx`` and
-``graphviz`` need to be installed before running the installation process::
+The system requires the ``libxml2`` and ``libxslt`` libraries.
- pip install graphviz sphinx sphinx_tabs
-
-After installing ``graphviz``, the ``dot`` command needs to be in PATH, otherwise,
+After installing ``graphviz`` (included in the ``requirements-doc.txt`` file),
+the ``dot`` command needs to be in PATH, otherwise,
the process will fail. Installing ``graphviz`` system-wide is also an option.
Since the process relies on a Qt installation, you need to specify where the
-``qtbase`` directory is located::
-
- export QT_SRC_DIR=/path/to/qtbase
+``qtbase`` directory of a Qt source tree is located by passing it to
+the command line option ``--qt-src-dir``.
-Once the common ``setup.py`` build process finishes (remember to use ``--build-docs`` to enable
-the documentation build), you can go to the generated ``*_build/*_release/pyside6``
-directory, and run::
+Once the common ``setup.py`` build process finishes (remember to use
+``--build-docs`` to enable the documentation build, and ``--doc-build-online``
+to get the HTML files), you can go to the generated
+``build/<your_env_name>/build/pyside6`` directory, and run::
ninja apidoc
-.. note:: The :command:`apidoc` make target builds offline documentation in QCH (Qt Creator Help)
- format by default. You can switch to building for the online use with the ``--doc-build-online``
- configure option.
+You can add ``-j X``, to perform the build process in parallel with
+X processes.
+
+.. note:: The :command:`apidoc` make target builds offline documentation in ``QCH``
+ (Qt Compressed Help) format by default. You can switch to building for the
+ online use with the ``--doc-build-online`` configure option.
The target executes several steps:
@@ -426,37 +487,42 @@ The target executes several steps:
#. ``sphinx`` is run to produce the documentation in HTML format.
Re-running the command will not execute step 1 unless the file
-``qdoc_output/webxml/qtcore-index.webxml`` is removed from the build tree.
-Similarly, step 2 will not be executed unless the file ``rst/PySide6/QtCore/index.rst``
+``qdoc-output/webxml/qtcore-index.webxml`` is removed from the build tree.
+Similarly, step 2 will not be executed unless the file ``base/PySide6/QtCore/index.rst``
is removed.
Finally, you will get a ``html`` directory containing all the generated documentation. The offline
help files, ``PySide.qch`` and ``Shiboken.qch``, can be moved to any directory of your choice. You
-can find ``Shiboken.qch`` in the build directory, ``*_build\*_release\shiboken6\doc\html``.
+can find ``Shiboken.qch`` in the build directory, ``build/<your_env_name>/build/shiboken6/doc/html``.
If you want to temporarily change a ``.rst`` file to examine the impact on
formatting, you can re-run ``sphinx`` in the ``doc`` directory::
- sphinx-build rst html
+ sphinx-build base html
Viewing offline documentation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The offline documentation (QCH) can be viewed using the Qt Creator IDE or Qt Assistant, which is
-a standalone application for viewing QCH files.
+The offline documentation (QCH) can be viewed using the *Qt Creator* IDE or
+*Qt Assistant*, which is a standalone application for viewing QCH files.
-To view the QCH using Qt Creator, following the instructions outlined in
-`Using Qt Creator Help Mode <https://doc.qt.io/qtcreator/creator-help.html>`_. If you chose to
-use Qt Assistant instead, use the following command to register the QCH file before launching
-Qt Assistant::
+To view the QCH using *Qt Creator*, following the instructions outlined in
+`Using Qt Creator Help Mode <https://doc.qt.io/qtcreator/creator-help.html>`_.
+If you chose to use *Qt Assistant* instead, use the following command to register
+the QCH file before launching *Qt Assistant*::
assistant -register PySide.qch
-.. note:: Qt Assistant renders the QCH content using the QTextBrowser backend, which supports
- a subset of the CSS styles, However, Qt Creator offers an alternative litehtml-based
- backend, which offers better browsing experience. At the moment, this is not the default
- backend, so you have to select the litehtml backend
- explicitly under the ``General`` tab in ``Qt Creator >> Tools >> Options >> Help``.
+Troubleshooting documentation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The documentation uses intersphinx to link from the PySide to the
+Shiboken documentation. This can fail if
+
+* the default ``QCH`` format is used; in which case the required ``objects.inv``
+ files are not generated. Use ``--doc-build-online``.
+* base and full doc builds are mixed, resulting in wrong values for the
+ intersphinx location in the CMake files. Re-run ``cmake`` to fix this.
Using the internal tools
------------------------
@@ -503,3 +569,4 @@ A set of tools can be found under the ``tools/`` directory inside the ``pyside-s
.. _repository: https://github.com/liyanage/macosx-shell-scripts/
.. _`wiki page`: https://wiki.qt.io/Qt_for_Python_Missing_Bindings
.. _BeautifulSoup: https://www.crummy.com/software/BeautifulSoup/
+.. _`CMake Unity Build Mode` : https://cmake.org/cmake/help/latest/prop_tgt/UNITY_BUILD.html
diff --git a/sources/pyside6/doc/gettingstarted/linux.rst b/sources/pyside6/doc/gettingstarted/linux.rst
new file mode 100644
index 000000000..912105ef8
--- /dev/null
+++ b/sources/pyside6/doc/gettingstarted/linux.rst
@@ -0,0 +1,115 @@
+Getting Started on Linux
+==========================
+
+Requirements
+------------
+
+* GCC
+* ``sphinx`` package for the documentation (optional).
+* Depending on your linux distribution, the following dependencies might also be required:
+
+ * ``libgl-dev``, ``python-dev``, and ``python-setuptools``.
+* Check the platform dependencies of `Qt for Linux/X11`_.
+
+Building from source
+--------------------
+
+Creating a virtual environment
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``venv`` module allows you to create a local, user-writeable copy of a python environment into
+which arbitrary modules can be installed and which can be removed after use::
+
+ python -m venv testenv
+ source testenv/bin/activate
+
+will create and use a new virtual environment, which is indicated by the command prompt changing.
+
+Setting up CLANG
+~~~~~~~~~~~~~~~~
+
+If you don't have libclang already in your system, you can download from the Qt servers::
+
+ wget https://download.qt.io/development_releases/prebuilt/libclang/libclang-release_140-based-linux-Rhel8.2-gcc9.2-x86_64.7z
+
+Extract the files, and leave it on any desired path, and set the environment
+variable required::
+
+ 7z x libclang-release_140-based-linux-Rhel8.2-gcc9.2-x86_64.7z
+ export LLVM_INSTALL_DIR=$PWD/libclang
+
+Getting the source
+~~~~~~~~~~~~~~~~~~
+
+Cloning the official repository can be done by::
+
+ git clone https://code.qt.io/pyside/pyside-setup
+
+Checking out the version that we want to build, for example 6.5::
+
+ cd pyside-setup && git checkout 6.5
+
+Install the general dependencies::
+
+ pip install -r requirements.txt
+
+.. note:: Keep in mind you need to use the same version as your Qt installation.
+ Additionally, :command:`git checkout -b 6.5 --track origin/6.5` could be a better option
+ in case you want to work on it.
+
+Building and Installing (setuptools)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``setuptools`` approach uses the ``setup.py`` file to execute the build,
+install, and packaging steps.
+
+Check your Qt installation path, to specifically use that version of qtpaths to build PySide.
+for example, :command:`/opt/Qt/6.5.0/gcc_64/bin/qtpaths`.
+
+Build can take a few minutes, so it is recommended to use more than one CPU core::
+
+ python setup.py build --qtpaths=/opt/Qt/6.5.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
+
+To install on the current directory, just run::
+
+ python setup.py install --qtpaths=/opt/Qt/6.5.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
+
+Building and Installing (cmake)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``setuptools`` approach includes internal ``CMake`` calls when
+building and installing the project, but a CMake-only approach is only
+recommended for packaging the project for distribution builds.
+
+Assumming that Qt is in PATH, for example, the configure step can be done with::
+
+ cmake -B /path/to/the/build/directory \
+ -S /path/to/the/pyside-setup \
+ -DCMAKE_INSTALL_PREFIX=/where/to/install \
+ -DPython_EXECUTABLE=/path/to/interpreter
+
+.. note:: You can add `-DFORCE_LIMITED_API=yes` in case you want to have a
+ build which will be compatible with Python 3.7+.
+
+and then for building::
+
+ cmake --build /path/to/the/build/directory --parallel X
+
+where `X` is the amount of processes you want to use.
+Finally, the install step can be done with::
+
+ cmake --install /path/to/the/build/directory
+
+.. note:: You can build only pyside6 or only shiboken6 by using
+ the diferent source directories with the option `-S`.
+
+
+Test installation
+~~~~~~~~~~~~~~~~~
+
+You can execute one of the examples to verify the process is properly working.
+Remember to properly set the environment variables for Qt and PySide::
+
+ python examples/widgets/widgets/tetrix.py
+
+.. _`Qt for Linux/X11`: https://doc.qt.io/qt-6/linux.html
diff --git a/sources/pyside6/doc/gettingstarted-macOS.rst b/sources/pyside6/doc/gettingstarted/macOS.rst
index 4bb99f7c9..ff457a4e2 100644
--- a/sources/pyside6/doc/gettingstarted-macOS.rst
+++ b/sources/pyside6/doc/gettingstarted/macOS.rst
@@ -4,14 +4,16 @@ Getting Started on macOS
Requirements
------------
- * `XCode`_ 8.2 (macOS 10.11), 8.3.3 (macOS 10.12), 9 (macOS 10.13), 10.1 (macOS 10.14)
- * ``sphinx`` package for the documentation (optional).
- * Depending on your OS, the following dependencies might also be required:
+* `XCode`_ 8.2 (macOS 10.11), 8.3.3 (macOS 10.12), 9 (macOS 10.13), 10.1 (macOS 10.14)
+* ``sphinx`` package for the documentation (optional).
+* Depending on your OS, the following dependencies might also be required:
- * ``libgl-dev``, ``python-dev``, ``python-distutils``, and ``python-setuptools``.
+ * ``libgl-dev``, ``python-dev``, and ``python-setuptools``.
-.. _XCode: https://developer.apple.com/xcode/
+* Check the platform dependencies of `Qt for macOS`_.
+.. _XCode: https://developer.apple.com/xcode/
+.. _`Qt for macOS`: https://doc.qt.io/qt-6/macos.html
Building from source
--------------------
@@ -24,7 +26,6 @@ which arbitrary modules can be installed and which can be removed after use::
python -m venv testenv # your interpreter could be called 'python3'
source testenv/bin/activate
- pip install -r requirements.txt # General dependencies, documentation, and examples.
will create and use a new virtual environment, which is indicated by the command prompt changing.
@@ -33,12 +34,12 @@ Setting up CLANG
If you don't have libclang already in your system, you can download from the Qt servers::
- wget https://download.qt.io/development_releases/prebuilt/libclang/libclang-release_100-based-mac.7z
+ wget https://download.qt.io/development_releases/prebuilt/libclang/libclang-release_140-based-macos-universal.7z
Extract the files, and leave it on any desired path, and set the environment
variable required::
- 7z x libclang-release_100-based-mac.7z
+ 7z x libclang-release_140-based-macos-universal.7z
export LLVM_INSTALL_DIR=$PWD/libclang
Getting PySide
@@ -46,11 +47,15 @@ Getting PySide
Cloning the official repository can be done by::
- git clone --recursive https://code.qt.io/pyside/pyside-setup
+ git clone https://code.qt.io/pyside/pyside-setup
+
+Checking out the version that we want to build, for example, 6.5::
+
+ cd pyside-setup && git checkout 6.5
-Checking out the version that we want to build, for example, 6.0::
+Install the general dependencies::
- cd pyside-setup && git checkout 6.0
+ pip install -r requirements.txt
.. note:: Keep in mind you need to use the same version as your Qt installation
@@ -58,18 +63,18 @@ Building PySide
~~~~~~~~~~~~~~~
Check your Qt installation path, to specifically use that version of qtpaths to build PySide.
-for example, ``/opt/Qt/6.0.0/gcc_64/bin/qtpaths``.
+for example, ``/opt/Qt/6.5.0/gcc_64/bin/qtpaths``.
Build can take a few minutes, so it is recommended to use more than one CPU core::
- python setup.py build --qtpaths=/opt/Qt/6.0.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
+ python setup.py build --qtpaths=/opt/Qt/6.5.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
Installing PySide
~~~~~~~~~~~~~~~~~
To install on the current directory, just run::
- python setup.py install --qtpaths=/opt/Qt/6.0.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
+ python setup.py install --qtpaths=/opt/Qt/6.5.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
Test installation
~~~~~~~~~~~~~~~~~
diff --git a/sources/pyside6/doc/gettingstarted/package_details.rst b/sources/pyside6/doc/gettingstarted/package_details.rst
new file mode 100644
index 000000000..113edb686
--- /dev/null
+++ b/sources/pyside6/doc/gettingstarted/package_details.rst
@@ -0,0 +1,75 @@
+.. _package_details:
+
+Package Details
+===============
+
+Having a large project as the Qt Framework available from one simple
+installation line::
+
+ pip install pyside6
+
+is really beneficial,
+but it might be confusing to newcomers.
+
+Besides your IDE, you don't need to install anything else to develop your
+Qt application, because the same command installs many tools
+that will help you design UIs, use QML types, generate
+files automatically, translate applications, etc.
+
+Package Dependencies
+--------------------
+
+.. image:: packages.png
+ :width: 400
+ :alt: Packages structure and dependency
+
+Starting from 6.3.0, the ``pyside6`` package (wheel) is almost empty,
+and only includes references to other packages that are required
+to properly use all the modules.
+This packages are:
+
+* ``pyside6-essentials``, `essential Qt modules <https://pypi.org/project/PySide6-Essentials/>`_,
+* ``pyside6-addons``, `additional Qt modules <https://pypi.org/project/PySide6-Addons/>`_,
+* ``shiboken6``, a utility Python module.
+
+You can verify this by running ``pip list`` to check the installed
+packages in your Python (virtual) environment::
+
+ (env) % pip list
+ Package Version
+ ------------------ -------
+ pip 22.0.4
+ PySide6 6.3.0
+ PySide6-Addons 6.3.0
+ PySide6-Essentials 6.3.0
+ setuptools 58.1.0
+ shiboken6 6.3.0
+
+Both ``pyside6-essentials`` and ``pyside6-addons`` contain Qt binaries
+(``.so``, ``.dll``, or ``.dylib``) that are used by the Python wrappers
+that enable you to use the Qt modules from Python.
+For example, in the ``QtCore`` module, you will find
+on Linux:
+
+* ``PySide6/QtCore.abi3.so``, and
+* ``PySide6/Qt/lib/libQt6Core.so.6``
+
+inside the ``site-packages`` directory of your (virtual) environment.
+The first is the *importable* module which depends on the second file
+which is the original QtCore library.
+
+.. note:: The package ``shiboken6-generator`` is not a dependency,
+ and it's not available on PyPi. The reason, is that it depends on
+ ``libclang``, which is a large library that we don't package, and
+ requires a special configuration for you to use. Check the `Shiboken
+ Documentation`_ for more details.
+
+..
+ Adding the full URL because it's a different sphinx project.
+.. _`Shiboken Documentation`: https://doc.qt.io/qtforpython/shiboken6/gettingstarted.html
+
+Tools Included
+--------------
+
+PySide6 comes bundled with a set of tools that assist in making the development experience with
+PySide6 more efficient. The list of tools can be found :ref:`here <package_tools>`.
diff --git a/sources/pyside6/doc/gettingstarted/packages.png b/sources/pyside6/doc/gettingstarted/packages.png
new file mode 100644
index 000000000..57e7ca47d
--- /dev/null
+++ b/sources/pyside6/doc/gettingstarted/packages.png
Binary files differ
diff --git a/sources/pyside6/doc/gettingstarted/porting_from2.rst b/sources/pyside6/doc/gettingstarted/porting_from2.rst
new file mode 100644
index 000000000..6699f54e0
--- /dev/null
+++ b/sources/pyside6/doc/gettingstarted/porting_from2.rst
@@ -0,0 +1,94 @@
+Porting Applications from PySide2 to PySide6
+============================================
+
+Module Availability
+-------------------
+
+Qt for Python 6.2.0 provides all modules planned for inclusion in Qt 6.
+
+Module-Level Changes
+--------------------
+
+* The modules *QtMacExtras*, *Qt Quick Controls 1*, *QtWinExtras*,
+ *QtXmlPatterns* and *QtX11Extras* have been removed.
+* ``QStateMachine`` and related classes have been extracted to a new
+ *QtStateMachine* module.
+* The modules *QtWebKit* and *QtWebKitWidgets* have been replaced by the new
+ *QtWebEngineCore*, *QtWebEngineQuick* and *QtWebEngineWidgets* modules.
+* ``QXmlReader`` and related classes (*SAX API*) have been removed.
+* The content of the *QtOpenGL* module has been replaced. The class
+ ``QGLWidget`` and related classes (``QGLContext``, ``QGLFunctions``,
+ ``QGLShaderProgram``) have been removed. Parts of the *Open GL*
+ functionality from *QtGui* have been extracted into this module, for example
+ ``QOpenGLBuffer`` and ``QOpenGLShaderProgram``.
+ There is a new module *QtOpenGLWidgets* which contains the class
+ ``QOpenGLWidget``, a replacement for ``QGLWidget``.
+
+As *Open GL* is phasing out,
+`QRhi <https://doc.qt.io/qt-6/topics-graphics.html>`_ should be considered
+for graphics applications.
+
+Imports
+-------
+
+The first thing to do when porting applications is to replace the
+import statements:
+
+.. code-block:: python
+
+ from PySide2.QtWidgets import QApplication
+ from PySide2 import QtCore
+
+needs to be changed to:
+
+.. code-block:: python
+
+ from PySide6.QtWidgets import QApplication
+ from PySide6 import QtCore
+
+
+Some classes are in a different module now, for example
+``QAction`` and ``QShortcut`` have been moved from ``QtWidgets`` to ``QtGui``.
+
+For *Qt Charts* and *Qt Data Visualization*, the additional namespaces have been
+removed. It is now possible to use:
+
+.. code-block:: python
+
+ from PySide6.QtCharts import QChartView
+
+directly.
+
+
+Class/Function Deprecations
+---------------------------
+
+Then, the code base needs to be checked for usage of deprecated API and adapted
+accordingly. For example:
+
+* The High DPI scaling attributes ``Qt.AA_EnableHighDpiScaling``,
+ ``Qt.AA_DisableHighDpiScaling`` and ``Qt.AA_UseHighDpiPixmaps`` are
+ deprecated. High DPI is by default enabled in Qt 6 and cannot be turned off.
+* ``QDesktopWidget`` has been removed. ``QScreen`` should be used instead,
+ which can be retrieved using ``QWidget.screen()``,
+ ``QGuiApplication.primaryScreen()`` or ``QGuiApplication.screens()``.
+* ``QFontMetrics.width()`` has been renamed to ``horizontalAdvance()``.
+* ``QMouseEvent.pos()`` and ``QMouseEvent.globalPos()`` returning a ``QPoint``
+ as well as ``QMouseEvent.x()`` and ``QMouseEvent.y()`` returning ``int``
+ are now deprecated. ``QMouseEvent.position()`` and
+ ``QMouseEvent.globalPosition()`` returning a ``QPointF`` should be used
+ instead.
+* ``Qt.MidButton`` has been renamed to ``Qt.MiddleButton``.
+* ``QOpenGLVersionFunctionsFactory.get()`` instead of
+ ``QOpenGLContext.versionFunctions()`` should be used to obtain
+ *Open GL* functions.
+* ``QRegExp`` has been replaced by ``QRegularExpression``.
+* ``QWidget.mapToGlobal()`` and ``QWidget.mapFromGlobal()`` now also accept
+ and return ``QPointF``.
+* Functions named ``exec_`` (classes ``QCoreApplication``, ``QDialog``,
+ ``QEventLoop``) have been renamed to ``exec`` which became possible
+ in Python 3.
+
+More information can be found in the
+`Porting to Qt 6 <https://doc.qt.io/qt-6/portingguide.html>`_ Guide
+and the `Qt 6.2 Documentation <https://doc.qt.io/qt-6/index.html>`_ .
diff --git a/sources/pyside6/doc/gettingstarted-windows.rst b/sources/pyside6/doc/gettingstarted/windows.rst
index 63e187682..f688acd90 100644
--- a/sources/pyside6/doc/gettingstarted-windows.rst
+++ b/sources/pyside6/doc/gettingstarted/windows.rst
@@ -7,15 +7,17 @@ selected when using the online installer.
Requirements
------------
- * `MSVC2017`_ (or MSVC2019) for Python 3 on Windows,
- * `OpenSSL`_ (optional for SSL support, Qt must have been configured using the same SSL library).
- * ``sphinx`` package for the documentation (optional).
+* `MSVC2022`_ or (MSVC2019) for Python 3 on Windows,
+* `OpenSSL`_ (optional for SSL support, Qt must have been configured using the same SSL library).
+* ``sphinx`` package for the documentation (optional).
+* Check the platform dependencies of `Qt for Windows`_.
-.. note:: Python 3.8.0 was missing some API required for PySide/Shiboken so it's not possible
- to use it for a Windows build.
+.. note:: The Python provided by the Microsoft Store is not compatible with PySide. Please
+ use https://www.python.org/downloads/ to get a Python Interpreter.
-.. _MSVC2017: https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools
+.. _MSVC2022: https://visualstudio.microsoft.com/downloads/
.. _OpenSSL: https://sourceforge.net/projects/openssl/
+.. _`Qt for Windows`: https://doc.qt.io/qt-6/windows.html
Building from source on Windows 10
----------------------------------
@@ -28,7 +30,6 @@ which arbitrary modules can be installed and which can be removed after use::
python -m venv testenv
call testenv\Scripts\activate
- pip install -r requirements.txt # General dependencies, documentation, and examples.
will create and use a new virtual environment, which is indicated by the command prompt changing.
@@ -37,7 +38,7 @@ Setting up CLANG
libclang can be downloaded from the
`Qt servers <https://download.qt.io/development_releases/prebuilt/libclang>`_.
-for example, ``libclang-release_130-based-windows-vs2019_64.7z``.
+for example, ``libclang-release_140-based-windows-vs2019_64.7z``.
Note that from version 12 onwards, the prebuilt Windows binaries from
`LLVM <https://www.llvm.org>`_ no longer contain CMake configuration files; so
@@ -54,11 +55,15 @@ Getting PySide
Cloning the official repository can be done by::
- git clone --recursive https://code.qt.io/pyside/pyside-setup
+ git clone https://code.qt.io/pyside/pyside-setup
-Checking out the version that we want to build, for example, 6.0::
+Checking out the version that we want to build, for example, 6.5::
- cd pyside-setup && git checkout 6.0
+ cd pyside-setup && git checkout 6.5
+
+Install the general dependencies::
+
+ pip install -r requirements.txt
.. note:: Keep in mind you need to use the same version as your Qt installation
@@ -66,12 +71,29 @@ Building PySide
~~~~~~~~~~~~~~~
Check your Qt installation path, to specifically use that version of qtpaths to build PySide.
-for example, ``E:\Qt\6.0.0\msvc2019_64\bin\qtpaths.exe``.
+for example, ``C:\Qt\6.5.0\msvc2019_64\bin\qtpaths.exe``.
Build can take a few minutes, so it is recommended to use more than one CPU core::
python setup.py build --qtpaths=c:\path\to\qtpaths.exe --openssl=c:\path\to\openssl\bin --build-tests --ignore-git --parallel=8
+.. _creating_windows_debug_builds:
+
+Creating Debug Builds
+~~~~~~~~~~~~~~~~~~~~~
+
+* Choose *Custom Installation* when installing Python and tick the options for
+ debug binaries and libraries
+
+* Use ``venv`` to create a virtual environment and pass the debug binary::
+
+ python_d.exe -m venv testenv_d
+
+* Use ``python_d.exe`` to invoke ``setup.py``
+
+.. note:: Make sure you add the ``--debug`` option to the ``python setup.py install`` to produce a debug build
+
+
Installing PySide
~~~~~~~~~~~~~~~~~
diff --git a/sources/pyside6/doc/images/Commercial.svg b/sources/pyside6/doc/images/Commercial.svg
new file mode 100644
index 000000000..f37cce629
--- /dev/null
+++ b/sources/pyside6/doc/images/Commercial.svg
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 26.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 75 75" style="enable-background:new 0 0 75 75;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill-rule:evenodd;clip-rule:evenodd;fill:url(#handshake_00000120533523703459691090000008987813838278108073_);}
+</style>
+<g id="Icons">
+ <g id="Icon_Partner_75">
+ <g id="Icons_00000013163458512384628070000011202706081841226428_">
+ <g id="Icon_Partner_75_00000024708088633722110760000017651124705385698191_">
+
+ <linearGradient id="handshake_00000144337817784615937160000016289583607924598409_" gradientUnits="userSpaceOnUse" x1="-263.8588" y1="427.9277" x2="-265.086" y2="429.2586" gradientTransform="matrix(75 -2.450961e-05 -2.450747e-05 -74.9934 19864.2129 32166.1777)">
+ <stop offset="0" style="stop-color:#6FFE80"/>
+ <stop offset="0.3726" style="stop-color:#43CE58"/>
+ <stop offset="1" style="stop-color:#425FCF"/>
+ </linearGradient>
+
+ <path id="handshake" style="fill-rule:evenodd;clip-rule:evenodd;fill:url(#handshake_00000144337817784615937160000016289583607924598409_);" d="
+ M59.3,50c1.9,1.9,1.9,5.1,0,7.1c-0.6,0.6-1.4,1.1-2.2,1.3l0.5,0.5c1.9,1.9,1.9,5.1,0,7.1c-1.5,1.5-3.8,1.9-5.7,1
+ c-0.2,1-0.7,1.9-1.4,2.6c-1.5,1.5-3.9,1.9-5.7,1c-0.2,1-0.7,1.9-1.4,2.6c-1,1-2.3,1.5-3.5,1.5c-1.3,0-2.6-0.5-3.5-1.5L15,51.7
+ c-3.8-3.8-4.6-8.5-5.3-12.3c-0.5-2.7-0.9-5.1-2.2-6.5c-0.5-0.5-0.5-1.3,0-1.8c0.5-0.5,1.3-0.5,1.8,0c1.9,1.9,2.4,4.8,2.9,7.8
+ c0.6,3.6,1.3,7.7,4.6,10.9L38,71.2c1,1,2.6,1,3.5,0c0.5-0.5,0.7-1.1,0.7-1.8c0-0.7-0.3-1.3-0.7-1.8L30.1,56.2
+ c-0.5-0.5-0.5-1.3,0-1.8c0.5-0.5,1.3-0.5,1.8,0l11.5,11.5h0l1.8,1.8c0.9,0.9,2.6,0.9,3.5,0c1-1,1-2.6,0-3.5L34.5,50
+ c-0.5-0.5-0.5-1.3,0-1.8c0.5-0.5,1.3-0.5,1.8,0l15.9,15.9c1,1,2.6,1,3.5,0c1-1,1-2.6,0-3.5L38.9,43.8c-0.5-0.5-0.5-1.3,0-1.8
+ c0.5-0.5,1.3-0.5,1.8,0L54,55.3c1,1,2.6,1,3.5,0c1-1,1-2.6,0-3.5L44.2,38.5c-0.5-0.5-0.5-1.3,0-1.8c0.5-0.5,1.3-0.5,1.8,0
+ L59.3,50L59.3,50z M66.3,26.2c-2,2-2.7,5.3-3.4,8.5c-0.6,2.8-1.2,5.8-2.7,7.3l-1.8,1.8c-0.5,0.5-0.5,1.3,0,1.8
+ c0.2,0.2,0.6,0.4,0.9,0.4c0.3,0,0.6-0.1,0.9-0.4l1.8-1.8c2-2,2.7-5.3,3.4-8.5c0.6-2.8,1.2-5.8,2.7-7.3c0.5-0.5,0.5-1.3,0-1.8
+ S66.8,25.7,66.3,26.2L66.3,26.2z M19.6,34.1c0,0.7,0.3,1.3,0.7,1.8l0.9,0.9c1.2,1.2,2.7,1.8,4.4,1.8s3.2-0.6,4.4-1.8l6.2-6.2
+ c2.5,2.1,5.5,3.2,8.8,3.2h0c3.7,0,7.1-1.4,9.7-4c0.5-0.5,0.5-1.3,0-1.8c-0.5-0.5-1.3-0.5-1.8,0c-2.1,2.1-5,3.3-8,3.3h0
+ c-3,0-5.8-1.2-8-3.3c-0.5-0.5-1.3-0.5-1.8,0L28.3,35c-1.4,1.4-3.9,1.4-5.3,0l-0.9-0.9l15-15c1.4-1.4,2.7-1.4,4.4-1.4
+ c1.8,0,4.1,0,6.2-2.1l3.5-3.5c0.5-0.5,0.5-1.3,0-1.8c-0.5-0.5-1.3-0.5-1.8,0L46,13.7c-1.4,1.4-2.7,1.4-4.4,1.4
+ c-1.8,0-4.1,0-6.2,2.1l-15,15C19.9,32.8,19.6,33.4,19.6,34.1L19.6,34.1z M23,17.3l3.5,3.5c0.2,0.2,0.6,0.4,0.9,0.4
+ c0.3,0,0.6-0.1,0.9-0.4c0.5-0.5,0.5-1.3,0-1.8l-3.5-3.5c-0.5-0.5-1.3-0.5-1.8,0C22.5,16,22.5,16.8,23,17.3L23,17.3z M21.6,11.4
+ l-7.5-7.5c-0.5-0.5-1.3-0.5-1.8,0s-0.5,1.3,0,1.8l6.6,6.6L2.1,29.1c-0.5,0.5-0.5,1.3,0,1.8c0.2,0.2,0.6,0.4,0.9,0.4
+ s0.6-0.1,0.9-0.4l17.7-17.7C22.1,12.6,22.1,11.9,21.6,11.4L21.6,11.4z M72.9,24.8L55.3,7.3l4.1-4.1c0.5-0.5,0.5-1.3,0-1.8
+ s-1.3-0.5-1.8,0l-5,5c-0.5,0.5-0.5,1.3,0,1.8l18.4,18.4c0.2,0.2,0.6,0.4,0.9,0.4c0.3,0,0.6-0.1,0.9-0.4
+ C73.4,26.1,73.4,25.3,72.9,24.8L72.9,24.8z M30.4,71.9c-0.7,0.4-1.9,0.4-3-0.7c-1.1-1.1-1.1-2.3-0.7-2.9
+ c0.3-0.5,0.2-1.2-0.3-1.6c-0.5-0.4-1.2-0.4-1.7,0.1c-1,1-2.6,1-3.5,0c-1-1-1-2.6,0-3.5c0.2-0.2,0.4-0.6,0.4-0.9
+ s-0.1-0.6-0.4-0.9c-0.5-0.5-1.3-0.5-1.8,0l-0.9,0.9c-1,1-2.6,1-3.5,0c-1-1-1-2.6,0-3.5l0.9-0.9c0.4-0.4,0.5-1.1,0.1-1.6
+ c-0.4-0.5-1.1-0.6-1.6-0.3c-0.7,0.4-1.9,0.3-2.9-0.7c-1.1-1.1-1.1-2.3-0.7-2.8c0.4-0.6,0.2-1.3-0.3-1.7
+ c-0.6-0.4-1.3-0.2-1.7,0.3c-1,1.5-1,4,1,6c0.8,0.8,1.7,1.3,2.5,1.5c-0.3,0.6-0.4,1.3-0.4,2c0,1.3,0.5,2.6,1.5,3.5
+ c1.3,1.3,3.1,1.7,4.7,1.3c0.1,1.1,0.6,2.2,1.4,3.1c1.2,1.2,3,1.7,4.6,1.4c0.2,1,0.7,2.1,1.6,3.1c1.2,1.2,2.5,1.6,3.7,1.6
+ c0.8,0,1.5-0.2,2.1-0.5c0.6-0.3,0.8-1.1,0.5-1.7C31.8,71.8,31,71.5,30.4,71.9L30.4,71.9z"/>
+ </g>
+ </g>
+ </g>
+</g>
+</svg>
diff --git a/sources/pyside6/doc/images/Development.svg b/sources/pyside6/doc/images/Development.svg
new file mode 100644
index 000000000..2149ee8a0
--- /dev/null
+++ b/sources/pyside6/doc/images/Development.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="41px" height="38px" viewBox="0 0 41 38" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 44.1 (41455) - http://www.bohemiancoding.com/sketch -->
+ <title>globe-share</title>
+ <desc>Created with Sketch.</desc>
+ <defs>
+ <linearGradient x1="100%" y1="100%" x2="-22.8515625%" y2="-33.2356771%" id="linearGradient-1">
+ <stop stop-color="#6FFF80" offset="0%"></stop>
+ <stop stop-color="#43CE57" offset="37.2587344%"></stop>
+ <stop stop-color="#425FD0" offset="100%"></stop>
+ </linearGradient>
+ </defs>
+ <g id="Mainpage" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Mainpage_Layout_V4_Megamenu" transform="translate(-831.000000, -3529.000000)" fill="url(#linearGradient-1)">
+ <g id="Content" transform="translate(-44.000000, 1530.000000)">
+ <g id="Deliver" transform="translate(62.000000, 1032.000000)">
+ <g id="Product" transform="translate(776.000000, 967.000000)">
+ <g id="Auto" transform="translate(36.420728, 0.000000)">
+ <path d="M10.8786296,24.4285714 L14.7525939,24.4285714 C15.675451,27.47875 17.4736653,29.6847857 18.8301296,31.0052857 C15.2113082,30.29075 12.2371296,27.7725714 10.8786296,24.4285714 L10.8786296,24.4285714 Z M18.8301296,9.709 C17.4736653,11.0295 15.675451,13.2355357 14.7525939,16.2857143 L10.8786296,16.2857143 C12.2371296,12.9417143 15.2113082,10.4235357 18.8301296,9.709 L18.8301296,9.709 Z M30.994201,16.2857143 L27.1202368,16.2857143 C26.1973796,13.2355357 24.3984868,11.0295 23.0420225,9.709 C26.6615225,10.4235357 29.6350225,12.9417143 30.994201,16.2857143 L30.994201,16.2857143 Z M23.0420225,31.0052857 C24.3984868,29.6847857 26.1973796,27.47875 27.1202368,24.4285714 L30.994201,24.4285714 C29.635701,27.7725714 26.6615225,30.29075 23.0420225,31.0052857 L23.0420225,31.0052857 Z M20.2578439,24.4285714 L20.2578439,30.4678571 C19.076451,29.3991071 17.2063082,27.3471071 16.2006653,24.4285714 L20.2578439,24.4285714 Z M20.2578439,10.2464286 L20.2578439,16.2857143 L16.2006653,16.2857143 C17.2063082,13.3671786 19.076451,11.3151786 20.2578439,10.2464286 L20.2578439,10.2464286 Z M21.6149868,16.2857143 L21.6149868,10.2464286 C22.7963796,11.3151786 24.6665225,13.3671786 25.6714868,16.2857143 L21.6149868,16.2857143 Z M21.6149868,30.4678571 L21.6149868,24.4285714 L25.6714868,24.4285714 C24.6665225,27.3471071 22.7963796,29.3991071 21.6149868,30.4678571 L21.6149868,30.4678571 Z M26.3649868,20.3571429 C26.3649868,21.32275 26.2475939,22.2245714 26.058951,23.0714286 L21.6149868,23.0714286 L21.6149868,17.6428571 L26.058951,17.6428571 C26.2475939,18.4897143 26.3649868,19.3915357 26.3649868,20.3571429 L26.3649868,20.3571429 Z M31.7935582,20.3571429 C31.7935582,21.2956071 31.6605582,22.2021786 31.435951,23.0714286 L27.460201,23.0714286 C27.626451,22.2218571 27.7221296,21.3173214 27.7221296,20.3571429 C27.7221296,19.3969643 27.626451,18.4924286 27.460201,17.6428571 L31.435951,17.6428571 C31.6605582,18.5121071 31.7935582,19.4186786 31.7935582,20.3571429 L31.7935582,20.3571429 Z M15.5078439,20.3571429 C15.5078439,19.3915357 15.6252368,18.4897143 15.8138796,17.6428571 L20.2578439,17.6428571 L20.2578439,23.0714286 L15.8138796,23.0714286 C15.6252368,22.2245714 15.5078439,21.32275 15.5078439,20.3571429 L15.5078439,20.3571429 Z M10.0792725,20.3571429 C10.0792725,19.4186786 10.2115939,18.5121071 10.436201,17.6428571 L14.4126296,17.6428571 C14.245701,18.4924286 14.150701,19.3969643 14.150701,20.3571429 C14.150701,21.3173214 14.245701,22.2218571 14.4126296,23.0714286 L10.436201,23.0714286 C10.2115939,22.2021786 10.0792725,21.2956071 10.0792725,20.3571429 L10.0792725,20.3571429 Z M20.9377725,32.5714286 C26.3982368,32.57075 31.0308439,28.9682143 32.5895225,24.016 C32.590201,24.0139643 32.5908796,24.0126071 32.5915582,24.01125 C32.9539153,22.857 33.150701,21.6294643 33.150701,20.3571429 C33.150701,19.0848214 32.9539153,17.8572857 32.5915582,16.7030357 C32.5908796,16.7016786 32.590201,16.7003214 32.5895225,16.6982857 C31.0308439,11.7460714 26.3968796,8.14285714 20.9364153,8.14285714 C15.4752725,8.14285714 10.8413082,11.7460714 9.28262962,16.6989643 L9.28195105,16.7023571 C8.91891533,17.8566071 8.72212962,19.0841429 8.72212962,20.3571429 C8.72212962,21.6301429 8.91891533,22.8576786 9.28195105,24.0119286 L9.28262962,24.0153214 C10.8413082,28.9675357 15.4745939,32.57075 20.9343796,32.5714286 L20.9350582,32.5714286 L20.9357368,32.5714286 L20.9357368,32.5714286 L20.9364153,32.5714286 L20.9370939,32.5714286 L20.9377725,32.5714286 Z M31.7935582,36.6428571 C31.0450939,36.6428571 30.4364153,36.0341786 30.4364153,35.2857143 C30.4364153,34.53725 31.0450939,33.9285714 31.7935582,33.9285714 C32.5413439,33.9285714 33.150701,34.53725 33.150701,35.2857143 C33.150701,36.0341786 32.5413439,36.6428571 31.7935582,36.6428571 L31.7935582,36.6428571 Z M31.7935582,32.5714286 C31.4142368,32.5714286 31.0539153,32.6508214 30.7261653,32.7912857 L29.597701,31.4551786 C29.3561296,31.1688214 28.927951,31.1315 28.6415939,31.3744286 C28.3545582,31.616 28.3192725,32.0441786 28.5601653,32.3305357 L29.6574153,33.6306786 C29.3004868,34.0900714 29.0792725,34.6600714 29.0792725,35.2857143 C29.0792725,36.7826429 30.2966296,38 31.7935582,38 C33.2904868,38 34.5078439,36.7826429 34.5078439,35.2857143 C34.5078439,33.7887857 33.2904868,32.5714286 31.7935582,32.5714286 L31.7935582,32.5714286 Z M10.0792725,36.6428571 C9.33080819,36.6428571 8.72212962,36.0341786 8.72212962,35.2857143 C8.72212962,34.53725 9.33080819,33.9285714 10.0792725,33.9285714 C10.8277368,33.9285714 11.4364153,34.53725 11.4364153,35.2857143 C11.4364153,36.0341786 10.8277368,36.6428571 10.0792725,36.6428571 L10.0792725,36.6428571 Z M12.3022725,31.3846071 L11.096451,32.7729643 C10.7815939,32.6453929 10.4395939,32.5714286 10.0792725,32.5714286 C8.58234391,32.5714286 7.36498676,33.7887857 7.36498676,35.2857143 C7.36498676,36.7826429 8.58234391,38 10.0792725,38 C11.5755225,38 12.7935582,36.7826429 12.7935582,35.2857143 C12.7935582,34.64175 12.5587725,34.0575 12.1828439,33.592 L13.3269153,32.2742143 C13.5725582,31.99125 13.542701,31.5623929 13.2590582,31.31675 C12.9760939,31.0711071 12.5472368,31.1009643 12.3022725,31.3846071 L12.3022725,31.3846071 Z M38.5792725,16.2857143 C37.8308082,16.2857143 37.2221296,15.6770357 37.2221296,14.9285714 C37.2221296,14.1801071 37.8308082,13.5714286 38.5792725,13.5714286 C39.3270582,13.5714286 39.9364153,14.1801071 39.9364153,14.9285714 C39.9364153,15.6770357 39.3270582,16.2857143 38.5792725,16.2857143 L38.5792725,16.2857143 Z M38.5792725,12.2142857 C37.0823439,12.2142857 35.8649868,13.4316429 35.8649868,14.9285714 C35.8649868,15.0133929 35.881951,15.0941429 35.8900939,15.1776071 L34.5885939,15.6804286 C34.238451,15.8161429 34.0647368,16.2090357 34.200451,16.5585 C34.3042725,16.8272143 34.5607725,16.9927857 34.8328796,16.9927857 C34.9143082,16.9927857 34.9970939,16.9778571 35.0778439,16.9466429 L36.3399868,16.4580714 C36.8292368,17.1726071 37.6496296,17.6428571 38.5792725,17.6428571 C40.076201,17.6428571 41.2935582,16.4255 41.2935582,14.9285714 C41.2935582,13.4316429 40.076201,12.2142857 38.5792725,12.2142857 L38.5792725,12.2142857 Z M3.29355819,16.2857143 C2.54509391,16.2857143 1.93641533,15.6770357 1.93641533,14.9285714 C1.93641533,14.1801071 2.54509391,13.5714286 3.29355819,13.5714286 C4.04202248,13.5714286 4.65070105,14.1801071 4.65070105,14.9285714 C4.65070105,15.6770357 4.04202248,16.2857143 3.29355819,16.2857143 L3.29355819,16.2857143 Z M7.71173676,16.5781786 C7.84745105,16.2287143 7.67441533,15.8358214 7.32495105,15.7001071 L5.98273676,15.1782857 C5.99020105,15.0948214 6.00784391,15.0140714 6.00784391,14.9285714 C6.00784391,13.4316429 4.78980819,12.2142857 3.29355819,12.2142857 C1.79662962,12.2142857 0.579272478,13.4316429 0.579272478,14.9285714 C0.579272478,16.4255 1.79662962,17.6428571 3.29355819,17.6428571 C4.22184391,17.6428571 5.04223676,17.1732857 5.53216533,16.4594286 L6.83366533,16.9649643 C6.91441533,16.9961786 6.99720105,17.0111071 7.07930819,17.0111071 C7.35073676,17.0111071 7.60723676,16.8468929 7.71173676,16.5781786 L7.71173676,16.5781786 Z M20.9364153,1.35714286 C21.684201,1.35714286 22.2935582,1.96582143 22.2935582,2.71428571 C22.2935582,3.46275 21.684201,4.07142857 20.9364153,4.07142857 C20.187951,4.07142857 19.5792725,3.46275 19.5792725,2.71428571 C19.5792725,1.96582143 20.187951,1.35714286 20.9364153,1.35714286 L20.9364153,1.35714286 Z M20.2578439,5.33221429 L20.2578439,6.44642857 C20.2578439,6.821 20.5618439,7.125 20.9364153,7.125 C21.3109868,7.125 21.6149868,6.821 21.6149868,6.44642857 L21.6149868,5.33221429 C22.7821296,5.02889286 23.650701,3.97507143 23.650701,2.71428571 C23.650701,1.21735714 22.4333439,0 20.9364153,0 C19.4394868,0 18.2221296,1.21735714 18.2221296,2.71428571 C18.2221296,3.97507143 19.090701,5.02889286 20.2578439,5.33221429 L20.2578439,5.33221429 Z" id="globe-share"></path>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
+
diff --git a/sources/pyside6/doc/images/Examples.svg b/sources/pyside6/doc/images/Examples.svg
index 98116957e..a506e7798 100644
--- a/sources/pyside6/doc/images/Examples.svg
+++ b/sources/pyside6/doc/images/Examples.svg
@@ -1,24 +1,34 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg width="49px" height="48px" viewBox="0 0 49 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 44.1 (41455) - http://www.bohemiancoding.com/sketch -->
- <title>web-development</title>
- <desc>Created with Sketch.</desc>
- <defs>
- <linearGradient x1="100%" y1="100%" x2="-22.8515625%" y2="-33.2356771%" id="linearGradient-1">
- <stop stop-color="#6FFF80" offset="0%"></stop>
- <stop stop-color="#43CE57" offset="37.2587344%"></stop>
- <stop stop-color="#425FD0" offset="100%"></stop>
- </linearGradient>
- </defs>
- <g id="Mainpage" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="Mainpage_Layout_V4_Megamenu" transform="translate(-1084.000000, -1756.000000)" fill="url(#linearGradient-1)">
- <g id="Content" transform="translate(-44.000000, 1530.000000)">
- <g id="WhatQtis" transform="translate(194.000000, 0.000000)">
- <g id="Block3_Hover" transform="translate(726.316067, 114.000000)">
- <path d="M214.4,115.2 C215.2816,115.2 216,115.9176 216,116.8 C216,117.6824 215.2816,118.4 214.4,118.4 C213.5176,118.4 212.8,117.6824 212.8,116.8 C212.8,115.9176 213.5176,115.2 214.4,115.2 L214.4,115.2 Z M217.6,116.8 C217.6,117.6824 218.3176,118.4 219.2,118.4 C220.0816,118.4 220.8,117.6824 220.8,116.8 C220.8,115.9176 220.0816,115.2 219.2,115.2 C218.3176,115.2 217.6,115.9176 217.6,116.8 L217.6,116.8 Z M222.4,116.8 C222.4,117.6824 223.1176,118.4 224,118.4 C224.8816,118.4 225.6,117.6824 225.6,116.8 C225.6,115.9176 224.8816,115.2 224,115.2 C223.1176,115.2 222.4,115.9176 222.4,116.8 L222.4,116.8 Z M215.2,128 L216.8,128 C217.2424,128 217.6,127.6416 217.6,127.2 C217.6,126.7584 217.2424,126.4 216.8,126.4 L215.2,126.4 C214.7576,126.4 214.4,126.7584 214.4,127.2 C214.4,127.6416 214.7576,128 215.2,128 L215.2,128 Z M215.2,131.2 L216.8,131.2 C217.2424,131.2 217.6,130.8416 217.6,130.4 C217.6,129.9584 217.2424,129.6 216.8,129.6 L215.2,129.6 C214.7576,129.6 214.4,129.9584 214.4,130.4 C214.4,130.8416 214.7576,131.2 215.2,131.2 L215.2,131.2 Z M215.2,134.4 L216.8,134.4 C217.2424,134.4 217.6,134.0416 217.6,133.6 C217.6,133.1584 217.2424,132.8 216.8,132.8 L215.2,132.8 C214.7576,132.8 214.4,133.1584 214.4,133.6 C214.4,134.0416 214.7576,134.4 215.2,134.4 L215.2,134.4 Z M215.2,137.6 L216.8,137.6 C217.2424,137.6 217.6,137.2416 217.6,136.8 C217.6,136.3584 217.2424,136 216.8,136 L215.2,136 C214.7576,136 214.4,136.3584 214.4,136.8 C214.4,137.2416 214.7576,137.6 215.2,137.6 L215.2,137.6 Z M215.2,140.8 L216.8,140.8 C217.2424,140.8 217.6,140.4416 217.6,140 C217.6,139.5584 217.2424,139.2 216.8,139.2 L215.2,139.2 C214.7576,139.2 214.4,139.5584 214.4,140 C214.4,140.4416 214.7576,140.8 215.2,140.8 L215.2,140.8 Z M215.2,144 L216.8,144 C217.2424,144 217.6,143.6416 217.6,143.2 C217.6,142.7584 217.2424,142.4 216.8,142.4 L215.2,142.4 C214.7576,142.4 214.4,142.7584 214.4,143.2 C214.4,143.6416 214.7576,144 215.2,144 L215.2,144 Z M215.2,147.2 L216.8,147.2 C217.2424,147.2 217.6,146.8416 217.6,146.4 C217.6,145.9584 217.2424,145.6 216.8,145.6 L215.2,145.6 C214.7576,145.6 214.4,145.9584 214.4,146.4 C214.4,146.8416 214.7576,147.2 215.2,147.2 L215.2,147.2 Z M215.2,150.4 L216.8,150.4 C217.2424,150.4 217.6,150.0416 217.6,149.6 C217.6,149.1584 217.2424,148.8 216.8,148.8 L215.2,148.8 C214.7576,148.8 214.4,149.1584 214.4,149.6 C214.4,150.0416 214.7576,150.4 215.2,150.4 L215.2,150.4 Z M215.2,153.6 L216.8,153.6 C217.2424,153.6 217.6,153.2416 217.6,152.8 C217.6,152.3584 217.2424,152 216.8,152 L215.2,152 C214.7576,152 214.4,152.3584 214.4,152.8 C214.4,153.2416 214.7576,153.6 215.2,153.6 L215.2,153.6 Z M242.4,128 C242.8424,128 243.2,127.6416 243.2,127.2 C243.2,126.7584 242.8424,126.4 242.4,126.4 L239.2,126.4 C238.7576,126.4 238.4,126.7584 238.4,127.2 C238.4,127.6416 238.7576,128 239.2,128 L242.4,128 L242.4,128 Z M235.2,130.4 C235.2,130.8416 235.5576,131.2 236,131.2 L244,131.2 C244.4424,131.2 244.8,130.8416 244.8,130.4 C244.8,129.9584 244.4424,129.6 244,129.6 L236,129.6 C235.5576,129.6 235.2,129.9584 235.2,130.4 L235.2,130.4 Z M220,131.2 L232.8,131.2 C233.2424,131.2 233.6,130.8416 233.6,130.4 C233.6,129.9584 233.2424,129.6 232.8,129.6 L220,129.6 C219.5576,129.6 219.2,129.9584 219.2,130.4 C219.2,130.8416 219.5576,131.2 220,131.2 L220,131.2 Z M220,128 L228,128 C228.4424,128 228.8,127.6416 228.8,127.2 C228.8,126.7584 228.4424,126.4 228,126.4 L220,126.4 C219.5576,126.4 219.2,126.7584 219.2,127.2 C219.2,127.6416 219.5576,128 220,128 L220,128 Z M236,126.4 L231.2,126.4 C230.7576,126.4 230.4,126.7584 230.4,127.2 C230.4,127.6416 230.7576,128 231.2,128 L236,128 C236.4424,128 236.8,127.6416 236.8,127.2 C236.8,126.7584 236.4424,126.4 236,126.4 L236,126.4 Z M248,133.6 C248,133.1584 247.6424,132.8 247.2,132.8 L234.4,132.8 C233.9576,132.8 233.6,133.1584 233.6,133.6 C233.6,134.0416 233.9576,134.4 234.4,134.4 L247.2,134.4 C247.6424,134.4 248,134.0416 248,133.6 L248,133.6 Z M242.4,137.6 C242.8424,137.6 243.2,137.2416 243.2,136.8 C243.2,136.3584 242.8424,136 242.4,136 L236,136 C235.5576,136 235.2,136.3584 235.2,136.8 C235.2,137.2416 235.5576,137.6 236,137.6 L242.4,137.6 L242.4,137.6 Z M220,137.6 L232.8,137.6 C233.2424,137.6 233.6,137.2416 233.6,136.8 C233.6,136.3584 233.2424,136 232.8,136 L220,136 C219.5576,136 219.2,136.3584 219.2,136.8 C219.2,137.2416 219.5576,137.6 220,137.6 L220,137.6 Z M220,134.4 L223.2,134.4 C223.6424,134.4 224,134.0416 224,133.6 C224,133.1584 223.6424,132.8 223.2,132.8 L220,132.8 C219.5576,132.8 219.2,133.1584 219.2,133.6 C219.2,134.0416 219.5576,134.4 220,134.4 L220,134.4 Z M226.4,132.8 C225.9576,132.8 225.6,133.1584 225.6,133.6 C225.6,134.0416 225.9576,134.4 226.4,134.4 L231.2,134.4 C231.6424,134.4 232,134.0416 232,133.6 C232,133.1584 231.6424,132.8 231.2,132.8 L226.4,132.8 L226.4,132.8 Z M237.6,146.4 C237.6,145.9584 237.2424,145.6 236.8,145.6 L234.4,145.6 C233.9576,145.6 233.6,145.9584 233.6,146.4 C233.6,146.8416 233.9576,147.2 234.4,147.2 L236.8,147.2 C237.2424,147.2 237.6,146.8416 237.6,146.4 L237.6,146.4 Z M220,147.2 L223.2,147.2 C223.6424,147.2 224,146.8416 224,146.4 C224,145.9584 223.6424,145.6 223.2,145.6 L220,145.6 C219.5576,145.6 219.2,145.9584 219.2,146.4 C219.2,146.8416 219.5576,147.2 220,147.2 L220,147.2 Z M231.2,145.6 L226.4,145.6 C225.9576,145.6 225.6,145.9584 225.6,146.4 C225.6,146.8416 225.9576,147.2 226.4,147.2 L231.2,147.2 C231.6424,147.2 232,146.8416 232,146.4 C232,145.9584 231.6424,145.6 231.2,145.6 L231.2,145.6 Z M220,150.4 L229.6,150.4 C230.0424,150.4 230.4,150.0416 230.4,149.6 C230.4,149.1584 230.0424,148.8 229.6,148.8 L220,148.8 C219.5576,148.8 219.2,149.1584 219.2,149.6 C219.2,150.0416 219.5576,150.4 220,150.4 L220,150.4 Z M232.8,150.4 L234.4,150.4 C234.8424,150.4 235.2,150.0416 235.2,149.6 C235.2,149.1584 234.8424,148.8 234.4,148.8 L232.8,148.8 C232.3576,148.8 232,149.1584 232,149.6 C232,150.0416 232.3576,150.4 232.8,150.4 L232.8,150.4 Z M220,153.6 L224.8,153.6 C225.2424,153.6 225.6,153.2416 225.6,152.8 C225.6,152.3584 225.2424,152 224.8,152 L220,152 C219.5576,152 219.2,152.3584 219.2,152.8 C219.2,153.2416 219.5576,153.6 220,153.6 L220,153.6 Z M227.2,152.8 C227.2,153.2416 227.5576,153.6 228,153.6 L236,153.6 C236.4424,153.6 236.8,153.2416 236.8,152.8 C236.8,152.3584 236.4424,152 236,152 L228,152 C227.5576,152 227.2,152.3584 227.2,152.8 L227.2,152.8 Z M244.8,140 C244.8,139.5584 244.4424,139.2 244,139.2 L231.2,139.2 C230.7576,139.2 230.4,139.5584 230.4,140 C230.4,140.4416 230.7576,140.8 231.2,140.8 L244,140.8 C244.4424,140.8 244.8,140.4416 244.8,140 L244.8,140 Z M239.2,143.2 C239.2,142.7584 238.8424,142.4 238.4,142.4 L232.8,142.4 C232.3576,142.4 232,142.7584 232,143.2 C232,143.6416 232.3576,144 232.8,144 L238.4,144 C238.8424,144 239.2,143.6416 239.2,143.2 L239.2,143.2 Z M220,144 L229.6,144 C230.0424,144 230.4,143.6416 230.4,143.2 C230.4,142.7584 230.0424,142.4 229.6,142.4 L220,142.4 C219.5576,142.4 219.2,142.7584 219.2,143.2 C219.2,143.6416 219.5576,144 220,144 L220,144 Z M220,140.8 L228,140.8 C228.4424,140.8 228.8,140.4416 228.8,140 C228.8,139.5584 228.4424,139.2 228,139.2 L220,139.2 C219.5576,139.2 219.2,139.5584 219.2,140 C219.2,140.4416 219.5576,140.8 220,140.8 L220,140.8 Z M256,149.6 L256,152.8 C256,153.2416 255.6424,153.6 255.2,153.6 L253.9816,153.6 C253.8976,153.8384 253.8008,154.072 253.692,154.3 L254.5528,155.1608 C254.8656,155.4736 254.8656,155.98 254.5528,156.292 L252.2904,158.5544 C252.1408,158.7048 251.9376,158.7888 251.7248,158.7888 C251.5128,158.7888 251.3096,158.7048 251.1592,158.5544 L250.2976,157.6928 C250.0704,157.8008 249.8376,157.8976 249.5992,157.9816 L249.5992,159.2 C249.5992,159.6416 249.2416,160 248.7992,160 L245.5992,160 C245.1568,160 244.7992,159.6416 244.7992,159.2 L244.7992,157.9816 C244.5616,157.8976 244.3288,157.8008 244.1008,157.692 L243.24,158.5528 C242.94,158.8528 242.4088,158.8528 242.1088,158.5528 L239.8464,156.2904 C239.5336,155.9784 239.5336,155.472 239.8464,155.1592 L240.7072,154.2984 C240.5992,154.0704 240.5024,153.8376 240.4184,153.6 L239.2,153.6 C238.7576,153.6 238.4,153.2416 238.4,152.8 L238.4,149.6 C238.4,149.1584 238.7576,148.8 239.2,148.8 L240.4184,148.8 C240.5024,148.5616 240.5992,148.328 240.708,148.1 L239.8472,147.2392 C239.5344,146.9264 239.5344,146.42 239.8472,146.108 L242.1088,143.8456 C242.4088,143.5456 242.94,143.5456 243.24,143.8456 L244.1016,144.7072 C244.3288,144.5984 244.5624,144.5016 244.8008,144.4176 L244.8008,143.2 C244.8008,142.7584 245.1584,142.4 245.6008,142.4 L248.8,142.4 C249.2424,142.4 249.6,142.7584 249.6,143.2 L249.6,144.4176 C249.8384,144.5016 250.072,144.5984 250.2984,144.7064 L251.16,143.8456 C251.4728,143.5344 251.9792,143.5336 252.2912,143.8464 L254.5536,146.1088 C254.8664,146.4208 254.8664,146.9272 254.5536,147.24 L253.6928,148.1008 C253.8016,148.3288 253.8976,148.5624 253.9816,148.8 L255.2,148.8 C255.6424,148.8 256,149.1584 256,149.6 L256,149.6 Z M254.4,150.4 L253.3896,150.4 C253.0248,150.4 252.7064,150.1528 252.6152,149.7992 C252.4848,149.2928 252.2848,148.8088 252.0192,148.3608 C251.8344,148.0464 251.8848,147.6464 252.1432,147.388 L252.8568,146.6744 L251.7256,145.5432 L251.012,146.2568 C250.7528,146.5144 250.352,146.5648 250.0392,146.3792 C249.5928,146.116 249.1088,145.916 248.6,145.784 C248.2472,145.6928 248,145.3744 248,145.0096 L248,144 L246.4008,144 L246.4008,145.0096 C246.4008,145.3744 246.1536,145.6928 245.8008,145.784 C245.292,145.916 244.8072,146.116 244.36,146.38 C244.0472,146.5656 243.6472,146.5152 243.388,146.256 L242.6744,145.5424 L241.544,146.6736 L242.2568,147.3872 C242.5152,147.6456 242.5656,148.0456 242.3808,148.36 C242.1152,148.8072 241.9152,149.292 241.7848,149.7992 C241.6936,150.1528 241.3752,150.4 241.0104,150.4 L240,150.4 L240,152 L241.0104,152 C241.3752,152 241.6936,152.2472 241.7848,152.6 C241.9152,153.1064 242.1152,153.5904 242.3808,154.0384 C242.5656,154.3528 242.5152,154.7528 242.2568,155.0112 L241.5432,155.7248 L242.6744,156.856 L243.388,156.1424 C243.6472,155.884 244.048,155.8336 244.3608,156.0192 C244.8112,156.2848 245.2944,156.4848 245.7976,156.6144 C246.152,156.7048 246.3992,157.024 246.3992,157.3888 L246.3992,158.4 L247.9992,158.4 L247.9992,157.3896 C247.9992,157.0248 248.2464,156.7056 248.6,156.6152 C249.1064,156.4848 249.5904,156.284 250.0384,156.02 C250.352,155.8344 250.7536,155.8848 251.0112,156.1432 L251.7248,156.8576 L252.856,155.7264 L252.1424,155.0128 C251.8832,154.7544 251.8336,154.3536 252.0192,154.0392 C252.2848,153.5912 252.4848,153.1072 252.6152,152.6008 C252.7064,152.2472 253.0248,152 253.3896,152 L254.4,152 L254.4,150.4 L254.4,150.4 Z M249.6,151.2 C249.6,152.5232 248.5232,153.6 247.2,153.6 C245.8768,153.6 244.8,152.5232 244.8,151.2 C244.8,149.8768 245.8768,148.8 247.2,148.8 C248.5232,148.8 249.6,149.8768 249.6,151.2 L249.6,151.2 Z M248,151.2 C248,150.7592 247.6416,150.4 247.2,150.4 C246.7584,150.4 246.4,150.7592 246.4,151.2 C246.4,151.6408 246.7584,152 247.2,152 C247.6416,152 248,151.6408 248,151.2 L248,151.2 Z M239.2,158.4 L212,158.4 C210.6768,158.4 209.6,157.3232 209.6,156 L209.6,124 C209.6,123.5584 209.2424,123.2 208.8,123.2 C208.3576,123.2 208,123.5584 208,124 L208,156 C208,158.2056 209.7944,160 212,160 L239.2,160 C239.6424,160 240,159.6416 240,159.2 C240,158.7584 239.6424,158.4 239.2,158.4 L239.2,158.4 Z M252,112 L212,112 C209.7944,112 208,113.7944 208,116 L208,120.8 C208,121.2416 208.3576,121.6 208.8,121.6 L252,121.6 C252.4424,121.6 252.8,121.2416 252.8,120.8 C252.8,120.3584 252.4424,120 252,120 L209.6,120 L209.6,116 C209.6,114.6768 210.6768,113.6 212,113.6 L252,113.6 C253.3232,113.6 254.4,114.6768 254.4,116 L254.4,143.2 C254.4,143.6416 254.7576,144 255.2,144 C255.6424,144 256,143.6416 256,143.2 L256,116 C256,113.7944 254.2056,112 252,112 L252,112 Z" id="web-development"></path>
- </g>
- </g>
- </g>
- </g>
- </g>
-</svg> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 75 75" style="enable-background:new 0 0 75 75;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill-rule:evenodd;clip-rule:evenodd;fill:url(#SVGID_1_);}
+ .st1{fill:none;}
+</style>
+<g id="icon">
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="87.5133" y1="87.5133" x2="-26.0279" y2="-26.0279">
+ <stop offset="0" style="stop-color:#6FFE80"/>
+ <stop offset="0.3726" style="stop-color:#43CE58"/>
+ <stop offset="1" style="stop-color:#425FCF"/>
+ </linearGradient>
+ <path class="st0" d="M75,6.2v62.5c0,3.4-2.8,6.2-6.2,6.2H6.2C2.8,75,0,72.2,0,68.8v-50c0-0.7,0.6-1.2,1.2-1.2s1.2,0.6,1.2,1.2v50
+ c0,2.1,1.7,3.8,3.8,3.8h62.5c2.1,0,3.8-1.7,3.8-3.8V6.2c0-2.1-1.7-3.8-3.8-3.8H6.2c-2.1,0-3.8,1.7-3.8,3.8v6.2h66.2
+ c0.7,0,1.2,0.6,1.2,1.2S69.4,15,68.8,15H1.2C0.6,15,0,14.4,0,13.8V6.2C0,2.8,2.8,0,6.2,0h62.5C72.2,0,75,2.8,75,6.2L75,6.2z
+ M7.5,7.5C7.5,8.9,8.6,10,10,10s2.5-1.1,2.5-2.5S11.4,5,10,5S7.5,6.1,7.5,7.5L7.5,7.5z M15,7.5c0,1.4,1.1,2.5,2.5,2.5
+ S20,8.9,20,7.5S18.9,5,17.5,5S15,6.1,15,7.5L15,7.5z M22.5,7.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5S26.4,5,25,5
+ S22.5,6.1,22.5,7.5L22.5,7.5z M63.8,53.7H51.2V41.2c0-0.7-0.6-1.2-1.2-1.2c-8.3,0-15,6.7-15,15s6.7,15,15,15s15-6.7,15-15
+ C65,54.3,64.4,53.7,63.8,53.7z M50,67.5c-6.9,0-12.5-5.6-12.5-12.5c0-6.5,4.9-11.8,11.2-12.4v13.7h13.7
+ C61.8,62.6,56.5,67.5,50,67.5z M55,35c-0.7,0-1.2,0.6-1.2,1.2v15h15c0.7,0,1.2-0.6,1.2-1.2C70,41.7,63.3,35,55,35z M56.2,48.7V37.6
+ c5.9,0.6,10.6,5.3,11.2,11.2H56.2z M38.7,24.9l-6.3,16.7c-0.2,0.5-0.6,0.8-1.1,0.8c-0.5,0-1-0.3-1.2-0.8l-2.5-5.9l-7.6,19.6
+ c-0.2,0.5-0.7,0.8-1.2,0.8c0,0,0,0-0.1,0c-0.5,0-1-0.4-1.1-0.9L9.9,26.8l-2.4,7.3c-0.2,0.7-0.9,1-1.6,0.8c-0.7-0.2-1-0.9-0.8-1.6
+ l3.8-11.2c0.2-0.5,0.7-0.9,1.2-0.9c0.6,0,1,0.4,1.2,0.9L19,51L26.3,32c0.2-0.5,0.6-0.8,1.1-0.8c0,0,0,0,0,0c0.5,0,1,0.3,1.1,0.8
+ l2.5,5.9l6.4-17.1c0.2-0.5,0.7-0.8,1.2-0.8c0.5,0,1,0.3,1.2,0.8l2.9,8.5l4.9-7.5c0.2-0.4,0.7-0.6,1.1-0.6c0.4,0,0.8,0.3,1.1,0.6
+ l3.9,6.9l2.7-4.4c0.2-0.4,0.6-0.6,1.1-0.6c0,0,0,0,0,0c0.4,0,0.8,0.2,1.1,0.6l2.5,4c0.4,0.6,0.2,1.4-0.4,1.7
+ c-0.6,0.4-1.4,0.2-1.7-0.4l-1.4-2.3l-2.7,4.5c-0.2,0.4-0.6,0.6-1.1,0.6c-0.4,0-0.9-0.2-1.1-0.6l-4-7l-5.1,7.9
+ c-0.3,0.4-0.7,0.6-1.2,0.6c-0.5-0.1-0.9-0.4-1-0.8L38.7,24.9z"/>
+</g>
+<g id="_x37_5px_frame">
+ <rect x="0" y="0" class="st1" width="75" height="75"/>
+</g>
+</svg>
diff --git a/sources/pyside6/doc/images/Tooling.svg b/sources/pyside6/doc/images/Tooling.svg
new file mode 100644
index 000000000..98116957e
--- /dev/null
+++ b/sources/pyside6/doc/images/Tooling.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="49px" height="48px" viewBox="0 0 49 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 44.1 (41455) - http://www.bohemiancoding.com/sketch -->
+ <title>web-development</title>
+ <desc>Created with Sketch.</desc>
+ <defs>
+ <linearGradient x1="100%" y1="100%" x2="-22.8515625%" y2="-33.2356771%" id="linearGradient-1">
+ <stop stop-color="#6FFF80" offset="0%"></stop>
+ <stop stop-color="#43CE57" offset="37.2587344%"></stop>
+ <stop stop-color="#425FD0" offset="100%"></stop>
+ </linearGradient>
+ </defs>
+ <g id="Mainpage" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="Mainpage_Layout_V4_Megamenu" transform="translate(-1084.000000, -1756.000000)" fill="url(#linearGradient-1)">
+ <g id="Content" transform="translate(-44.000000, 1530.000000)">
+ <g id="WhatQtis" transform="translate(194.000000, 0.000000)">
+ <g id="Block3_Hover" transform="translate(726.316067, 114.000000)">
+ <path d="M214.4,115.2 C215.2816,115.2 216,115.9176 216,116.8 C216,117.6824 215.2816,118.4 214.4,118.4 C213.5176,118.4 212.8,117.6824 212.8,116.8 C212.8,115.9176 213.5176,115.2 214.4,115.2 L214.4,115.2 Z M217.6,116.8 C217.6,117.6824 218.3176,118.4 219.2,118.4 C220.0816,118.4 220.8,117.6824 220.8,116.8 C220.8,115.9176 220.0816,115.2 219.2,115.2 C218.3176,115.2 217.6,115.9176 217.6,116.8 L217.6,116.8 Z M222.4,116.8 C222.4,117.6824 223.1176,118.4 224,118.4 C224.8816,118.4 225.6,117.6824 225.6,116.8 C225.6,115.9176 224.8816,115.2 224,115.2 C223.1176,115.2 222.4,115.9176 222.4,116.8 L222.4,116.8 Z M215.2,128 L216.8,128 C217.2424,128 217.6,127.6416 217.6,127.2 C217.6,126.7584 217.2424,126.4 216.8,126.4 L215.2,126.4 C214.7576,126.4 214.4,126.7584 214.4,127.2 C214.4,127.6416 214.7576,128 215.2,128 L215.2,128 Z M215.2,131.2 L216.8,131.2 C217.2424,131.2 217.6,130.8416 217.6,130.4 C217.6,129.9584 217.2424,129.6 216.8,129.6 L215.2,129.6 C214.7576,129.6 214.4,129.9584 214.4,130.4 C214.4,130.8416 214.7576,131.2 215.2,131.2 L215.2,131.2 Z M215.2,134.4 L216.8,134.4 C217.2424,134.4 217.6,134.0416 217.6,133.6 C217.6,133.1584 217.2424,132.8 216.8,132.8 L215.2,132.8 C214.7576,132.8 214.4,133.1584 214.4,133.6 C214.4,134.0416 214.7576,134.4 215.2,134.4 L215.2,134.4 Z M215.2,137.6 L216.8,137.6 C217.2424,137.6 217.6,137.2416 217.6,136.8 C217.6,136.3584 217.2424,136 216.8,136 L215.2,136 C214.7576,136 214.4,136.3584 214.4,136.8 C214.4,137.2416 214.7576,137.6 215.2,137.6 L215.2,137.6 Z M215.2,140.8 L216.8,140.8 C217.2424,140.8 217.6,140.4416 217.6,140 C217.6,139.5584 217.2424,139.2 216.8,139.2 L215.2,139.2 C214.7576,139.2 214.4,139.5584 214.4,140 C214.4,140.4416 214.7576,140.8 215.2,140.8 L215.2,140.8 Z M215.2,144 L216.8,144 C217.2424,144 217.6,143.6416 217.6,143.2 C217.6,142.7584 217.2424,142.4 216.8,142.4 L215.2,142.4 C214.7576,142.4 214.4,142.7584 214.4,143.2 C214.4,143.6416 214.7576,144 215.2,144 L215.2,144 Z M215.2,147.2 L216.8,147.2 C217.2424,147.2 217.6,146.8416 217.6,146.4 C217.6,145.9584 217.2424,145.6 216.8,145.6 L215.2,145.6 C214.7576,145.6 214.4,145.9584 214.4,146.4 C214.4,146.8416 214.7576,147.2 215.2,147.2 L215.2,147.2 Z M215.2,150.4 L216.8,150.4 C217.2424,150.4 217.6,150.0416 217.6,149.6 C217.6,149.1584 217.2424,148.8 216.8,148.8 L215.2,148.8 C214.7576,148.8 214.4,149.1584 214.4,149.6 C214.4,150.0416 214.7576,150.4 215.2,150.4 L215.2,150.4 Z M215.2,153.6 L216.8,153.6 C217.2424,153.6 217.6,153.2416 217.6,152.8 C217.6,152.3584 217.2424,152 216.8,152 L215.2,152 C214.7576,152 214.4,152.3584 214.4,152.8 C214.4,153.2416 214.7576,153.6 215.2,153.6 L215.2,153.6 Z M242.4,128 C242.8424,128 243.2,127.6416 243.2,127.2 C243.2,126.7584 242.8424,126.4 242.4,126.4 L239.2,126.4 C238.7576,126.4 238.4,126.7584 238.4,127.2 C238.4,127.6416 238.7576,128 239.2,128 L242.4,128 L242.4,128 Z M235.2,130.4 C235.2,130.8416 235.5576,131.2 236,131.2 L244,131.2 C244.4424,131.2 244.8,130.8416 244.8,130.4 C244.8,129.9584 244.4424,129.6 244,129.6 L236,129.6 C235.5576,129.6 235.2,129.9584 235.2,130.4 L235.2,130.4 Z M220,131.2 L232.8,131.2 C233.2424,131.2 233.6,130.8416 233.6,130.4 C233.6,129.9584 233.2424,129.6 232.8,129.6 L220,129.6 C219.5576,129.6 219.2,129.9584 219.2,130.4 C219.2,130.8416 219.5576,131.2 220,131.2 L220,131.2 Z M220,128 L228,128 C228.4424,128 228.8,127.6416 228.8,127.2 C228.8,126.7584 228.4424,126.4 228,126.4 L220,126.4 C219.5576,126.4 219.2,126.7584 219.2,127.2 C219.2,127.6416 219.5576,128 220,128 L220,128 Z M236,126.4 L231.2,126.4 C230.7576,126.4 230.4,126.7584 230.4,127.2 C230.4,127.6416 230.7576,128 231.2,128 L236,128 C236.4424,128 236.8,127.6416 236.8,127.2 C236.8,126.7584 236.4424,126.4 236,126.4 L236,126.4 Z M248,133.6 C248,133.1584 247.6424,132.8 247.2,132.8 L234.4,132.8 C233.9576,132.8 233.6,133.1584 233.6,133.6 C233.6,134.0416 233.9576,134.4 234.4,134.4 L247.2,134.4 C247.6424,134.4 248,134.0416 248,133.6 L248,133.6 Z M242.4,137.6 C242.8424,137.6 243.2,137.2416 243.2,136.8 C243.2,136.3584 242.8424,136 242.4,136 L236,136 C235.5576,136 235.2,136.3584 235.2,136.8 C235.2,137.2416 235.5576,137.6 236,137.6 L242.4,137.6 L242.4,137.6 Z M220,137.6 L232.8,137.6 C233.2424,137.6 233.6,137.2416 233.6,136.8 C233.6,136.3584 233.2424,136 232.8,136 L220,136 C219.5576,136 219.2,136.3584 219.2,136.8 C219.2,137.2416 219.5576,137.6 220,137.6 L220,137.6 Z M220,134.4 L223.2,134.4 C223.6424,134.4 224,134.0416 224,133.6 C224,133.1584 223.6424,132.8 223.2,132.8 L220,132.8 C219.5576,132.8 219.2,133.1584 219.2,133.6 C219.2,134.0416 219.5576,134.4 220,134.4 L220,134.4 Z M226.4,132.8 C225.9576,132.8 225.6,133.1584 225.6,133.6 C225.6,134.0416 225.9576,134.4 226.4,134.4 L231.2,134.4 C231.6424,134.4 232,134.0416 232,133.6 C232,133.1584 231.6424,132.8 231.2,132.8 L226.4,132.8 L226.4,132.8 Z M237.6,146.4 C237.6,145.9584 237.2424,145.6 236.8,145.6 L234.4,145.6 C233.9576,145.6 233.6,145.9584 233.6,146.4 C233.6,146.8416 233.9576,147.2 234.4,147.2 L236.8,147.2 C237.2424,147.2 237.6,146.8416 237.6,146.4 L237.6,146.4 Z M220,147.2 L223.2,147.2 C223.6424,147.2 224,146.8416 224,146.4 C224,145.9584 223.6424,145.6 223.2,145.6 L220,145.6 C219.5576,145.6 219.2,145.9584 219.2,146.4 C219.2,146.8416 219.5576,147.2 220,147.2 L220,147.2 Z M231.2,145.6 L226.4,145.6 C225.9576,145.6 225.6,145.9584 225.6,146.4 C225.6,146.8416 225.9576,147.2 226.4,147.2 L231.2,147.2 C231.6424,147.2 232,146.8416 232,146.4 C232,145.9584 231.6424,145.6 231.2,145.6 L231.2,145.6 Z M220,150.4 L229.6,150.4 C230.0424,150.4 230.4,150.0416 230.4,149.6 C230.4,149.1584 230.0424,148.8 229.6,148.8 L220,148.8 C219.5576,148.8 219.2,149.1584 219.2,149.6 C219.2,150.0416 219.5576,150.4 220,150.4 L220,150.4 Z M232.8,150.4 L234.4,150.4 C234.8424,150.4 235.2,150.0416 235.2,149.6 C235.2,149.1584 234.8424,148.8 234.4,148.8 L232.8,148.8 C232.3576,148.8 232,149.1584 232,149.6 C232,150.0416 232.3576,150.4 232.8,150.4 L232.8,150.4 Z M220,153.6 L224.8,153.6 C225.2424,153.6 225.6,153.2416 225.6,152.8 C225.6,152.3584 225.2424,152 224.8,152 L220,152 C219.5576,152 219.2,152.3584 219.2,152.8 C219.2,153.2416 219.5576,153.6 220,153.6 L220,153.6 Z M227.2,152.8 C227.2,153.2416 227.5576,153.6 228,153.6 L236,153.6 C236.4424,153.6 236.8,153.2416 236.8,152.8 C236.8,152.3584 236.4424,152 236,152 L228,152 C227.5576,152 227.2,152.3584 227.2,152.8 L227.2,152.8 Z M244.8,140 C244.8,139.5584 244.4424,139.2 244,139.2 L231.2,139.2 C230.7576,139.2 230.4,139.5584 230.4,140 C230.4,140.4416 230.7576,140.8 231.2,140.8 L244,140.8 C244.4424,140.8 244.8,140.4416 244.8,140 L244.8,140 Z M239.2,143.2 C239.2,142.7584 238.8424,142.4 238.4,142.4 L232.8,142.4 C232.3576,142.4 232,142.7584 232,143.2 C232,143.6416 232.3576,144 232.8,144 L238.4,144 C238.8424,144 239.2,143.6416 239.2,143.2 L239.2,143.2 Z M220,144 L229.6,144 C230.0424,144 230.4,143.6416 230.4,143.2 C230.4,142.7584 230.0424,142.4 229.6,142.4 L220,142.4 C219.5576,142.4 219.2,142.7584 219.2,143.2 C219.2,143.6416 219.5576,144 220,144 L220,144 Z M220,140.8 L228,140.8 C228.4424,140.8 228.8,140.4416 228.8,140 C228.8,139.5584 228.4424,139.2 228,139.2 L220,139.2 C219.5576,139.2 219.2,139.5584 219.2,140 C219.2,140.4416 219.5576,140.8 220,140.8 L220,140.8 Z M256,149.6 L256,152.8 C256,153.2416 255.6424,153.6 255.2,153.6 L253.9816,153.6 C253.8976,153.8384 253.8008,154.072 253.692,154.3 L254.5528,155.1608 C254.8656,155.4736 254.8656,155.98 254.5528,156.292 L252.2904,158.5544 C252.1408,158.7048 251.9376,158.7888 251.7248,158.7888 C251.5128,158.7888 251.3096,158.7048 251.1592,158.5544 L250.2976,157.6928 C250.0704,157.8008 249.8376,157.8976 249.5992,157.9816 L249.5992,159.2 C249.5992,159.6416 249.2416,160 248.7992,160 L245.5992,160 C245.1568,160 244.7992,159.6416 244.7992,159.2 L244.7992,157.9816 C244.5616,157.8976 244.3288,157.8008 244.1008,157.692 L243.24,158.5528 C242.94,158.8528 242.4088,158.8528 242.1088,158.5528 L239.8464,156.2904 C239.5336,155.9784 239.5336,155.472 239.8464,155.1592 L240.7072,154.2984 C240.5992,154.0704 240.5024,153.8376 240.4184,153.6 L239.2,153.6 C238.7576,153.6 238.4,153.2416 238.4,152.8 L238.4,149.6 C238.4,149.1584 238.7576,148.8 239.2,148.8 L240.4184,148.8 C240.5024,148.5616 240.5992,148.328 240.708,148.1 L239.8472,147.2392 C239.5344,146.9264 239.5344,146.42 239.8472,146.108 L242.1088,143.8456 C242.4088,143.5456 242.94,143.5456 243.24,143.8456 L244.1016,144.7072 C244.3288,144.5984 244.5624,144.5016 244.8008,144.4176 L244.8008,143.2 C244.8008,142.7584 245.1584,142.4 245.6008,142.4 L248.8,142.4 C249.2424,142.4 249.6,142.7584 249.6,143.2 L249.6,144.4176 C249.8384,144.5016 250.072,144.5984 250.2984,144.7064 L251.16,143.8456 C251.4728,143.5344 251.9792,143.5336 252.2912,143.8464 L254.5536,146.1088 C254.8664,146.4208 254.8664,146.9272 254.5536,147.24 L253.6928,148.1008 C253.8016,148.3288 253.8976,148.5624 253.9816,148.8 L255.2,148.8 C255.6424,148.8 256,149.1584 256,149.6 L256,149.6 Z M254.4,150.4 L253.3896,150.4 C253.0248,150.4 252.7064,150.1528 252.6152,149.7992 C252.4848,149.2928 252.2848,148.8088 252.0192,148.3608 C251.8344,148.0464 251.8848,147.6464 252.1432,147.388 L252.8568,146.6744 L251.7256,145.5432 L251.012,146.2568 C250.7528,146.5144 250.352,146.5648 250.0392,146.3792 C249.5928,146.116 249.1088,145.916 248.6,145.784 C248.2472,145.6928 248,145.3744 248,145.0096 L248,144 L246.4008,144 L246.4008,145.0096 C246.4008,145.3744 246.1536,145.6928 245.8008,145.784 C245.292,145.916 244.8072,146.116 244.36,146.38 C244.0472,146.5656 243.6472,146.5152 243.388,146.256 L242.6744,145.5424 L241.544,146.6736 L242.2568,147.3872 C242.5152,147.6456 242.5656,148.0456 242.3808,148.36 C242.1152,148.8072 241.9152,149.292 241.7848,149.7992 C241.6936,150.1528 241.3752,150.4 241.0104,150.4 L240,150.4 L240,152 L241.0104,152 C241.3752,152 241.6936,152.2472 241.7848,152.6 C241.9152,153.1064 242.1152,153.5904 242.3808,154.0384 C242.5656,154.3528 242.5152,154.7528 242.2568,155.0112 L241.5432,155.7248 L242.6744,156.856 L243.388,156.1424 C243.6472,155.884 244.048,155.8336 244.3608,156.0192 C244.8112,156.2848 245.2944,156.4848 245.7976,156.6144 C246.152,156.7048 246.3992,157.024 246.3992,157.3888 L246.3992,158.4 L247.9992,158.4 L247.9992,157.3896 C247.9992,157.0248 248.2464,156.7056 248.6,156.6152 C249.1064,156.4848 249.5904,156.284 250.0384,156.02 C250.352,155.8344 250.7536,155.8848 251.0112,156.1432 L251.7248,156.8576 L252.856,155.7264 L252.1424,155.0128 C251.8832,154.7544 251.8336,154.3536 252.0192,154.0392 C252.2848,153.5912 252.4848,153.1072 252.6152,152.6008 C252.7064,152.2472 253.0248,152 253.3896,152 L254.4,152 L254.4,150.4 L254.4,150.4 Z M249.6,151.2 C249.6,152.5232 248.5232,153.6 247.2,153.6 C245.8768,153.6 244.8,152.5232 244.8,151.2 C244.8,149.8768 245.8768,148.8 247.2,148.8 C248.5232,148.8 249.6,149.8768 249.6,151.2 L249.6,151.2 Z M248,151.2 C248,150.7592 247.6416,150.4 247.2,150.4 C246.7584,150.4 246.4,150.7592 246.4,151.2 C246.4,151.6408 246.7584,152 247.2,152 C247.6416,152 248,151.6408 248,151.2 L248,151.2 Z M239.2,158.4 L212,158.4 C210.6768,158.4 209.6,157.3232 209.6,156 L209.6,124 C209.6,123.5584 209.2424,123.2 208.8,123.2 C208.3576,123.2 208,123.5584 208,124 L208,156 C208,158.2056 209.7944,160 212,160 L239.2,160 C239.6424,160 240,159.6416 240,159.2 C240,158.7584 239.6424,158.4 239.2,158.4 L239.2,158.4 Z M252,112 L212,112 C209.7944,112 208,113.7944 208,116 L208,120.8 C208,121.2416 208.3576,121.6 208.8,121.6 L252,121.6 C252.4424,121.6 252.8,121.2416 252.8,120.8 C252.8,120.3584 252.4424,120 252,120 L209.6,120 L209.6,116 C209.6,114.6768 210.6768,113.6 212,113.6 L252,113.6 C253.3232,113.6 254.4,114.6768 254.4,116 L254.4,143.2 C254.4,143.6416 254.7576,144 255.2,144 C255.6424,144 256,143.6416 256,143.2 L256,116 C256,113.7944 254.2056,112 252,112 L252,112 Z" id="web-development"></path>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/sources/pyside6/doc/images/linux.svg b/sources/pyside6/doc/images/linux.svg
new file mode 100644
index 000000000..af05345a2
--- /dev/null
+++ b/sources/pyside6/doc/images/linux.svg
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.0"
+ viewBox="0 0 266 312"
+ id="svg4"
+ sodipodi:docname="linux.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs8" />
+ <sodipodi:namedview
+ id="namedview6"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ showgrid="false"
+ inkscape:zoom="2.7916667"
+ inkscape:cx="119.46269"
+ inkscape:cy="156.35821"
+ inkscape:window-width="2552"
+ inkscape:window-height="1432"
+ inkscape:window-x="1924"
+ inkscape:window-y="4"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg4" />
+ <path
+ d="M128.6640625 79.2793c0 1-1 1-1 1h-1c-1 0-1-1-2-2 0 0-1-1-1-2s0-1 1-1l2 1c1 1 2 2 2 3m-18-10c0-5-2-8-5-8 0 0 0 1-1 1v2h3c0 2 1 3 1 5h2m35-5c2 0 3 2 4 5h2c-1-1-1-2-1-3s0-2-1-3-2-2-3-2c0 0-1 1-2 1 0 1 1 1 1 2m-30 16c-1 0-1 0-1-1s0-2 1-3c2 0 3-1 3-1 1 0 1 1 1 1 0 1-1 2-3 4h-1m-11-1c-4-2-5-5-5-10 0-3 0-5 2-7 1-2 3-3 5-3s3 1 5 3c1 3 2 6 2 9v2h1v-1c1 0 1-2 1-6 0-3 0-6-2-9s-4-5-8-5c-3 0-6 2-7 5-2 4-2.4 7-2.4 12 0 4 1.4 8 5.4 12 1-1 2-1 3-2m125 141c1 0 1-.4 1-1.3 0-2.2-1-4.8-4-7.7-3-3-8-4.9-14-5.7-1-.1-2-.1-2-.1-1-.2-1-.2-2-.2-1-.1-3-.3-4-.5 3-9.3 4-17.5 4-24.7 0-10-2-17-6-23s-8-9-13-10c-1 1-1 1-1 2 5 2 10 6 13 12 3 7 4 13 4 20 0 5.6-1 13.9-5 24.5-4 1.6-8 5.3-11 11.1 0 .9 0 1.4 1 1.4 0 0 1-.9 2-2.6 2-1.7 3-3.4 5-5.1 3-1.7 5-2.6 8-2.6 5 0 10 .7 13 2.1 4 1.3 6 2.7 7 4.3 1 1.5 2 2.9 3 4.2 0 1.3 1 1.9 1 1.9m-92-145c-1-1-1-3-1-5 0-4 0-6 2-9 2-2 4-3 6-3 3 0 5 2 7 4 1 3 2 5 2 8 0 5-2 8-6 9 0 0 1 1 2 1 2 0 3 1 5 2 1-6 2-10 2-15 0-6-1-10-3-13-3-3-6-4-10-4-3 0-6 1-9 3-2 3-3 5-3 8 0 5 1 9 3 13 1 0 2 1 3 1m12 16c-13 9-23 13-31 13-7 0-14-3-20-8 1 2 2 4 3 5l6 6c4 4 9 6 14 6 7 0 15-4 25-11l9-6c2-2 4-4 4-7 0-1 0-2-1-2-1-2-6-5-16-8-9-4-16-6-20-6-3 0-8 2-15 6-6 4-10 8-10 12 0 0 1 1 2 3 6 5 12 8 18 8 8 0 18-4 31-14v2c1 0 1 1 1 1m23 202c4 7.52 11 11.3 19 11.3 2 0 4-.3 6-.9 2-.4 4-1.1 5-1.9 1-.7 2-1.4 3-2.2 2-.7 2-1.2 3-1.7l17-14.7c4-3.19 8-5.98 13-8.4 4-2.4 8-4 10-4.9 3-.8 5-2 7-3.6 1-1.5 2-3.4 2-5.8 0-2.9-2-5.1-4-6.7s-4-2.7-6-3.4-4-2.3-7-5c-2-2.6-4-6.2-5-10.9l-1-5.8c-1-2.7-1-4.7-2-5.8 0-.3 0-.4-1-.4s-3 .9-4 2.6c-2 1.7-4 3.6-6 5.6-1 2-4 3.8-6 5.5-3 1.7-6 2.6-8 2.6-8 0-12-2.2-15-6.5-2-3.2-3-6.9-4-11.1-2-1.7-3-2.6-5-2.6-5 0-7 5.2-7 15.7v31.1c0 .9-1 2.9-1 6-1 3.1-1 6.62-1 10.6l-2 11.1v.17m-145-5.29c9.3 1.36 20 4.27 32.1 8.71 12.1 4.4 19.5 6.7 22.2 6.7 7 0 12.8-3.1 17.6-9.09 1-1.94 1-4.22 1-6.84 0-9.45-5.7-21.4-17.1-35.9l-6.8-9.1c-1.4-1.9-3.1-4.8-5.3-8.7-2.1-3.9-4-6.9-5.5-9-1.3-2.3-3.4-4.6-6.1-6.9-2.6-2.3-5.6-3.8-8.9-4.6-4.2.8-7.1 2.2-8.5 4.1s-2.2 4-2.4 6.2c-.3 2.1-.9 3.5-1.9 4.2-1 .6-2.7 1.1-5 1.6-.5 0-1.4 0-2.7.1h-2.7c-5.3 0-8.9.6-10.8 1.6-2.5 2.9-3.8 6.2-3.8 9.7 0 1.6.4 4.3 1.2 8.1.8 3.7 1.2 6.7 1.2 8.8 0 4.1-1.2 8.2-3.7 12.3-2.5 4.3-3.8 7.5-3.8 9.78 1 3.88 7.6 6.61 19.7 8.21m33.3-90.9c0-6.9 1.8-14.5 5.5-23.5 3.6-9 7.2-15 10.7-19-.2-1-.7-1-1.5-1l-1-1c-2.9 3-6.4 10-10.6 20-4.2 9-6.4 17.3-6.4 23.4 0 4.5 1.1 8.4 3.1 11.8 2.2 3.3 7.5 8.1 15.9 14.2l10.6 6.9c11.3 9.8 17.3 16.6 17.3 20.6 0 2.1-1 4.2-4 6.5-2 2.4-4.7 3.6-7 3.6-.2 0-.3.2-.3.7 0 .1 1 2.1 3.1 6 4.2 5.7 13.2 8.5 25.2 8.5 22 0 39-9 52-27 0-5 0-8.1-1-9.4v-3.7c0-6.5 1-11.4 3-14.6s4-4.7 7-4.7c2 0 4 .7 6 2.2 1-7.7 1-14.4 1-20.4 0-9.1 0-16.6-2-23.6-1-6-3-11-5-15l-6-9c-2-3-3-6-5-9-1-4-2-7-2-12-3-5-5-10-8-15-2-5-4-10-6-14l-9 7c-10 7-18 10-25 10-6 0-11-1-14-5l-6-5c0 3-1 7-3 11l-6.3 12c-2.8 7-4.3 11-4.6 14-.4 2-.7 4-.9 4l-7.5 15c-8.1 15-12.2 28.9-12.2 40.4 0 2.3.2 4.7.6 7.1-4.5-3.1-6.7-7.4-6.7-13m71.6 94.6c-13 0-23 1.76-30 5.25v-.3c-5 6-10.6 9.1-18.4 9.1-4.9 0-12.6-1.9-23-5.7-10.5-3.6-19.8-6.36-27.9-8.18-.8-.23-2.6-.57-5.5-1.03-2.8-.45-5.4-.91-7.7-1.37-2.1-.45-4.5-1.13-7.1-2.05-2.5-.79-4.5-1.82-6-3.07-1.38-1.26-2.06-2.68-2.06-4.27 0-1.6.34-3.31 1.02-5.13.64-1.1 1.34-2.2 2.04-3.2.7-1.1 1.3-2.1 1.7-3.1.6-.9 1-1.8 1.4-2.8.4-.9.8-1.8 1-2.9.2-1 .4-2 .4-3s-.4-4-1.2-9.3c-.8-5.2-1.2-8.5-1.2-9.9 0-4.4 1-7.9 3.2-10.4s4.3-3.8 6.5-3.8h11.5c.9 0 2.3-.5 4.4-1.7.7-1.6 1.3-2.9 1.7-4.1.5-1.2.7-2.1.9-2.5.2-.6.4-1.2.6-1.7.4-.7.9-1.5 1.6-2.3-.8-1-1.2-2.3-1.2-3.9 0-1.1 0-2.1.2-2.7 0-3.6 1.7-8.7 5.3-15.4l3.5-6.3c2.9-5.4 5.1-9.4 6.7-13.4 1.7-4 3.5-10 5.5-18 1.6-7 5.4-14 11.4-21l7.5-9c5.2-6 8.6-11 10.5-15s2.9-9 2.9-13c0-2-.5-8-1.6-18-1-10-1.5-20-1.5-29 0-7 .6-12 1.9-17s3.6-10 7-14c3-4 7-8 13-10s13-3 21-3c3 0 6 0 9 1 3 0 7 1 12 3 4 2 8 4 11 7 4 3 7 8 10 13 2 6 4 12 5 20 1 5 1 10 2 17 0 6 1 10 1 13 1 3 1 7 2 12 1 4 2 8 4 11 2 4 4 8 7 12 3 5 7 10 11 16 9 10 16 21 20 32 5 10 8 23 8 36.9 0 6.9-1 13.6-3 20.1 2 0 3 .8 4 2.2s2 4.4 3 9.1l1 7.4c1 2.2 2 4.3 5 6.1 2 1.8 4 3.3 7 4.5 2 1 5 2.4 7 4.2 2 2 3 4.1 3 6.3 0 3.4-1 5.9-3 7.7-2 2-4 3.4-7 4.3-2 1-6 3-12 5.82-5 2.96-10 6.55-15 10.8l-10 8.51c-4 3.9-8 6.7-11 8.4-3 1.8-7 2.7-11 2.7l-7-.8c-8-2.1-13-6.1-16-12.2-16-1.94-29-2.9-37-2.9"
+ id="path2"
+ style="fill:#53586b;fill-opacity:1" />
+</svg>
diff --git a/sources/pyside6/doc/images/macos.svg b/sources/pyside6/doc/images/macos.svg
new file mode 100644
index 000000000..01b8cb002
--- /dev/null
+++ b/sources/pyside6/doc/images/macos.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ viewBox="0 0 4875 4875"
+ version="1.1"
+ id="svg4"
+ sodipodi:docname="macOS.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs8" />
+ <sodipodi:namedview
+ id="namedview6"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ showgrid="false"
+ inkscape:zoom="0.17866667"
+ inkscape:cx="2056.9029"
+ inkscape:cy="2443.097"
+ inkscape:window-width="1920"
+ inkscape:window-height="1080"
+ inkscape:window-x="1920"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg4" />
+ <path
+ fill="#666"
+ d="m 4217.2809,3659.1573 c -67.1033,155.0227 -146.5318,297.7206 -238.5597,428.9145 -125.4425,178.8514 -228.1514,302.6507 -307.3064,371.3978 -122.7033,112.843 -254.1713,170.6343 -394.952,173.9209 -101.0661,0 -222.9479,-28.7587 -364.8238,-87.0974 -142.3418,-58.0655 -273.1524,-86.8235 -392.7608,-86.8235 -125.4424,0 -259.9782,28.758 -403.8809,86.8235 -144.1218,58.3387 -260.2248,88.7411 -348.9927,91.7538 -135.0014,5.7518 -269.5646,-53.6831 -403.8809,-178.5773 -85.7283,-74.7731 -192.9569,-202.9541 -321.4121,-384.5447 C 902.88949,3881.0097 789.58031,3656.1447 700.81195,3399.782 605.74429,3122.8775 558.08701,2854.7371 558.08701,2595.1424 c 0,-297.3638 64.25482,-553.8363 192.95678,-768.7591 101.14827,-172.6342 235.71135,-308.8131 404.12711,-408.7836 168.4162,-99.9703 350.3899,-150.914 546.3595,-154.1734 107.2285,0 247.8447,33.1682 422.5877,98.3545 174.25,65.4052 286.1345,98.5736 335.1882,98.5736 36.6747,0 160.9663,-38.7834 371.6716,-116.1026 199.256,-71.705 367.4256,-101.3949 505.1932,-89.7 373.3149,30.1284 653.78,177.2902 840.3002,442.4178 -333.8741,202.2962 -499.0309,485.6375 -495.7444,849.1192 3.0132,283.1218 105.7221,518.7232 307.5803,705.7915 91.4803,86.8235 193.6417,153.9273 307.3064,201.5844 -24.6494,71.4857 -50.6695,139.9584 -78.3327,205.6926 z M 3361.0953,290.01478 c 0,221.90982 -81.0722,429.10615 -242.6678,620.88525 -195.0111,227.98777 -430.8867,359.72937 -686.6746,338.94127 -3.2589,-26.6223 -5.1489,-54.6418 -5.1489,-84.085 0,-213.03328 92.7396,-441.02035 257.431,-627.43123 82.222,-94.38292 186.794,-172.86107 313.606,-235.46509 126.5378,-61.66949 246.2285,-95.77377 358.7983,-101.61416 3.2866,29.66615 4.656,59.3338 4.656,88.76593 z"
+ id="path2"
+ style="fill:#53586b;fill-opacity:1;stroke-width:4.43719" />
+</svg>
diff --git a/sources/pyside6/doc/images/windows.svg b/sources/pyside6/doc/images/windows.svg
new file mode 100644
index 000000000..a40519bb0
--- /dev/null
+++ b/sources/pyside6/doc/images/windows.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ viewBox="0 0 4875 4875"
+ version="1.1"
+ id="svg4"
+ sodipodi:docname="windows.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs8" />
+ <sodipodi:namedview
+ id="namedview6"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ showgrid="false"
+ inkscape:zoom="0.17866667"
+ inkscape:cx="2224.8134"
+ inkscape:cy="2437.5"
+ inkscape:window-width="2552"
+ inkscape:window-height="1432"
+ inkscape:window-x="1924"
+ inkscape:window-y="4"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg4" />
+ <path
+ fill="#0078d4"
+ d="M0 0h2311v2310H0zm2564 0h2311v2310H2564zM0 2564h2311v2311H0zm2564 0h2311v2311H2564"
+ id="path2"
+ style="fill:#53586b;fill-opacity:1" />
+</svg>
diff --git a/sources/pyside6/doc/import_inheritance.py b/sources/pyside6/doc/import_inheritance.py
new file mode 100644
index 000000000..e694941c9
--- /dev/null
+++ b/sources/pyside6/doc/import_inheritance.py
@@ -0,0 +1,152 @@
+import inspect
+import sys
+
+"""Helpers for determining base classes by importing the class.
+When passed something like:
+ PySide6.QtCore.QStateMachine.SignalEvent
+try to import the underlying module and return a
+handle to the object. In a loop, import
+ PySide6.QtCore.QStateMachine.SignalEvent
+ PySide6.QtCore.QStateMachine
+ PySide6.QtCore
+until the import succeeds and walk up the attributes
+to obtain the object."""
+
+
+TEST_DRIVER_USAGE = """Usage: import_inheritance.py class_name [current_module]
+
+Example:
+python import_inheritance.py PySide6.QtWidgets.QWizard PySide6.QtWidgets
+"""
+
+
+class InheritanceException(Exception):
+ pass
+
+
+def _importClassOrModule(name):
+ components = name.split('.')
+ for i in range(len(components), 0, -1):
+ importPath = '.'.join(components[: i])
+ try:
+ __import__(importPath)
+ except ImportError:
+ continue
+ if i == len(components):
+ return sys.modules[importPath]
+ remaining = components[i:]
+ cls = sys.modules[importPath]
+ for component in remaining:
+ try:
+ cls = getattr(cls, component)
+ except Exception: # No such attribute
+ return None
+ return cls
+ return None
+
+
+def _import_class_or_module(name, currmodule):
+ """
+ Import a class using its fully-qualified *name*.
+ """
+ todoc = _importClassOrModule(name)
+ if not todoc and currmodule is not None:
+ todoc = _importClassOrModule(f"{currmodule}.{name}")
+ if not todoc:
+ moduleStr = f'(module {currmodule})' if currmodule else ''
+ raise InheritanceException(f'Could not import class {name} specified for '
+ f'inheritance diagram {moduleStr}.')
+ if inspect.isclass(todoc):
+ return [todoc]
+ elif inspect.ismodule(todoc):
+ classes = []
+ for cls in todoc.__dict__.values():
+ if inspect.isclass(cls) and cls.__module__ == todoc.__name__:
+ classes.append(cls)
+ return classes
+ raise InheritanceException(f'{name} specified for inheritance diagram is '
+ 'not a class or module')
+
+
+def _import_classes(class_names, currmodule):
+ """Import a list of classes."""
+ classes = []
+ for name in class_names:
+ classes.extend(_import_class_or_module(name, currmodule))
+ return classes
+
+
+def _class_name(cls, parts=0):
+ """Given a class object, return a fully-qualified name.
+
+ This works for things I've tested in matplotlib so far, but may not be
+ completely general.
+ """
+ module = cls.__module__
+ if module == '__builtin__':
+ fullname = cls.__name__
+ else:
+ fullname = f"{module}.{cls.__qualname__}"
+ if parts == 0:
+ return fullname
+ name_parts = fullname.split('.')
+ return '.'.join(name_parts[-parts:])
+
+
+def _class_info(classes, builtins=None, show_builtins=False, parts=0):
+ """Return name and bases for all classes that are ancestors of
+ *classes*.
+
+ *parts* gives the number of dotted name parts that is removed from the
+ displayed node names.
+ """
+ all_classes = {}
+ builtins_list = builtins.values() if builtins else []
+
+ def recurse(cls):
+ if not show_builtins and cls in builtins_list:
+ return
+
+ nodename = _class_name(cls, parts)
+ fullname = _class_name(cls, 0)
+
+ baselist = []
+ all_classes[cls] = (nodename, fullname, baselist)
+ for base in cls.__bases__:
+ if not show_builtins and base in builtins_list:
+ continue
+ if base.__name__ == "Object" and base.__module__ == "Shiboken":
+ continue
+ baselist.append(_class_name(base, parts))
+ if base not in all_classes:
+ recurse(base)
+
+ for cls in classes:
+ recurse(cls)
+
+ return list(all_classes.values())
+
+
+def get_inheritance_entries_by_import(class_names, currmodule,
+ builtins=None,
+ show_builtins=False, parts=0):
+ classes = _import_classes(class_names, currmodule)
+ class_info = _class_info(classes, builtins, show_builtins, parts)
+ if not class_info:
+ raise InheritanceException('No classes found for '
+ 'inheritance diagram')
+ return class_info
+
+
+if __name__ == "__main__":
+ module = None
+ if len(sys.argv) < 2:
+ print(TEST_DRIVER_USAGE)
+ sys.exit(-1)
+ class_name = sys.argv[1]
+ if len(sys.argv) >= 3:
+ module = sys.argv[2]
+ entries = get_inheritance_entries_by_import([class_name], module, None,
+ False, 2)
+ for e in entries:
+ print(e)
diff --git a/sources/pyside6/doc/index.rst b/sources/pyside6/doc/index.rst
index 10b878d9b..1bb28f9c1 100644
--- a/sources/pyside6/doc/index.rst
+++ b/sources/pyside6/doc/index.rst
@@ -3,8 +3,9 @@
.. ifconfig:: output_format == 'html'
- **Qt for Python** offers the official Python bindings for `Qt`_, and
- has two main components:
+ **Qt for Python** offers the official Python bindings for `Qt`_,
+ which enables you to use Python to write your Qt applications.
+ The project has two main components:
* `PySide6`_, so that you can use Qt6 APIs in your Python applications, and
* `Shiboken6 <shiboken6/index.html>`__, a binding generator tool, which can
@@ -13,8 +14,9 @@
.. ifconfig:: output_format == 'qthelp'
- **Qt for Python** offers the official Python bindings for `Qt`_, and
- has two main components:
+ **Qt for Python** offers the official Python bindings for `Qt`_,
+ which enables you to use Python to write your Qt applications.
+ The project has two main components:
* `PySide6`_, so that you can use Qt6 APIs in your Python applications, and
* `Shiboken6 <../shiboken6/index.html>`__, a binding generator tool, which can
@@ -29,118 +31,184 @@ This project is available under the LGPLv3/GPLv3 and the `Qt commercial license`
.. _Qt: https://doc.qt.io
.. _PySide6: quickstart.html
.. _`Qt commercial license`: https://www.qt.io/licensing/
-.. _`Porting from PySide2 to PySide6`: porting_from2.html
+.. _`Porting from PySide2 to PySide6`: gettingstarted/porting_from2.html
+Quick Start
+===========
+You can obtain the latest stable version by running ``pip install pyside6``.
+If you want to build it yourself, check the `getting started guide`_.
-Documentation
-=============
-
-.. panels::
- :body: align-items-center jutify-content-center text-center
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
- :img-top-cls: d-flex align-self-center img-responsive card-img-top-main
-
- :img-top: images/Desktop.svg
-
- Write your first Qt application.
-
- +++
-
- .. link-button:: quickstart
- :type: ref
- :text: Check it out!
- :classes: btn-qt btn-block stretched-link
- ---
- :img-top: images/Support.svg
-
- Install and build from source.
-
- +++
-
- .. link-button:: gettingstarted
- :type: ref
- :text: Getting Started
- :classes: btn-qt btn-block stretched-link
- ---
- :img-top: images/Dev.svg
-
- PySide API reference.
-
- +++
-
- .. link-button:: api
- :type: ref
- :text: API Docs
- :classes: btn-qt btn-block stretched-link
-
- ---
- :img-top: images/Tutorials.svg
-
- Learn with step-by-step guides.
+To learn how to use it, check out `write your first application`_,
+and to learn what is installed with the ``pyside6``, check the
+`package content, structure, and tools`_ page.
- +++
- .. link-button:: tutorials/index
- :type: ref
- :text: Tutorials
- :classes: btn-qt btn-block stretched-link
- ---
- :img-top: images/Examples.svg
+.. _`getting started guide`: gettingstarted/index.html
+.. _`write your first application`: quickstart.html
+.. _`package content, structure, and tools`: gettingstarted/package_details.html
- Check all the available examples.
-
- +++
-
- .. link-button:: examples/index
- :type: ref
- :text: Examples
- :classes: btn-qt btn-block stretched-link
- ---
- :img-top: images/Training.svg
-
- Watch webinars, talks, and more.
-
- +++
-
- .. link-button:: videos
- :type: ref
- :text: Videos
- :classes: btn-qt btn-block stretched-link
-
- ---
- :img-top: images/Deployment.svg
-
- Learn to deploy your applications.
-
- +++
-
- .. link-button:: deployment-guides
- :type: ref
- :text: Deployment
- :classes: btn-qt btn-block stretched-link
- ---
- :img-top: images/stopwatch.svg
-
- API differences and known issues.
-
- +++
-
- .. link-button:: considerations
- :type: ref
- :text: Considerations
- :classes: btn-qt btn-block stretched-link
- ---
- :img-top: images/cpp_python.svg
+Documentation
+=============
- Generate C++ to Python bindings.
+.. grid:: 1 3 3 3
+ :gutter: 2
+
+ .. grid-item-card::
+ :img-top: images/Desktop.svg
+ :class-item: text-center
+
+ Write your first Qt application.
+ +++
+ .. button-ref:: quick-start
+ :color: primary
+ :outline:
+ :expand:
+
+ Start here!
+
+ .. grid-item-card::
+ :img-top: images/Support.svg
+ :class-item: text-center
+
+ Modules, docs, and cross compilation.
+ +++
+ .. button-ref:: gettingstarted/index
+ :color: primary
+ :outline:
+ :expand:
+
+ Build Instructions
+
+ .. grid-item-card::
+ :img-top: images/Commercial.svg
+ :class-item: text-center
+
+ Packages, installation, and details.
+ +++
+ .. button-ref:: commercial-page
+ :color: primary
+ :outline:
+ :expand:
+
+ Commercial
+
+ .. grid-item-card::
+ :img-top: images/Dev.svg
+ :class-item: text-center
+
+ PySide API reference.
+ +++
+ .. button-ref:: pyside-api
+ :color: primary
+ :outline:
+ :expand:
+
+ API Docs
+
+ .. grid-item-card::
+ :img-top: images/Tutorials.svg
+ :class-item: text-center
+
+ Learn with step-by-step guides.
+ +++
+ .. button-ref:: tutorials/index
+ :color: primary
+ :outline:
+ :expand:
+
+ Tutorials
+
+ .. grid-item-card::
+ :img-top: images/Examples.svg
+ :class-item: text-center
+
+ Check all the available examples.
+ +++
+ .. button-ref:: examples/index
+ :color: primary
+ :outline:
+ :expand:
+
+ Examples
+
+ .. grid-item-card::
+ :img-top: images/Training.svg
+ :class-item: text-center
+
+ Watch webinars, talks, and more.
+ +++
+ .. button-ref:: videos
+ :color: primary
+ :outline:
+ :expand:
+
+ Videos
+
+ .. grid-item-card::
+ :img-top: images/Tooling.svg
+ :class-item: text-center
+
+ Discover the tools included.
+ +++
+ .. button-ref:: package_tools
+ :color: primary
+ :outline:
+ :expand:
+
+ Tooling
+
+ .. grid-item-card::
+ :img-top: images/Deployment.svg
+ :class-item: text-center
+
+ Learn to deploy your applications.
+ +++
+ .. button-ref:: deployment-guides
+ :color: primary
+ :outline:
+ :expand:
+
+ Deployment
+
+ .. grid-item-card::
+ :img-top: images/cpp_python.svg
+ :class-item: text-center
+
+ Generate C++ to Python bindings.
+ +++
+ .. button-link:: shiboken6/index.html
+ :color: primary
+ :outline:
+ :expand:
+
+ Shiboken
+
+ .. grid-item-card::
+ :img-top: images/stopwatch.svg
+ :class-item: text-center
+
+ API differences and known issues.
+ +++
+ .. button-ref:: considerations
+ :color: primary
+ :outline:
+ :expand:
+
+ Considerations
- +++
+ .. grid-item-card::
+ :img-top: images/Development.svg
+ :class-item: text-center
- .. link-button:: shiboken6/index.html
- :text: Shiboken
- :classes: btn-qt btn-block stretched-link
+ Notes for Developers.
+ +++
+ .. button-ref:: developer-notes
+ :color: primary
+ :outline:
+ :expand:
+
+ Developers
We have also a `wiki page`_ where you can find how to report bugs, contribute or contact the community.
@@ -152,6 +220,3 @@ We have also a `wiki page`_ where you can find how to report bugs, contribute or
:glob:
contents.rst
- gettingstarted*
- overviews/*
- feature-why
diff --git a/sources/pyside6/doc/inheritance_diagram.py b/sources/pyside6/doc/inheritance_diagram.py
index 846367050..e972fac4c 100644
--- a/sources/pyside6/doc/inheritance_diagram.py
+++ b/sources/pyside6/doc/inheritance_diagram.py
@@ -37,10 +37,6 @@ r"""
:license: BSD, see LICENSE for details.
"""
-import os
-import re
-import sys
-import inspect
try:
from hashlib import md5
except ImportError:
@@ -51,211 +47,8 @@ from docutils.parsers.rst import directives, Directive
from sphinx.ext.graphviz import render_dot_html, render_dot_latex
-class InheritanceException(Exception):
- pass
-
-# When passed something like:
-# PySide6.QtCore.QStateMachine.SignalEvent
-# try to import the underlying module and return a
-# handle to the object. In a loop, import
-# PySide6.QtCore.QStateMachine.SignalEvent
-# PySide6.QtCore.QStateMachine
-# PySide6.QtCore
-# until the import succeeds and walk up the attributes
-# to obtain the object
-
-def importClassOrModule(name):
- components = name.split('.')
- for i in range(len(components), 0, -1):
- importPath = '.'.join(components[: i])
- try:
- __import__(importPath)
- except ImportError:
- continue
- if i == len(components):
- return sys.modules[importPath]
- remaining = components[i :]
- cls = sys.modules[importPath]
- for component in remaining:
- try:
- cls = getattr(cls, component)
- except Exception: # No such attribute
- return None
- return cls
- return None
-
-class InheritanceGraph(object):
- """
- Given a list of classes, determines the set of classes that they inherit
- from all the way to the root "object", and then is able to generate a
- graphviz dot graph from them.
- """
- def __init__(self, class_names, currmodule, show_builtins=False, parts=0):
- """
- *class_names* is a list of child classes to show bases from.
-
- If *show_builtins* is True, then Python builtins will be shown
- in the graph.
- """
- self.class_names = class_names
- classes = self._import_classes(class_names, currmodule)
- self.class_info = self._class_info(classes, show_builtins, parts)
- if not self.class_info:
- raise InheritanceException('No classes found for '
- 'inheritance diagram')
-
- def _import_class_or_module(self, name, currmodule):
- """
- Import a class using its fully-qualified *name*.
- """
- todoc = importClassOrModule(name)
- if not todoc and currmodule is not None:
- todoc = importClassOrModule(f"{currmodule}.{name}")
- if not todoc:
- moduleStr = f'(module {currmodule})' if currmodule else ''
- raise InheritanceException(f'Could not import class {name} specified for '
- f'inheritance diagram {moduleStr}.')
- if inspect.isclass(todoc):
- return [todoc]
- elif inspect.ismodule(todoc):
- classes = []
- for cls in todoc.__dict__.values():
- if inspect.isclass(cls) and cls.__module__ == todoc.__name__:
- classes.append(cls)
- return classes
- raise InheritanceException(f'{name} specified for inheritance diagram is '
- 'not a class or module')
-
- def _import_classes(self, class_names, currmodule):
- """Import a list of classes."""
- classes = []
- for name in class_names:
- classes.extend(self._import_class_or_module(name, currmodule))
- return classes
-
- def _class_info(self, classes, show_builtins, parts):
- """Return name and bases for all classes that are ancestors of
- *classes*.
-
- *parts* gives the number of dotted name parts that is removed from the
- displayed node names.
- """
- all_classes = {}
- builtins = __builtins__.values()
-
- def recurse(cls):
- if not show_builtins and cls in builtins:
- return
-
- nodename = self.class_name(cls, parts)
- fullname = self.class_name(cls, 0)
-
- baselist = []
- all_classes[cls] = (nodename, fullname, baselist)
- for base in cls.__bases__:
- if not show_builtins and base in builtins:
- continue
- if base.__name__ == "Object" and base.__module__ == "Shiboken":
- continue
- baselist.append(self.class_name(base, parts))
- if base not in all_classes:
- recurse(base)
-
- for cls in classes:
- recurse(cls)
-
- return list(all_classes.values())
-
- def class_name(self, cls, parts=0):
- """Given a class object, return a fully-qualified name.
-
- This works for things I've tested in matplotlib so far, but may not be
- completely general.
- """
- module = cls.__module__
- if module == '__builtin__':
- fullname = cls.__name__
- else:
- fullname = f"{module}.{cls.__qualname__}"
- if parts == 0:
- return fullname
- name_parts = fullname.split('.')
- return '.'.join(name_parts[-parts:])
-
- def get_all_class_names(self):
- """
- Get all of the class names involved in the graph.
- """
- return [fullname for (_, fullname, _) in self.class_info]
-
- # These are the default attrs for graphviz
- default_graph_attrs = {
- 'rankdir': 'LR',
- 'size': '"8.0, 12.0"',
- }
- default_node_attrs = {
- 'shape': 'box',
- 'fontsize': 10,
- 'height': 0.25,
- 'fontname': '"Vera Sans, DejaVu Sans, Liberation Sans, '
- 'Arial, Helvetica, sans"',
- 'style': '"setlinewidth(0.5)"',
- }
- default_edge_attrs = {
- 'arrowsize': 0.5,
- 'style': '"setlinewidth(0.5)"',
- }
-
- def _format_node_attrs(self, attrs):
- return ','.join([f'{x[0]}={x[1]}' for x in attrs.items()])
-
- def _format_graph_attrs(self, attrs):
- return ''.join([f"{x[0]}={x[1]};\n" for x in attrs.items()])
-
- def generate_dot(self, name, urls={}, env=None,
- graph_attrs={}, node_attrs={}, edge_attrs={}):
- """
- Generate a graphviz dot graph from the classes that
- were passed in to __init__.
-
- *name* is the name of the graph.
-
- *urls* is a dictionary mapping class names to HTTP URLs.
-
- *graph_attrs*, *node_attrs*, *edge_attrs* are dictionaries containing
- key/value pairs to pass on as graphviz properties.
- """
- g_attrs = self.default_graph_attrs.copy()
- n_attrs = self.default_node_attrs.copy()
- e_attrs = self.default_edge_attrs.copy()
- g_attrs.update(graph_attrs)
- n_attrs.update(node_attrs)
- e_attrs.update(edge_attrs)
- if env:
- g_attrs.update(env.config.inheritance_graph_attrs)
- n_attrs.update(env.config.inheritance_node_attrs)
- e_attrs.update(env.config.inheritance_edge_attrs)
-
- res = []
- res.append(f'digraph {name} {{\n')
- res.append(self._format_graph_attrs(g_attrs))
-
- for name, fullname, bases in self.class_info:
- # Write the node
- this_node_attrs = n_attrs.copy()
- url = urls.get(fullname)
- if url is not None:
- this_node_attrs['URL'] = f'"{url}"'
- this_node_attrs['target'] = '"_top"' # Browser target frame attribute (same page)
- attribute = self._format_node_attrs(this_node_attrs)
- res.append(f' "{name}" [{attribute}];\n')
-
- # Write the edges
- for base_name in bases:
- attribute = self._format_node_attrs(e_attrs)
- res.append(f' "{base_name}" -> "{name}" [{attribute}];\n')
- res.append('}\n')
- return ''.join(res)
+from inheritance_graph import InheritanceGraph
+from import_inheritance import (InheritanceException)
class inheritance_diagram(nodes.General, nodes.Element):
@@ -291,7 +84,7 @@ class InheritanceDiagram(Directive):
try:
graph = InheritanceGraph(
class_names, env.temp_data.get('py:module'),
- parts=node['parts'])
+ __builtins__, parts=node['parts'])
except InheritanceException as err:
return [node.document.reporter.warning(err.args[0],
line=self.lineno)]
@@ -315,27 +108,6 @@ def get_graph_hash(node):
return md5(hashString.encode('utf-8')).hexdigest()[-10:]
-def fix_class_name(name):
- """Fix duplicated modules 'PySide6.QtCore.PySide6.QtCore.QObject'"""
- mod_pos = name.rfind('.PySide')
- return name[mod_pos + 1:] if mod_pos != -1 else name
-
-
-def expand_ref_uri(uri):
- """Fix a ref URI like 'QObject.html#PySide6.QtCore.PySide6.QtCore.QObject'
- to point from the image directory back to the HTML directory."""
- anchor_pos = uri.find('#')
- if anchor_pos == -1:
- return uri
- # Determine the path from the anchor "#PySide6.QtCore.PySide6.QtCore.QObject"
- class_name = fix_class_name(uri[anchor_pos + 1:])
- path = '../'
- modules = class_name.split('.')
- for m in range(min(2, len(modules))):
- path += f'{modules[m]}/'
- return path + uri[:anchor_pos] # Strip anchor
-
-
def html_visit_inheritance_diagram(self, node):
"""
Output the graph for HTML. This will insert a PNG with clickable
@@ -352,7 +124,7 @@ def html_visit_inheritance_diagram(self, node):
ref_title = child.get('reftitle')
uri = child.get('refuri')
if uri and ref_title:
- urls[fix_class_name(ref_title)] = expand_ref_uri(uri)
+ urls[ref_title] = uri
dotcode = graph.generate_dot(name, urls, env=self.builder.env)
render_dot_html(self, node, dotcode, {}, 'inheritance', 'inheritance',
diff --git a/sources/pyside6/doc/inheritance_diagram.pyproject b/sources/pyside6/doc/inheritance_diagram.pyproject
new file mode 100644
index 000000000..a44dc93b8
--- /dev/null
+++ b/sources/pyside6/doc/inheritance_diagram.pyproject
@@ -0,0 +1,6 @@
+{
+ "files": ["inheritance_diagram.py",
+ "import_inheritance.py",
+ "inheritance_graph.py",
+ "json_inheritance.py"]
+}
diff --git a/sources/pyside6/doc/inheritance_graph.py b/sources/pyside6/doc/inheritance_graph.py
new file mode 100644
index 000000000..00e0ac486
--- /dev/null
+++ b/sources/pyside6/doc/inheritance_graph.py
@@ -0,0 +1,145 @@
+# Copyright (C) 2022 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 sys
+
+from import_inheritance import (get_inheritance_entries_by_import)
+from json_inheritance import (is_inheritance_from_json_enabled,
+ get_inheritance_entries_from_json)
+
+
+TEST_DRIVER_USAGE = """Usage: inheritance_graph.py [module] [class]
+
+Example:
+python inheritance_graph.py PySide6.QtWidgets PySide6.QtWidgets.QWizard
+"""
+
+
+def format_dict(d):
+ """Format the URL dict for error message."""
+ result = '{'
+ n = 0
+ for k, v in d.items():
+ n += 1
+ if n > 10:
+ result += "..."
+ break
+ if n > 1:
+ result += ", "
+ result += f'"{k}": "{v}"'
+ result += '}'
+ return result
+
+
+class InheritanceGraph(object):
+ """
+ Given a list of classes, determines the set of classes that they inherit
+ from all the way to the root "object", and then is able to generate a
+ graphviz dot graph from them.
+ """
+ def __init__(self, class_names, currmodule, builtins=None, show_builtins=False, parts=0):
+ """
+ *class_names* is a list of child classes to show bases from.
+
+ If *show_builtins* is True, then Python builtins will be shown
+ in the graph.
+ """
+ self.class_names = class_names
+ if is_inheritance_from_json_enabled():
+ self.class_info = get_inheritance_entries_from_json(class_names)
+ else:
+ self.class_info = get_inheritance_entries_by_import(class_names,
+ currmodule,
+ builtins,
+ show_builtins,
+ parts)
+
+ def get_all_class_names(self):
+ """
+ Get all of the class names involved in the graph.
+ """
+ return [fullname for (_, fullname, _) in self.class_info]
+
+ # These are the default attrs for graphviz
+ default_graph_attrs = {
+ 'rankdir': 'LR',
+ 'size': '"8.0, 12.0"',
+ }
+ default_node_attrs = {
+ 'shape': 'box',
+ 'fontsize': 10,
+ 'height': 0.25,
+ 'fontname': '"Vera Sans, DejaVu Sans, Liberation Sans, '
+ 'Arial, Helvetica, sans"',
+ 'style': '"setlinewidth(0.5)"',
+ }
+ default_edge_attrs = {
+ 'arrowsize': 0.5,
+ 'style': '"setlinewidth(0.5)"',
+ }
+
+ def _format_node_attrs(self, attrs):
+ return ','.join([f'{x[0]}={x[1]}' for x in attrs.items()])
+
+ def _format_graph_attrs(self, attrs):
+ return ''.join([f"{x[0]}={x[1]};\n" for x in attrs.items()])
+
+ def generate_dot(self, name, urls={}, env=None,
+ graph_attrs={}, node_attrs={}, edge_attrs={}):
+ """
+ Generate a graphviz dot graph from the classes that
+ were passed in to __init__.
+
+ *name* is the name of the graph.
+
+ *urls* is a dictionary mapping class names to HTTP URLs.
+
+ *graph_attrs*, *node_attrs*, *edge_attrs* are dictionaries containing
+ key/value pairs to pass on as graphviz properties.
+ """
+ g_attrs = self.default_graph_attrs.copy()
+ n_attrs = self.default_node_attrs.copy()
+ e_attrs = self.default_edge_attrs.copy()
+ g_attrs.update(graph_attrs)
+ n_attrs.update(node_attrs)
+ e_attrs.update(edge_attrs)
+ if env:
+ g_attrs.update(env.config.inheritance_graph_attrs)
+ n_attrs.update(env.config.inheritance_node_attrs)
+ e_attrs.update(env.config.inheritance_edge_attrs)
+
+ res = []
+ res.append(f'digraph {name} {{\n')
+ res.append(self._format_graph_attrs(g_attrs))
+
+ for name, fullname, bases in self.class_info:
+ # Write the node
+ this_node_attrs = n_attrs.copy()
+ url = urls.get(fullname)
+ if url is not None:
+ this_node_attrs['URL'] = f'"{url}"'
+ this_node_attrs['target'] = '"_top"' # Browser target frame attribute (same page)
+ else:
+ urls_str = format_dict(urls)
+ print(f'inheritance_graph.py: No URL found for {name} ({fullname}) in {urls_str}.',
+ file=sys.stderr)
+ attribute = self._format_node_attrs(this_node_attrs)
+ res.append(f' "{name}" [{attribute}];\n')
+
+ # Write the edges
+ for base_name in bases:
+ attribute = self._format_node_attrs(e_attrs)
+ res.append(f' "{base_name}" -> "{name}" [{attribute}];\n')
+ res.append('}\n')
+ return ''.join(res)
+
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2:
+ print(TEST_DRIVER_USAGE)
+ sys.exit(-1)
+ module = sys.argv[1]
+ class_names = sys.argv[2:]
+ graph = InheritanceGraph(class_names, module)
+ dot = graph.generate_dot("test")
+ print(dot)
diff --git a/sources/pyside6/doc/json_inheritance.py b/sources/pyside6/doc/json_inheritance.py
new file mode 100644
index 000000000..06be33ea4
--- /dev/null
+++ b/sources/pyside6/doc/json_inheritance.py
@@ -0,0 +1,74 @@
+# Copyright (C) 2022 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 json
+import os
+import sys
+from pathlib import Path
+
+
+"""Helpers for determining base classes by reading a JSON
+ file written by shiboken's doc generator."""
+
+
+TEST_DRIVER_USAGE = """Usage: json_inheritance.py class_name json_file
+
+Example:
+python json_inheritance.py PySide6.QtWidgets.QWizard ~/inheritance.json
+"""
+
+
+ENV_VAR = "INHERITANCE_FILE"
+
+
+def strip_module(class_name):
+ return class_name[8:] if class_name.startswith("PySide") else class_name
+
+
+def get_inheritance_entries_recursion(json_dict, class_name):
+ """Get all edges of the inheritance graph of class_name."""
+ result = []
+ bases_entry = json_dict.get(class_name)
+ bases = bases_entry if bases_entry else []
+ node_name = strip_module(class_name)
+ base_list = [strip_module(b) for b in bases]
+ result.append((node_name, class_name, base_list))
+ for b in bases:
+ nested_bases = get_inheritance_entries_recursion(json_dict, b)
+ if nested_bases:
+ result.extend(nested_bases)
+ return result
+
+
+def _get_inheritance_entries_from_json(json_file, class_names):
+ """Get all edges of the inheritance graph of class_name
+ from the JSON file generated by shiboken."""
+ result = []
+ try:
+ with Path(json_file).open("r") as f:
+ json_dict = json.load(f)
+ for c in class_names:
+ result.extend(get_inheritance_entries_recursion(json_dict, c))
+ except (json.JSONDecodeError, KeyError) as e:
+ print(f"Error reading {json_file}: {e}")
+ raise
+ return result
+
+
+def is_inheritance_from_json_enabled():
+ return os.environ.get(ENV_VAR)
+
+
+def get_inheritance_entries_from_json(class_names):
+ json_file = os.environ[ENV_VAR]
+ return _get_inheritance_entries_from_json(json_file, class_names)
+
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2:
+ print(TEST_DRIVER_USAGE)
+ sys.exit(-1)
+ class_name = sys.argv[1]
+ json_file = sys.argv[2]
+ for e in _get_inheritance_entries_from_json(json_file, [class_name]):
+ print(e)
diff --git a/sources/pyside6/doc/modules.rst b/sources/pyside6/doc/modules.rst
index 9b20d6906..8e77a4616 100644
--- a/sources/pyside6/doc/modules.rst
+++ b/sources/pyside6/doc/modules.rst
@@ -1,5 +1,5 @@
-Qt Modules
-===========
+Qt Modules Supported by Qt for Python
+=====================================
.. toctree::
:hidden:
@@ -7,295 +7,228 @@ Qt Modules
PySide6/Qt*/index
-.. panels::
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
+.. grid:: 1 3 3 3
+ :gutter: 2
- :mod:`QtBluetooth <PySide6.QtBluetooth>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtBluetooth <PySide6.QtBluetooth>`
- The Bluetooth API provides connectivity between Bluetooth enabled devices.
+ The Bluetooth API provides connectivity between Bluetooth enabled
+ devices.
- ---
+ .. grid-item-card:: :mod:`QtCharts <PySide6.QtCharts>`
- :mod:`QtCharts <PySide6.QtCharts>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides a set of easy to use chart components.
- Provides a set of easy to use chart components.
+ .. grid-item-card:: :mod:`QtConcurrent <PySide6.QtConcurrent>`
- ---
+ Provides high-level APIs that make it possible to write multi-threaded
+ programs without using low-level threading primitives such as mutexes,
+ read-write locks, wait conditions, or semaphores.
- :mod:`QtConcurrent <PySide6.QtConcurrent>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Provides high-level APIs that make it possible
- to write multi-threaded programs without using low-level threading
- primitives such as mutexes, read-write locks, wait conditions, or semaphores.
+ .. grid-item-card:: :mod:`QtCore <PySide6.QtCore>`
- ---
+ Provides core non-GUI functionality.
- :mod:`QtCore <PySide6.QtCore>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtDataVisualization <PySide6.QtDataVisualization>`
- Provides core non-GUI functionality.
+ Provides a way to visualize data in 3D as bar, scatter, and surface
+ graphs.
- ---
+ .. grid-item-card:: :mod:`QtDBus <PySide6.QtDBus>`
- :mod:`QtDataVisualization <PySide6.QtDataVisualization>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ D-Bus is an Inter-Process Communication (IPC) and Remote Procedure
+ Calling (RPC) mechanism originally developed for Linux to replace
+ existing and competing IPC solutions with one unified protocol
- Provides a way to visualize data in 3D as bar, scatter, and surface graphs.
+ .. grid-item-card:: :mod:`QtDesigner <PySide6.QtDesigner>`
- ---
+ Provides classes to extend *Qt Widgets Designer*.
- :mod:`QtDBus <PySide6.QtDBus>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtGui <PySide6.QtGui>`
- D-Bus is an Inter-Process Communication (IPC) and Remote Procedure
- Calling (RPC) mechanism originally developed for Linux to replace
- existing and competing IPC solutions with one unified protocol
+ Extends QtCore with GUI functionality.
- ---
+ .. grid-item-card:: :mod:`QtHelp <PySide6.QtHelp>`
- :mod:`QtDesigner <PySide6.QtDesigner>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides classes for integrating online documentation in applications.
- Provides classes to extend Qt Designer.
+ .. grid-item-card:: :mod:`Qt Multimedia <PySide6.QtMultimedia>`
- ---
+ Provides API for multimedia-specific use cases.
- :mod:`QtGui <PySide6.QtGui>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`Qt Multimedia Widgets <PySide6.QtMultimediaWidgets>`
- Extends QtCore with GUI functionality.
+ Provides the widget-based multimedia API.
- ---
+ .. grid-item-card:: :mod:`QtNetwork <PySide6.QtNetwork>`
- :mod:`QtHelp <PySide6.QtHelp>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Offers classes that let you to write TCP/IP clients and servers.
- Provides classes for integrating online documentation in applications.
+ .. grid-item-card:: :mod:`Qt Network Authorization <PySide6.QtNetworkAuth>`
- ---
+ Provides a set of APIs that enable Qt applications to obtain limited
+ access to online accounts and HTTP services without exposing users'
+ passwords.
- :mod:`QtNetwork <PySide6.QtNetwork>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtNfc <PySide6.QtNfc>`
- Offers classes that let you to write TCP/IP clients and servers.
+ The NFC API provides connectivity between NFC enabled devices.
- ---
+ .. grid-item-card:: :mod:`QtOpenGL <PySide6.QtOpenGL>`
- :mod:`QtNfc <PySide6.QtNfc>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Offers classes that make it easy to use OpenGL in Qt applications.
- The NFC API provides connectivity between NFC enabled devices.
+ .. grid-item-card:: :mod:`QtOpenGL Widgets <PySide6.QtOpenGLWidgets>`
- ---
+ Provides the OpenGLWidget class enabling OpenGL rendering for
+ a certain part of the widget tree.
- :mod:`QtNetworkAuth <PySide6.QtNetworkAuth>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`Qt Positioning <PySide6.QtPositioning>`
- Provides a set of APIs that enable Qt applications to obtain limited
- access to online accounts and HTTP services without exposing users'
- passwords.
+ Provides access to position, satellite info and area monitoring
+ classes.
- ---
+ .. grid-item-card:: :mod:`Qt PDF <PySide6.QtPdf>`
- :mod:`QtRemoteObjects <PySide6.QtRemoteObjects>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Classes and functions for rendering PDF documents.
- Inter-Process Communication (IPC) module developed for Qt. This module
- extends Qt's existing functionalities to enable information exchange
- between processes or computers, easily.
+ .. grid-item-card:: :mod:`Qt PDF Widgets <PySide6.QtPdfWidgets>`
- ---
+ A PDF viewer widget.
- :mod:`QtOpenGL <PySide6.QtOpenGL>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtPrintSupport <PySide6.QtPrintSupport>`
- Offers classes that make it easy to use OpenGL in Qt applications.
+ Provides extensive cross-platform support for printing.
- ---
+ .. grid-item-card:: :mod:`QtQml <PySide6.QtQml>`
- :mod:`QtOpenGLFunctions <PySide6.QtOpenGLFunctions>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Python API for Qt QML.
- The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
+ .. grid-item-card:: :mod:`QtQuick <PySide6.QtQuick>`
- ---
+ Provides classes for embedding Qt Quick in Qt applications.
- :mod:`QtOpenGLWidgets <PySide6.QtOpenGLWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtQuickControls2 <PySide6.QtQuickControls2>`
- The QOpenGLWidget class is a widget for rendering OpenGL graphics.
+ Provides classes for setting up the controls from C++.
- ---
+ .. grid-item-card:: :mod:`QtQuickTest <PySide6.QtQuickTest>`
- :mod:`QtPrintSupport <PySide6.QtPrintSupport>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ A unit test framework for QML applications where test cases are written as JavaScript functions.
- Provides extensive cross-platform support for printing.
+ .. grid-item-card:: :mod:`QtQuickWidgets <PySide6.QtQuickWidgets>`
- ---
+ Provides the QQuickWidget class for embedding Qt Quick in widget-based applications.
- :mod:`QtQml <PySide6.QtQml>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtRemoteObjects <PySide6.QtRemoteObjects>`
- Python API for Qt QML.
+ Inter-Process Communication (IPC) module developed for Qt. This module
+ extends Qt's existing functionalities to enable information exchange
+ between processes or computers, easily.
- ---
+ .. grid-item-card:: :mod:`Qt Scxml <PySide6.QtScxml>`
- :mod:`QtQuick <PySide6.QtQuick>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides classes to create and use state machines from SCXML files.
- Provides classes for embedding Qt Quick in Qt applications.
+ .. grid-item-card:: :mod:`Qt Sensors <PySide6.QtSensors>`
- ---
+ Provides access to sensor hardware.
- :mod:`QtQuickControls2 <PySide6.QtQuickControls2>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`Qt Serial Bus <PySide6.QtSerialBus>`
- Provides classes for setting up the controls from C++.
+ Provides access to serial industrial bus interfaces. Currently, the
+ module supports the CAN bus and Modbus protocols.
- ---
+ .. grid-item-card:: :mod:`Qt Serial Port <PySide6.QtSerialPort>`
- :mod:`QtQuickWidgets <PySide6.QtQuickWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides classes to interact with hardware and virtual serial ports.
- Provides the QQuickWidget class for embedding Qt Quick in widget-based applications.
+ .. grid-item-card:: :mod:`Qt Spatial Audio <PySide6.QtSpatialAudio>`
- ---
+ Provides APIs for modeling sound source and their surrounds in 3D
+ space.
- :mod:`Qt Scxml <PySide6.QtScxml>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtSql <PySide6.QtSql>`
- Provides classes to create and use state machines from SCXML files.
+ Helps you provide seamless database integration to your Qt
+ applications.
- ---
+ .. grid-item-card:: :mod:`QtStateMachine <PySide6.QtStateMachine>`
- :mod:`QtSql <PySide6.QtSql>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides classes for creating and executing state graphs.
- Helps you provide seamless database integration to your Qt applications.
+ .. grid-item-card:: :mod:`QtSvg <PySide6.QtSvg>`
- ---
+ Provides classes for displaying the contents of SVG files.
- :mod:`QtStateMachine <PySide6.QtStateMachine>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtSvgWidgets <PySide6.QtSvgWidgets>`
- Provides classes for creating and executing state graphs.
+ Provides a widget that is used to display the contents of SVG files.
- ---
+ .. grid-item-card:: :mod:`QtTest <PySide6.QtTest>`
- :mod:`QtSerialPort <PySide6.QtSerialPort>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides classes for unit testing Qt applications and libraries.
- Provides the basic functionality, which includes configuring, I/O
- operations, getting and setting the control signals of the RS-232
- pinouts.
+ .. grid-item-card:: :mod:`QtUiTools <PySide6.QtUiTools>`
- ---
+ Provides classes to handle forms created with *Qt Widgets Designer*.
- :mod:`QtSvg <PySide6.QtSvg>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`Qt WebChannel <PySide6.QtWebChannel>`
- Provides classes for displaying the contents of SVG files.
+ Provides access to QObject or QML objects from HTML clients for
+ seamless integration of Qt applications with HTML/JavaScript clients.
- ---
+ .. grid-item-card:: :mod:`QtWebEngine Core C++ Classes <PySide6.QtWebEngineCore>`
- :mod:`QtSvgWidgets <PySide6.QtSvgWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides public API shared by both QtWebEngine and QtWebEngineWidgets.
- Provides a widget that is used to display the contents of SVG files.
+ .. grid-item-card:: :mod:`QtWebEngine Widgets C++ Classes <PySide6.QtWebEngineWidgets>`
- ---
+ Provides C++ classes for rendering web content in a QWidget based
+ application.
- :mod:`QtTest <PySide6.QtTest>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtWebEngine QML Types <PySide6.QtWebEngineQuick>`
- Provides classes for unit testing Qt applications and libraries.
+ Provides QML types for rendering web content within a QML application.
- ---
+ .. grid-item-card:: :mod:`Qt WebSockets <PySide6.QtWebSockets>`
- :mod:`QtUiTools <PySide6.QtUiTools>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides WebSocket communication compliant with RFC 6455.
- Provides classes to handle forms created with Qt Designer.
+ .. grid-item-card:: :mod:`QtWidgets <PySide6.QtWidgets>`
- ---
+ Extends Qt GUI with C++ widget functionality.
- :mod:`QtWidgets <PySide6.QtWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`QtXml <PySide6.QtXml>`
- Extends Qt GUI with C++ widget functionality.
+ Provides a C++ implementation of DOM.
- ---
+ .. grid-item-card:: :mod:`Qt3DAnimation <PySide6.Qt3DAnimation>`
- :mod:`QtXml <PySide6.QtXml>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides basic elements required to animate 3D objects.
- Provides a C++ implementation of DOM.
+ .. grid-item-card:: :mod:`Qt3D Core <PySide6.Qt3DCore>`
- ---
+ Contains functionality to support near-realtime simulation systems.
- :mod:`Qt3DAnimation <PySide6.Qt3DAnimation>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`Qt3D Extras <PySide6.Qt3DExtras>`
- Provides basic elements required to animate 3D objects.
+ Provides a set of prebuilt elements to help you get started with Qt 3D.
- ---
+ .. grid-item-card:: :mod:`Qt3D Input <PySide6.Qt3DInput>`
- :mod:`QtWebEngine Core C++ Classes <PySide6.QtWebEngineCore>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Provides classes for handling user input in applications using Qt 3D.
- Provides public API shared by both QtWebEngine and QtWebEngineWidgets.
+ .. grid-item-card:: :mod:`Qt3D Logic <PySide6.Qt3DLogic>`
- ---
+ Enables synchronizing frames with the Qt 3D backend.
- :mod:`QtWebEngine Widgets C++ Classes <PySide6.QtWebEngineWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: :mod:`Qt3D Render <PySide6.Qt3DRender>`
- Provides C++ classes for rendering web content in a QWidget based application.
+ Contains functionality to support 2D and 3D rendering using Qt 3D.
- ---
+ .. grid-item-card:: :mod:`QtAsyncio <PySide6.QtAsyncio>`
- :mod:`QtWebEngine QML Types <PySide6.QtWebEngineQuick>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Provides QML types for rendering web content within a QML application.
-
- ---
-
- :mod:`Qt3D Core <PySide6.Qt3DCore>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Contains functionality to support near-realtime simulation systems.
-
- ---
-
- :mod:`Qt3D Extras <PySide6.Qt3DExtras>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Provides a set of prebuilt elements to help you get started with Qt 3D.
-
- ---
-
- :mod:`Qt3D Input <PySide6.Qt3DInput>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Provides classes for handling user input in applications using Qt 3D.
-
- ---
-
- :mod:`Qt3D Logic <PySide6.Qt3DLogic>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Enables synchronizing frames with the Qt 3D backend.
-
- ---
-
- :mod:`Qt3D Render <PySide6.Qt3DRender>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Contains functionality to support 2D and 3D rendering using Qt 3D.
+ Provides integration between asyncio and Qt's event loop.
diff --git a/sources/pyside6/doc/porting_from2.rst b/sources/pyside6/doc/porting_from2.rst
deleted file mode 100644
index aa3e41780..000000000
--- a/sources/pyside6/doc/porting_from2.rst
+++ /dev/null
@@ -1,100 +0,0 @@
-Porting Applications from PySide2 to PySide6
-============================================
-
-Module Availability
--------------------
-
-Qt for Python 6.0.0 initially ships with the essential
-`Modules <https://doc.qt.io/qt-6/qtmodules.html>`_ and some
-add-ons (Qt 3D, Qt Concurrent, Qt Help, Qt OpenGL, Qt Print Support
-Qt Quick Widgets, Qt SQL, Qt SVG, Qt UI Tools and Qt XML).
-
-More modules will follow in subsequent releases as they
-are added to Qt.
-
-For Qt for Python 6.1, Active Qt, Qt Charts, Qt Data Visualization,
-Qt StateMachine and Qt SCXML are planned.
-
-Module-Level Changes
---------------------
-
-* *Qt Quick Controls 1* have been removed.
-* ``QStateMachine`` and related classes have been extracted to a new
- *QtStateMachine* module.
-* ``QXmlReader`` and related classes (*SAX API*) have been removed.
-* The content of the *QtOpenGL* module has been replaced. The class
- ``QGLWidget`` and related classes (``QGLContext``, ``QGLFunctions``,
- ``QGLShaderProgram``) have been removed. Parts of the *Open GL*
- functionality from *QtGui* have been extracted into this module, for example
- ``QOpenGLBuffer`` and ``QOpenGLShaderProgram``.
- There is a new module *QtOpenGLWidgets* which contains the class
- ``QOpenGLWidget``, a replacement for ``QGLWidget``.
-
-As *Open GL* is phasing out,
-`QRhi <https://doc.qt.io/qt-6/topics-graphics.html>`_ should be considered
-for graphics applications.
-
-Imports
--------
-
-The first thing to do when porting applications is to replace the
-import statements:
-
-.. code-block:: python
-
- from PySide2.QtWidgets import QApplication...
- from PySide2 import QtCore
-
-needs to be changed to:
-
-.. code-block:: python
-
- from PySide6.QtWidgets import QApplication...
- from PySide6 import QtCore
-
-
-Some classes are in a different module now, for example
-``QAction`` and ``QShortcut`` have been moved from ``QtWidgets`` to ``QtGui``.
-
-For *Qt Charts* and *Qt Data Visualization*, the additional namespaces have been
-removed. It is now possible to use:
-
-.. code-block:: python
-
- from PySide6.QtCharts import QChartView
-
-directly.
-
-
-Class/Function Deprecations
----------------------------
-
-Then, the code base needs to be checked for usage of deprecated API and adapted
-accordingly. For example:
-
- * The High DPI scaling attributes ``Qt.AA_EnableHighDpiScaling``,
- ``Qt.AA_DisableHighDpiScaling`` and ``Qt.AA_UseHighDpiPixmaps`` are
- deprecated. High DPI is by default enabled in Qt 6 and cannot be turned off.
- * ``QDesktopWidget`` has been removed. ``QScreen`` should be used instead,
- which can be retrieved using ``QWidget.screen()``,
- ``QGuiApplication.primaryScreen()`` or ``QGuiApplication.screens()``.
- * ``QFontMetrics.width()`` has been renamed to ``horizontalAdvance()``.
- * ``QMouseEvent.pos()`` and ``QMouseEvent.globalPos()`` returning a ``QPoint``
- as well as ``QMouseEvent.x()`` and ``QMouseEvent.y()`` returning ``int``
- are now deprecated. ``QMouseEvent.position()`` and
- ``QMouseEvent.globalPosition()`` returning a ``QPointF`` should be used
- instead.
- * ``Qt.MidButton`` has been renamed to ``Qt.MiddleButton``.
- * ``QOpenGLVersionFunctionsFactory.get()`` instead of
- ``QOpenGLContext.versionFunctions()`` should be used to obtain
- *Open GL* functions.
- * ``QRegExp`` has been replaced by ``QRegularExpression``.
- * ``QWidget.mapToGlobal()`` and ``QWidget.mapFromGlobal()`` now also accept
- and return ``QPointF``.
- * Functions named ``exec_`` (classes ``QCoreApplication``, ``QDialog``,
- ``QEventLoop``) have been renamed to ``exec`` which became possible
- in Python 3.
-
-More information can be found in the
-`Porting to Qt 6 <https://doc.qt.io/qt-6/portingguide.html>`_ Guide
-and the `Qt 6.0 Documentation <https://doc.qt.io/qt-6/index.html>`_ .
diff --git a/sources/pyside6/doc/pysideinclude.py b/sources/pyside6/doc/pysideinclude.py
index 91fffe115..8e2834cce 100644
--- a/sources/pyside6/doc/pysideinclude.py
+++ b/sources/pyside6/doc/pysideinclude.py
@@ -11,9 +11,9 @@ from os import path
from docutils import nodes
from docutils.parsers.rst import Directive, directives
-from sphinx import addnodes
from sphinx.util import parselinenos
+
class PySideInclude(Directive):
"""
Like ``.. include:: :literal:``, but only warns if the include file is
@@ -68,7 +68,7 @@ class PySideInclude(Directive):
codec_info = codecs.lookup(encoding)
try:
f = codecs.StreamReaderWriter(open(fn, 'Ub'),
- codec_info[2], codec_info[3], 'strict')
+ codec_info[2], codec_info[3], 'strict')
lines = f.readlines()
f.close()
except (IOError, OSError):
@@ -91,7 +91,7 @@ class PySideInclude(Directive):
'Object named %r not found in include file %r' %
(objectname, filename), line=self.lineno)]
else:
- lines = lines[tags[objectname][1]-1 : tags[objectname][2]-1]
+ lines = lines[tags[objectname][1] - 1: tags[objectname][2] - 1]
linespec = self.options.get('lines')
if linespec is not None:
@@ -102,10 +102,10 @@ class PySideInclude(Directive):
lines = [lines[i] for i in linelist]
startafter = self.options.get('start-after')
- endbefore = self.options.get('end-before')
- prepend = self.options.get('prepend')
- append = self.options.get('append')
- snippet = self.options.get('snippet')
+ endbefore = self.options.get('end-before')
+ prepend = self.options.get('prepend')
+ append = self.options.get('append')
+ snippet = self.options.get('snippet')
if snippet:
startafter = "//![%s]" % snippet
@@ -126,9 +126,9 @@ class PySideInclude(Directive):
lines = res
if prepend:
- lines.insert(0, prepend + '\n')
+ lines.insert(0, prepend + '\n')
if append:
- lines.append(append + '\n')
+ lines.append(append + '\n')
text = ''.join(lines)
if self.options.get('tab-width'):
@@ -143,5 +143,6 @@ class PySideInclude(Directive):
document.settings.env.note_dependency(rel_fn)
return [retnode]
+
def setup(app):
app.add_directive('pysideinclude', PySideInclude)
diff --git a/sources/pyside6/doc/qdoc_spawner.py.in b/sources/pyside6/doc/qdoc_spawner.py.in
new file mode 100644
index 000000000..d9d434366
--- /dev/null
+++ b/sources/pyside6/doc/qdoc_spawner.py.in
@@ -0,0 +1,105 @@
+# Copyright (C) 2024 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 argparse
+import subprocess
+import os
+import sys
+import time
+from multiprocessing import Pool, cpu_count
+from pathlib import Path
+
+
+def run_qdoc(file, qdoc_args, args):
+ env = os.environ
+ env["BUILDDIR"] = args.build_dir
+ env["QT_INSTALL_DOCS"] = args.qt_install_docs
+ env["QT_VERSION"] = args.qt_version
+ env["QT_VER"] = ".".join(args.qt_version.split(".")[:2])
+ env["QT_VERSION_TAG"] = args.qt_version
+
+ command = [
+ args.qdoc_bin,
+ file,
+ *qdoc_args,
+ "-installdir",
+ args.doc_data_dir,
+ "-outputdir",
+ args.doc_data_dir,
+ ]
+
+ start_time = time.time()
+ _ = subprocess.Popen(command, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = _.communicate()
+ returncode = _.wait()
+ duration = round(time.time() - start_time)
+
+ if args.verbose or returncode != 0 or err:
+ cmd_str = " ".join(command)
+ print(f"> Output of: {cmd_str}")
+ if out:
+ print(out.decode("utf-8"), file=sys.stdout)
+ if err:
+ print(err.decode("utf-8"), file=sys.stderr)
+ print(f"> Finished: {file} {duration}s (exit code {returncode})")
+
+ if returncode != 0:
+ raise Exception(f"Failing executing the command {command} ({returncode})")
+
+
+def get_qdocconf_files():
+ if not Path("pyside.qdocconf").exists():
+ print("ERROR: the working dir doesn't include a 'pyside.qdocconf' file")
+ sys.exit(-1)
+
+ # Generate the temporary qdocconf files
+ # This is necessary because using a file like 'pyside-qtcore.qtdocconf'
+ # will generate an error, because inside we call functions like 'include()'
+ files_single_exec = []
+ files_prepare = []
+ with open("pyside.qdocconf") as f:
+ for i in f.read().splitlines():
+ _p = Path(i)
+ _name = f"_{_p.stem}.qdocconf"
+ with open(_name, "w", encoding="utf-8") as f:
+ f.write(i)
+ files_single_exec.append(_name)
+ files_prepare.append(i.strip())
+
+ return files_prepare, files_single_exec
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(prog="qdoc spawner")
+ parser.add_argument("--qt", dest="qt_version", action="store", required=True)
+ parser.add_argument("--doc-data-dir", dest="doc_data_dir", action="store", required=True)
+ parser.add_argument("--qdoc-binary", dest="qdoc_bin", action="store", required=True)
+ parser.add_argument("--build-dir", dest="build_dir", action="store", required=True)
+ parser.add_argument("--qt-install-docs", dest="qt_install_docs", action="store", required=True)
+ parser.add_argument("--parallel", dest="parallel", action="store", default="4")
+ parser.add_argument("--verbose", dest="verbose", action="store_true", default=False)
+
+ args = parser.parse_args()
+
+ core_index = Path(args.doc_data_dir) / "webxml" / "qtcore-index.webxml"
+ if core_index.is_file():
+ print(f"qdoc_spawner: {core_index} already exists, bailing out")
+ sys.exit(0)
+
+ files_prepare, files_single_exec = get_qdocconf_files()
+
+ parallel = args.parallel
+ if parallel == "auto":
+ parallel = cpu_count()
+
+ try:
+ # mode: -prepare -no-link-errors
+ with Pool(int(parallel)) as p:
+ p.starmap(run_qdoc, [(str(f), ["-prepare", "-no-link-errors"], args) for f in files_prepare])
+
+ # mode: -single-exec
+ with Pool(int(parallel)) as p:
+ p.starmap(run_qdoc, [(str(f), ["-single-exec"], args) for f in files_single_exec])
+ except Exception as e:
+ print(f"qdoc_spawner: error: {e}", file=sys.stderr)
+ sys.exit(-1)
diff --git a/sources/pyside6/doc/qtattributionsscannertorst.py b/sources/pyside6/doc/qtattributionsscannertorst.py
index ba824a1a9..677371c45 100644
--- a/sources/pyside6/doc/qtattributionsscannertorst.py
+++ b/sources/pyside6/doc/qtattributionsscannertorst.py
@@ -8,18 +8,25 @@ Tool to run qtattributionsscanner and convert its output to rst
import os
import json
import subprocess
-import sys
import warnings
+from argparse import ArgumentParser, RawTextHelpFormatter
from pathlib import Path
+USAGE = "Usage: qtattributionsscannertorst [directory] [file]'"
+
+
+libexec_dir = None
+
+
def indent(lines, indent):
result = ''
- for l in lines:
- result = f"{result}{indent}{l}\n"
+ for line in lines:
+ result = f"{result}{indent}{line}\n"
return result
-rstHeader="""Licenses Used in Qt for Python
+
+rstHeader = """Licenses Used in Qt for Python
******************************
Qt for Python contains some code that is not provided under the
@@ -45,29 +52,37 @@ code licensed under third-party opensource licenses:
"""
+
def rstHeadline(title):
return f"{title}\n{'-' * len(title)}\n"
+
def rstUrl(title, url):
return f"`{title} <{url}>`_"
+
def rstLiteralBlock(lines):
return f"::\n\n{indent(lines, ' ')}\n\n"
+
def rstLiteralBlockFromText(text):
return rstLiteralBlock(text.strip().split('\n'))
+
def readFile(fileName):
with open(fileName, 'r') as file:
return file.readlines()
-def runScanner(directory, targetFileName):
+
+def get_libexec_dir():
+ libexec_b = subprocess.check_output("qtpaths6 -query QT_INSTALL_LIBEXECS", shell=True)
+ return libexec_b.decode('utf-8').strip()
+
+
+def runScanner(directory, targetFileName, libexec_dir):
# qtattributionsscanner recursively searches for qt_attribution.json files
# and outputs them in JSON with the paths of the 'LicenseFile' made absolute
- libexec_b = subprocess.check_output('qtpaths -query QT_INSTALL_LIBEXECS',
- shell=True)
- libexec = libexec_b.decode('utf-8').strip()
- scanner = os.path.join(libexec, 'qtattributionsscanner')
+ scanner = os.path.join(libexec_dir, 'qtattributionsscanner')
command = f'{scanner} --output-format json {directory}'
jsonS = subprocess.check_output(command, shell=True)
if not jsonS:
@@ -80,7 +95,7 @@ def runScanner(directory, targetFileName):
url = entry['Homepage']
version = entry['Version']
if url and version:
- content = f"{content}{rstUrl('Project Homepage', url)}, upstream version: {version}\n\n"
+ content = f"{content}{rstUrl('Project Homepage', url)}, upstream version: {version}\n\n" # noqa E:501
copyright = entry['Copyright']
if copyright:
content += rstLiteralBlockFromText(copyright)
@@ -93,10 +108,16 @@ def runScanner(directory, targetFileName):
warnings.warn(f'"{licenseFile}" is not a file', RuntimeWarning)
targetFile.write(content)
-if len(sys.argv) < 3:
- print("Usage: qtattributionsscannertorst [directory] [file]'")
- sys.exit(0)
-directory = sys.argv[1]
-targetFileName = sys.argv[2]
-runScanner(directory, targetFileName)
+if __name__ == '__main__':
+ parser = ArgumentParser(description=USAGE, formatter_class=RawTextHelpFormatter)
+ parser.add_argument("-l", "--libexec", type=str, help="libexec directory of Qt")
+ parser.add_argument('directory')
+ parser.add_argument('target')
+ options = parser.parse_args()
+ directory = options.directory
+ targetFileName = options.target
+ libexec_dir = options.libexec
+ if not libexec_dir:
+ libexec_dir = get_libexec_dir()
+ runScanner(directory, targetFileName, libexec_dir)
diff --git a/sources/pyside6/doc/qtmodules/pyside-qtdoc.qdocconf.in b/sources/pyside6/doc/qtmodules/pyside-qtdoc.qdocconf.in
new file mode 100644
index 000000000..88cc3eac4
--- /dev/null
+++ b/sources/pyside6/doc/qtmodules/pyside-qtdoc.qdocconf.in
@@ -0,0 +1,2 @@
+include(@QT_SRC_DIR@/../qtdoc/doc/config/qtdoc.qdocconf)
+include(../pyside-config.qdocconf)
diff --git a/sources/pyside6/doc/qtmodules/pyside-qtpdf.qdocconf.in b/sources/pyside6/doc/qtmodules/pyside-qtpdf.qdocconf.in
new file mode 100644
index 000000000..43eb302af
--- /dev/null
+++ b/sources/pyside6/doc/qtmodules/pyside-qtpdf.qdocconf.in
@@ -0,0 +1,3 @@
+include(@QT_SRC_DIR@/../qtwebengine/src/pdf/doc/qtpdf.qdocconf)
+includepaths += -I @QT_SRC_DIR@/../qtwebengine/src/pdf/doc
+include(../pyside-config.qdocconf)
diff --git a/sources/pyside6/doc/qtmodules/pyside-qtquickcontrols2.qdocconf.in b/sources/pyside6/doc/qtmodules/pyside-qtquickcontrols2.qdocconf.in
index bfd339ba6..4d0a55946 100644
--- a/sources/pyside6/doc/qtmodules/pyside-qtquickcontrols2.qdocconf.in
+++ b/sources/pyside6/doc/qtmodules/pyside-qtquickcontrols2.qdocconf.in
@@ -1,3 +1,3 @@
-include(@QT_SRC_DIR@/../qtdeclarative/src/quickcontrols2/doc/qtquickcontrols.qdocconf)
-includepaths += -I @QT_SRC_DIR@/../qtquickcontrols2/src/quickcontrols2
+include(@QT_SRC_DIR@/../qtdeclarative/src/quickcontrols/doc/qtquickcontrols.qdocconf)
+includepaths += -I @QT_SRC_DIR@/../qtdeclarative/src/quickcontrols
include(../pyside-config.qdocconf)
diff --git a/sources/pyside6/doc/qtmodules/pyside-qtquicktest.qdocconf.in b/sources/pyside6/doc/qtmodules/pyside-qtquicktest.qdocconf.in
new file mode 100644
index 000000000..1d8397537
--- /dev/null
+++ b/sources/pyside6/doc/qtmodules/pyside-qtquicktest.qdocconf.in
@@ -0,0 +1,3 @@
+include(@QT_SRC_DIR@/../qtdeclarative/src/qmltest/doc/qtqmltest.qdocconf)
+includepaths += -I @QT_SRC_DIR@/../qtdeclarative/src/qmltest
+include(../pyside-config.qdocconf)
diff --git a/sources/pyside6/doc/qtmodules/pyside-qtserialbus.qdocconf.in b/sources/pyside6/doc/qtmodules/pyside-qtserialbus.qdocconf.in
new file mode 100644
index 000000000..4c67664a5
--- /dev/null
+++ b/sources/pyside6/doc/qtmodules/pyside-qtserialbus.qdocconf.in
@@ -0,0 +1,2 @@
+include(@QT_SRC_DIR@/../qtserialbus/src/serialbus/doc/qtserialbus.qdocconf)
+include(../pyside-config.qdocconf)
diff --git a/sources/pyside6/doc/qtmodules/pyside-qtspatialaudio.qdocconf.in b/sources/pyside6/doc/qtmodules/pyside-qtspatialaudio.qdocconf.in
new file mode 100644
index 000000000..be64648a5
--- /dev/null
+++ b/sources/pyside6/doc/qtmodules/pyside-qtspatialaudio.qdocconf.in
@@ -0,0 +1,3 @@
+include(@QT_SRC_DIR@/../qtmultimedia/src/spatialaudio/doc/qtspatialaudio.qdocconf)
+includepaths += -I @QT_SRC_DIR@/../qtmultimedia/src/spatialaudio/doc
+include(../pyside-config.qdocconf)
diff --git a/sources/pyside6/doc/quickstart.rst b/sources/pyside6/doc/quickstart.rst
index babbab82e..7e1a210f2 100644
--- a/sources/pyside6/doc/quickstart.rst
+++ b/sources/pyside6/doc/quickstart.rst
@@ -1,44 +1,80 @@
-|project| Quick start
-======================
+.. _quick-start:
+
+Quick start
+===========
+
+New to Qt? Check also the :ref:`faq-section` section at the end of this page.
+In case you own a Qt License, please refer to :ref:`commercial-page`.
+
+.. note:: Having Qt installed in your system will not interfere with your
+ PySide6 installation if you do it via ``pip install``, because the Python
+ packages (wheels) include already Qt binaries. Most notably, style plugins
+ from the system won't have any effect on PySide applications.
Requirements
------------
Before you can install |project|, first you must install the following software:
- * Python 3.6+,
- * We recommend using a virtual environment, such as
- `venv <https://docs.python.org/3/library/venv.html>`_ or
- `virtualenv <https://virtualenv.pypa.io/en/latest>`_
+* Python 3.7+,
+* We **highly** recommend using a virtual environment, such as
+ `venv <https://docs.python.org/3/library/venv.html>`_ or
+ `virtualenv <https://virtualenv.pypa.io/en/latest>`_
+ and avoid installing PySide6 via ``pip`` in your system.
+
+.. note:: For Windows users, please use the interpreter from https://python.org/download
+ rather than the one installed from the Microsoft Store.
Installation
------------
-
-.. raw:: html
-
- <img src="https://qt-wiki-uploads.s3.amazonaws.com/images/8/8a/Pyside6_install.gif"
- style="float: right; width: 35%; padding-left: 20px;"
- alt="PySide6 installation animation" />
+.. note:: For a commercial installation, refer to :ref:`commercial-page`.
* **Creating and activating an environment**
You can do this by running the following on a terminal:
- * :command:`python -m venv env`, (Your Python executable might be called ``python3``)
- * :command:`source env/bin/activate` for Linux and macOS
- * :command:`env\\\Scripts\\\activate.bat` for Windows
+ * Create environment (Your Python executable might be called ``python3``)::
+
+ python -m venv env
-* **Installation**
+ * Activate the environment (Linux and macOS)::
+
+ source env/bin/activate
+
+ * Activate the environment (Windows)::
+
+ env\Scripts\activate.bat
+
+ Check this animation on how to do it:
+
+ .. image:: https://qt-wiki-uploads.s3.amazonaws.com/images/8/8a/Pyside6_install.gif
+ :alt: Installation GIF
+
+* **Installing PySide6**
Now you are ready to install the |project| packages using ``pip``.
From the terminal, run the following command:
- * :command:`pip install pyside6`, for the latest version.
- * :command:`pip install pyside6==6.0`, for the version ``6.0`` specifically.
+ * For the latest version::
+
+ pip install pyside6
+
+ * For a specific version, like 6.4.1::
+
+ pip install pyside6==6.4.1
+
* It is also possible to install a specific snapshot from our servers.
To do so, you can use the following command::
- pip install --index-url=https://download.qt.io/snapshots/ci/pyside/6.0.0/latest pyside6 --trusted-host download.qt.io
+ pip install --index-url=https://download.qt.io/snapshots/ci/pyside/6.4/latest pyside6 --trusted-host download.qt.io
+
+ .. note:: Starting with 6.4.3, PySide6 can be used from inside a
+ `conda <https://conda.io>`_ environment, but any manual changes you make to
+ the ``qt.conf`` file will be ignored. If you want to set custom values to
+ the Qt configuration, set them in a ``qt6.conf`` file instead.
+ Read more about `qt.conf`_.
+
+.. _`qt.conf`: https://doc.qt.io/qt-6/qt-conf.html
* **Test your installation**
@@ -53,8 +89,11 @@ Installation
# Prints the Qt version used to compile PySide6
print(PySide6.QtCore.__version__)
-Create a Simple Application
----------------------------
+.. note:: For more information about what's included in the ``pyside6``
+ package, check :ref:`package_details`.
+
+Create a Simple Qt Widgets Application
+--------------------------------------
Your |project| setup is ready. You can explore it further by developing a simple application
that prints "Hello World" in several languages. The following instructions will
@@ -69,12 +108,12 @@ guide you through the development process:
from PySide6 import QtCore, QtWidgets, QtGui
The |pymodname| Python module provides access to the Qt APIs as its submodule.
- In this case, you are importing the :code:`QtCore`, :code:`QtWidgets`, and :code:`QtGui` submodules.
+ In this case, you are importing the :ref:`QtCore`, :ref:`QtWidgets`, and :ref:`QtGui` submodules.
* **Main Class**
- Define a class named :code:`MyWidget`, which extends QWidget and includes a QPushButton and
- QLabel.::
+ Define a class named :code:`MyWidget`, which extends :ref:`QWidget` and
+ includes a :ref:`QPushButton` and :ref:`QLabel`.::
class MyWidget(QtWidgets.QWidget):
def __init__(self):
@@ -96,8 +135,9 @@ guide you through the development process:
def magic(self):
self.text.setText(random.choice(self.hello))
- The MyWidget class has the :code:`magic` member function that randomly chooses an item from the
- :code:`hello` list. When you click the button, the :code:`magic` function is called.
+ The ``MyWidget`` class has the :code:`magic` member function that randomly
+ chooses an item from the :code:`hello` list. When you click the button, the
+ :code:`magic` function is called.
* **Application execution**
@@ -118,3 +158,130 @@ guide you through the development process:
.. image:: images/screenshot_hello.png
:alt: Hello World application
+
+Create a Simple Quick Application
+---------------------------------
+
+To do the same using Qt Quick:
+
+* **Imports**
+
+ Create a new file named :code:`hello_world_quick.py`, and add the following imports to it.::
+
+ import sys
+ from PySide6.QtGui import QGuiApplication
+ from PySide6.QtQml import QQmlApplicationEngine
+
+* **Declarative UI**
+
+ The UI can be described in the QML language (assigned to a Python variable)::
+
+ QML = """
+ import QtQuick
+ import QtQuick.Controls
+ import QtQuick.Layouts
+
+ Window {
+ width: 300
+ height: 200
+ visible: true
+ title: "Hello World"
+
+ readonly property list<string> texts: ["Hallo Welt", "Hei maailma",
+ "Hola Mundo", "Привет мир"]
+
+ function setText() {
+ var i = Math.round(Math.random() * 3)
+ text.text = texts[i]
+ }
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ Text {
+ id: text
+ text: "Hello World"
+ Layout.alignment: Qt.AlignHCenter
+ }
+ Button {
+ text: "Click me"
+ Layout.alignment: Qt.AlignHCenter
+ onClicked: setText()
+ }
+ }
+ }
+ """
+
+ .. note:: Keep in mind ideally this content should go into
+ a ``qml`` file, but for simplicity, we are using a string variable.
+
+* **Application execution**
+
+ Now, add a main function where you instantiate a :ref:`QQmlApplicationEngine` and
+ load the QML::
+
+ if __name__ == "__main__":
+ app = QGuiApplication(sys.argv)
+ engine = QQmlApplicationEngine()
+ engine.loadData(QML.encode('utf-8'))
+ if not engine.rootObjects():
+ sys.exit(-1)
+ exit_code = app.exec()
+ del engine
+ sys.exit(exit_code)
+
+
+ .. note:: This is a simplified example. Normally, the QML code should be in a separate
+ :code:`.qml` file, which can be edited by design tools.
+
+.. _faq-section:
+
+Frequently Asked Questions
+--------------------------
+
+Here you can find a couple of common questions and situations that will
+clarify questions before you start programming.
+
+.. grid:: 1 3 3 3
+ :gutter: 2
+
+ .. grid-item-card:: What is Qt
+ :link: faq/whatisqt.html
+
+ Qt, QML, Widgets... What is the difference?
+
+ .. grid-item-card:: Compatible IDEs
+ :link: faq/whichide.html
+
+ Which IDEs are compatible with PySide?
+
+ .. grid-item-card:: Binding Generation
+ :link: faq/whatisshiboken.html
+
+ What is Shiboken?
+
+ .. grid-item-card:: File types
+ :link: faq/typesoffiles.html
+
+ File Types in PySide
+
+ .. grid-item-card:: App distribution
+ :link: faq/distribution.html
+
+ Distributing your application to other systems and platforms
+
+ .. grid-item-card:: Why Qt for Python?
+ :link: faq/whyqtforpython.html
+
+ As a Qt/C++ developer, why should I consider Qt for Python?
+
+.. toctree::
+ :hidden:
+
+ faq/whatisqt.rst
+ faq/whichide.rst
+ faq/whatisshiboken.rst
+ faq/typesoffiles.rst
+ faq/distribution.rst
+ faq/whyqtforpython.rst
+
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_0.cpp.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_0.cpp.py
new file mode 100644
index 000000000..d21595041
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_0.cpp.py
@@ -0,0 +1,4 @@
+i, ok = QInputDialog.getInt(self, "QInputDialog::getInt()",
+ "Percentage:", 25, 0, 100, 1)
+if ok:
+ integerLabel.setText(f"{i}")
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_1.cpp.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_1.cpp.py
new file mode 100644
index 000000000..4cb3dfdb3
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_1.cpp.py
@@ -0,0 +1,5 @@
+d, ok = QInputDialog.getDouble(self, "QInputDialog::getDouble()",
+ "Amount:", 37.56, -10000, 10000, 2,
+ Qt.WindowFlags(), 1)
+if ok:
+ doubleLabel.setText(f"${d}")
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_2.cpp.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_2.cpp.py
new file mode 100644
index 000000000..7e3d27afb
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_2.cpp.py
@@ -0,0 +1,5 @@
+items = ["Spring", "Summer", "Fall", "Winter"]
+item, ok = QInputDialog.getItem(self, "QInputDialog::getItem()",
+ "Season:", items, 0, False)
+if ok and item:
+ itemLabel.setText(item)
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_3.cpp.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_3.cpp.py
new file mode 100644
index 000000000..85a22a16c
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_3.cpp.py
@@ -0,0 +1,5 @@
+text, ok = QInputDialog.getText(self, "QInputDialog.getText()",
+ "User name:", QLineEdit.Normal,
+ QDir.home().dirName())
+if ok and text:
+ textLabel.setText(text)
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_4.cpp.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_4.cpp.py
new file mode 100644
index 000000000..d16045141
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/dialogs/standarddialogs/dialog_4.cpp.py
@@ -0,0 +1,4 @@
+text, ok = QInputDialog.getMultiLineText(self, "QInputDialog.getMultiLineText()", ""
+ "Address:", "John Doe\nFreedom Street")
+if ok and text:
+ multiLineTextLabel.setText(text)
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py
new file mode 100644
index 000000000..de386a5ac
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py
@@ -0,0 +1,18 @@
+class SpinBoxDelegate(QStyledItemDelegate):
+ """A delegate that allows the user to change integer values from the model
+ using a spin box widget. """
+
+ def __init__(self, parent=None):
+ ...
+
+ def createEditor(self, parent, option, index):
+ ...
+
+ def setEditorData(self, editor, index):
+ ...
+
+ def setModelData(self, editor, model, index):
+ ...
+
+ def updateEditorGeometry(self, editor, option, index):
+ ...
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/tutorials/modelview/1_readonly/mymodel_Quoting_ModelView_Tutorial.h.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/tutorials/modelview/1_readonly/mymodel_Quoting_ModelView_Tutorial.h.py
new file mode 100644
index 000000000..231792c5d
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/tutorials/modelview/1_readonly/mymodel_Quoting_ModelView_Tutorial.h.py
@@ -0,0 +1,15 @@
+from PySide6.QtCore import QAbstractTableModel
+
+class MyModel(QAbstractTableModel):
+
+ def __init__(self, parent = None):
+ ...
+
+ def rowCount(self, parent = None):
+ ...
+
+ def columnCount(self, parent = None):
+ ...
+
+ def data(self, index, role = Qt.DisplayRole):
+ ...
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/tutorials/modelview/5_edit/mymodel_Quoting_ModelView_Tutorial.h.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/tutorials/modelview/5_edit/mymodel_Quoting_ModelView_Tutorial.h.py
new file mode 100644
index 000000000..4da28f0a0
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/tutorials/modelview/5_edit/mymodel_Quoting_ModelView_Tutorial.h.py
@@ -0,0 +1,27 @@
+from PySide6.QtCore import QAbstractTableModel
+
+COLS = 3
+ROWS = 2
+
+
+class MyModel(QAbstractTableModel):
+
+ editCompleted = Signal(str)
+
+ def __init__(self, parent=None):
+ ...
+
+ def rowCount(self, parent=None):
+ ...
+
+ def columnCount(self, parent=None):
+ ...
+
+ def data(self, index, role=Qt.DisplayRole):
+ ...
+
+ def setData(self, index, value, role):
+ ...
+
+ def flags(self, index):
+ ...
diff --git a/sources/pyside6/doc/snippets/qtbase/src/gui/doc/snippets/code/src_gui_painting_qpainter_drawText.cpp.py b/sources/pyside6/doc/snippets/qtbase/src/gui/doc/snippets/code/src_gui_painting_qpainter_drawText.cpp.py
new file mode 100644
index 000000000..cad2c5395
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/src/gui/doc/snippets/code/src_gui_painting_qpainter_drawText.cpp.py
@@ -0,0 +1,13 @@
+painter = QPainter(self)
+font = painter.font()
+font.setPixelSize(48)
+painter.setFont(font)
+rectangle = QRect(0, 0, 100, 50)
+boundingRect = painter.drawText(rectangle, 0, "Hello")
+pen = painter.pen()
+pen.setStyle(Qt.DotLine)
+painter.setPen(pen)
+painter.drawRect(boundingRect.adjusted(0, 0, -pen.width(), -pen.width()))
+pen.setStyle(Qt.DashLine)
+painter.setPen(pen)
+painter.drawRect(rectangle.adjusted(0, 0, -pen.width(), -pen.width()))
diff --git a/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py b/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py
new file mode 100644
index 000000000..02a02aaf8
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py
@@ -0,0 +1,24 @@
+class StringListModel(QAbstractListModel):
+ def __init__(self, strings, parent=None):
+ ...
+
+ def rowCount(self, parent=QModelIndex()):
+ ...
+
+ def data(self, index, role):
+ ...
+
+ def headerData(self, section, orientation, role=Qt.DisplayRole):
+ ...
+
+ def flags(self, index):
+ ...
+
+ def setData(self, index, value, role=Qt.EditRole):
+ ...
+
+ def insertRows(self, position, rows, parent):
+ ...
+
+ def removeRows(self, position, rows, parent):
+ ...
diff --git a/sources/pyside6/doc/tools/index.rst b/sources/pyside6/doc/tools/index.rst
new file mode 100644
index 000000000..b421a428f
--- /dev/null
+++ b/sources/pyside6/doc/tools/index.rst
@@ -0,0 +1,211 @@
+.. _package_tools:
+
+Tools
+=====
+
+Following the same idea from the modules, we also include in the packages
+(wheels) Qt tools that are important for any Qt application development
+workflow, like ``uic``, ``rcc``, etc.
+
+All the tools **must** be used from the PySide wrappers, and not directly.
+For example, if exploring the ``site-packages/`` directory on your installation
+you find ``uic.exe`` (on Windows), you should not click on that, and use
+``pyside6-uic.exe`` instead.
+The reason for this is the proper setup of PATHs, plugins, and more,
+to properly work with the installed Python package.
+
+Here you can find all the tools we include in |project| starting
+from 6.3.0, grouped by different topics:
+
+Project development
+~~~~~~~~~~~~~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-project``
+ :link: pyside6-project
+ :link-type: ref
+
+ to build *Qt Widgets Designer* forms (``.ui`` files),
+ resource files (``.qrc``) and QML type files (``.qmltype``)
+ from a ``.pyproject`` file.
+
+Widget Development
+~~~~~~~~~~~~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-designer``
+ :link: pyside6-designer
+ :link-type: ref
+
+ drag-and-drop tool for designing Widget UIs (generates ``.ui`` files,
+ see :ref:`using_ui_files`).
+
+ .. grid-item-card:: ``pyside6-uic``
+ :link: pyside6-uic
+ :link-type: ref
+
+ to generate Python code from ``.ui`` form files.
+
+ .. grid-item-card:: ``pyside6-rcc``
+ :link: pyside6-rcc
+ :link-type: ref
+
+ to generate serialized data from ``.qrc`` resources files.
+ Keep in mind these files can be used in other non-widget projects.
+
+
+QML Development
+~~~~~~~~~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-qmllint``
+ :link: pyside6-qmllint
+ :link-type: ref
+
+ that verifies the syntactic validity of QML files.
+
+ .. grid-item-card:: ``pyside6-qmltyperegistrar``
+ :link: pyside6-qmltyperegistrar
+ :link-type: ref
+
+ to read metatypes files and generate files that contain the necessary
+ code to register all the types marked with relevant macros.
+
+ .. grid-item-card:: ``pyside6-qmlimportscanner``
+ :link: pyside6-qmlimportscanner
+ :link-type: ref
+
+ to identify the QML modules imported from a
+ project/QML files and dump the result as a JSON array.
+
+ .. grid-item-card:: ``pyside6-qmlcachegen``
+ :link: pyside6-qmlcachegen
+ :link-type: ref
+
+ to compile QML to bytecode at compile time for bundling inside the
+ binary.
+
+ .. grid-item-card:: ``pyside6-qml``
+ :link: pyside6-qml
+ :link-type: ref
+
+ to enable quick prototyping with QML files. This tool mimics some of
+ the capabilities of Qt's ``QML`` runtime utility by
+ directly invoking QQmlEngine/QQuickView.
+
+Translations
+~~~~~~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-linguist``
+ :link: pyside6-linguist
+ :link-type: ref
+
+ for translating text in applications.
+
+ .. grid-item-card:: ``pyside6-lrelease``
+ :link: pyside6-lrelease
+ :link-type: ref
+
+ to create run-time translation files for the application.
+
+ .. grid-item-card:: ``pyside6-lupdate``
+ :link: pyside6-lupdate
+ :link-type: ref
+
+ to synchronize source code and translations.
+
+Qt Help
+~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-assistant``
+ :link: pyside6-assistant
+ :link-type: ref
+
+ for viewing online documentation in Qt Help file format.
+ Read more about the formats on the `QtHelp Framework`_ page.
+
+.. _`QtHelp Framework`: https://doc.qt.io/qt-6/qthelp-framework.html
+
+PySide Utilities
+~~~~~~~~~~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-genpyi``
+ :link: pyside6-genpyi
+ :link-type: ref
+
+ to generate Python stubs (``.pyi`` files) for Qt modules.
+
+ .. grid-item-card:: ``pyside6-metaobjectdump``
+ :link: pyside6-metaobjectdump
+ :link-type: ref
+
+ a tool to print out the metatype information in JSON to be used as
+ input for ``qmltyperegistrar``.
+
+Deployment
+~~~~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-deploy``
+ :link: pyside6-deploy
+ :link-type: ref
+
+ to deploy PySide6 applications to desktop platforms - Linux, Windows
+ and macOS.
+
+ .. grid-item-card:: ``pyside6-android-deploy``
+ :link: pyside6-android-deploy
+ :link-type: ref
+
+ to deploy PySide6 application as an Android app targeting different
+ Android platforms - aarch64, armv7a, i686, x86_64.
+
+Shader Tools
+~~~~~~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-qsb``
+ :link: pyside6-qsb
+ :link-type: ref
+
+ a command-line tool provided by the Qt Shader Tools modules to
+ generate and inspect .qsb files.
+
+Qt Quick 3D
+~~~~~~~~~~~
+
+.. grid:: 2
+ :gutter: 3 3 4 5
+
+ .. grid-item-card:: ``pyside6-balsam``
+ :link: pyside6-balsam
+ :link-type: ref
+
+ a command line tool that takes assets created in digital content
+ creation tools like Maya, 3ds Max or Blender and converts them into an
+ efficient runtime format for use with Qt Quick 3D.
+
+ .. grid-item-card:: ``pyside6-balsamui``
+ :link: pyside6-balsamui
+ :link-type: ref
+
+ a graphical user interface for the ``pyside6-balsam`` tool.
diff --git a/sources/pyside6/doc/tools/pyside-assistant.rst b/sources/pyside6/doc/tools/pyside-assistant.rst
new file mode 100644
index 000000000..c9b3470c3
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-assistant.rst
@@ -0,0 +1,21 @@
+.. _pyside6-assistant:
+
+pyside6-assistant
+=================
+
+``pyside6-assistant`` is a tool that wraps `Qt Assistant`_, the help
+viewer of Qt for use with the Qt help file format (see `The Qt Help Framework`_).
+
+The version of assistant shipped with Qt for Python does not contain
+any documentation.
+
+You can build the Qt for Python documentation in the Qt help file format
+(see :ref:`building_documentation`) and register it for use in `Preferences`
+dialog of ``pyside6-assistant`` (`Edit/Preferences`).
+
+.. image:: pyside6-assistant_screenshot.webp
+ :width: 381
+ :alt: PySide6 Assistant Screenshot
+
+.. _`Qt Assistant`: https://doc.qt.io/qt-6/qtassistant-index.html
+.. _`The Qt Help Framework`: https://doc.qt.io/qt-6/qthelp-framework.html
diff --git a/sources/pyside6/doc/tools/pyside-designer.rst b/sources/pyside6/doc/tools/pyside-designer.rst
new file mode 100644
index 000000000..4cde6b2bf
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-designer.rst
@@ -0,0 +1,91 @@
+.. _pyside6-designer:
+
+pyside6-designer
+================
+
+``pyside6-designer`` is a tool that wraps the `Qt Widgets Designer`_,
+to enable you to design Qt Widgets applications with a *drag-and-drop*
+approach.
+
+.. image:: pyside6-designer_screenshot.webp
+ :width: 100%
+ :alt: PySide6 Designer Screenshot
+
+Usage
+-----
+
+With ``pyside6-designer`` you can design your application in a simple way,
+to later save the end result in a ``.ui`` file. When you start the tool, you
+will see a dialog to select the base window: a QWidget, a QMainWindow, etc.
+
+.. image:: pyside6-designer_base_screenshot.webp
+ :width: 50%
+ :alt: PySide6 Designer Initial Screenshot
+
+Once you select one of those options, you can start placing widgets
+into the interface, and have access to the whole structure, properties,
+and more.
+
+.. image:: pyside6-designer_sections_screenshot.webp
+ :width: 100%
+ :alt: PySide6 Designer Initial Screenshot
+
+A simple distinction of the areas you might use is described in the
+previous screenshot. In the section **1** you will find all the elements
+you can use in your application, which is the area **2**.
+The application designs follows a hierarchical configuration,
+in **3** you can see the structure of the example which contains
+only a ``QMainWindow`` and a ``QPushButton``. Lastly
+you can access and modify the properties of the item in **4**,
+where you could adjust dimensions, names, etc.
+
+
+When your application is finished, you will save your design in a ``.ui``
+file. This ``.ui`` file can later be converted into a Python file,
+with the help of the :ref:`pyside6-uic` tool. You can find
+more details of this process in: :ref:`using_ui_files`.
+
+If you are interested in more functionality of the tool, you can check
+the official `Qt Widgets Designer Manual`_.
+
+
+Custom Widgets
+--------------
+
+One of the features that the `Qt Widgets Designer`_ provides is the possibility
+of loading custom widgets, in order to facilitate the development with ad-hoc
+widgets.
+
+On the following screenshot, you can see a new component on the left column
+that is already added on the main widget, a tic-tac-toe custom widget.
+
+.. image:: pyside6-designer_customwidgets_screenshot.webp
+ :width: 100%
+ :alt: PySide6 Designer Custom Widgets Screenshot
+
+To achieve this, you need to register a custom widget by setting the environment
+variable ``PYSIDE_DESIGNER_PLUGINS`` to the directory where your register file
+is located. The registration file for the tic-tac-toe widget looks like this:
+
+.. code-block:: Python
+
+ from tictactoe import TicTacToe
+ from tictactoeplugin import TicTacToePlugin
+
+ from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
+
+
+ if __name__ == '__main__':
+ QPyDesignerCustomWidgetCollection.addCustomWidget(TicTacToePlugin())
+
+As you can see in the previous code, ``TicTacToe`` is the custom widget,
+imported from a different file, and the ``TicTacToePlugin`` is the interface
+layer for `Qt Widgets Designer`_ to recognize it.
+We provide a helper class, ``QPyDesignerCustomWidgetCollection``, to
+simplify the registration process.
+
+If you are interested in all the details of this specific case, you can
+check the :ref:`task-menu-extension-example`.
+
+.. _`Qt Widgets Designer`: https://doc.qt.io/qt-6/qtdesigner-manual.html
+.. _`Qt Widgets Designer Manual`: https://doc.qt.io/qt-6/qtdesigner-manual.html
diff --git a/sources/pyside6/doc/tools/pyside-genpyi.rst b/sources/pyside6/doc/tools/pyside-genpyi.rst
new file mode 100644
index 000000000..0240c5005
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-genpyi.rst
@@ -0,0 +1,52 @@
+.. _pyside6-genpyi:
+
+pyside6-genpyi
+==============
+
+`pyside6-genpyi` is a command line tool to generate Python stub files
+(.pyi) for PySide modules. Stub files define signatures of all classes,
+methods (including overloads), constants and enums of the PySide
+modules. Signatures also contain type hints. This helps PySide integrate
+with Python type checkers and IDEs. For example, if you use any function
+from the Qt API with PySide, your IDE's function lookup feature will
+show you the function signature and its parameters and return value
+including types.
+
+PySide6 already ships with stub files that were generated with
+`pyside6-genpyi`. However, if you want to generate new stub files for
+several (or all) modules, for example to toggle a few features, you can
+run `pyside6-genpyi` manually. If you want to generate stub files for
+your own custom module, refer to :ref:`shiboken6-genpyi`.
+
+
+Usage
+-----
+
+To generate stub files for a PySide module, run the following command:
+
+.. code-block:: bash
+
+ pyside6-genpyi <module_names> [OPTIONS]
+
+where `<module_names>` is a space-separated list of module names (the
+modules must be importable from the working directory) and where
+`[OPTIONS]` can be one of the following:
+
+* **--quiet**: Run the tool quietly without output to stdout.
+* **--outpath <output_dir>**: Specify the output directory for the
+ generated stub files. If not specified, the stub files are generated
+ in the location of the module binary.
+* **--sys-path <paths>**: Prepend the system path (`sys.path`) with a
+ space-separated list of strings `<paths>`. This is useful if the
+ module is not installed in a default lookup location.
+* **--feature <features>**: A space-separate list of optional PySide
+ features to enable (see :ref:`pysideapi2`). This option has no effect
+ when using PyPy. Currently, the following features are available:
+
+ * **snake_case**: All methods in the module are switched from
+ ``camelCase`` to ``snake_case``. A single upper case letter is
+ replaced by an underscore and the lower case letter.
+ * **true_property**: All getter and setter functions in the module
+ which are marked as a property in the Qt6 docs are replaced by Python
+ property objects. Properties are also listed as such in the according
+ QMetaObject of a class.
diff --git a/sources/pyside6/doc/tools/pyside-linguist.rst b/sources/pyside6/doc/tools/pyside-linguist.rst
new file mode 100644
index 000000000..e13124a8e
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-linguist.rst
@@ -0,0 +1,20 @@
+.. _pyside6-linguist:
+
+pyside6-linguist
+=================
+
+``pyside6-linguist`` is a tool that wraps `Qt Linguist`_, Qt's tool to
+translate user interfaces and manage application localizations. It
+supports Qt's own TS file format as well as the XML Localization
+Interchange File Format (XLIFF). There are no differences between the
+version bundled with PySide and the one from Qt.
+
+For more information on how to use this tool, read Qt's documentation
+here: `Qt Linguist`_. Read more about how to translate PySide
+applications here: :ref:`translations`.
+
+.. image:: pyside6-linguist_screenshot.webp
+ :width: 500
+ :alt: PySide6 Linguist Screenshot
+
+.. _`Qt Linguist`: https://doc.qt.io/qt-6/qtlinguist-index.html
diff --git a/sources/pyside6/doc/tools/pyside-lrelease.rst b/sources/pyside6/doc/tools/pyside-lrelease.rst
new file mode 100644
index 000000000..7c628f2aa
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-lrelease.rst
@@ -0,0 +1,25 @@
+.. _pyside6-lrelease:
+
+pyside6-lrelease
+================
+
+.. note:: This tool is automatically called by :ref:`pyside6-project`
+ so you don't need to call it manually. *Qt Creator* will take care
+ of this step as well while executing a project.
+
+``pyside6-lrelease`` is a command line tool wrapping `lrelease`_. It produces
+``.qm`` files out of ``.ts`` files. The ``.qm`` file format is a compact binary
+format that the localized application uses. It provides extremely fast lookup
+for translations (see :ref:`translations`).
+
+Usage
+-----
+
+To convert a ``.ts`` file of the :ref:`qt-linguist-example`
+into its binary representation, run:
+
+.. code-block:: bash
+
+ pyside6-lrelease example_de.ts -qm example_de.qm
+
+.. _`lrelease`: https://doc.qt.io/qt-6/linguist-lrelease.html
diff --git a/sources/pyside6/doc/tools/pyside-lupdate.rst b/sources/pyside6/doc/tools/pyside-lupdate.rst
new file mode 100644
index 000000000..1c0d73c15
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-lupdate.rst
@@ -0,0 +1,23 @@
+.. _pyside6-lupdate:
+
+pyside6-lupdate
+===============
+
+.. note:: This tool is automatically called by :ref:`pyside6-project`
+ so you don't need to call it manually.
+
+``pyside6-lupdate`` is a command line tool wrapping `lupdate`_. It finds
+translatable strings in Python, ``.ui``, and ``.qml`` files and generates or
+updates ``.ts`` files (see :ref:`translations`).
+
+Usage
+-----
+
+To create or update the ``.ts`` file of the :ref:`qt-linguist-example`,
+run:
+
+.. code-block:: bash
+
+ pyside6-lupdate main.py main.qml form.ui -ts example_de.ts
+
+.. _`lupdate`: https://doc.qt.io/qt-6/linguist-lupdate.html
diff --git a/sources/pyside6/doc/tools/pyside-metaobjectdump.rst b/sources/pyside6/doc/tools/pyside-metaobjectdump.rst
new file mode 100644
index 000000000..1522b7ad5
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-metaobjectdump.rst
@@ -0,0 +1,92 @@
+.. _pyside6-metaobjectdump:
+
+pyside6-metaobjectdump
+======================
+
+``pyside6-metaobjectdump`` is a command line tool. It scans Python source
+files and dumps out information on classes to be registered with QML in
+JSON-format. This serves as input for the :ref:`pyside6-qmltyperegistrar` tool.
+
+The tool is the equivalent of the `moc`_ tool in Qt / C++.
+
+It is automatically run by the :ref:`pyside6-project` tool
+when passing the ``qmllint`` argument instructing it to check
+the QML source files.
+
+Usage
+-----
+
+Classes to be registered with QML are indicated by QML decorators
+like :deco:`QmlElement`. Invoking:
+
+.. code-block:: bash
+
+ pyside6-metaobjectdump birthdayparty.py
+
+produces the JSON data on stdout:
+
+.. code-block:: json
+
+ [
+ {
+ "classes": [
+ {
+ "className": "BirthdayParty",
+ "qualifiedClassName": "BirthdayParty",
+ "object": true,
+ "superClasses": [
+ {
+ "access": "public",
+ "name": "QObject"
+ }
+ ],
+ "classInfos": [
+ {
+ "name": "QML.Element",
+ "value": "auto"
+ }
+ ],
+ "properties": [
+ {
+ "name": "host",
+ "type": "Person",
+ "index": 0,
+ "read": "host",
+ "notify": "host_changed",
+ "write": "host"
+ },
+ {
+ "name": "guests",
+ "type": "QQmlListProperty<Person>",
+ "index": 1
+ }
+ ],
+ "signals": [
+ {
+ "access": "public",
+ "name": "host_changed",
+ "arguments": [],
+ "returnType": "void"
+ },
+ {
+ "access": "public",
+ "name": "guests_changed",
+ "arguments": [],
+ "returnType": "void"
+ }
+ ]
+ }
+ ],
+ "outputRevision": 68,
+ "QML_IMPORT_NAME": "People",
+ "QML_IMPORT_MAJOR_VERSION": 1,
+ "QML_IMPORT_MINOR_VERSION": 0,
+ "QT_MODULES": [
+ "QtCore",
+ "QtQml"
+ ],
+ "inputFile": ".../examples/qml/tutorials/extending-qml-advanced/advanced1-Base-project/birthdayparty.py"
+ }
+ ]
+
+.. _`moc`: https://doc.qt.io/qt-6/moc.html
diff --git a/sources/pyside6/doc/tools/pyside-project.rst b/sources/pyside6/doc/tools/pyside-project.rst
new file mode 100644
index 000000000..0359e1b7d
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-project.rst
@@ -0,0 +1,64 @@
+.. _pyside6-project:
+
+pyside6-project
+===============
+
+`pyside6-project` is a command line tool for creating, building and deploying
+|project| applications. It operates on a project file which is also used by
+`Qt Creator`_.
+
+Project file format
+-------------------
+
+The project file format is a simple `JSON`_-based format with the suffix
+``.pyproject`` listing all files of the project excluding generated files
+(typically ``.py``, ``.qml``, ``.qrc``, ``.ts``, or ``.ui`` files):
+
+.. code-block:: json
+
+ {
+ "files": ["main.py"]
+ }
+
+
+Usage
+-----
+
+The tool has several subcommands. New projects can be created using
+the below commands, passing the project name (directory):
+
+*new-ui*
+ Creates a new QtWidgets project with a *Qt Widgets Designer*-based main
+ window.
+
+*new-widget*
+ Creates a new QtWidgets project with a main window.
+
+*new-quick*
+ Creates a new QtQuick project.
+
+The other commands take the project file as an argument.
+It is also possible to specify a directory containing the project file.
+
+*build*
+ Builds the project, generating the required build artifacts
+ (see :ref:`using_ui_files`, :ref:`using_qrc_files`).
+
+*run*
+ Builds the project and runs the main.
+
+*deploy*
+ Deploys the application (see see :ref:`pyside6-deploy`).
+
+*lupdate*
+ Updates translation (.ts) files (see :ref:`translations`).
+
+*clean*
+ Cleans the build artifacts.
+
+*qmllint*
+ Runs the ``qmllint`` tool, checking the QML files.
+
+
+.. _`Qt Creator`: https://www.qt.io/product/development-tools
+.. _`JSON`: https://www.json.org/
diff --git a/sources/pyside6/doc/tools/pyside-qml.rst b/sources/pyside6/doc/tools/pyside-qml.rst
new file mode 100644
index 000000000..0502dd94a
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-qml.rst
@@ -0,0 +1,84 @@
+.. _pyside6-qml:
+
+pyside6-qml
+===========
+
+``pyside6-qml`` mimics some capabilities of Qt's `qml <qml_runtime>`_ runtime utility by directly
+invoking QQmlEngine/QQuickView. It enables prototyping with QML/QtQuick without the need to write
+any Python code that loads the QML files either through `QQmlApplicationEngine <qqmlappengine>`_ or
+the `QQuickView <qquickview>`_ class. The tool also detects the QML classes implemented in Python
+and registers them with the QML type system.
+
+Usage
+-----
+
+Consider the example `Extending QML - Plugins Example <extending_qml_example>`_. This example does
+not have a Python file with a ``main`` function that initializes a QmlEngine to load the QML file
+``app.qml``. You can run the example by running
+
+.. code-block:: bash
+
+ pyside6-qml examples/qml/tutorials/extending-qml/chapter6-plugins/app.qml -I examples/qml/tutorials/extending-qml/chapter6-plugins/Charts
+
+The ``-I`` flag is used to point ``pyside6-qml`` to the folder containing Python files that
+implement QML classes.
+
+Command Line Options
+--------------------
+
+Here are all the command line options of ``pyside6-qml``:
+
+Arguments
+^^^^^^^^^
+
+* **file**: This option refers to the QML file to be loaded by ``pyside6-qml``. This option does not
+ have a name or a flag. Therefore, this option should be the first option supplied to
+ ``pyside6-qml``. For example,
+
+.. code-block:: bash
+
+ pyside6-qml /path/to/test.qml
+
+Options
+^^^^^^^
+
+* **--module-paths/-I**: Specify space-separated folder/file paths which point to the Python files
+ that implement QML classes. By default, the parent directory of the QML file supplied to
+ ``pyside6-qml`` is searched recursively for all Python files and they are imported. Otherwise,
+ only the paths given in module paths are searched.
+
+* **--verbose/-v**: Run ``pyside6-qml`` in verbose mode. When run in this mode, pyside6-qml prints
+ log messages during various stages of processing.
+
+Options that align with `QML <qml_runtime>`_ runtime utility
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* **--app-typ/-a**: Specifies which application class to use. It takes one of the three values -
+ ``core, gui, widget``. The default value is *gui*.
+
+* **--config/-c**: Load the given built-in configuration. It takes one of two values - ``default,
+ resizeToItem``. This option is only relevant for a QtQuick application. If ``default`` is used,
+ the view resizes to the size of the root item in the QML. If ``resizeToItem`` is used, the view
+ automatically resizes the root item to the size of the view.
+
+* **--list-conf**: List the built-in configurations. ``pyside6-qml`` has two built-in configurations
+ - ``default`` and ``resizeToItem``. See the option ``--config`` for more information.
+
+* **--rhi/-r**: Specifies the backend for the Qt graphics abstraction (RHI). It takes one of the
+ four values - ``vulkan, metal, d3dll, gl``.
+
+* **--verbose/-v**: List the built-in configurations. ``pyside6-qml`` has two built-in
+ configurations - *default* and *resizeToItem*. See the option ``--config`` for more information.
+
+* **--gles**: Force use of GLES (AA_UseOpenGLES).
+
+* **--desktop**: Force use of desktop OpenGL (AA_UseDesktopOpenGL).
+
+* **--software**: Force use of software rendering(AA_UseSoftwareOpenGL).
+
+* **--disable-context-sharing**: Disable the use of a shared GL context for QtQuick Windows".
+
+.. _`qml_runtime`: https://doc.qt.io/qt-6/qtquick-qml-runtime.html
+.. _`qqmlappengine`: https://doc.qt.io/qt-6/qqmlapplicationengine.html
+.. _`qquickview`: https://doc.qt.io/qt-6/qquickview.html
+.. _`extending_qml_example`: https://doc.qt.io/qtforpython-6/examples/example_qml_tutorials_extending-qml_chapter6-plugins.html
diff --git a/sources/pyside6/doc/tools/pyside-qmlcachegen.rst b/sources/pyside6/doc/tools/pyside-qmlcachegen.rst
new file mode 100644
index 000000000..ecd8e6afd
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-qmlcachegen.rst
@@ -0,0 +1,25 @@
+.. _pyside6-qmlcachegen:
+
+pyside6-qmlcachegen
+===================
+
+``pyside6-qmlcachegen`` is a command line tool that wraps `qmlcachegen`_.
+This tool creates C++ code or `QML byte code` for ``.qml`` files. For
+Qt for Python, only `QML byte code` is relevant. The file suffix is
+``.qmlc`` and it works similar to compiled Python bytecode
+(``.pyc`` files).
+
+Usage
+-----
+
+The command line option ``--only-bytecode`` should be used to
+create `QML byte code`. For example:
+
+.. code-block:: bash
+
+ qmlcachegen --only-bytecode gallery.qml
+
+produces a file ``gallery.qmlc`` containing `QML byte code` which is
+automatically loaded by the QML engine.
+
+.. _`qmlcachegen`: https://doc.qt.io/qt-6/qtqml-tool-qmlcachegen.html
diff --git a/sources/pyside6/doc/tools/pyside-qmllint.rst b/sources/pyside6/doc/tools/pyside-qmllint.rst
new file mode 100644
index 000000000..54a72470e
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-qmllint.rst
@@ -0,0 +1,49 @@
+.. _pyside6-qmllint:
+
+pyside6-qmllint
+===============
+
+``pyside6-qmllint`` is a command line tool that wraps `qmllint`_. This tool
+verifies the syntatic validity of QML files and warns about some QML
+anti-patterns.
+
+It is automatically run by the :ref:`pyside6-project` tool
+when passing the ``qmllint`` argument instructing it to check
+the QML source files.
+
+Usage
+-----
+
+The tool should normally not be invoked manually since it requires
+a number of import paths and additional type information
+generated by :ref:`pyside6-qmltyperegistrar` to function.
+
+For example, for a ``.qml`` file like:
+
+.. code-block:: javascript
+
+ import QtQuick
+ import QtQuick.Controls
+
+ Item {
+ Text {
+ id: name
+ text: qsTr("Hello World")
+ }
+ }
+
+when running:
+
+.. code-block:: bash
+
+ pyside6-qmllint Main.qml
+
+it would warn about unused imports:
+
+.. code-block::
+
+ Info: Main.qml:2:1: Unused import [unused-imports]
+ import QtQuick.Controls
+ ^^^^^^
+
+.. _`qmllint`: https://doc.qt.io/qt-6/qtquick-tool-qmllint.html
diff --git a/sources/pyside6/doc/tools/pyside-qmltyperegistrar.rst b/sources/pyside6/doc/tools/pyside-qmltyperegistrar.rst
new file mode 100644
index 000000000..0e8d66bd5
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-qmltyperegistrar.rst
@@ -0,0 +1,17 @@
+.. _pyside6-qmltyperegistrar:
+
+pyside6-qmltyperegistrar
+========================
+
+``pyside6-qmltyperegistrar`` is a command line tool that wraps the
+``qmltyperegistrar`` tool of Qt.
+
+It takes the file produced by :ref:`pyside6-metaobjectdump`
+as input and generates C++ code to register C++ classes to QML
+and a ``.qmltypes`` file containing a JSON description of the
+classes. For Qt for Python, only the ``.qmltypes`` file
+is of interest as input for :ref:`pyside6-qmllint`.
+
+The tool is automatically run by the :ref:`pyside6-project` tool
+when passing the ``qmllint`` argument instructing it to check
+the QML source files.
diff --git a/sources/pyside6/doc/tools/pyside-rcc.rst b/sources/pyside6/doc/tools/pyside-rcc.rst
new file mode 100644
index 000000000..e5688485e
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-rcc.rst
@@ -0,0 +1,55 @@
+.. _pyside6-rcc:
+
+pyside6-rcc
+===========
+
+.. note:: This tool is automatically called by :ref:`pyside6-project`
+ so you don't need to call it manually. *Qt Creator* will take care
+ of this step as well while executing a project.
+
+
+``pyside6-rcc`` is a command line tool for converting ``.qrc`` files into ``.py``
+files, so they can be used within your Python code.
+
+The tool is a wrapper around the `rcc`_ tool, which was originally
+designed to generate C++ code, but it also has Python support.
+
+Even though the equivalent of ``pyside6-rcc`` is running ``rcc -g python``
+we strongly recommend you to rely on ``pyside6-rcc`` in order to avoid
+mismatches between versions for the generated code.
+
+Usage
+-----
+
+Once you have gathered your resources on a qrc file,
+you can transform your ``.qrc`` file with the following command:
+
+.. code-block:: bash
+
+ pyside6-rcc your_file.qrc -o rc_your_file.py
+
+It is important to use the ``-o`` option to generate the Python file with the
+conversion, otherwise you will receive all the output as stdout in your terminal.
+
+To enable the usage of those resources in your program, you need to import
+the file:
+
+.. code-block:: Python
+
+ import rc_your_file
+
+then you can use a specific resource, for example an image, with the prefix ``:/``,
+for example:
+
+.. code-block:: Python
+
+ pixmap = QPixmap(":/icons/image.png")
+
+
+For additional options, you can use ``pyside6-rcc -h`` in order to get
+more information about additional options.
+
+Visit the tutorial :ref:`using_qrc_files` for a hands-on example.
+
+.. _`rcc`: https://doc.qt.io/qt-6/rcc.html
+
diff --git a/sources/pyside6/doc/tools/pyside-uic.rst b/sources/pyside6/doc/tools/pyside-uic.rst
new file mode 100644
index 000000000..ba4e36b4e
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside-uic.rst
@@ -0,0 +1,59 @@
+.. _pyside6-uic:
+
+pyside6-uic
+===========
+
+.. note:: This tool is automatically called by :ref:`pyside6-project`
+ so you don't need to call it manually. *Qt Creator* will take care
+ of this step as well while executing a project.
+
+``pyside6-uic`` is a command line tool for converting ``.ui`` files into ``.py``
+files, with the objective of using application designs as Python classes.
+
+The tool is a wrapper around the `uic`_ tool, which was originally
+designed to generate C++ code, but it also has Python support.
+
+Even though the equivalent of ``pyside6-uic`` is running ``uic -g python``
+we strongly recommend you to rely on ``pyside6-uic`` in order to avoid
+mismatches between versions for the generated code.
+
+Usage
+-----
+
+Once you have designed your application with :ref:`pyside6-designer`,
+you can transform your ``.ui`` file with the following command:
+
+.. code-block:: bash
+
+ pyside6-uic your_file.ui -o ui_your_file.py
+
+It is important to use the ``-o`` option to generate the Python file with the
+conversion, otherwise you will receive all the output as stdout in your terminal.
+
+The structure of the generated Python file will be similar in all cases,
+and you will get one class called ``Ui_TheNameOfYourDesign(object)`` that
+is in charge of positioning all the elements like your design.
+
+To use this Python file, you should follow our tutorial in
+:ref:`using_ui_files`, but in summary, it is mainly importing the class
+from the generated file and setting it up in your code:
+
+.. code-block:: Python
+
+ self.ui = Ui_TheNameOfYourDesign()
+ self.ui.setupUi(self)
+
+For additional options, you can use ``pyside-uic -h`` in order to get
+more information related to relative imports, absolute imports, using resources,
+translations, etc.
+
+.. note:: Remember that you need to have a class corresponding to the base
+ form you selected in :ref:`pyside6-designer`, a ``QWidget``, or ``QDialog``,
+ or ``QMainWindow``, etc, in order for ``setupUi`` to work. Check
+ :ref:`using_ui_files` for more information.
+
+.. warning:: Do not modify the content of the generated Python file from your
+ ``.ui`` file, otherwise everything will be lost when you re-generate it.
+
+.. _`uic`: https://doc.qt.io/qt-6/uic.html
+
diff --git a/sources/pyside6/doc/tools/pyside6-assistant_screenshot.webp b/sources/pyside6/doc/tools/pyside6-assistant_screenshot.webp
new file mode 100644
index 000000000..7d898d8e6
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-assistant_screenshot.webp
Binary files differ
diff --git a/sources/pyside6/doc/tools/pyside6-balsam.rst b/sources/pyside6/doc/tools/pyside6-balsam.rst
new file mode 100644
index 000000000..c6677f6a3
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-balsam.rst
@@ -0,0 +1,59 @@
+.. _pyside6-balsam:
+
+pyside6-balsam
+==============
+
+``pyside6-qsb`` is a tool that wraps the `balsam <Balsam Asset Import Tool>`_
+tool provided with Qt Quick 3D. The Balsam tool is a command line application
+that is part of Qt Quick 3D's asset conditioning pipeline. The purpose is to
+take assets created in digital content creation tools like `Maya`_, `3ds Max`_
+or `Blender`_ and converts them into an efficient runtime format for use with Qt
+Quick 3D. It is not possible, nor does it make sense to reference the
+interchange formats directly in applications because a large amount of
+resources are needed to parse and condition the content of the asset before it
+is usable for real-time rendering. Instead, the interchange formats can be
+converted via the Balsam tool into QML Components and resources like geometry
+and textures.
+
+
+For more information on how to use this tool, read Qt's documentation
+here: `Balsam Asset Import Tool`_.
+
+Usage
+-----
+
+.. code-block:: bash
+
+ pyside6-balsam [options] sourceFileName
+
+To convert a 3D asset contained in the file ``testModel.fbx`` with
+``pyside6-balsam`` the following command would be used:
+
+.. code-block:: bash
+
+ pyside6-balsam testModel.fbx
+
+This would generate the following files:
+
+* meshes/testModel.mesh
+* TestModel.qml
+
+Which can then be used in a Qt Quick 3D project by using that QML Component:
+
+.. code-block:: xml
+
+ import QtQuick3D 1.0
+
+ Scene {
+ Model {
+ source: "TestModel.qml"
+ }
+ }
+
+For other modes of operation, refer to the `Balsam Asset Import Tool`_.
+
+.. _`Balsam Asset Import Tool`: https://doc.qt.io/qt-6/qtquick3d-tool-balsam.html
+.. _Maya: https://www.autodesk.com/products/maya/overview
+.. _3ds Max: https://www.autodesk.com/products/3ds-max/overview
+.. _Blender: https://www.blender.org/
+
diff --git a/sources/pyside6/doc/tools/pyside6-balsamui.rst b/sources/pyside6/doc/tools/pyside6-balsamui.rst
new file mode 100644
index 000000000..f34cb6045
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-balsamui.rst
@@ -0,0 +1,22 @@
+.. _pyside6-balsamui:
+
+pyside6-balsamui
+================
+
+``pyside6-balsamui`` is graphical user interface frontend to the command line
+tool :ref:`pyside6-balsam`. The purpose of the tool is to take assets created
+in digital content creation tools like `Maya`_, `3ds Max`_ or `Blender`_ and
+converts them into an efficient runtime format for use with Qt Quick 3D.
+
+For more information on the further capabilities of the tool, read Qt's
+documentation here: `Balsam Asset Import Tool`_.
+
+.. image:: pyside6-balsamui_screenshot.webp
+ :width: 500
+ :alt: pyside6-balsamui screenshot
+
+.. _`Balsam Asset Import Tool`: https://doc.qt.io/qt-6/qtquick3d-tool-balsam.html
+.. _Maya: https://www.autodesk.com/products/maya/overview
+.. _3ds Max: https://www.autodesk.com/products/3ds-max/overview
+.. _Blender: https://www.blender.org/
+
diff --git a/sources/pyside6/doc/tools/pyside6-balsamui_screenshot.webp b/sources/pyside6/doc/tools/pyside6-balsamui_screenshot.webp
new file mode 100644
index 000000000..5c194fdb6
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-balsamui_screenshot.webp
Binary files differ
diff --git a/sources/pyside6/doc/tools/pyside6-designer_base_screenshot.webp b/sources/pyside6/doc/tools/pyside6-designer_base_screenshot.webp
new file mode 100644
index 000000000..88ff77786
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-designer_base_screenshot.webp
Binary files differ
diff --git a/sources/pyside6/doc/tools/pyside6-designer_customwidgets_screenshot.webp b/sources/pyside6/doc/tools/pyside6-designer_customwidgets_screenshot.webp
new file mode 100644
index 000000000..c84436c1d
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-designer_customwidgets_screenshot.webp
Binary files differ
diff --git a/sources/pyside6/doc/tools/pyside6-designer_screenshot.webp b/sources/pyside6/doc/tools/pyside6-designer_screenshot.webp
new file mode 100644
index 000000000..27f03652b
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-designer_screenshot.webp
Binary files differ
diff --git a/sources/pyside6/doc/tools/pyside6-designer_sections_screenshot.webp b/sources/pyside6/doc/tools/pyside6-designer_sections_screenshot.webp
new file mode 100644
index 000000000..6ff025503
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-designer_sections_screenshot.webp
Binary files differ
diff --git a/sources/pyside6/doc/tools/pyside6-linguist_screenshot.webp b/sources/pyside6/doc/tools/pyside6-linguist_screenshot.webp
new file mode 100644
index 000000000..cd91007ba
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-linguist_screenshot.webp
Binary files differ
diff --git a/sources/pyside6/doc/tools/pyside6-qmlimportscanner.rst b/sources/pyside6/doc/tools/pyside6-qmlimportscanner.rst
new file mode 100644
index 000000000..ba27414d7
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-qmlimportscanner.rst
@@ -0,0 +1,53 @@
+.. _pyside6-qmlimportscanner:
+
+pyside6-qmlimportscanner
+========================
+
+``pyside6-qmlimportscanner`` is a command line tool that wraps the
+``qmlimportscanner`` tool of Qt.
+
+
+The tool is automatically run by the :ref:`pyside6-project` tool
+when passing the ``qmllint`` argument instructing it to check
+the QML source files.
+
+Usage
+-----
+
+Invoking the tool in the directory of the :ref:`filesystemexplorer_example`
+example using:
+
+.. code-block:: bash
+
+ pyside6-qmlimportscanner -rootPath .
+
+produces:
+
+.. code-block:: json
+
+ [
+ {
+ "name": "QtQuick",
+ "type": "module"
+ },
+ {
+ "name": "QtQuick.Controls.Basic",
+ "type": "module"
+ },
+ {
+ "name": "QtQuick.Layouts",
+ "type": "module"
+ },
+ {
+ "name": "FileSystemModule",
+ "type": "module"
+ },
+ {
+ "name": "QtQuick.Controls",
+ "type": "module"
+ },
+ {
+ "name": "QtQuick.Effects",
+ "type": "module"
+ }
+ ]
diff --git a/sources/pyside6/doc/tools/pyside6-qsb.rst b/sources/pyside6/doc/tools/pyside6-qsb.rst
new file mode 100644
index 000000000..f6f1847d4
--- /dev/null
+++ b/sources/pyside6/doc/tools/pyside6-qsb.rst
@@ -0,0 +1,39 @@
+.. _pyside6-qsb:
+
+pyside6-qsb
+===========
+
+``pyside6-qsb`` is a tool that wraps the `qsb <QSB Manual>`_ tool. qsb is a
+command line tool provided by the `Qt Shader Tools`_ module. It integrates
+third-party libraries such as `glslang`_ and `SPIRV-Cross`_, optionally invokes
+external tools, such as ``fxc`` or ``spirv-opt``, and generates .qsb files.
+Additionally, it can be used to inspect the contents of a .qsb package.
+
+For more information on how to use this tool, read Qt's documentation
+here: `QSB Manual`_.
+
+Usage
+-----
+
+To create a qsb file from a shader file, e.g., ``shader.frag``, use the
+following command:
+
+.. code-block:: bash
+
+ pyside6-qsb -o shader.frag.qsb shader.frag
+
+To inspect the file produced, i.e., ``shader.frag.qsb``, use the following
+command:
+
+.. code-block:: bash
+
+ pyside6-qsb -d shader.frag.qsb
+
+This will print the reflection metadata (in JSON form) and the included shaders.
+
+For other modes of operation, refer to the `QSB Manual`_.
+
+.. _`glslang`: https://github.com/KhronosGroup/glslang
+.. _`spirv-cross`: https://github.com/KhronosGroup/SPIRV-Cross
+.. _`QSB Manual`: https://doc.qt.io/qt-6/qtshadertools-qsb.html
+.. _`Qt Shader Tools`: https://doc.qt.io/qt-6/qtshadertools-index.html
diff --git a/sources/pyside6/doc/tutorials/basictutorial/clickablebutton.rst b/sources/pyside6/doc/tutorials/basictutorial/clickablebutton.rst
index 2221858bc..c5464640b 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/clickablebutton.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/clickablebutton.rst
@@ -60,7 +60,8 @@ signal to the `say_hello()` function:
button.clicked.connect(say_hello)
Finally, we show the button and start the Qt main loop:
-::
+
+.. code-block:: python
# Show the button
button.show()
@@ -68,9 +69,8 @@ Finally, we show the button and start the Qt main loop:
app.exec()
Here is the complete code for this example:
-::
- #!/usr/bin/python
+.. code-block:: python
import sys
from PySide6.QtWidgets import QApplication, QPushButton
diff --git a/sources/pyside6/doc/tutorials/basictutorial/dialog.rst b/sources/pyside6/doc/tutorials/basictutorial/dialog.rst
index bc06d6d9b..b7712672b 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/dialog.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/dialog.rst
@@ -3,8 +3,8 @@ Creating a Dialog Application
This tutorial shows how to build a simple dialog with some
basic widgets. The idea is to let users provide their name
-in a `QLineEdit`, and the dialog greets them on click of a
-`QPushButton`.
+in a ``QLineEdit``, and the dialog greets them on click of a
+``QPushButton``.
Let us just start with a simple stub that creates and shows
a dialog. This stub is updated during the course of this
@@ -31,24 +31,24 @@ tutorial, but you can use this stub as is if you need to:
sys.exit(app.exec())
The imports aren't new to you, the same for the creation of the
-`QApplication` and the execution of the Qt main loop.
+``QApplication`` and the execution of the Qt main loop.
The only novelty here is the **class definition**.
You can create any class that subclasses PySide6 widgets.
-In this case, we are subclassing `QDialog` to define a custom
+In this case, we are subclassing ``QDialog`` to define a custom
dialog, which we name as **Form**. We have also implemented the
-`init()` method that calls the `QDialog`'s init method with the
-parent widget, if any. Also, the new `setWindowTitle()` method
-just sets the title of the dialog window. In `main()`, you can see
+``init()`` method that calls the ``QDialog``'s init method with the
+parent widget, if any. Also, the new ``setWindowTitle()`` method
+just sets the title of the dialog window. In ``main()``, you can see
that we are creating a *Form object* and showing it to the world.
Create the Widgets
------------------
-We are going to create two widgets: a `QLineEdit` where users can
-enter their name, and a `QPushButton` that prints the contents of
-the `QLineEdit`.
-So, let's add the following code to the `init()` method of our Form:
+We are going to create two widgets: a ``QLineEdit`` where users can
+enter their name, and a ``QPushButton`` that prints the contents of
+the ``QLineEdit``.
+So, let's add the following code to the ``init()`` method of our Form:
::
# Create widgets
@@ -62,8 +62,8 @@ Create a layout to organize the Widgets
---------------------------------------
Qt comes with layout-support that helps you organize the widgets
-in your application. In this case, let's use `QVBoxLayout` to lay out
-the widgets vertically. Add the following code to the `init()` method,
+in your application. In this case, let's use ``QVBoxLayout`` to lay out
+the widgets vertically. Add the following code to the ``init()`` method,
after creating the widgets:
::
@@ -72,40 +72,41 @@ after creating the widgets:
layout.addWidget(self.edit)
layout.addWidget(self.button)
-So, we create the layout, add the widgets with `addWidget()`.
+So, we create the layout, add the widgets with ``addWidget()``.
Create the function to greet and connect the Button
---------------------------------------------------
Finally, we just have to add a function to our custom **Form**
and *connect* our button to it. Our function will be a part of
-the Form, so you have to add it after the `init()` function:
+the Form, so you have to add it after the ``init()`` function:
::
# Greets the user
def greetings(self):
print(f"Hello {self.edit.text()}")
-Our function just prints the contents of the `QLineEdit` to the
+Our function just prints the contents of the ``QLineEdit`` to the
python console. We have access to the text by means of the
-`QLineEdit.text()` method.
+``QLineEdit.text()`` method.
Now that we have everything, we just need to *connect* the
-`QPushButton` to the `Form.greetings()` method. To do so, add the
-following line to the `init()` method:
+``QPushButton`` to the ``Form.greetings()`` method. To do so, add the
+following line to the ``init()`` method:
::
# Add button signal to greetings slot
self.button.clicked.connect(self.greetings)
-Once executed, you can enter your name in the `QLineEdit` and watch
+Once executed, you can enter your name in the ``QLineEdit`` and watch
the console for greetings.
Complete code
-------------
Here is the complete code for this tutorial:
-::
+
+.. code-block:: python
import sys
from PySide6.QtWidgets import (QLineEdit, QPushButton, QApplication,
diff --git a/sources/pyside6/doc/tutorials/basictutorial/icons.zip b/sources/pyside6/doc/tutorials/basictutorial/icons.zip
new file mode 100644
index 000000000..e279e37b8
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/basictutorial/icons.zip
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/basictutorial/qrcfiles.rst b/sources/pyside6/doc/tutorials/basictutorial/qrcfiles.rst
index 477c5b738..858293beb 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/qrcfiles.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/qrcfiles.rst
@@ -1,7 +1,7 @@
.. _using_qrc_files:
-Using `.qrc` Files (`pyside6-rcc`)
-**********************************
+Using ``.qrc`` Files (``pyside6-rcc``)
+**************************************
The `Qt Resource System`_ is a mechanism for storing binary files
in an application.
@@ -17,7 +17,7 @@ In this tutorial you will learn how to load custom images as button icons.
For inspiration, we will try to adapt the multimedia player example
from Qt.
-As you can see on the following image, the `QPushButton` that are used
+As you can see on the following image, the ``QPushButton`` that are used
for the media actions (play, pause, stop, and so on) are using the
default icons meant for such actions.
@@ -25,29 +25,27 @@ default icons meant for such actions.
:alt: Multimedia Player Qt Example
You could make the application more attractive by designing the icons,
-but in case you don't want to design them, `download the following set`_
-and use them.
+but in case you don't want to design them, you can download and use them.
+
+:download:`Download icons <icons.zip>`
.. image:: icons.png
:alt: New Multimedia icons
-You can find more information about the `rcc` command, and `.qrc` file
+You can find more information about the ``rcc`` command, and ``.qrc`` file
format, and the resource system in general in the `Qt Resource System`_
site.
-.. _`download the following set`: icons/
-
-The `.qrc` file
-================
+The ``.qrc`` file
+=================
-Before running any command, add information about the resources to a `.qrc`
+Before running any command, add information about the resources to a ``.qrc``
file.
-In the following example, notice how the resources are listed in `icons.qrc`
+In the following example, notice how the resources are listed in ``icons.qrc``
::
- </ui>
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>icons/play.png</file>
@@ -62,15 +60,15 @@ In the following example, notice how the resources are listed in `icons.qrc`
Generating a Python file
=========================
-Now that the `icons.qrc` file is ready, use the `pyside6-rcc` tool to generate
+Now that the ``icons.qrc`` file is ready, use the ``pyside6-rcc`` tool to generate
a Python class containing the binary information about the resources
To do this, we need to run::
- pyside6-rcc icons.rc -o rc_icons.py
+ pyside6-rcc icons.qrc -o rc_icons.py
-The `-o` option lets you specify the output filename,
-which is `rc_icons.py` in this case.
+The ``-o`` option lets you specify the output filename,
+which is ``rc_icons.py`` in this case.
To use the generated file, add the following import at the top of your main Python file::
@@ -167,7 +165,7 @@ Now, the constructor of your class should look like this:
Executing the example
=====================
-Run the application by calling `python main.py` to checkout the new icon-set:
+Run the application by calling ``python main.py`` to checkout the new icon-set:
.. image:: player-new.png
:alt: New Multimedia Player Qt Example
diff --git a/sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst b/sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst
index 470b4ab70..0bfd9e276 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst
@@ -43,101 +43,104 @@ a signal directly to another signal. (This will emit the second signal
immediately whenever the first is emitted.)
Qt's widgets have many predefined signals and slots. For example,
-`QAbstractButton` (base class of buttons in Qt) has a `clicked()`
-signal and `QLineEdit` (single line input field) has a slot named
-'clear()`. So, a text input field with a button to clear the text
-could be implemented by placing a `QToolButton` to the right of the
-`QLineEdit` and connecting its `clicked()` signal to the slot
-'clear()`. This is done using the `connect()` method of the signal:
+``QAbstractButton`` (base class of buttons in Qt) has a ``clicked()``
+signal and ``QLineEdit`` (single line input field) has a slot named
+``clear()``. So, a text input field with a button to clear the text
+could be implemented by placing a ``QToolButton`` to the right of the
+``QLineEdit`` and connecting its ``clicked()`` signal to the slot
+``clear()``. This is done using the ``connect()`` method of the signal:
- .. code-block:: python
+.. code-block:: python
- button = QToolButton()
- line_edit = QLineEdit()
- button.clicked.connect(line_edit.clear)
+ button = QToolButton()
+ line_edit = QLineEdit()
+ button.clicked.connect(line_edit.clear)
-`connect()` returns a `QMetaObject.Connection` object, which can be
-used with the `disconnect()` method to sever the connection.
+``connect()`` returns a ``QMetaObject.Connection`` object, which can be
+used with the ``disconnect()`` method to sever the connection.
Signals can also be connected to free functions:
- .. code-block:: python
+.. code-block:: python
- import sys
- from PySide6.QtWidgets import QApplication, QPushButton
+ import sys
+ from PySide6.QtWidgets import QApplication, QPushButton
- def function():
- print("The 'function' has been called!")
+ def function():
+ print("The 'function' has been called!")
- app = QApplication()
- button = QPushButton("Call function")
- button.clicked.connect(func)
- button.show()
- sys.exit(app.exec())
+ app = QApplication()
+ button = QPushButton("Call function")
+ button.clicked.connect(function)
+ button.show()
+ sys.exit(app.exec())
Connections can be spelled out in code or, for widget forms,
designed in the
`Signal-Slot Editor <https://doc.qt.io/qt-6/designer-connection-mode.html>`_
-of Qt Designer.
+of *Qt Widgets Designer*.
The Signal Class
----------------
When writing classes in Python, signals are declared as class level
variables of the class ``QtCore.Signal()``. A QWidget-based button
-that emits a `clicked()` signal could look as
+that emits a ``clicked()`` signal could look as
follows:
- .. code-block:: python
+.. code-block:: python
- from PySide6.QtCore import Qt, Signal
- from PySide6.QtWidgets import QWidget
+ from PySide6.QtCore import Qt, Signal
+ from PySide6.QtWidgets import QWidget
- class Button(QWidget):
+ class Button(QWidget):
- clicked = Signal(Qt.MouseButton)
+ clicked = Signal(Qt.MouseButton)
- ...
+ ...
- def mousePressEvent(self, event):
- self.clicked.emit(event.button())
+ def mousePressEvent(self, event):
+ self.clicked.emit(event.button())
The constructor of ``Signal`` takes a tuple or a list of Python types
and C types:
- .. code-block:: python
+.. code-block:: python
- signal1 = Signal(int) # Python types
- signal2 = Signal(QUrl) # Qt Types
- signal3 = Signal(int, str, int) # more than one type
- signal4 = Signal((float,), (QDate,)) # optional types
+ signal1 = Signal(int) # Python types
+ signal2 = Signal(QUrl) # Qt Types
+ signal3 = Signal(int, str, int) # more than one type
+ signal4 = Signal((float,), (QDate,)) # optional types
In addition to that, it can receive also a named argument ``name`` that defines
the signal name. If nothing is passed, the new signal will have the same name
as the variable that it is being assigned to.
- .. code-block:: python
+.. code-block:: python
- # TODO
- signal5 = Signal(int, name='rangeChanged')
- # ...
- rangeChanged.emit(...)
+ # TODO
+ signal5 = Signal(int, name='rangeChanged')
+ # ...
+ rangeChanged.emit(...)
Another useful option of ``Signal`` is the arguments name,
useful for QML applications to refer to the emitted values by name:
- .. code-block:: python
+.. code-block:: python
- sumResult = Signal(int, arguments=['sum'])
+ sumResult = Signal(int, arguments=['sum'])
- .. code-block:: javascript
+.. code-block:: javascript
- Connections {
- target: ...
- function onSumResult(sum) {
- // do something with 'sum'
- }
+ Connections {
+ target: ...
+ function onSumResult(sum) {
+ // do something with 'sum'
+ }
+
+
+.. _slot-decorator:
The Slot Class
--------------
@@ -146,11 +149,11 @@ Slots in QObject-derived classes should be indicated by the decorator
``@QtCore.Slot()``. Again, to define a signature just pass the types
similar to the ``QtCore.Signal()`` class.
- .. code-block:: python
+.. code-block:: python
- @Slot(str)
- def slot_function(self, s):
- ...
+ @Slot(str)
+ def slot_function(self, s):
+ ...
``Slot()`` also accepts a ``name`` and a ``result`` keyword.
@@ -159,6 +162,19 @@ Python type. The ``name`` keyword behaves the same way as in ``Signal()``. If
nothing is passed as name then the new slot will have the same name as the
function that is being decorated.
+We recommend marking all methods used by signal connections with a
+``@QtCore.Slot()`` decorator. Not doing causes run-time overhead due to the
+method being added to the ``QMetaObject`` when creating the connection. This is
+particularly important for ``QObject`` classes registered with QML, where
+missing decorators can introduce bugs.
+
+Missing decorators can be diagnosed by setting activating warnings of the
+logging category ``qt.pyside.libpyside``; for example by setting the
+environment variable:
+
+.. code-block:: bash
+
+ export QT_LOGGING_RULES="qt.pyside.libpyside.warning=true"
.. _overloading-signals-and-slots:
@@ -172,62 +188,76 @@ In Qt 6, signals have distinct names for different types.
The following example uses two handlers for a Signal and a Slot to showcase
the different functionality.
- .. code-block:: python
+.. code-block:: python
- import sys
- from PySide6.QtWidgets import QApplication, QPushButton
- from PySide6.QtCore import QObject, Signal, Slot
+ import sys
+ from PySide6.QtWidgets import QApplication, QPushButton
+ from PySide6.QtCore import QObject, Signal, Slot
- class Communicate(QObject):
- # create two new signals on the fly: one will handle
- # int type, the other will handle strings
- speak = Signal((int,), (str,))
+ class Communicate(QObject):
+ # create two new signals on the fly: one will handle
+ # int type, the other will handle strings
+ speak = Signal((int,), (str,))
- def __init__(self, parent=None):
- super().__init__(self, parent)
+ def __init__(self, parent=None):
+ super().__init__(parent)
- self.speak[int].connect(self.say_something)
- self.speak[str].connect(self.say_something)
+ self.speak[int].connect(self.say_something)
+ self.speak[str].connect(self.say_something)
- # define a new slot that receives a C 'int' or a 'str'
- # and has 'say_something' as its name
- @Slot(int)
- @Slot(str)
- def say_something(self, arg):
- if isinstance(arg, int):
- print("This is a number:", arg)
- elif isinstance(arg, str):
- print("This is a string:", arg)
+ # define a new slot that receives a C 'int' or a 'str'
+ # and has 'say_something' as its name
+ @Slot(int)
+ @Slot(str)
+ def say_something(self, arg):
+ if isinstance(arg, int):
+ print("This is a number:", arg)
+ elif isinstance(arg, str):
+ print("This is a string:", arg)
+
+ if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ someone = Communicate()
- if __name__ == "__main__":
- app = QApplication(sys.argv)
- someone = Communicate()
+ # emit 'speak' signal with different arguments.
+ # we have to specify the str as int is the default
+ someone.speak.emit(10)
+ someone.speak[str].emit("Hello everybody!")
- # emit 'speak' signal with different arguments.
- # we have to specify the str as int is the default
- someone.speak.emit(10)
- someone.speak[str].emit("Hello everybody!")
+.. _signals-and-slots-strings:
Specifying Signals and Slots by Method Signature Strings
--------------------------------------------------------
Signals and slots can also be specified as C++ method signature
-strings passed through the `SIGNAL()` and/or `SLOT()` functions:
+strings passed through the ``SIGNAL()`` and/or ``SLOT()`` functions:
+
+.. code-block:: python
+
+ from PySide6.QtCore import SIGNAL, SLOT
+
+ button.connect(SIGNAL("clicked(Qt::MouseButton)"),
+ action_handler, SLOT("action1(Qt::MouseButton)"))
+
+This is not normally recommended; it is only needed
+for a few cases where signals are only accessible via ``QMetaObject``
+(``QAxObject``, ``QAxWidget``, ``QDBusInterface`` or ``QWizardPage::registerField()``):
- .. code-block:: python
+.. code-block:: python
- from PySide6.QtCore import SIGNAL, SLOT
+ wizard.registerField("text", line_edit, "text",
+ SIGNAL("textChanged(QString)"))
- button.connect(SIGNAL("clicked(Qt::MouseButton)"),
- action_handler, SLOT("action1(Qt::MouseButton)"))
+The signature strings can be found by querying ``QMetaMethod.methodSignature()``
+when introspecting ``QMetaObject``:
-This is not recommended for connecting signals, it is mostly
-used to specify signals for methods like `QWizardPage::registerField()`:
+.. code-block:: python
- .. code-block:: python
+ mo = widget.metaObject()
+ for m in range(mo.methodOffset(), mo.methodCount()):
+ print(mo.method(m).methodSignature())
- wizard.registerField("text", line_edit, "text",
- SIGNAL("textChanged(QString)"))
+Slots should be decorated using :ref:`@Slot <slot-decorator>`.
diff --git a/sources/pyside6/doc/tutorials/basictutorial/translations.rst b/sources/pyside6/doc/tutorials/basictutorial/translations.rst
index 31cd004a3..21c16cdcd 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/translations.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/translations.rst
@@ -9,10 +9,10 @@ Translating Applications
Qt Linguist
-----------
-`Qt Linguist <https://doc.qt.io/qt-6/qtlinguist-index.html>`_ and
+`Qt Linguist`_ and
its related tools can be used to provide translations for applications.
-The ``examples/widgets/linguist`` example illustrates this. The example is
+The :ref:`qt-linguist-example` example illustrates this. The example is
very simple, it has a menu and shows a list of programming languages with
multiselection.
@@ -28,18 +28,18 @@ The linguist example has a number of messages enclosed in ``self.tr()``.
The status bar message shown in response to a selection change uses
a plural form depending on a count:
- .. code-block:: python
+.. code-block:: python
- count = len(self._list_widget.selectionModel().selectedRows())
- message = self.tr("%n language(s) selected", "", count)
+ count = len(self._list_widget.selectionModel().selectedRows())
+ message = self.tr("%n language(s) selected", "", count)
The translation workflow for the example is as follows:
The translated messages are extracted using the ``lupdate`` tool,
producing XML-based ``.ts`` files:
- .. code-block:: bash
+.. code-block:: bash
- pyside6-lupdate main.py -ts example_de.ts
+ pyside6-lupdate main.py -ts example_de.ts
If ``example_de.ts`` already exists, it will be updated with the new
messages added to the code in-between.
@@ -52,15 +52,29 @@ they should be passed to the ``pyside6-lupdate`` tool as well:
pyside6-lupdate main.py main.qml form.ui -ts example_de.ts
The source files generated by ``pyside6-uic`` from the form files
-should `not` be passed.
+should **not** be passed.
+
+The ``lupdate`` mode of ``pyside6-project`` can also be used for this. It
+collects all source files and runs ``pyside6-lupdate`` when ``.ts`` file(s)
+are given in the ``.pyproject`` file:
+
+.. code-block:: bash
+
+ pyside6-project lupdate .
``.ts`` files are translated using *Qt Linguist*. Once this is complete,
the files are converted to a binary form (``.qm`` files):
- .. code-block:: bash
+.. code-block:: bash
+
+ pyside6-lrelease example_de.ts -qm example_de.qm
+
+``pyside6-project`` will build the ``.qm`` file automatically when
+``.ts`` file(s) are given in the ``.pyproject`` file:
- mkdir translations
- pyside6-lrelease example_de.ts -qm translations/example_de.qm
+.. code-block:: bash
+
+ pyside6-project build .
To avoid having to ship the ``.qm`` files, it is recommend
to put them into a Qt resource file along with icons and other
@@ -68,43 +82,45 @@ applications resources (see :ref:`using_qrc_files`).
The resource file ``linguist.qrc`` provides the ``example_de.qm``
under ``:/translations``:
- .. code-block:: xml
+.. code-block:: xml
- <!DOCTYPE RCC><RCC version="1.0">
- <qresource>
- <file>translations/example_de.qm</file>
- </qresource>
- </RCC>
+ <!DOCTYPE RCC><RCC version="1.0">
+ <qresource prefix="translations">
+ <file>example_de.qm</file>
+ </qresource>
+ </RCC>
At runtime, the translations need to be loaded using the ``QTranslator`` class:
- .. code-block:: python
+.. code-block:: python
- path = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
- translator = QTranslator(app)
- if translator.load(QLocale.system(), 'qtbase', '_', path):
- app.installTranslator(translator)
- translator = QTranslator(app)
- path = ':/translations'
- if translator.load(QLocale.system(), 'example', '_', path):
- app.installTranslator(translator)
+ path = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
+ translator = QTranslator(app)
+ if translator.load(QLocale.system(), 'qtbase', '_', path):
+ app.installTranslator(translator)
+ translator = QTranslator(app)
+ path = ':/translations'
+ if translator.load(QLocale.system(), 'example', '_', path):
+ app.installTranslator(translator)
The code first loads the translations shipped for Qt and then
the translations of the applications loaded from resources.
The example can then be run in German:
- .. code-block:: bash
+.. code-block:: bash
+
+ LANG=de python main.py
- LANG=de python main.py
+.. _Qt Linguist: https://doc.qt.io/qt-6/qtlinguist-index.html
GNU gettext
-----------
-The `GNU gettext <https://docs.python.org/3/library/gettext.html>`_ module
+The `GNU gettext`_ module
can be used to provide translations for applications.
-The ``examples/widgets/gettext`` example illustrates this. The example is
+The :ref:`gettext-example` example illustrates this. The example is
very simple, it has a menu and shows a list of programming languages with
multiselection.
@@ -116,29 +132,29 @@ aliased to ``ngettext``.
Those functions are defined at the top:
- .. code-block:: python
+.. code-block:: python
- import gettext
- ...
- _ = None
- ngettext = None
+ import gettext
+ # ...
+ _ = None
+ ngettext = None
and later assigned as follows:
- .. code-block:: python
-
- src_dir = Path(__file__).resolve().parent
- try:
- translation = gettext.translation('example', localedir=src_dir / 'locales')
- if translation:
- translation.install()
- _ = translation.gettext
- ngettext = translation.ngettext
- except FileNotFoundError:
- pass
- if not _:
- _ = gettext.gettext
- ngettext = gettext.ngettext
+.. code-block:: python
+
+ src_dir = Path(__file__).resolve().parent
+ try:
+ translation = gettext.translation('example', localedir=src_dir / 'locales')
+ if translation:
+ translation.install()
+ _ = translation.gettext
+ ngettext = translation.ngettext
+ except FileNotFoundError:
+ pass
+ if not _:
+ _ = gettext.gettext
+ ngettext = gettext.ngettext
This specifies that our translation file has the base name ``example`` and
will be found in the source tree under ``locales``. The code will try
@@ -146,18 +162,18 @@ to load a translation matching the current language.
Messages to be translated look like:
- .. code-block:: python
+.. code-block:: python
- file_menu = self.menuBar().addMenu(_("&File"))
+ file_menu = self.menuBar().addMenu(_("&File"))
The status bar message shown in response to a selection change uses
a plural form depending on a count:
- .. code-block:: python
+.. code-block:: python
- count = len(self._list_widget.selectionModel().selectedRows())
- message = ngettext("{0} language selected",
- "{0} languages selected", count).format(count)
+ count = len(self._list_widget.selectionModel().selectedRows())
+ message = ngettext("{0} language selected",
+ "{0} languages selected", count).format(count)
The ``ngettext()`` function takes the singular form, plural form and the count.
The returned string still contains the formatting placeholder, so it needs
@@ -172,43 +188,45 @@ is first created:
xgettext -L Python -o locales/example.pot main.py
This file has a few generic placeholders which can be replaced by the
-appropriate values. It is then copied to the ``de_DE/LC_MESSAGES`` directory.
+appropriate values. It is then copied to the ``de_DE/LC_MESSAGES`` directory.
- .. code-block:: bash
+.. code-block:: bash
- cd locales/de_DE/LC_MESSAGES/
- cp ../../example.pot .
+ cd locales/de_DE/LC_MESSAGES/
+ cp ../../example.pot .
Further adaptions need to be made to account for the German plural
form and encoding:
- .. code-block::
+.. code-block::
- "Project-Id-Version: PySide6 gettext example\n"
- "POT-Creation-Date: 2021-07-05 14:16+0200\n"
- "Language: de_DE\n"
- "MIME-Version: 1.0\n"
- "Content-Type: text/plain; charset=UTF-8\n"
- "Content-Transfer-Encoding: 8bit\n"
- "Plural-Forms: nplurals=2; plural=n != 1;\n"
+ "Project-Id-Version: PySide6 gettext example\n"
+ "POT-Creation-Date: 2021-07-05 14:16+0200\n"
+ "Language: de_DE\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: text/plain; charset=UTF-8\n"
+ "Content-Transfer-Encoding: 8bit\n"
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
Below, the translated messages can be given:
- .. code-block::
+.. code-block::
- #: main.py:57
- msgid "&File"
- msgstr "&Datei"
+ #: main.py:57
+ msgid "&File"
+ msgstr "&Datei"
Finally, the ``.pot`` is converted to its binary form (machine object file,
``.mo``), which needs to be deployed:
- .. code-block:: bash
+.. code-block:: bash
- msgfmt -o example.mo example.pot
+ msgfmt -o example.mo example.pot
The example can then be run in German:
- .. code-block:: bash
+.. code-block:: bash
+
+ LANG=de python main.py
- LANG=de python main.py
+.. _GNU gettext: https://docs.python.org/3/library/gettext.html
diff --git a/sources/pyside6/doc/tutorials/basictutorial/treewidget.rst b/sources/pyside6/doc/tutorials/basictutorial/treewidget.rst
index b286de507..f431cb5c4 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/treewidget.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/treewidget.rst
@@ -11,14 +11,14 @@ information in trees. You can also create a data model and display it using a
further on. To know more about the Model/View architecture in Qt, refer to
its `official documentation <https://doc.qt.io/qt-6/model-view-programming.html>`_.
-1. Import ``QTreeWidget`` and ``QTreeWidgetItem`` for this application:
+#. Import ``QTreeWidget`` and ``QTreeWidgetItem`` for this application:
.. code-block:: python
import sys
from PySide6.QtWidgets import QApplication, QTreeWidget, QTreeWidgetItem
-2. Define a dictionary with project structures to display the information as a
+#. Define a dictionary with project structures to display the information as a
tree, with files belonging to each project:
.. code-block:: python
@@ -27,13 +27,13 @@ information in trees. You can also create a data model and display it using a
"Project B": ["file_b.csv", "photo.jpg"],
"Project C": []}
-3. Initialize the ``QApplication`` singleton:
+#. Initialize the ``QApplication`` singleton:
.. code-block:: python
app = QApplication()
-4. Configure the ``QTreeWidget`` to have two columns, one for the item name,
+#. Configure the ``QTreeWidget`` to have two columns, one for the item name,
and the other for item type information of the files in the project
directories.
You can set the column name with the ``setHeaderLabels`` as described below:
@@ -44,7 +44,7 @@ information in trees. You can also create a data model and display it using a
tree.setColumnCount(2)
tree.setHeaderLabels(["Name", "Type"])
-5. Iterate the data structure, create the ``QTreeWidgetItem`` elements, and add
+#. Iterate the data structure, create the ``QTreeWidgetItem`` elements, and add
the corresponding children to each parent.
We also extract the extension name for only the files and add them
into the second column.
@@ -64,7 +64,7 @@ information in trees. You can also create a data model and display it using a
tree.insertTopLevelItems(0, items)
-7. Show the tree and execute the ``QApplication``.
+#. Show the tree and execute the ``QApplication``.
.. code-block:: python
diff --git a/sources/pyside6/doc/tutorials/basictutorial/uifiles.rst b/sources/pyside6/doc/tutorials/basictutorial/uifiles.rst
index cd1057c97..cb945908d 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/uifiles.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/uifiles.rst
@@ -1,27 +1,27 @@
.. _using_ui_files:
-Using `.ui` files from Designer or QtCreator with `QUiLoader` and `pyside6-uic`
-*******************************************************************************
+Using ``.ui`` files from Designer or QtCreator with ``QUiLoader`` and ``pyside6-uic``
+*************************************************************************************
This page describes the use of
-`Qt Designer <https://doc.qt.io/qt-6/qtdesigner-manual.html>`_ to create
+`Qt Widgets Designer <https://doc.qt.io/qt-6/qtdesigner-manual.html>`_ to create
graphical interfaces based on Qt Widgets for your Qt for Python project.
-**Qt Designer** is a graphical UI design tool which is available as a
+*Qt Widgets Designer* is a graphical UI design tool which is available as a
standalone binary (``pyside6-designer``) or embedded into the
-`Qt Creator IDE <https://doc.qt.io/qtcreator>`_. Its use within **Qt Creator**
+`Qt Creator IDE <https://doc.qt.io/qtcreator>`_. Its use within *Qt Creator*
is described at
-`Using Qt Designer <https://doc.qt.io/qtcreator/creator-using-qt-designer.html>`_.
+`Using Qt Widgets Designer <https://doc.qt.io/qtcreator/creator-using-qt-designer.html>`_.
.. image:: uifiles.png
:alt: Designer and the equivalent code
-The designs are stored in `.ui` files, which is an XML-based format. It will
+The designs are stored in ``.ui`` files, which is an XML-based format. It will
be converted to Python or C++ code populating a widget instance at project build
time by the `pyside6-uic <https://doc.qt.io/qt-6/uic.html>`_ tool.
-To create a new Qt Design Form in **Qt Creator**, choose
-`File/New File Or Project` and "Main Window" for template. Save it as
-`mainwindow.ui`. Add a `QPushButton` to the center of the centralwidget.
+To create a new Qt Design Form in *Qt Creator*, choose
+``File/New File Or Project`` and "Main Window" for template. Save it as
+``mainwindow.ui``. Add a ``QPushButton`` to the center of the centralwidget.
Your file ``mainwindow.ui`` should look something like this:
@@ -88,12 +88,12 @@ Option A: Generating a Python class
===================================
The standard way to interact with a **UI file** is to generate a Python
-class from it. This is possible thanks to the `pyside6-uic` tool.
+class from it. This is possible thanks to the ``pyside6-uic`` tool.
To use this tool, you need to run the following command on a console::
- pyside6-uic mainwindow.ui > ui_mainwindow.py
+ pyside6-uic mainwindow.ui -o ui_mainwindow.py
-We redirect all the output of the command to a file called `ui_mainwindow.py`,
+We redirect all the output of the command to a file called ``ui_mainwindow.py``,
which will be imported directly::
from ui_mainwindow import Ui_MainWindow
@@ -136,7 +136,7 @@ file:
.. note::
- You must run `pyside6-uic` again every time you make changes
+ You must run ``pyside6-uic`` again every time you make changes
to the **UI file**.
Option B: Loading it directly
@@ -149,7 +149,7 @@ module:
from PySide6.QtUiTools import QUiLoader
-The `QUiLoader` lets us load the **ui file** dynamically
+The ``QUiLoader`` lets us load the **ui file** dynamically
and use it right away:
.. code-block:: python
@@ -192,40 +192,41 @@ The complete code of this example looks like this:
Then to execute it we just need to run the following on a
command prompt:
-.. code-block:: python
+.. code-block:: bash
python main.py
.. note::
- `QUiLoader` uses connect() calls taking the function signatures as string
+ ``QUiLoader`` uses ``connect()`` calls taking the function signatures as string
arguments for signal/slot connections.
- It is thus unable to handle Python types like `str` or `list` from
+ It is thus unable to handle Python types like ``str`` or ``list`` from
custom widgets written in Python since these types are internally mapped
to different C++ types.
.. _designer_custom_widgets:
-Custom Widgets in Qt Designer
-=============================
+Custom Widgets in Qt Widgets Designer
+=====================================
-**Qt Designer** is able to use user-provided (custom) widgets. They are shown
-in the widget box and can be dragged onto the form just like Qt's widgets (see
-`Using Custom Widgets with Qt Designer <https://doc.qt.io/qt-6/designer-using-custom-widgets.html>`_
-). Normally, this requires implementing the widget as a plugin to Qt Designer
-written in C++ implementing its
-`QDesignerCustomWidgetInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetinterface.html>`_ .
+*Qt Widgets Designer* is able to use user-provided (custom) widgets.
+They are shown in the widget box and can be dragged onto the form just like
+Qt's widgets (see
+`Using Custom Widgets with Qt Widgets Designer <https://doc.qt.io/qt-6/designer-using-custom-widgets.html>`_
+). Normally, this requires implementing the widget as a plugin to
+*Qt Widgets Designer* written in C++ implementing its
+`QDesignerCustomWidgetInterface`_ .
Qt for Python provides a simple interface for this which is similar to
:meth:`registerCustomWidget()<PySide6.QtUiTools.QUiLoader.registerCustomWidget>`.
The widget needs to be provided as a Python module, as shown by
-the widgetbinding example (file ``wigglywidget.py``) or
-the taskmenuextension example (file ``tictactoe.py``).
+the :ref:`widgetbinding-example` (file ``wigglywidget.py``) or
+the :ref:`task-menu-extension-example` (file ``tictactoe.py``).
-Registering this with Qt Designer is done by providing
+Registering this with *Qt Widgets Designer* is done by providing
a registration script named ``register*.py`` and pointing
-the path-type environment variable ``PYSIDE_DESIGNER_PLUGINS``
+the path-type environment variable ``PYSIDE_DESIGNER_PLUGINS``
to the directory.
The code of the registration script looks as follows:
@@ -262,20 +263,20 @@ The code of the registration script looks as follows:
QPyDesignerCustomWidgetCollection provides an implementation of
-`QDesignerCustomWidgetCollectionInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetcollectioninterface.html>`_
-exposing custom widgets to **Qt Designer** with static convenience functions
-for registering types or adding instances of
-`QDesignerCustomWidgetInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetinterface.html>`_ .
+`QDesignerCustomWidgetCollectionInterface`_
+exposing custom widgets to *Qt Widgets Designer* with static convenience
+functions for registering types or adding instances of
+`QDesignerCustomWidgetInterface`_ .
The function
:meth:`registerCustomWidget()<PySide6.QtDesigner.QPyDesignerCustomWidgetCollection.registerCustomWidget>`
-is used to register a widget type with **Qt Designer**. In the simple case, it
-can be used like `QUiLoader.registerCustomWidget()`. It takes the custom widget
+is used to register a widget type with *Qt Widgets Designer*. In the simple case, it
+can be used like ``QUiLoader.registerCustomWidget()``. It takes the custom widget
type and some optional keyword arguments passing values that correspond to the
getters of
-`QDesignerCustomWidgetInterface <https://doc.qt.io/qt-6/qdesignercustomwidgetinterface.html>`_ :
+`QDesignerCustomWidgetInterface`_ :
-When launching **Qt Designer** via its launcher ``pyside6-designer``,
+When launching *Qt Widgets Designer* via its launcher ``pyside6-designer``,
the custom widget should be visible in the widget box.
For advanced usage, it is also possible to pass the function an implementation
@@ -286,15 +287,18 @@ is registered for the custom widget. The example is a port of the
corresponding C++
`Task Menu Extension Example <https://doc.qt.io/qt-6/qtdesigner-taskmenuextension-example.html>`_ .
-Troubleshooting the Qt Designer Plugin
-++++++++++++++++++++++++++++++++++++++
+.. _QDesignerCustomWidgetCollectionInterface: https://doc.qt.io/qt-6/qdesignercustomwidgetcollectioninterface.html
+.. _QDesignerCustomWidgetInterface: https://doc.qt.io/qt-6/qdesignercustomwidgetinterface.html
+
+Troubleshooting the Qt Widgets Designer Plugin
+++++++++++++++++++++++++++++++++++++++++++++++
- The launcher ``pyside6-designer`` must be used. The standalone
- **Qt Designer** will not load the plugin.
+ *Qt Widgets Designer* will not load the plugin.
- The menu item **Help/About Plugin** brings up a dialog showing the plugins
found and potential load error messages.
- Check the console or Windows Debug view for further error messages.
- Due to the buffering of output by Python, error messages may appear
- only after **Qt Designer** has terminated.
+ only after *Qt Widgets Designer* has terminated.
- When building Qt for Python, be sure to set the ``--standalone`` option
for the plugin to be properly installed.
diff --git a/sources/pyside6/doc/tutorials/basictutorial/widgetstyling.rst b/sources/pyside6/doc/tutorials/basictutorial/widgetstyling.rst
index e1af8b8a9..2fa51c0a8 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/widgetstyling.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/widgetstyling.rst
@@ -23,7 +23,7 @@ to each component. As an example, look at the following simple snippet:
w.show()
sys.exit(app.exec())
-When you execute this code, you will see a simple `QLabel` aligned at the
+When you execute this code, you will see a simple ``QLabel`` aligned at the
center, and with a placeholder text.
.. image:: widgetstyling-simple-no.png
@@ -32,8 +32,8 @@ center, and with a placeholder text.
You can style your application using the CSS-like syntax.
For more information, see `Qt Style Sheets Reference`_.
-A `QLabel` can be styled differently by setting some of its CSS
-properties, such as `background-color` and `font-family`,
+A ``QLabel`` can be styled differently by setting some of its CSS
+properties, such as ``background-color`` and ``font-family``,
so let's see how does the code look like with these changes:
.. code-block:: python
@@ -55,7 +55,7 @@ so let's see how does the code look like with these changes:
w.show()
sys.exit(app.exec())
-Now when you run the code, notice that the `QLabel` looks different with your
+Now when you run the code, notice that the ``QLabel`` looks different with your
custom style:
.. image:: widgetstyling-simple-yes.png
@@ -64,15 +64,15 @@ custom style:
.. note::
- If you don't have the font `Titillium` installed, you can try with any
+ If you don't have the font ``Titillium`` installed, you can try with any
other you prefer.
- Remember you can list your installed fonts using `QFontDatabase`,
- specifically the `families()` method.
+ Remember you can list your installed fonts using ``QFontDatabase``,
+ specifically the ``families()`` method.
Styling each UI element separately like you did in the previous snippet is a
lot of work. The easier alternative for this is to use Qt Style Sheets,
-which is one or more `.qss` files defining the style for the UI elements in
+which is one or more ``.qss`` files defining the style for the UI elements in
your application.
More examples can be found in the `Qt Style Sheet Examples`_ documentation
@@ -94,7 +94,7 @@ Qt Style Sheets
It's recommended to create a full new Qt style to cover all the possible
corner cases.
-A `qss` file is quite similar to a CSS file, but you need to specify the Widget
+A ``qss`` file is quite similar to a CSS file, but you need to specify the Widget
component and optionally the name of the object::
QLabel {
@@ -105,8 +105,8 @@ component and optionally the name of the object::
font-size: 20px;
}
-The first style defines a `background-color` for all `QLabel` objects in your
-application, whereas the later one styles the `title` object only.
+The first style defines a ``background-color`` for all ``QLabel`` objects in your
+application, whereas the later one styles the ``title`` object only.
.. note::
@@ -115,8 +115,8 @@ application, whereas the later one styles the `title` object only.
`label.setObjectName("title")`
-Once you have a `qss` file for your application, you can apply it by reading
-the file and using the `QApplication.setStyleSheet(str)` function:
+Once you have a ``qss`` file for your application, you can apply it by reading
+the file and using the ``QApplication.setStyleSheet(str)`` function:
.. code-block:: python
@@ -132,7 +132,7 @@ the file and using the `QApplication.setStyleSheet(str)` function:
sys.exit(app.exec())
-Having a general `qss` file allows you to decouple the styling aspects of
+Having a general ``qss`` file allows you to decouple the styling aspects of
the code, without mixing it in the middle of the general functionality, and you
can simply enable it or disable it.
@@ -142,14 +142,14 @@ Look at this new example, with more widgets components:
:linenos:
:lines: 22-44
-This displays a two column widget, with a `QListWidget` on the left and a
-`QLabel` and a `QPushButton` on the right. It looks like this when you run the
+This displays a two column widget, with a ``QListWidget`` on the left and a
+``QLabel`` and a ``QPushButton`` on the right. It looks like this when you run the
code:
.. image:: widgetstyling-no.png
:alt: Widget with no style
-If you add content to the previously described `style.qss` file, you can modify
+If you add content to the previously described ``style.qss`` file, you can modify
the look-n-feel of the previous example:
.. literalinclude:: style.qss
@@ -161,7 +161,7 @@ You can also use state-based styling on the QListWidget *items* for example, to
style them differently depending on whether they are *selected* or not.
After applying all the styling alternatives you explored in this topic, notice
-that the `QLabel` example looks a lot different now.
+that the ``QLabel`` example looks a lot different now.
Try running the code to check its new look:
.. image:: widgetstyling-yes.png
diff --git a/sources/pyside6/doc/tutorials/datavisualize/index.rst b/sources/pyside6/doc/tutorials/datavisualize/index.rst
index 44226e779..35b56706a 100644
--- a/sources/pyside6/doc/tutorials/datavisualize/index.rst
+++ b/sources/pyside6/doc/tutorials/datavisualize/index.rst
@@ -26,5 +26,6 @@ visualize data from a CSV in a line chart.
add_chart*
plot*
-You can download the sources from :download:`here <datavisualize.tar.bz2>`.
+You can download the sources from `here`_.
+.. _here: https://code.qt.io/cgit/pyside/pyside-setup.git/tree/sources/pyside6/doc/tutorials/datavisualize
diff --git a/sources/pyside6/doc/tutorials/debugging/mixed_debugging.rst b/sources/pyside6/doc/tutorials/debugging/mixed_debugging.rst
index 82b34d919..85c326347 100644
--- a/sources/pyside6/doc/tutorials/debugging/mixed_debugging.rst
+++ b/sources/pyside6/doc/tutorials/debugging/mixed_debugging.rst
@@ -5,10 +5,10 @@ When debugging PySide code, very often you would also like to debug the
corresponding C++ extension of the PySide module. This is done by attaching your
debugger to the Python interpreter. In this tutorial, we are going to take you
through a comprehensive guide in building Qt 6, using the built Qt 6 to build
-PySide6, and then starting a debugging process in either Qt Creator or VSCode.
+PySide6, and then starting a debugging process in either *Qt Creator* or VSCode.
With VSCode, you should be able to see the combined call stacks for both C++ and
-Python together. With Qt Creator, unfortunately you would only be able to
+Python together. With *Qt Creator*, unfortunately you would only be able to
debug the native C++ code of the PySide module; that is you won't be able to set
breakpoints inside the Python code.
@@ -74,7 +74,7 @@ Find the build system information `Qt 6 Build System
.. code-block:: bash
- cmake -GNinja -DMCAKE_BUILD_TYPE=Debug \
+ cmake -GNinja -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_INSTALL_PREFIX=/path/to/install/Qt -DBUILD_qtwebengine=OFF ..
cmake --build . --parallel
cmake --install .
@@ -101,7 +101,7 @@ Build PySide6 using the Qt 6 that you built earlier
----------------------------------------------------
Follow the steps mentioned `Getting Started - Qt for Python
-<https://doc.qt.io/qtforpython/gettingstarted.html>`_
+<https://doc.qt.io/qtforpython/gettingstarted/index.html>`_
You may manually select the modules to install using the ``--module-subset`` cli
argument for `setup.py`. This was my installation script
@@ -116,7 +116,7 @@ It is recommended to use a Python virtual environment rather than installing in
Debugging the process using your preferred IDE
----------------------------------------------
-The following sections guide you through the setup for Qt Creator or VSCode.
+The following sections guide you through the setup for *Qt Creator* or VSCode.
.. toctree::
:glob:
diff --git a/sources/pyside6/doc/tutorials/debugging/qml_debugging.rst b/sources/pyside6/doc/tutorials/debugging/qml_debugging.rst
new file mode 100644
index 000000000..223e608fc
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/debugging/qml_debugging.rst
@@ -0,0 +1,32 @@
+Using Qt Creator's QML Debugger for a PySide6 QML Application
+*************************************************************
+
+Besides the C++ debugger, *Qt Creator* provides a `QML debugger`_ which lets you
+inspect JavaScript code. It works by connecting to a socket server run by the
+``QmlEngine`` instance. The port is passed on the command line. To enable it,
+add the below code to your QML application:
+
+.. code-block:: python
+
+ from argparse import ArgumentParser, RawTextHelpFormatter
+
+ ...
+
+ if __name__ == "__main__":
+ argument_parser = ArgumentParser(...)
+ argument_parser.add_argument("-qmljsdebugger", action="store",
+ help="Enable QML debugging")
+ options = argument_parser.parse_args()
+ if options.qmljsdebugger:
+ QQmlDebuggingEnabler.enableDebugging(True)
+ app = QApplication(sys.argv)
+
+
+For instructions on how to use the QML debugger, see
+`Debugging a Qt Quick Example Application`_.
+
+.. note:: The code should be removed or disabled when shipping the application
+ as it poses a security risk.
+
+.. _`QML debugger`: https://doc.qt.io/qtcreator/creator-debugging-qml.html
+.. _`Debugging a Qt Quick Example Application`: https://doc.qt.io/qtcreator/creator-qml-debugging-example.html
diff --git a/sources/pyside6/doc/tutorials/debugging/qtcreator/qtcreator.rst b/sources/pyside6/doc/tutorials/debugging/qtcreator/qtcreator.rst
index c8c9fb8ae..a78a67fad 100644
--- a/sources/pyside6/doc/tutorials/debugging/qtcreator/qtcreator.rst
+++ b/sources/pyside6/doc/tutorials/debugging/qtcreator/qtcreator.rst
@@ -1,9 +1,9 @@
Debugging PySide with Qt Creator (Linux)
****************************************
-As opposed to VSCode, presently Qt Creator does not support mixed mode debugging.
+As opposed to VSCode, presently *Qt Creator* does not support mixed mode debugging.
However, we can debug the C++ implementation of the corresponding Python PySide
-code. Unlike VSCode, Qt Creator provides a very easy interface to attach GDB to
+code. Unlike VSCode, *Qt Creator* provides a very easy interface to attach GDB to
the Python interpreter. It saves you from doing all the extra configuration
steps, that have to be done with VSCode.
@@ -14,26 +14,26 @@ Here are the steps:
2. Go to Projects -> Run -> Run Configuration -> Add. This is going to open a
new window shown below.
- .. image:: custom_executable_create.png
- :alt: creation of custom executable
- :align: center
+ .. image:: custom_executable_create.png
+ :alt: creation of custom executable
+ :align: center
3. Click on Custom Executable and `Create` a new configuration. Feed in the
-details like shown below.
+ details like shown below.
- .. image:: custom_executable_run_config.png
- :alt: run configuration of custom executable
- :align: center
+ .. image:: custom_executable_run_config.png
+ :alt: run configuration of custom executable
+ :align: center
4. Debug -> Start Debugging -> Start Debugging Without Deployment.
- .. image:: start_debugging_without_deployment.png
- :alt: start debugging without deployment
- :align: center
+ .. image:: start_debugging_without_deployment.png
+ :alt: start debugging without deployment
+ :align: center
You will now hit you breakpoint and can start debugging your code.
- .. image:: breakpoint_cpp.png
- :alt: breakpoint cpp
- :align: center
+.. image:: breakpoint_cpp.png
+ :alt: breakpoint cpp
+ :align: center
diff --git a/sources/pyside6/doc/tutorials/debugging/vscode/python_set_interpreter.png b/sources/pyside6/doc/tutorials/debugging/vscode/python_set_interpreter.png
new file mode 100644
index 000000000..1a26c9d9c
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/debugging/vscode/python_set_interpreter.png
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/debugging/vscode/vscode.rst b/sources/pyside6/doc/tutorials/debugging/vscode/vscode.rst
index 2563b4377..b2a527b0e 100644
--- a/sources/pyside6/doc/tutorials/debugging/vscode/vscode.rst
+++ b/sources/pyside6/doc/tutorials/debugging/vscode/vscode.rst
@@ -1,20 +1,42 @@
-Debugging PySide with VSCode (Linux)
-************************************
+Debugging PySide with VSCode (Linux + Windows)
+**********************************************
VSCode enables you to use more than one debugger in a single debugging session.
-This means that we can use GDB and Python PDB in a single session. With VSCode
-you would be able to do the following:
+This means that we can use Python PDB and GDB (or the MSVC debugger for Windows)
+in a single session. With VSCode you would be able to do the following:
* See the call stacks for both Python and C++ together.
* Put breakpoints in both the Python and the C++ code.
* Step from Python to C++ code and vice versa.
+For Windows, see :ref:`creating_windows_debug_builds`.
+
Let's get started with setting up everything and debugging a Python process.
+Setting the Python interpreter
+------------------------------
+
+In order to debug Python code, it is necessary to set the correct Python
+interpreter in VSCode - this will ensure that all Python integrations of VSCode
+use the same interpreter. However, this does not affect C++ debugging, and the
+Python executable path must be set for the corresponding launch target
+separately (see the section below).
+
+To set the Python interpreter, open a Python file and click the corresponding
+option on the right side of the VSCode status bar, which should look similar to
+this:
+
+.. image:: python_set_interpreter.png
+ :alt: set Python interpreter
+ :align: center
+
+Alternatively, open the VSCode command palette (F1 or Ctrl + Shift + P) and
+search for "Python: Select Interpreter".
+
Creating Configurations in launch.json
--------------------------------------
-Run -> Add Configuration -> Python -> Python File
+``Run -> Add Configuration -> Python -> Python File``
This should create a launch.json file which looks like this:
@@ -36,13 +58,22 @@ This should create a launch.json file which looks like this:
]
}
-It should already consist of a configuration named "Python: Current File", which
-allows us to debug the current open Python file. With a Python virtual
-environment, make sure to change the value of "program" to refer to the path of the Python
-interpreter inside the virtual environment.
+It should already consist of a configuration named "Python: Current File",
+which allows us to debug the current open Python file.
+
+Now, we need to add a configuration to attach the C++ debugger to the Python
+process that is already running in debug mode. If you have the C/C++ extension
+installed and the appropriate debugger for your system, VSCode should be able
+to automatically offer to add a configuration. On Linux, this is suggested with
+the name
+
+* "C/C++: (gdb) Attach"
+
+and on Windows with the name
+
+* "C/C++: (Windows) Attach"
-Now, we need to add a configuration to attach the GDB debugger to the Python
-process that is already running in debug mode. Let's call it "(gdb) Attach"
+Your launch.json should now look like this on Linux:
.. code-block:: javascript
@@ -58,7 +89,8 @@ process that is already running in debug mode. Let's call it "(gdb) Attach"
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
- }, {
+ },
+ {
"name": "(gdb) Attach",
"type": "cppdbg",
"request": "attach",
@@ -75,8 +107,35 @@ process that is already running in debug mode. Let's call it "(gdb) Attach"
]
}
-Here also make sure that the value of "program" refers to your Python interpreter. We need the
-processId to attach the gdb debugger to the process. With
+And like this on Windows:
+
+.. code-block:: javascript
+
+ {
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Python: Current File",
+ "type": "python",
+ "request": "launch",
+ "program": "${file}",
+ "console": "integratedTerminal"
+ },
+ {
+ "name": "(Windows) Attach",
+ "type": "cppvsdbg",
+ "request": "attach",
+ "processId": "${command:pickProcess}",
+ }
+ ]
+ }
+
+For Linux, also make sure that the value of "program" refers to your Python
+interpreter inside your virtual environment (for Windows this is not needed).
+We need the processId to attach the gdb debugger to the process. With
"${command:pickProcess}", we find the processId on the go, as we will see later.
Now, we are ready to debug.
@@ -86,51 +145,48 @@ Debug The Process
1. Set a breakpoint in the Python code.
-2. Go to `Run And Debug` (Ctrl + Shift + D) and run the "python: Current File"
- by clicking the run symbol (green right-arrow). This will hit the breakpoint and
- will halt the Python debugger.
+2. Go to ``Run And Debug`` (Ctrl + Shift + D) and run the "Python: Current File"
+ by clicking the run symbol (green right-arrow). This will hit the breakpoint
+ and will halt the Python debugger.
-3. Using the drop-down menu change from "python:
- Current File" to "(gdb) Attach". Your setup should now look like this.
+3. Using the drop-down menu change from "Python:
+ Current File" to "(gdb) Attach" or "(Windows) Attach". Your setup should now
+ look like this.
- .. image:: breakpoint_gdb.png
- :alt: breakpoint before attach gdb
- :align: center
+ .. image:: breakpoint_gdb.png
+ :alt: breakpoint before attach gdb
+ :align: center
-4. Run "(gdb) Attach" and this should ask you for the processId of the Python
- process to which you want to attach gdb. VSCode also lets you to search for the
- process by its name. .. tip:: You can find the processId by running `ps aux |
- grep python`
+4. Run "(gdb) Attach" or "(Windows) Attach" and this should ask you for the
+ processId of the Python process to which you want to attach the C++ debugger.
+ VSCode also lets you search for the process by its name.
- .. image:: find_process_gdb.png
- :alt: find process vscode
- :align: center
+ .. tip:: You can find the processId by running ``ps aux | grep python``
-5. VSCode will now ask you for superuser permissions. Type 'y' and enter your
- password.
+ .. image:: find_process_gdb.png
+ :alt: find process vscode
+ :align: center
- .. code-block:: bash
+5. VSCode might now ask you for superuser permissions. In that case, type 'y'
+ and enter your password.
- Superuser access is required to attach to a process. Attaching as
- superuser can potentially harm your computer. Do you want to continue?
- [y/N]_
+ .. code-block:: bash
+
+ Superuser access is required to attach to a process. Attaching as
+ superuser can potentially harm your computer. Do you want to continue?
+ [y/N]_
6. That is it. You should now be able to hit the breakpoints that you have set
on the C++ counterparts.
- .. figure:: audioformat_wrapper.png
- :alt: Breakpoint set on the shiboken wrapper class
- :align: left
-
- Breakpoint set on the shiboken wrapper class
-
- .. figure:: audioformat_cpp.png
- :alt: Breakpoint set on C++ implementation
- :align: left
-
- Breakpoint set on C++ implementation
-
-
+ .. figure:: audioformat_wrapper.png
+ :alt: Breakpoint set on the shiboken wrapper class
+ :align: left
+ Breakpoint set on the shiboken wrapper class
+ .. figure:: audioformat_cpp.png
+ :alt: Breakpoint set on C++ implementation
+ :align: left
+ Breakpoint set on C++ implementation
diff --git a/sources/pyside6/doc/tutorials/expenses/expenses.rst b/sources/pyside6/doc/tutorials/expenses/expenses.rst
index c8ae5c034..2064488ae 100644
--- a/sources/pyside6/doc/tutorials/expenses/expenses.rst
+++ b/sources/pyside6/doc/tutorials/expenses/expenses.rst
@@ -20,9 +20,9 @@ The requirements:
(`QPushButton <https://doc.qt.io/qtforpython/PySide6/QtWidgets/QPushButton.html>`_).
* A verification step to avoid invalid data entry.
* A chart to visualize the expense data
- (`QChart <https://doc.qt.io/qtforpython/PySide6/QtCharts/QtCharts.QChart.html>`_) that will
+ (`QChart <https://doc.qt.io/qtforpython/PySide6/QtCharts/QChart.html>`_) that will
be embedded in a chart view
- (`QChartView <https://doc.qt.io/qtforpython/PySide6/QtCharts/QtCharts.QChartView.html>`_).
+ (`QChartView <https://doc.qt.io/qtforpython/PySide6/QtCharts/QChartView.html>`_).
Empty window
------------
@@ -33,10 +33,10 @@ code block.
.. code-block:: python
:linenos:
- if __name__ == "__main__":
- app = QApplication([])
- # ...
- sys.exit(app.exec())
+ if __name__ == "__main__":
+ app = QApplication([])
+ # ...
+ sys.exit(app.exec())
Now, to start the development, create an empty window called `MainWindow`.
You could do that by defining a class that inherits from `QMainWindow`.
@@ -56,45 +56,18 @@ Now that our class is defined, create an instance of it and call `show()`.
Menu bar
--------
-Using a `QMainWindow` gives some features for free, among them a *menu bar*. To use it, you need
+Using a `QMainWindow` gives some features for free, among them a *menu bar*. To use it, you need
to call the method `menuBar()` and populate it inside the `MainWindow` class.
.. literalinclude:: steps/02-expenses.py
:linenos:
- :lines: 9-21
- :emphasize-lines: 6
+ :lines: 9-19
+ :emphasize-lines: 10
Notice that the code snippet adds a *File* menu with the *Exit* option only.
-First signal/slot connection
-----------------------------
-
-The *Exit* option must be connected to a slot that triggers the application to exit. The main
-idea to achieve this, is the following:
-
-.. code-block:: python
-
- element.signal_name.connect(slot_name)
-
-All the interface's elements could be connected through signals to certain slots,
-in the case of a `QAction`, the signal `triggered` can be used:
-
-.. code-block:: python
-
- exit_action.triggered.connect(slot_name)
-
-.. note:: Now a *slot* needs to be defined to exit the application, which can be done using
- `QApplication.quit()`. If we put all these concepts together you will end up with the
- following code:
-
-.. literalinclude:: steps/03-expenses.py
- :linenos:
- :lines: 19-28
- :emphasize-lines: 4, 8-10
-
-Notice that the decorator `@Slot()` is required for each slot you declare to properly
-register them. Slots are normal functions, but the main difference is that they
-will be invokable from `Signals` of QObjects when connected.
+The *Exit* option must be connected to a slot that triggers the application to exit. We pass
+``QWidget.close()`` here. After the last window has been closed, the application exits.
Empty widget and data
---------------------
@@ -107,13 +80,13 @@ Additionally, you will define example data to visualize later.
.. literalinclude:: steps/04-expenses.py
:linenos:
- :lines: 9-16
+ :lines: 8-15
With the `Widget` class in place, modify `MainWindow`'s initialization code
.. literalinclude:: steps/04-expenses.py
:linenos:
- :lines: 43-47
+ :lines: 37-40
Window layout
-------------
@@ -121,7 +94,7 @@ Window layout
Now that the main empty window is in place, you need to start adding widgets to achieve the main
goal of creating an expenses application.
-After declaring the example data, you can visualize it on a simple `QTableWidget`. To do so, you
+After declaring the example data, you can visualize it on a simple `QTableWidget`. To do so, you
will add this procedure to the `Widget` constructor.
.. warning:: Only for the example purpose a QTableWidget will be used,
@@ -130,7 +103,7 @@ will add this procedure to the `Widget` constructor.
.. literalinclude:: steps/05-expenses.py
:linenos:
- :lines: 11-36
+ :lines: 11-31
As you can see, the code also includes a `QHBoxLayout` that provides the container to place widgets
horizontally.
@@ -143,7 +116,7 @@ displayed below.
.. literalinclude:: steps/05-expenses.py
:linenos:
- :lines: 38-44
+ :lines: 33-39
Having this process on a separate method is a good practice to leave the constructor more readable,
and to split the main functions of the class in independent processes.
@@ -156,8 +129,8 @@ Because the data that is being used is just an example, you are required to incl
input items to the table, and extra buttons to clear the table's content, and also quit the
application.
-To distribute these input lines and buttons, you will use a `QVBoxLayout` that allows you to place
-elements vertically inside a layout.
+For input lines along with descriptive labels, you will use a `QFormLayout`. Then,
+you will nest the form layout into a `QVBoxLayout` along with the buttons.
.. literalinclude:: steps/06-expenses.py
:linenos:
@@ -169,7 +142,7 @@ example:
.. literalinclude:: steps/06-expenses.py
:linenos:
- :lines: 5-10
+ :lines: 45-48
The next step will be connecting those new buttons to slots.
@@ -183,17 +156,19 @@ documentation <https://doc.qt.io/qtforpython/PySide6/QtWidgets/QAbstractButton.h
.. literalinclude:: steps/07-expenses.py
:linenos:
- :lines: 55-58
+ :lines: 50-52
As you can see on the previous lines, we are connecting each *clicked* signal to different slots.
In this example slots are normal class methods in charge of perform a determined task associated
-with our buttons. It is really important to decorate each method declaration with a `@Slot()`, in
-that way PySide6 knows internally how to register them into Qt.
+with our buttons. It is really important to decorate each method declaration with a `@Slot()`,
+that way, PySide6 knows internally how to register them into Qt and they
+will be invokable from `Signals` of QObjects when connected.
+
.. literalinclude:: steps/07-expenses.py
:linenos:
- :lines: 63-92
- :emphasize-lines: 2,16,28
+ :lines: 57-82
+ :emphasize-lines: 1, 23
Since these slots are methods, we can access the class variables, like our `QTableWidget` to
interact with it.
@@ -216,24 +191,21 @@ Verification step
Adding information to the table needs to be a critical action that require a verification step
to avoid adding invalid information, for example, empty information.
-You can use a signal from `QLineEdit` called *textChanged[str]* which will be emitted every
+You can use a signal from `QLineEdit` called *textChanged* which will be emitted every
time something inside changes, i.e.: each key stroke.
-Notice that this time, there is a *[str]* section on the signal, this means that the signal
-will also emit the value of the text that was changed, which will be really useful to verify
-the current content of the `QLineEdit`.
You can connect two different object's signal to the same slot, and this will be the case
for your current application:
.. literalinclude:: steps/08-expenses.py
:linenos:
- :lines: 62-63
+ :lines: 57-58
The content of the *check_disable* slot will be really simple:
.. literalinclude:: steps/08-expenses.py
:linenos:
- :lines: 82-87
+ :lines: 77-80
You have two options, write a verification based on the current value
of the string you retrieve, or manually get the whole content of both
@@ -255,15 +227,15 @@ side of your application.
.. literalinclude:: steps/09-expenses.py
:linenos:
- :lines: 29-31
+ :lines: 30-32
Additionally the order of how you include widgets to the right
`QVBoxLayout` will also change.
.. literalinclude:: steps/09-expenses.py
:linenos:
- :lines: 44-54
- :emphasize-lines: 9
+ :lines: 46-54
+ :emphasize-lines: 8
Notice that before we had a line with `self.right.addStretch()`
to fill up the vertical space between the *Add* and the *Clear* buttons,
@@ -279,8 +251,8 @@ to a slot that creates a chart and includes it into your `QChartView`.
.. literalinclude:: steps/10-expenses.py
:linenos:
- :lines: 66-72
- :emphasize-lines: 6
+ :lines: 62-67
+ :emphasize-lines: 3
That is nothing new, since you already did it for the other buttons,
but now take a look at how to create a chart and include it into
@@ -288,7 +260,7 @@ your `QChartView`.
.. literalinclude:: steps/10-expenses.py
:linenos:
- :lines: 102-114
+ :lines: 95-107
The following steps show how to fill a `QPieSeries`:
diff --git a/sources/pyside6/doc/tutorials/expenses/main.py b/sources/pyside6/doc/tutorials/expenses/main.py
index 3c22eff34..a3a998470 100644
--- a/sources/pyside6/doc/tutorials/expenses/main.py
+++ b/sources/pyside6/doc/tutorials/expenses/main.py
@@ -3,16 +3,17 @@
import sys
from PySide6.QtCore import Qt, Slot
-from PySide6.QtGui import QAction, QPainter
-from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
- QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import (QApplication, QFormLayout, QHeaderView,
+ QHBoxLayout, QLineEdit, QMainWindow,
+ QPushButton, QTableWidget, QTableWidgetItem,
QVBoxLayout, QWidget)
from PySide6.QtCharts import QChartView, QPieSeries, QChart
class Widget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
self.items = 0
# Example data
@@ -32,43 +33,38 @@ class Widget(QWidget):
# Right
self.description = QLineEdit()
+ self.description.setClearButtonEnabled(True)
self.price = QLineEdit()
+ self.price.setClearButtonEnabled(True)
+
self.add = QPushButton("Add")
self.clear = QPushButton("Clear")
- self.quit = QPushButton("Quit")
self.plot = QPushButton("Plot")
# Disabling 'Add' button
self.add.setEnabled(False)
+ form_layout = QFormLayout()
+ form_layout.addRow("Description", self.description)
+ form_layout.addRow("Price", self.price)
self.right = QVBoxLayout()
- self.right.addWidget(QLabel("Description"))
- self.right.addWidget(self.description)
- self.right.addWidget(QLabel("Price"))
- self.right.addWidget(self.price)
+ self.right.addLayout(form_layout)
self.right.addWidget(self.add)
self.right.addWidget(self.plot)
self.right.addWidget(self.chart_view)
self.right.addWidget(self.clear)
- self.right.addWidget(self.quit)
# QWidget Layout
- self.layout = QHBoxLayout()
-
- #self.table_view.setSizePolicy(size)
+ self.layout = QHBoxLayout(self)
self.layout.addWidget(self.table)
self.layout.addLayout(self.right)
- # Set the layout to the QWidget
- self.setLayout(self.layout)
-
# Signals and Slots
self.add.clicked.connect(self.add_element)
- self.quit.clicked.connect(self.quit_application)
self.plot.clicked.connect(self.plot_data)
self.clear.clicked.connect(self.clear_table)
- self.description.textChanged[str].connect(self.check_disable)
- self.price.textChanged[str].connect(self.check_disable)
+ self.description.textChanged.connect(self.check_disable)
+ self.price.textChanged.connect(self.check_disable)
# Fill example data
self.fill_table()
@@ -76,32 +72,25 @@ class Widget(QWidget):
@Slot()
def add_element(self):
des = self.description.text()
- price = self.price.text()
-
- try:
- price_item = QTableWidgetItem(f"{float(price):.2f}")
- price_item.setTextAlignment(Qt.AlignRight)
-
- self.table.insertRow(self.items)
- description_item = QTableWidgetItem(des)
+ price = float(self.price.text())
- self.table.setItem(self.items, 0, description_item)
- self.table.setItem(self.items, 1, price_item)
+ self.table.insertRow(self.items)
+ description_item = QTableWidgetItem(des)
+ price_item = QTableWidgetItem(f"{price:.2f}")
+ price_item.setTextAlignment(Qt.AlignRight)
- self.description.setText("")
- self.price.setText("")
+ self.table.setItem(self.items, 0, description_item)
+ self.table.setItem(self.items, 1, price_item)
- self.items += 1
- except ValueError:
- print("Wrong price", price)
+ self.description.clear()
+ self.price.clear()
+ self.items += 1
@Slot()
def check_disable(self, s):
- if not self.description.text() or not self.price.text():
- self.add.setEnabled(False)
- else:
- self.add.setEnabled(True)
+ enabled = bool(self.description.text() and self.price.text())
+ self.add.setEnabled(enabled)
@Slot()
def plot_data(self):
@@ -117,10 +106,6 @@ class Widget(QWidget):
chart.legend().setAlignment(Qt.AlignLeft)
self.chart_view.setChart(chart)
- @Slot()
- def quit_application(self):
- QApplication.quit()
-
def fill_table(self, data=None):
data = self._data if not data else data
for desc, price in data.items():
@@ -140,7 +125,7 @@ class Widget(QWidget):
class MainWindow(QMainWindow):
def __init__(self, widget):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -148,17 +133,11 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
- self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/expenses/main_snake_prop.py b/sources/pyside6/doc/tutorials/expenses/main_snake_prop.py
index 3f8f6f061..055544409 100644
--- a/sources/pyside6/doc/tutorials/expenses/main_snake_prop.py
+++ b/sources/pyside6/doc/tutorials/expenses/main_snake_prop.py
@@ -61,7 +61,7 @@ class Widget(QWidget):
#self.table_view.setSizePolicy(size)
self.layout.add_widget(self.table)
- self.layout.add_layout(self.right)
+ self.layout.form_layout(self.right)
# Set the layout to the QWidget
self.set_layout(self.layout)
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/01-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/01-expenses.py
index 0db8c60e7..27f2aef65 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/01-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/01-expenses.py
@@ -7,7 +7,7 @@ from PySide6.QtWidgets import QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
if __name__ == "__main__":
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/02-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/02-expenses.py
index 142aff4c8..039b818df 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/02-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/02-expenses.py
@@ -2,13 +2,12 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import sys
-from PySide6.QtGui import QAction
from PySide6.QtWidgets import QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -16,11 +15,9 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- self.file_menu.addAction(exit_action)
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/03-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/03-expenses.py
index 7fd6f5014..039b818df 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/03-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/03-expenses.py
@@ -2,14 +2,12 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import sys
-from PySide6.QtCore import Slot
-from PySide6.QtGui import QAction
from PySide6.QtWidgets import QApplication, QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -17,15 +15,8 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
-
- self.file_menu.addAction(exit_action)
-
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
if __name__ == "__main__":
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/04-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/04-expenses.py
index f907d31cf..6723690a8 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/04-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/04-expenses.py
@@ -2,14 +2,12 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import sys
-from PySide6.QtCore import Slot
-from PySide6.QtGui import QAction
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget
class Widget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
# Example data
self._data = {"Water": 24.5, "Electricity": 55.1, "Rent": 850.0,
@@ -19,7 +17,7 @@ class Widget(QWidget):
class MainWindow(QMainWindow):
def __init__(self, widget):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -27,17 +25,11 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
- self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/05-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/05-expenses.py
index 753bc89d5..df0362fde 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/05-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/05-expenses.py
@@ -2,15 +2,14 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import sys
-from PySide6.QtCore import Slot
-from PySide6.QtGui import QAction
-from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QMainWindow,
- QTableWidget, QTableWidgetItem, QWidget)
+from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout,
+ QMainWindow, QTableWidget, QTableWidgetItem,
+ QWidget)
class Widget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
self.items = 0
# Example data
@@ -25,14 +24,9 @@ class Widget(QWidget):
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# QWidget Layout
- self.layout = QHBoxLayout()
-
- #self.table_view.setSizePolicy(size)
+ self.layout = QHBoxLayout(self)
self.layout.addWidget(self.table)
- # Set the layout to the QWidget
- self.setLayout(self.layout)
-
# Fill example data
self.fill_table()
@@ -47,7 +41,7 @@ class Widget(QWidget):
class MainWindow(QMainWindow):
def __init__(self, widget):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -55,17 +49,11 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
- self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/06-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/06-expenses.py
index e9abf6a28..d19a6220f 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/06-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/06-expenses.py
@@ -2,16 +2,15 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import sys
-from PySide6.QtCore import Slot
-from PySide6.QtGui import QAction
-from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
- QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
- QVBoxLayout, QWidget)
+from PySide6.QtWidgets import (QApplication, QFormLayout, QHeaderView,
+ QHBoxLayout, QLineEdit, QMainWindow, QPushButton,
+ QTableWidget, QTableWidgetItem, QVBoxLayout,
+ QWidget)
class Widget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
self.items = 0
# Example data
@@ -27,31 +26,27 @@ class Widget(QWidget):
# Right
self.description = QLineEdit()
+ self.description.setClearButtonEnabled(True)
self.price = QLineEdit()
+ self.price.setClearButtonEnabled(True)
+
self.add = QPushButton("Add")
self.clear = QPushButton("Clear")
- self.quit = QPushButton("Quit")
+ form_layout = QFormLayout()
+ form_layout.addRow("Description", self.description)
+ form_layout.addRow("Price", self.price)
self.right = QVBoxLayout()
- self.right.addWidget(QLabel("Description"))
- self.right.addWidget(self.description)
- self.right.addWidget(QLabel("Price"))
- self.right.addWidget(self.price)
+ self.right.addLayout(form_layout)
self.right.addWidget(self.add)
self.right.addStretch()
self.right.addWidget(self.clear)
- self.right.addWidget(self.quit)
# QWidget Layout
- self.layout = QHBoxLayout()
-
- #self.table_view.setSizePolicy(size)
+ self.layout = QHBoxLayout(self)
self.layout.addWidget(self.table)
self.layout.addLayout(self.right)
- # Set the layout to the QWidget
- self.setLayout(self.layout)
-
# Fill example data
self.fill_table()
@@ -66,7 +61,7 @@ class Widget(QWidget):
class MainWindow(QMainWindow):
def __init__(self, widget):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -74,17 +69,11 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
- self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/07-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/07-expenses.py
index 10b83f2f6..b1ed3fecc 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/07-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/07-expenses.py
@@ -3,15 +3,15 @@
import sys
from PySide6.QtCore import Slot
-from PySide6.QtGui import QAction
-from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
- QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
- QVBoxLayout, QWidget)
+from PySide6.QtWidgets import (QApplication, QFormLayout, QHeaderView,
+ QHBoxLayout, QLineEdit, QMainWindow, QPushButton,
+ QTableWidget, QTableWidgetItem, QVBoxLayout,
+ QWidget)
class Widget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
self.items = 0
# Example data
@@ -27,33 +27,28 @@ class Widget(QWidget):
# Right
self.description = QLineEdit()
+ self.description.setClearButtonEnabled(True)
self.price = QLineEdit()
+ self.price.setClearButtonEnabled(True)
+
self.add = QPushButton("Add")
self.clear = QPushButton("Clear")
- self.quit = QPushButton("Quit")
+ form_layout = QFormLayout()
+ form_layout.addRow("Description", self.description)
+ form_layout.addRow("Price", self.price)
self.right = QVBoxLayout()
- self.right.addWidget(QLabel("Description"))
- self.right.addWidget(self.description)
- self.right.addWidget(QLabel("Price"))
- self.right.addWidget(self.price)
+ self.right.addLayout(form_layout)
self.right.addWidget(self.add)
self.right.addStretch()
- self.right.addWidget(self.quit)
# QWidget Layout
- self.layout = QHBoxLayout()
-
- #self.table_view.setSizePolicy(size)
+ self.layout = QHBoxLayout(self)
self.layout.addWidget(self.table)
self.layout.addLayout(self.right)
- # Set the layout to the QWidget
- self.setLayout(self.layout)
-
# Signals and Slots
self.add.clicked.connect(self.add_element)
- self.quit.clicked.connect(self.quit_application)
self.clear.clicked.connect(self.clear_table)
# Fill example data
@@ -68,15 +63,11 @@ class Widget(QWidget):
self.table.setItem(self.items, 0, QTableWidgetItem(des))
self.table.setItem(self.items, 1, QTableWidgetItem(price))
- self.description.setText("")
- self.price.setText("")
+ self.description.clear()
+ self.price.clear()
self.items += 1
- @Slot()
- def quit_application(self):
- QApplication.quit()
-
def fill_table(self, data=None):
data = self._data if not data else data
for desc, price in data.items():
@@ -93,7 +84,7 @@ class Widget(QWidget):
class MainWindow(QMainWindow):
def __init__(self, widget):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -101,17 +92,11 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
- self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/08-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/08-expenses.py
index 1979bd6b8..0e7e21a32 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/08-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/08-expenses.py
@@ -3,15 +3,15 @@
import sys
from PySide6.QtCore import Slot
-from PySide6.QtGui import QAction
-from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
- QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
- QVBoxLayout, QWidget)
+from PySide6.QtWidgets import (QApplication, QFormLayout, QHeaderView,
+ QHBoxLayout, QLineEdit, QMainWindow, QPushButton,
+ QTableWidget, QTableWidgetItem, QVBoxLayout,
+ QWidget)
class Widget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
self.items = 0
# Example data
@@ -27,40 +27,35 @@ class Widget(QWidget):
# Right
self.description = QLineEdit()
+ self.description.setClearButtonEnabled(True)
self.price = QLineEdit()
+ self.price.setClearButtonEnabled(True)
+
self.add = QPushButton("Add")
self.clear = QPushButton("Clear")
- self.quit = QPushButton("Quit")
# Disabling 'Add' button
self.add.setEnabled(False)
+ form_layout = QFormLayout()
+ form_layout.addRow("Description", self.description)
+ form_layout.addRow("Price", self.price)
self.right = QVBoxLayout()
- self.right.addWidget(QLabel("Description"))
- self.right.addWidget(self.description)
- self.right.addWidget(QLabel("Price"))
- self.right.addWidget(self.price)
+ self.right.addLayout(form_layout)
self.right.addWidget(self.add)
self.right.addStretch()
self.right.addWidget(self.clear)
- self.right.addWidget(self.quit)
# QWidget Layout
- self.layout = QHBoxLayout()
-
- #self.table_view.setSizePolicy(size)
+ self.layout = QHBoxLayout(self)
self.layout.addWidget(self.table)
self.layout.addLayout(self.right)
- # Set the layout to the QWidget
- self.setLayout(self.layout)
-
# Signals and Slots
self.add.clicked.connect(self.add_element)
- self.quit.clicked.connect(self.quit_application)
self.clear.clicked.connect(self.clear_table)
- self.description.textChanged[str].connect(self.check_disable)
- self.price.textChanged[str].connect(self.check_disable)
+ self.description.textChanged.connect(self.check_disable)
+ self.price.textChanged.connect(self.check_disable)
# Fill example data
self.fill_table()
@@ -74,21 +69,15 @@ class Widget(QWidget):
self.table.setItem(self.items, 0, QTableWidgetItem(des))
self.table.setItem(self.items, 1, QTableWidgetItem(price))
- self.description.setText("")
- self.price.setText("")
+ self.description.clear()
+ self.price.clear()
self.items += 1
@Slot()
def check_disable(self, s):
- if not self.description.text() or not self.price.text():
- self.add.setEnabled(False)
- else:
- self.add.setEnabled(True)
-
- @Slot()
- def quit_application(self):
- QApplication.quit()
+ enabled = bool(self.description.text() and self.price.text())
+ self.add.setEnabled(enabled)
def fill_table(self, data=None):
data = self._data if not data else data
@@ -106,7 +95,7 @@ class Widget(QWidget):
class MainWindow(QMainWindow):
def __init__(self, widget):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -114,17 +103,11 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
- self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/09-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/09-expenses.py
index d06f96135..279a46512 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/09-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/09-expenses.py
@@ -3,16 +3,17 @@
import sys
from PySide6.QtCore import Slot
-from PySide6.QtGui import QAction, QPainter
-from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
- QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import (QApplication, QFormLayout, QHeaderView,
+ QHBoxLayout, QLineEdit, QMainWindow,
+ QPushButton, QTableWidget, QTableWidgetItem,
QVBoxLayout, QWidget)
from PySide6.QtCharts import QChartView
class Widget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
self.items = 0
# Example data
@@ -32,42 +33,37 @@ class Widget(QWidget):
# Right
self.description = QLineEdit()
+ self.description.setClearButtonEnabled(True)
self.price = QLineEdit()
+ self.price.setClearButtonEnabled(True)
self.add = QPushButton("Add")
self.clear = QPushButton("Clear")
- self.quit = QPushButton("Quit")
self.plot = QPushButton("Plot")
# Disabling 'Add' button
self.add.setEnabled(False)
+ form_layout = QFormLayout()
+ form_layout.addRow("Description", self.description)
+ form_layout.addRow("Price", self.price)
self.right = QVBoxLayout()
- self.right.addWidget(QLabel("Description"))
- self.right.addWidget(self.description)
- self.right.addWidget(QLabel("Price"))
- self.right.addWidget(self.price)
+ self.right.addLayout(form_layout)
self.right.addWidget(self.add)
self.right.addWidget(self.plot)
self.right.addWidget(self.chart_view)
self.right.addWidget(self.clear)
- self.right.addWidget(self.quit)
# QWidget Layout
- self.layout = QHBoxLayout()
+ self.layout = QHBoxLayout(self)
- #self.table_view.setSizePolicy(size)
self.layout.addWidget(self.table)
self.layout.addLayout(self.right)
- # Set the layout to the QWidget
- self.setLayout(self.layout)
-
# Signals and Slots
self.add.clicked.connect(self.add_element)
- self.quit.clicked.connect(self.quit_application)
self.clear.clicked.connect(self.clear_table)
- self.description.textChanged[str].connect(self.check_disable)
- self.price.textChanged[str].connect(self.check_disable)
+ self.description.textChanged.connect(self.check_disable)
+ self.price.textChanged.connect(self.check_disable)
# Fill example data
self.fill_table()
@@ -81,21 +77,15 @@ class Widget(QWidget):
self.table.setItem(self.items, 0, QTableWidgetItem(des))
self.table.setItem(self.items, 1, QTableWidgetItem(price))
- self.description.setText("")
- self.price.setText("")
+ self.description.clear()
+ self.price.clear()
self.items += 1
@Slot()
def check_disable(self, s):
- if not self.description.text() or not self.price.text():
- self.add.setEnabled(False)
- else:
- self.add.setEnabled(True)
-
- @Slot()
- def quit_application(self):
- QApplication.quit()
+ enabled = bool(self.description.text() and self.price.text())
+ self.add.setEnabled(enabled)
def fill_table(self, data=None):
data = self._data if not data else data
@@ -113,7 +103,7 @@ class Widget(QWidget):
class MainWindow(QMainWindow):
def __init__(self, widget):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -121,17 +111,11 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
- self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/expenses/steps/10-expenses.py b/sources/pyside6/doc/tutorials/expenses/steps/10-expenses.py
index bbed5c389..a3a998470 100644
--- a/sources/pyside6/doc/tutorials/expenses/steps/10-expenses.py
+++ b/sources/pyside6/doc/tutorials/expenses/steps/10-expenses.py
@@ -3,16 +3,17 @@
import sys
from PySide6.QtCore import Qt, Slot
-from PySide6.QtGui import QAction, QPainter
-from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
- QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
+from PySide6.QtGui import QPainter
+from PySide6.QtWidgets import (QApplication, QFormLayout, QHeaderView,
+ QHBoxLayout, QLineEdit, QMainWindow,
+ QPushButton, QTableWidget, QTableWidgetItem,
QVBoxLayout, QWidget)
from PySide6.QtCharts import QChartView, QPieSeries, QChart
class Widget(QWidget):
def __init__(self):
- QWidget.__init__(self)
+ super().__init__()
self.items = 0
# Example data
@@ -32,43 +33,38 @@ class Widget(QWidget):
# Right
self.description = QLineEdit()
+ self.description.setClearButtonEnabled(True)
self.price = QLineEdit()
+ self.price.setClearButtonEnabled(True)
+
self.add = QPushButton("Add")
self.clear = QPushButton("Clear")
- self.quit = QPushButton("Quit")
self.plot = QPushButton("Plot")
# Disabling 'Add' button
self.add.setEnabled(False)
+ form_layout = QFormLayout()
+ form_layout.addRow("Description", self.description)
+ form_layout.addRow("Price", self.price)
self.right = QVBoxLayout()
- self.right.addWidget(QLabel("Description"))
- self.right.addWidget(self.description)
- self.right.addWidget(QLabel("Price"))
- self.right.addWidget(self.price)
+ self.right.addLayout(form_layout)
self.right.addWidget(self.add)
self.right.addWidget(self.plot)
self.right.addWidget(self.chart_view)
self.right.addWidget(self.clear)
- self.right.addWidget(self.quit)
# QWidget Layout
- self.layout = QHBoxLayout()
-
- #self.table_view.setSizePolicy(size)
+ self.layout = QHBoxLayout(self)
self.layout.addWidget(self.table)
self.layout.addLayout(self.right)
- # Set the layout to the QWidget
- self.setLayout(self.layout)
-
# Signals and Slots
self.add.clicked.connect(self.add_element)
- self.quit.clicked.connect(self.quit_application)
self.plot.clicked.connect(self.plot_data)
self.clear.clicked.connect(self.clear_table)
- self.description.textChanged[str].connect(self.check_disable)
- self.price.textChanged[str].connect(self.check_disable)
+ self.description.textChanged.connect(self.check_disable)
+ self.price.textChanged.connect(self.check_disable)
# Fill example data
self.fill_table()
@@ -76,27 +72,25 @@ class Widget(QWidget):
@Slot()
def add_element(self):
des = self.description.text()
- price = self.price.text()
+ price = float(self.price.text())
self.table.insertRow(self.items)
description_item = QTableWidgetItem(des)
- price_item = QTableWidgetItem(f"{float(price):.2f}")
+ price_item = QTableWidgetItem(f"{price:.2f}")
price_item.setTextAlignment(Qt.AlignRight)
self.table.setItem(self.items, 0, description_item)
self.table.setItem(self.items, 1, price_item)
- self.description.setText("")
- self.price.setText("")
+ self.description.clear()
+ self.price.clear()
self.items += 1
@Slot()
def check_disable(self, s):
- if not self.description.text() or not self.price.text():
- self.add.setEnabled(False)
- else:
- self.add.setEnabled(True)
+ enabled = bool(self.description.text() and self.price.text())
+ self.add.setEnabled(enabled)
@Slot()
def plot_data(self):
@@ -112,10 +106,6 @@ class Widget(QWidget):
chart.legend().setAlignment(Qt.AlignLeft)
self.chart_view.setChart(chart)
- @Slot()
- def quit_application(self):
- QApplication.quit()
-
def fill_table(self, data=None):
data = self._data if not data else data
for desc, price in data.items():
@@ -135,7 +125,7 @@ class Widget(QWidget):
class MainWindow(QMainWindow):
def __init__(self, widget):
- QMainWindow.__init__(self)
+ super().__init__()
self.setWindowTitle("Tutorial")
# Menu
@@ -143,17 +133,11 @@ class MainWindow(QMainWindow):
self.file_menu = self.menu.addMenu("File")
# Exit QAction
- exit_action = QAction("Exit", self)
+ exit_action = self.file_menu.addAction("Exit", self.close)
exit_action.setShortcut("Ctrl+Q")
- exit_action.triggered.connect(self.exit_app)
- self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)
- @Slot()
- def exit_app(self, checked):
- QApplication.quit()
-
if __name__ == "__main__":
# Qt Application
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/Main.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/Main.qml
new file mode 100644
index 000000000..faa9175d6
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/Main.qml
@@ -0,0 +1,196 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls.Basic
+import QtQuick.Layouts
+import FileSystemModule
+
+pragma ComponentBehavior: Bound
+
+ApplicationWindow {
+ id: root
+
+ property bool expandPath: false
+ property bool showLineNumbers: true
+ property string currentFilePath: ""
+
+ width: 1100
+ height: 600
+ minimumWidth: 200
+ minimumHeight: 100
+ visible: true
+ color: Colors.background
+ flags: Qt.Window | Qt.FramelessWindowHint
+ title: qsTr("File System Explorer Example")
+
+ function getInfoText() : string {
+ let out = root.currentFilePath
+ if (!out)
+ return qsTr("File System Explorer")
+ return root.expandPath ? out : out.substring(out.lastIndexOf("/") + 1, out.length)
+ }
+
+ menuBar: MyMenuBar {
+ dragWindow: root
+ infoText: root.getInfoText()
+ MyMenu {
+ title: qsTr("File")
+
+ Action {
+ text: qsTr("Increase Font")
+ shortcut: StandardKey.ZoomIn
+ onTriggered: editor.text.font.pixelSize += 1
+ }
+ Action {
+ text: qsTr("Decrease Font")
+ shortcut: StandardKey.ZoomOut
+ onTriggered: editor.text.font.pixelSize -= 1
+ }
+ Action {
+ text: root.showLineNumbers ? qsTr("Toggle Line Numbers OFF")
+ : qsTr("Toggle Line Numbers ON")
+ shortcut: "Ctrl+L"
+ onTriggered: root.showLineNumbers = !root.showLineNumbers
+ }
+ Action {
+ text: root.expandPath ? qsTr("Toggle Short Path")
+ : qsTr("Toggle Expand Path")
+ enabled: root.currentFilePath
+ onTriggered: root.expandPath = !root.expandPath
+ }
+ Action {
+ text: qsTr("Reset Filesystem")
+ enabled: sidebar.currentTabIndex === 1
+ onTriggered: fileSystemView.rootIndex = undefined
+ }
+ Action {
+ text: qsTr("Exit")
+ onTriggered: Qt.exit(0)
+ shortcut: StandardKey.Quit
+ }
+ }
+
+ MyMenu {
+ title: qsTr("Edit")
+
+ Action {
+ text: qsTr("Cut")
+ shortcut: StandardKey.Cut
+ enabled: editor.text.selectedText.length > 0
+ onTriggered: editor.text.cut()
+ }
+ Action {
+ text: qsTr("Copy")
+ shortcut: StandardKey.Copy
+ enabled: editor.text.selectedText.length > 0
+ onTriggered: editor.text.copy()
+ }
+ Action {
+ text: qsTr("Paste")
+ shortcut: StandardKey.Paste
+ enabled: editor.text.canPaste
+ onTriggered: editor.text.paste()
+ }
+ Action {
+ text: qsTr("Select All")
+ shortcut: StandardKey.SelectAll
+ enabled: editor.text.length > 0
+ onTriggered: editor.text.selectAll()
+ }
+ Action {
+ text: qsTr("Undo")
+ shortcut: StandardKey.Undo
+ enabled: editor.text.canUndo
+ onTriggered: editor.text.undo()
+ }
+ }
+ }
+ // Set up the layout of the main components in a row:
+ // [ Sidebar, Navigation, Editor ]
+ RowLayout {
+ anchors.fill: parent
+ spacing: 0
+
+ // Stores the buttons that navigate the application.
+ Sidebar {
+ id: sidebar
+ dragWindow: root
+ Layout.preferredWidth: 50
+ Layout.fillHeight: true
+ }
+
+ // Allows resizing parts of the UI.
+ SplitView {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ // Customized handle to drag between the Navigation and the Editor.
+ handle: Rectangle {
+ implicitWidth: 10
+ color: SplitHandle.pressed ? Colors.color2 : Colors.background
+ border.color: SplitHandle.hovered ? Colors.color2 : Colors.background
+ opacity: SplitHandle.hovered || navigationView.width < 15 ? 1.0 : 0.0
+
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: 1400
+ }
+ }
+ }
+
+ Rectangle {
+ id: navigationView
+ color: Colors.surface1
+ SplitView.preferredWidth: 250
+ SplitView.fillHeight: true
+ // The stack-layout provides different views, based on the
+ // selected buttons inside the sidebar.
+ StackLayout {
+ anchors.fill: parent
+ currentIndex: sidebar.currentTabIndex > 1 ? 1 : sidebar.currentTabIndex
+
+ // Shows the help text.
+ Text {
+ text: qsTr("This example shows how to use and visualize the file system.\n\n"
+ + "Customized Qt Quick Components have been used to achieve this look.\n\n"
+ + "You can edit the files but they won't be changed on the file system.\n\n"
+ + "Click on the folder icon to the left to get started.")
+ wrapMode: TextArea.Wrap
+ color: Colors.text
+ }
+
+ // Shows the files on the file system.
+ FileSystemView {
+ id: fileSystemView
+ color: Colors.surface1
+ onFileClicked: path => root.currentFilePath = path
+ }
+ }
+ }
+
+ // The main view that contains the editor or the scheme-manager.
+ StackLayout {
+ currentIndex: sidebar.currentTabIndex > 1 ? 1 : 0
+
+ SplitView.fillWidth: true
+ SplitView.fillHeight: true
+
+ Editor {
+ id: editor
+ showLineNumbers: root.showLineNumbers
+ currentFilePath: root.currentFilePath
+ }
+
+ ColorScheme {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+
+ }
+ }
+ }
+
+ ResizeButton {
+ resizeWindow: root
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/app.qrc b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/app.qrc
new file mode 100644
index 000000000..ccd9eefec
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/app.qrc
@@ -0,0 +1,16 @@
+<RCC>
+ <qresource prefix="/qt/qml/FileSystemModule">
+ <file>qmldir</file>
+ <file>Main.qml</file>
+ <file>qml/About.qml</file>
+ <file>qml/Editor.qml</file>
+ <file>qml/Colors.qml</file>
+ <file>qml/FileSystemView.qml</file>
+ <file>qml/Icon.qml</file>
+ <file>qml/MyMenu.qml</file>
+ <file>qml/MyMenuBar.qml</file>
+ <file>qml/ResizeButton.qml</file>
+ <file>qml/Sidebar.qml</file>
+ <file>qml/WindowDragHandler.qml</file>
+ </qresource>
+</RCC>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons.qrc b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons.qrc
new file mode 100644
index 000000000..69bddc018
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons.qrc
@@ -0,0 +1,15 @@
+<RCC>
+ <qresource>
+ <file>icons/app_icon.svg</file>
+ <file>icons/folder_closed.svg</file>
+ <file>icons/folder_open.svg</file>
+ <file>icons/generic_file.svg</file>
+ <file>icons/globe.svg</file>
+ <file>icons/info_sign.svg</file>
+ <file>icons/leaf.svg</file>
+ <file>icons/light_bulb.svg</file>
+ <file>icons/qt_logo.svg</file>
+ <file>icons/read.svg</file>
+ <file>icons/resize.svg</file>
+ </qresource>
+</RCC>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/app_icon.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/app_icon.svg
new file mode 100644
index 000000000..5aae4221f
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/app_icon.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="#EBDBB2" d="M13.25 8.5a.75.75 0 1 1-.75-.75.75.75 0 0 1 .75.75zM9.911 21.35l.816.578C10.819 21.798 13 18.666 13 13h-1a15.503 15.503 0 0 1-2.089 8.35zM4 6.703V10a2.002 2.002 0 0 1-2 2v1a2.002 2.002 0 0 1 2 2v3.297A3.707 3.707 0 0 0 7.703 22H9v-1H7.703A2.706 2.706 0 0 1 5 18.297V15a2.999 2.999 0 0 0-1.344-2.5A2.999 2.999 0 0 0 5 10V6.703A2.706 2.706 0 0 1 7.703 4H9V3H7.703A3.707 3.707 0 0 0 4 6.703zM20 10V6.703A3.707 3.707 0 0 0 16.297 3H15v1h1.297A2.706 2.706 0 0 1 19 6.703V10a2.999 2.999 0 0 0 1.344 2.5A2.999 2.999 0 0 0 19 15v3.297A2.706 2.706 0 0 1 16.297 21H15v1h1.297A3.707 3.707 0 0 0 20 18.297V15a2.002 2.002 0 0 1 2-2v-1a2.002 2.002 0 0 1-2-2z"/><path fill="none" d="M0 0h24v24H0z"/></svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/folder_closed.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/folder_closed.svg
new file mode 100644
index 000000000..36f119c96
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/folder_closed.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ viewBox="-10 0 1792 1792"
+ id="svg51"
+ sodipodi:docname="folder_closed.svg"
+ width="1792"
+ height="1792"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs55" />
+ <sodipodi:namedview
+ id="namedview53"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="0.45033482"
+ inkscape:cx="842.70632"
+ inkscape:cy="896"
+ inkscape:window-width="1846"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg51" />
+ <path
+ fill="currentColor"
+ d="m 1718,672 v 704 q 0,92 -66,158 -66,66 -158,66 H 278 q -92,0 -158,-66 -66,-66 -66,-158 V 416 q 0,-92 66,-158 66,-66 158,-66 h 320 q 92,0 158,66 66,66 66,158 v 32 h 672 q 92,0 158,66 66,66 66,158 z"
+ id="path49" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/folder_open.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/folder_open.svg
new file mode 100644
index 000000000..daa55a7a1
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/folder_open.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ viewBox="-10 0 1792 1792"
+ id="svg139"
+ sodipodi:docname="folder_open.svg"
+ width="1792"
+ height="1792"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs143" />
+ <sodipodi:namedview
+ id="namedview141"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="0.24358259"
+ inkscape:cx="149.84651"
+ inkscape:cy="1098.1901"
+ inkscape:window-width="1846"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg139" />
+ <path
+ fill="currentColor"
+ d="M 1590,1376 V 672 q 0,-40 -28,-68 -28,-28 -68,-28 H 790 q -40,0 -68,-28 -28,-28 -28,-68 v -64 q 0,-40 -28,-68 -28,-28 -68,-28 H 278 q -40,0 -68,28 -28,28 -28,68 v 960 q 0,40 28,68 28,28 68,28 h 1216 q 40,0 68,-28 28,-28 28,-68 z m 128,-704 v 704 q 0,92 -66,158 -66,66 -158,66 H 278 q -92,0 -158,-66 -66,-66 -66,-158 V 416 q 0,-92 66,-158 66,-66 158,-66 h 320 q 92,0 158,66 66,66 66,158 v 32 h 672 q 92,0 158,66 66,66 66,158 z"
+ id="path137" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/generic_file.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/generic_file.svg
new file mode 100644
index 000000000..9c855676e
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/generic_file.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ viewBox="-10 0 1792 1792"
+ id="svg147"
+ sodipodi:docname="generic_file.svg"
+ width="1792"
+ height="1792"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs151" />
+ <sodipodi:namedview
+ id="namedview149"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="0.12179129"
+ inkscape:cx="-578.85911"
+ inkscape:cy="1687.3127"
+ inkscape:window-width="1846"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg147" />
+ <path
+ fill="currentColor"
+ d="m 1586,476 q 14,14 28,36 H 1142 V 40 q 22,14 36,28 z m -476,164 h 544 v 1056 q 0,40 -28,68 -28,28 -68,28 H 214 q -40,0 -68,-28 -28,-28 -28,-68 V 96 Q 118,56 146,28 174,0 214,0 h 800 v 544 q 0,40 28,68 28,28 68,28 z m 160,736 v -64 q 0,-14 -9,-23 -9,-9 -23,-9 H 534 q -14,0 -23,9 -9,9 -9,23 v 64 q 0,14 9,23 9,9 23,9 h 704 q 14,0 23,-9 9,-9 9,-23 z m 0,-256 v -64 q 0,-14 -9,-23 -9,-9 -23,-9 H 534 q -14,0 -23,9 -9,9 -9,23 v 64 q 0,14 9,23 9,9 23,9 h 704 q 14,0 23,-9 9,-9 9,-23 z m 0,-256 v -64 q 0,-14 -9,-23 -9,-9 -23,-9 H 534 q -14,0 -23,9 -9,9 -9,23 v 64 q 0,14 9,23 9,9 23,9 h 704 q 14,0 23,-9 9,-9 9,-23 z"
+ id="path145" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/globe.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/globe.svg
new file mode 100644
index 000000000..081433813
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/globe.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ viewBox="-10 0 1792 1792"
+ id="svg155"
+ sodipodi:docname="globe.svg"
+ width="1792"
+ height="1792"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs159" />
+ <sodipodi:namedview
+ id="namedview157"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="0.12179129"
+ inkscape:cx="504.9622"
+ inkscape:cy="1720.1558"
+ inkscape:window-width="1846"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg155" />
+ <path
+ fill="currentColor"
+ d="m 886,128 q 209,0 385.5,103 176.5,103 279.5,279.5 103,176.5 103,385.5 0,209 -103,385.5 Q 1448,1458 1271.5,1561 1095,1664 886,1664 677,1664 500.5,1561 324,1458 221,1281.5 118,1105 118,896 118,687 221,510.5 324,334 500.5,231 677,128 886,128 Z m 274,521 q -2,1 -9.5,9.5 -7.5,8.5 -13.5,9.5 2,0 4.5,-5 2.5,-5 5,-11 2.5,-6 3.5,-7 6,-7 22,-15 14,-6 52,-12 34,-8 51,11 -2,-2 9.5,-13 11.5,-11 14.5,-12 3,-2 15,-4.5 12,-2.5 15,-7.5 l 2,-22 q -12,1 -17.5,-7 -5.5,-8 -6.5,-21 0,2 -6,8 0,-7 -4.5,-8 -4.5,-1 -11.5,1 -7,2 -9,1 -10,-3 -15,-7.5 -5,-4.5 -8,-16.5 -3,-12 -4,-15 -2,-5 -9.5,-10.5 -7.5,-5.5 -9.5,-10.5 -1,-2 -2.5,-5.5 -1.5,-3.5 -3,-6.5 -1.5,-3 -4,-5.5 -2.5,-2.5 -5.5,-2.5 -3,0 -7,5 -4,5 -7.5,10 -3.5,5 -4.5,5 -3,-2 -6,-1.5 -3,0.5 -4.5,1 -1.5,0.5 -4.5,3 -3,2.5 -5,3.5 -3,2 -8.5,3 -5.5,1 -8.5,2 15,-5 -1,-11 -10,-4 -16,-3 9,-4 7.5,-12 -1.5,-8 -8.5,-14 h 5 q -1,-4 -8.5,-8.5 -7.5,-4.5 -17.5,-8.5 -10,-4 -13,-6 -8,-5 -34,-9.5 -26,-4.5 -33,-0.5 -5,6 -4.5,10.5 0.5,4.5 4,14 3.5,9.5 3.5,12.5 1,6 -5.5,13 -6.5,7 -6.5,12 0,7 14,15.5 14,8.5 10,21.5 -3,8 -16,16 -13,8 -16,12 -5,8 -1.5,18.5 3.5,10.5 10.5,16.5 2,2 1.5,4 -0.5,2 -3.5,4.5 -3,2.5 -5.5,4 -2.5,1.5 -6.5,3.5 l -3,2 q -11,5 -20.5,-6 -9.5,-11 -13.5,-26 -7,-25 -16,-30 -23,-8 -29,1 -5,-13 -41,-26 -25,-9 -58,-4 6,-1 0,-15 -7,-15 -19,-12 3,-6 4,-17.5 1,-11.5 1,-13.5 3,-13 12,-23 1,-1 7,-8.5 6,-7.5 9.5,-13.5 3.5,-6 0.5,-6 35,4 50,-11 5,-5 11.5,-17 6.5,-12 10.5,-17 9,-6 14,-5.5 5,0.5 14.5,5.5 9.5,5 14.5,5 14,1 15.5,-11 1.5,-12 -7.5,-20 12,1 3,-17 -5,-7 -8,-9 -12,-4 -27,5 -8,4 2,8 -1,-1 -9.5,10.5 Q 927,340 919,346 q -8,6 -16,-5 -1,-1 -5.5,-13.5 Q 893,315 888,314 q -8,0 -16,15 3,-8 -11,-15 -14,-7 -24,-8 19,-12 -8,-27 -7,-4 -20.5,-5 -13.5,-1 -19.5,4 -5,7 -5.5,11.5 -0.5,4.5 5,8 5.5,3.5 10.5,5.5 5,2 11.5,4 6.5,2 8.5,3 14,10 8,14 -2,1 -8.5,3.5 -6.5,2.5 -11.5,4.5 -5,2 -6,4 -3,4 0,14 3,10 -2,14 -5,-5 -9,-17.5 -4,-12.5 -7,-16.5 7,9 -25,6 l -10,-1 q -4,0 -16,2 -12,2 -20.5,1 -8.5,-1 -13.5,-8 -4,-8 0,-20 1,-4 4,-2 -4,-3 -11,-9.5 -7,-6.5 -10,-8.5 -46,15 -94,41 6,1 12,-1 5,-2 13,-6.5 8,-4.5 10,-5.5 34,-14 42,-7 l 5,-5 q 14,16 20,25 -7,-4 -30,-1 -20,6 -22,12 7,12 5,18 -4,-3 -11.5,-10 -7.5,-7 -14.5,-11 -7,-4 -15,-5 -16,0 -22,1 -146,80 -235,222 7,7 12,8 4,1 5,9 1,8 2.5,11 1.5,3 11.5,-3 9,8 3,19 1,-1 44,27 19,17 21,21 3,11 -10,18 -1,-2 -9,-9 -8,-7 -9,-4 -3,5 0.5,18.5 3.5,13.5 10.5,12.5 -7,0 -9.5,16 -2.5,16 -2.5,35.5 0,19.5 -1,23.5 l 2,1 q -3,12 5.5,34.5 8.5,22.5 21.5,19.5 -13,3 20,43 6,8 8,9 3,2 12,7.5 9,5.5 15,10 6,4.5 10,10.5 4,5 10,22.5 6,17.5 14,23.5 -2,6 9.5,20 11.5,14 10.5,23 -1,0 -2.5,1 -1.5,1 -2.5,1 3,7 15.5,14 12.5,7 15.5,13 1,3 2,10 1,7 3,11 2,4 8,2 2,-20 -24,-62 -15,-25 -17,-29 -3,-5 -5.5,-15.5 Q 541,919 539,915 q 2,0 6,1.5 4,1.5 8.5,3.5 4.5,2 7.5,4 3,2 2,3 -3,7 2,17.5 5,10.5 12,18.5 7,8 17,19 10,11 12,13 6,6 14,19.5 8,13.5 0,13.5 9,0 20,10 11,10 17,20 5,8 8,26 3,18 5,24 2,7 8.5,13.5 6.5,6.5 12.5,9.5 l 16,8 q 0,0 13,7 5,2 18.5,10.5 13.5,8.5 21.5,11.5 10,4 16,4 6,0 14.5,-2.5 8.5,-2.5 13.5,-3.5 15,-2 29,15 14,17 21,21 36,19 55,11 -2,1 0.5,7.5 2.5,6.5 8,15.5 5.5,9 9,14.5 3.5,5.5 5.5,8.5 5,6 18,15 13,9 18,15 6,-4 7,-9 -3,8 7,20 10,12 18,10 14,-3 14,-32 -31,15 -49,-18 0,-1 -2.5,-5.5 -2.5,-4.5 -4,-8.5 -1.5,-4 -2.5,-8.5 -1,-4.5 0,-7.5 1,-3 5,-3 9,0 10,-3.5 1,-3.5 -2,-12.5 -3,-9 -4,-13 -1,-8 -11,-20 -10,-12 -12,-15 -5,9 -16,8 -11,-1 -16,-9 0,1 -1.5,5.5 -1.5,4.5 -1.5,6.5 -13,0 -15,-1 1,-3 2.5,-17.5 1.5,-14.5 3.5,-22.5 1,-4 5.5,-12 4.5,-8 7.5,-14.5 3,-6.5 4,-12.5 1,-6 -4.5,-9.5 -5.5,-3.5 -17.5,-2.5 -19,1 -26,20 -1,3 -3,10.5 -2,7.5 -5,11.5 -3,4 -9,7 -7,3 -24,2 -17,-1 -24,-5 -13,-8 -22.5,-29 -9.5,-21 -9.5,-37 0,-10 2.5,-26.5 2.5,-16.5 3,-25 0.5,-8.5 -5.5,-24.5 3,-2 9,-9.5 6,-7.5 10,-10.5 2,-1 4.5,-1.5 2.5,-0.5 4.5,0 2,0.5 4,-1.5 2,-2 3,-6 -1,-1 -4,-3 -3,-3 -4,-3 7,3 28.5,-1.5 21.5,-4.5 27.5,1.5 15,11 22,-2 0,-1 -2.5,-9.5 Q 870,931 872,926 q 5,27 29,9 3,3 15.5,5 12.5,2 17.5,5 3,2 7,5.5 4,3.5 5.5,4.5 1.5,1 5,-0.5 3.5,-1.5 8.5,-6.5 10,14 12,24 11,40 19,44 7,3 11,2 4,-1 4.5,-9.5 0.5,-8.5 0,-14 Q 1006,989 1005,982 l -1,-8 v -18 l -1,-8 q -15,-3 -18.5,-12 -3.5,-9 1.5,-18.5 5,-9.5 15,-18.5 1,-1 8,-3.5 7,-2.5 15.5,-6.5 8.5,-4 12.5,-8 21,-19 15,-35 7,0 11,-9 -1,0 -5,-3 -4,-3 -7.5,-5 -3.5,-2 -4.5,-2 9,-5 2,-16 5,-3 7.5,-11 2.5,-8 7.5,-10 9,12 21,2 7,-8 1,-16 5,-7 20.5,-10.5 15.5,-3.5 18.5,-9.5 7,2 8,-2 1,-4 1,-12 0,-8 3,-12 4,-5 15,-9 11,-4 13,-5 l 17,-11 q 3,-4 0,-4 18,2 31,-11 10,-11 -6,-20 3,-6 -3,-9.5 -6,-3.5 -15,-5.5 3,-1 11.5,-0.5 8.5,0.5 10.5,-1.5 15,-10 -7,-16 -17,-5 -43,12 z m -163,877 q 206,-36 351,-189 -3,-3 -12.5,-4.5 -9.5,-1.5 -12.5,-3.5 -18,-7 -24,-8 1,-7 -2.5,-13 -3.5,-6 -8,-9 -4.5,-3 -12.5,-8 -8,-5 -11,-7 -2,-2 -7,-6 -5,-4 -7,-5.5 -2,-1.5 -7.5,-4.5 -5.5,-3 -8.5,-2 -3,1 -10,1 l -3,1 q -3,1 -5.5,2.5 -2.5,1.5 -5.5,3 -3,1.5 -4,3 -1,1.5 0,2.5 -21,-17 -36,-22 -5,-1 -11,-5.5 -6,-4.5 -10.5,-7 -4.5,-2.5 -10,-1.5 -5.5,1 -11.5,7 -5,5 -6,15 -1,10 -2,13 -7,-5 0,-17.5 7,-12.5 2,-18.5 -3,-6 -10.5,-4.5 -7.5,1.5 -12,4.5 -4.5,3 -11.5,8.5 -7,5.5 -9,6.5 -2,1 -8.5,5.5 -6.5,4.5 -8.5,7.5 -3,4 -6,12 -3,8 -5,11 -2,-4 -11.5,-6.5 -9.5,-2.5 -9.5,-5.5 2,10 4,35 2,25 5,38 7,31 -12,48 -27,25 -29,40 -4,22 12,26 0,7 -8,20.5 -8,13.5 -7,21.5 0,6 2,16 z"
+ id="path153" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/info_sign.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/info_sign.svg
new file mode 100644
index 000000000..517f76360
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/info_sign.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ viewBox="-10 0 1792 1792"
+ id="svg163"
+ sodipodi:docname="info_sign.svg"
+ width="1792"
+ height="1792"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs167" />
+ <sodipodi:namedview
+ id="namedview165"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="0.48716518"
+ inkscape:cx="72.870561"
+ inkscape:cy="896"
+ inkscape:window-width="1846"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg163" />
+ <path
+ fill="currentColor"
+ d="m 1142,1376 v -160 q 0,-14 -9,-23 -9,-9 -23,-9 h -96 V 672 q 0,-14 -9,-23 -9,-9 -23,-9 H 662 q -14,0 -23,9 -9,9 -9,23 v 160 q 0,14 9,23 9,9 23,9 h 96 v 320 h -96 q -14,0 -23,9 -9,9 -9,23 v 160 q 0,14 9,23 9,9 23,9 h 448 q 14,0 23,-9 9,-9 9,-23 z M 1014,480 V 320 q 0,-14 -9,-23 -9,-9 -23,-9 H 790 q -14,0 -23,9 -9,9 -9,23 v 160 q 0,14 9,23 9,9 23,9 h 192 q 14,0 23,-9 9,-9 9,-23 z m 640,416 q 0,209 -103,385.5 Q 1448,1458 1271.5,1561 1095,1664 886,1664 677,1664 500.5,1561 324,1458 221,1281.5 118,1105 118,896 118,687 221,510.5 324,334 500.5,231 677,128 886,128 1095,128 1271.5,231 1448,334 1551,510.5 1654,687 1654,896 Z"
+ id="path161" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/leaf.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/leaf.svg
new file mode 100644
index 000000000..c1cabb5cf
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/leaf.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="-10 0 1034 1024">
+ <path fill="currentColor"
+d="M765 327l-14 -11l-538 502l503 -533l-14 -12q-48 -26 -106 -23.5t-109 19.5q-14 4 -28.5 10t-28.5 13q-30 14 -57.5 32.5t-52.5 41.5q-55 52 -90.5 119t-52.5 140q-5 21 -9 42t-7 42q-3 26 -5.5 52.5t-4.5 53.5q-1 22 1.5 45.5t33.5 21.5h11.5h10.5q78 -2 156 -6t153 -29
+q49 -16 94 -42.5t82 -62.5q27 -27 50 -60t39 -69.5t24 -75.5t5 -78q-3 -35 -12.5 -70t-33.5 -62v0zM844 160l30 30l-563 531z" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/light_bulb.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/light_bulb.svg
new file mode 100644
index 000000000..ed2ed55fb
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/light_bulb.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ viewBox="-10 0 1538 1538"
+ id="svg4"
+ sodipodi:docname="light_bulb.svg"
+ width="1538"
+ height="1538"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs8" />
+ <sodipodi:namedview
+ id="namedview6"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ fit-margin-top="1"
+ fit-margin-left="1"
+ fit-margin-right="1"
+ fit-margin-bottom="1"
+ lock-margins="true"
+ inkscape:zoom="0.16"
+ inkscape:cx="1234.375"
+ inkscape:cy="409.375"
+ inkscape:window-width="1846"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg4" />
+ <path
+ fill="currentColor"
+ d="m 983,449 q 0,13 -9.5,22.5 Q 964,481 951,481 938,481 928.5,471.5 919,462 919,449 919,403 865,378 811,353 759,353 746,353 736.5,343.5 727,334 727,321 q 0,-13 9.5,-22.5 9.5,-9.5 22.5,-9.5 50,0 99.5,16 49.5,16 87,54 37.5,38 37.5,90 z m 160,0 q 0,-72 -34.5,-134 -34.5,-62 -90,-101.5 Q 963,174 895.5,151.5 828,129 759,129 690,129 622.5,151.5 555,174 499.5,213.5 444,253 409.5,315 375,377 375,449 q 0,101 68,180 10,11 30.5,33 20.5,22 30.5,33 128,153 141,298 h 228 q 13,-145 141,-298 10,-11 30.5,-33 20.5,-22 30.5,-33 68,-79 68,-180 z m 128,0 q 0,155 -103,268 -45,49 -74.5,87 -29.5,38 -59.5,95.5 -30,57.5 -34,107.5 47,28 47,82 0,37 -25,64 25,27 25,64 0,52 -45,81 13,23 13,47 0,46 -31.5,71 -31.5,25 -77.5,25 -20,44 -60,70 -40,26 -87,26 -47,0 -87,-26 -40,-26 -60,-70 -46,0 -77.5,-25 -31.5,-25 -31.5,-71 0,-24 13,-47 -45,-29 -45,-81 0,-37 25,-64 -25,-27 -25,-64 0,-54 47,-82 Q 514,957 484,899.5 454,842 424.5,804 395,766 350,717 247,604 247,449 247,350 291.5,264.5 336,179 408.5,122.5 481,66 572.5,33.5 664,1 759,1 q 95,0 186.5,32.5 91.5,32.5 164,89 72.5,56.5 117,142 Q 1271,350 1271,449 Z"
+ id="path2" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/qt_logo.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/qt_logo.svg
new file mode 100644
index 000000000..062daff3e
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/qt_logo.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ width="462pt"
+ height="339pt"
+ viewBox="0 0 462 339"
+ version="1.1"
+ id="svg2"
+>
+ <path
+ fill="#41cd52"
+ d=" M 63.50 0.00 L 462.00 0.00 L 462.00 274.79 C 440.60 296.26 419.13 317.66 397.61 339.00 L 0.00 339.00 L 0.00 63.39 C 21.08 42.18 42.34 21.13 63.50 0.00 Z"
+ id="path6"/>
+ <path
+ d=" M 122.37 71.33 C 137.50 61.32 156.21 58.79 174.00 58.95 C 190.94 59.16 208.72 62.13 222.76 72.24 C 232.96 79.41 239.59 90.48 244.01 101.93 C 251.16 120.73 253.26 141.03 253.50 161.01 C 253.53 181.13 252.62 201.69 245.96 220.86 C 241.50 233.90 233.01 245.48 221.81 253.52 C 229.87 266.58 238.09 279.54 246.15 292.60 C 236.02 297.27 225.92 301.97 215.78 306.62 C 207.15 292.38 198.56 278.11 189.90 263.89 C 178.19 265.81 166.21 265.66 154.44 264.36 C 140.34 262.67 125.97 258.37 115.09 248.88 C 106.73 241.64 101.48 231.51 97.89 221.21 C 92.01 203.79 90.43 185.25 90.16 166.97 C 90.02 147.21 91.28 127.14 97.24 108.18 C 101.85 93.92 109.48 79.69 122.37 71.33 Z"
+ id="path8"
+ fill="#ffffff"/>
+ <path
+ d=" M 294.13 70.69 C 304.73 70.68 315.33 70.68 325.93 70.69 C 325.96 84.71 325.92 98.72 325.95 112.74 C 339.50 112.76 353.05 112.74 366.60 112.75 C 366.37 121.85 366.12 130.95 365.86 140.05 C 352.32 140.08 338.79 140.04 325.25 140.07 C 325.28 163.05 325.18 186.03 325.30 209.01 C 325.56 215.30 325.42 221.94 328.19 227.75 C 330.21 232.23 335.65 233.38 340.08 233.53 C 348.43 233.50 356.77 233.01 365.12 232.86 C 365.63 241.22 366.12 249.59 366.60 257.95 C 349.99 260.74 332.56 264.08 316.06 258.86 C 309.11 256.80 302.63 252.19 299.81 245.32 C 294.76 233.63 294.35 220.62 294.13 208.07 C 294.11 185.40 294.13 162.74 294.12 140.07 C 286.73 140.05 279.34 140.08 271.95 140.05 C 271.93 130.96 271.93 121.86 271.95 112.76 C 279.34 112.73 286.72 112.77 294.11 112.74 C 294.14 98.72 294.10 84.71 294.13 70.69 Z"
+ id="path10"
+ fill="#ffffff"/>
+ <path
+ fill="#41cd52"
+ d=" M 160.51 87.70 C 170.80 86.36 181.60 86.72 191.34 90.61 C 199.23 93.73 205.93 99.84 209.47 107.58 C 214.90 119.31 216.98 132.26 218.03 145.05 C 219.17 162.07 219.01 179.25 216.66 196.17 C 215.01 206.24 212.66 216.85 205.84 224.79 C 198.92 232.76 188.25 236.18 178.01 236.98 C 167.21 237.77 155.82 236.98 146.07 231.87 C 140.38 228.84 135.55 224.09 132.73 218.27 C 129.31 211.30 127.43 203.69 126.11 196.07 C 122.13 171.91 121.17 146.91 126.61 122.89 C 128.85 113.83 132.11 104.53 138.73 97.70 C 144.49 91.85 152.51 88.83 160.51 87.70 Z"
+ id="path12"/>
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/read.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/read.svg
new file mode 100644
index 000000000..c3af473d2
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/read.svg
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ viewBox="-11 0 1792 1792"
+ id="svg184"
+ sodipodi:docname="read.svg"
+ width="1792"
+ height="1792"
+ inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs188" />
+ <sodipodi:namedview
+ id="namedview186"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="0.24358259"
+ inkscape:cx="519.33104"
+ inkscape:cy="1089.9794"
+ inkscape:window-width="1846"
+ inkscape:window-height="1016"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg184" />
+ <path
+ fill="currentColor"
+ d="m 1691.8576,478 q 40,57 18,129 l -275,906 q -19,64 -76.5,107.5 -57.5,43.5 -122.5,43.5 H 312.85764 q -77,0 -148.5,-53.5 Q 92.857644,1557 64.857644,1479 q -24,-67 -2,-127 0,-4 3,-27 3,-23 4,-37 1,-8 -3,-21.5 -4,-13.5 -3,-19.5 2,-11 8,-21 6,-10 16.5,-23.5 10.5,-13.5 16.499996,-23.5 23,-38 45,-91.5 22,-53.5 30,-91.5 3,-10 0.5,-30 -2.5,-20 -0.5,-28 3,-11 17,-28 14,-17 17,-23 21,-36 42,-92 21,-56 25,-90 1,-9 -2.5,-32 -3.5,-23 0.5,-28 4,-13 22,-30.5 18,-17.5 22,-22.5 19,-26 42.5,-84.5 23.5,-58.5 27.5,-96.5 1,-8 -3,-25.5 -4,-17.5 -2,-26.5 2,-8 9,-18 7,-10 18,-23 11,-13 17,-21 8,-12 16.5,-30.5 8.5,-18.5 15,-35 6.5,-16.5 16,-36 9.5,-19.5 19.5,-32 10,-12.5 26.5,-23.5 16.5,-11 36,-11.5 19.5,-0.5 47.5,5.5 l -1,3 q 38,-9 51,-9 h 760.99996 q 74,0 114,56 40,56 18,130 l -274,906 q -36,119 -71.5,153.5 -35.5,34.5 -128.5,34.5 H 208.85764 q -27,0 -38,15 -11,16 -1,43 24,70 144,70 h 922.99996 q 29,0 56,-15.5 27,-15.5 35,-41.5 l 300,-987 q 7,-22 5,-57 38,15 59,43 z m -1063.99996,2 q -4,13 2,22.5 6,9.5 20,9.5 h 607.99996 q 13,0 25.5,-9.5 12.5,-9.5 16.5,-22.5 l 21,-64 q 4,-13 -2,-22.5 -6,-9.5 -20,-9.5 H 690.85764 q -13,0 -25.5,9.5 -12.5,9.5 -16.5,22.5 z m -83,256 q -4,13 2,22.5 6,9.5 20,9.5 h 607.99996 q 13,0 25.5,-9.5 12.5,-9.5 16.5,-22.5 l 21,-64 q 4,-13 -2,-22.5 -6,-9.5 -20,-9.5 H 607.85764 q -13,0 -25.5,9.5 -12.5,9.5 -16.5,22.5 z"
+ id="path182" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/resize.svg b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/resize.svg
new file mode 100644
index 000000000..e86d612f3
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons/resize.svg
@@ -0,0 +1,6 @@
+<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100'>
+ <line x1="00" y1="100" x2="100" y2="00" stroke="black" stroke-width="3" />
+ <line x1="20" y1="100" x2="100" y2="20" stroke="black" stroke-width="3" />
+ <line x1="40" y1="100" x2="100" y2="40" stroke="black" stroke-width="3" />
+ <line x1="60" y1="100" x2="100" y2="60" stroke="black" stroke-width="3" />
+</svg>
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/About.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/About.qml
new file mode 100644
index 000000000..178bf03e4
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/About.qml
@@ -0,0 +1,93 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls.Basic
+import FileSystemModule
+
+ApplicationWindow {
+ id: root
+ width: 650
+ height: 550
+ flags: Qt.Window | Qt.FramelessWindowHint
+ color: Colors.surface1
+
+ menuBar: MyMenuBar {
+ id: menuBar
+
+ dragWindow: root
+ implicitHeight: 27
+ infoText: "About Qt"
+ }
+
+ Image {
+ id: logo
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.margins: 20
+
+ source: "../icons/qt_logo.svg"
+ sourceSize.width: 80
+ sourceSize.height: 80
+ fillMode: Image.PreserveAspectFit
+
+ smooth: true
+ antialiasing: true
+ asynchronous: true
+ }
+
+ ScrollView {
+ anchors.top: logo.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.margins: 20
+
+ TextArea {
+ selectedTextColor: Colors.textFile
+ selectionColor: Colors.selection
+ horizontalAlignment: Text.AlignHCenter
+ textFormat: Text.RichText
+
+ text: qsTr("<h3>About Qt</h3>"
+ + "<p>This program uses Qt version %1.</p>"
+ + "<p>Qt is a C++ toolkit for cross-platform application "
+ + "development.</p>"
+ + "<p>Qt provides single-source portability across all major desktop "
+ + "operating systems. It is also available for embedded Linux and other "
+ + "embedded and mobile operating systems.</p>"
+ + "<p>Qt is available under multiple licensing options designed "
+ + "to accommodate the needs of our various users.</p>"
+ + "<p>Qt licensed under our commercial license agreement is appropriate "
+ + "for development of proprietary/commercial software where you do not "
+ + "want to share any source code with third parties or otherwise cannot "
+ + "comply with the terms of GNU (L)GPL.</p>"
+ + "<p>Qt licensed under GNU (L)GPL is appropriate for the "
+ + "development of Qt&nbsp;applications provided you can comply with the terms "
+ + "and conditions of the respective licenses.</p>"
+ + "<p>Please see <a href=\"http://%2/\">%2</a> "
+ + "for an overview of Qt licensing.</p>"
+ + "<p>Copyright (C) %3 The Qt Company Ltd and other "
+ + "contributors.</p>"
+ + "<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>"
+ + "<p>Qt is The Qt Company Ltd product developed as an open source "
+ + "project. See <a href=\"http://%4/\">%4</a> for more information.</p>")
+ .arg(Application.version).arg("qt.io/licensing").arg("2023").arg("qt.io")
+ color: Colors.textFile
+ wrapMode: Text.WordWrap
+ readOnly: true
+ antialiasing: true
+ background: null
+
+ onLinkActivated: function(link) {
+ Qt.openUrlExternally(link)
+ }
+ }
+ }
+
+ ResizeButton {
+ resizeWindow: root
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/ColorScheme.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/ColorScheme.qml
new file mode 100644
index 000000000..19c8cd905
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/ColorScheme.qml
@@ -0,0 +1,118 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import FileSystemModule
+
+ColumnLayout {
+ id: colorScheme
+
+ spacing: 20
+
+ // Inline component that customizes TabButton
+ component MyTabButton: TabButton {
+ id: root
+
+ implicitWidth: 150
+ implicitHeight: 30
+ padding: 6
+ spacing: 6
+
+ contentItem: Text {
+ anchors.centerIn: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+
+ text: root.text
+ font.bold: true
+ color: Colors.text
+ }
+
+ background: Rectangle {
+ anchors.fill: parent
+ implicitHeight: 40
+
+ color: root.checked ? Colors.active : Colors.selection
+ Rectangle {
+ height: 4
+ width: parent.width
+ color: root.checked ? Colors.color1 : Colors.selection
+ }
+ }
+ }
+
+ Item {
+ // Spacer item
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+
+ Text {
+ Layout.alignment: Qt.AlignHCenter
+
+ text: "Select a Scheme!"
+ font.pointSize: 30
+ font.bold: true
+ color: Colors.text
+ }
+
+ // Display all the color-scheme names. The model is a string-list provided
+ // by our python class.
+ TabBar {
+ id: schemeSelector
+
+ Layout.alignment: Qt.AlignHCenter
+
+ background: Rectangle {
+ color: Colors.surface1
+ }
+
+ Repeater {
+ model: Colors.getKeys()
+ MyTabButton {
+ text: modelData
+ onClicked: {
+ Colors.setScheme(modelData)
+ themePreviewContainer.background
+ = (modelData === "Solarized") ? "#777777" : "#FEFAEC"
+ }
+ }
+ }
+ }
+
+ // The current colors can be visualized using the same method as above.
+ Rectangle {
+ id: themePreviewContainer
+
+ property color background: "#FEFAEC"
+
+ Layout.alignment: Qt.AlignHCenter
+
+ width: 700
+ height: 50
+ radius: 10
+ color: background
+
+ // Display all used colors inside a row
+ Row {
+ anchors.centerIn: parent
+ spacing: 10
+
+ Repeater {
+ model: Colors.currentColors
+ Rectangle {
+ width: 35
+ height: width
+ radius: width / 2
+ color: modelData
+ }
+ }
+ }
+ }
+ Item {
+ // Spacer item
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Editor.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Editor.qml
new file mode 100644
index 000000000..80f7c04c5
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Editor.qml
@@ -0,0 +1,160 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import FileSystemModule
+
+pragma ComponentBehavior: Bound
+
+// This is the text editor that displays the currently open file, including
+// their corresponding line numbers.
+Rectangle {
+ id: root
+
+ required property string currentFilePath
+ required property bool showLineNumbers
+ property alias text: textArea
+ property int currentLineNumber: -1
+ property int rowHeight: Math.ceil(fontMetrics.lineSpacing)
+
+ color: Colors.background
+
+ onWidthChanged: textArea.update()
+ onHeightChanged: textArea.update()
+
+ RowLayout {
+ anchors.fill: parent
+ // We use a flickable to synchronize the position of the editor and
+ // the line numbers. This is necessary because the line numbers can
+ // extend the available height.
+ Flickable {
+ id: lineNumbers
+
+ // Calculate the width based on the logarithmic scale.
+ Layout.preferredWidth: fontMetrics.averageCharacterWidth
+ * (Math.floor(Math.log10(textArea.lineCount)) + 1) + 10
+ Layout.fillHeight: true
+
+ interactive: false
+ contentY: editorFlickable.contentY
+ visible: textArea.text !== "" && root.showLineNumbers
+
+ Column {
+ anchors.fill: parent
+ Repeater {
+ id: repeatedLineNumbers
+
+ model: LineNumberModel {
+ lineCount: textArea.text !== "" ? textArea.lineCount : 0
+ }
+
+ delegate: Item {
+ required property int index
+
+ width: parent.width
+ height: root.rowHeight
+ Label {
+ id: numbers
+
+ text: parent.index + 1
+
+ width: parent.width
+ height: parent.height
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+
+ color: (root.currentLineNumber === parent.index)
+ ? Colors.iconIndicator : Qt.darker(Colors.text, 2)
+ font: textArea.font
+ }
+ Rectangle {
+ id: indicator
+
+ anchors.left: numbers.right
+ width: 1
+ height: parent.height
+ color: Qt.darker(Colors.text, 3)
+ }
+ }
+ }
+ }
+ }
+
+ Flickable {
+ id: editorFlickable
+
+ property alias textArea: textArea
+
+ // We use an inline component to customize the horizontal and vertical
+ // scroll-bars. This is convenient when the component is only used in one file.
+ component MyScrollBar: ScrollBar {
+ id: scrollBar
+ background: Rectangle {
+ implicitWidth: scrollBar.interactive ? 8 : 4
+ implicitHeight: scrollBar.interactive ? 8 : 4
+
+ opacity: scrollBar.active && scrollBar.size < 1.0 ? 1.0 : 0.0
+ color: Colors.background
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: 500
+ }
+ }
+ }
+ contentItem: Rectangle {
+ implicitWidth: scrollBar.interactive ? 8 : 4
+ implicitHeight: scrollBar.interactive ? 8 : 4
+ opacity: scrollBar.active && scrollBar.size < 1.0 ? 1.0 : 0.0
+ color: Colors.color1
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: 1000
+ }
+ }
+ }
+ }
+
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ ScrollBar.horizontal: MyScrollBar {}
+ ScrollBar.vertical: MyScrollBar {}
+
+ boundsBehavior: Flickable.StopAtBounds
+
+ TextArea.flickable: TextArea {
+ id: textArea
+ anchors.fill: parent
+
+ focus: false
+ topPadding: 0
+ leftPadding: 10
+
+ text: FileSystemModel.readFile(root.currentFilePath)
+ tabStopDistance: fontMetrics.averageCharacterWidth * 4
+
+ // Grab the current line number from the C++ interface.
+ onCursorPositionChanged: {
+ root.currentLineNumber = FileSystemModel.currentLineNumber(
+ textArea.textDocument, textArea.cursorPosition)
+ }
+
+ color: Colors.textFile
+ selectedTextColor: Colors.textFile
+ selectionColor: Colors.selection
+
+ textFormat: TextEdit.PlainText
+ renderType: Text.QtRendering
+ selectByMouse: true
+ antialiasing: true
+ background: null
+ }
+
+ FontMetrics {
+ id: fontMetrics
+ font: textArea.font
+ }
+ }
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/FileSystemView.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/FileSystemView.qml
new file mode 100644
index 000000000..db955168c
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/FileSystemView.qml
@@ -0,0 +1,156 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Effects
+import QtQuick.Controls.Basic
+import FileSystemModule
+
+pragma ComponentBehavior: Bound
+
+// This is the file system view which gets populated by the C++ model.
+Rectangle {
+ id: root
+
+ signal fileClicked(string filePath)
+ property alias rootIndex: fileSystemTreeView.rootIndex
+
+ TreeView {
+ id: fileSystemTreeView
+
+ property int lastIndex: -1
+
+ anchors.fill: parent
+ model: FileSystemModel
+ rootIndex: FileSystemModel.rootIndex
+ boundsBehavior: Flickable.StopAtBounds
+ boundsMovement: Flickable.StopAtBounds
+ clip: true
+
+ Component.onCompleted: fileSystemTreeView.toggleExpanded(0)
+
+ // The delegate represents a single entry in the filesystem.
+ delegate: TreeViewDelegate {
+ id: treeDelegate
+ indentation: 8
+ implicitWidth: fileSystemTreeView.width > 0 ? fileSystemTreeView.width : 250
+ implicitHeight: 25
+
+ // Since we have the 'ComponentBehavior Bound' pragma, we need to
+ // require these properties from our model. This is a convenient way
+ // to bind the properties provided by the model's role names.
+ required property int index
+ required property url filePath
+ required property string fileName
+
+ indicator: Image {
+ id: directoryIcon
+
+ x: treeDelegate.leftMargin + (treeDelegate.depth * treeDelegate.indentation)
+ anchors.verticalCenter: parent.verticalCenter
+ source: treeDelegate.hasChildren ? (treeDelegate.expanded
+ ? "../icons/folder_open.svg" : "../icons/folder_closed.svg")
+ : "../icons/generic_file.svg"
+ sourceSize.width: 20
+ sourceSize.height: 20
+ fillMode: Image.PreserveAspectFit
+
+ smooth: true
+ antialiasing: true
+ asynchronous: true
+ }
+
+ contentItem: Text {
+ text: treeDelegate.fileName
+ color: Colors.text
+ }
+
+ background: Rectangle {
+ color: (treeDelegate.index === fileSystemTreeView.lastIndex)
+ ? Colors.selection
+ : (hoverHandler.hovered ? Colors.active : "transparent")
+ }
+
+ // We color the directory icons with this MultiEffect, where we overlay
+ // the colorization color ontop of the SVG icons.
+ MultiEffect {
+ id: iconOverlay
+
+ anchors.fill: directoryIcon
+ source: directoryIcon
+ colorization: 1.0
+ brightness: 1.0
+ colorizationColor: {
+ const isFile = treeDelegate.index === fileSystemTreeView.lastIndex
+ && !treeDelegate.hasChildren;
+ if (isFile)
+ return Qt.lighter(Colors.folder, 3)
+
+ const isExpandedFolder = treeDelegate.expanded && treeDelegate.hasChildren;
+ if (isExpandedFolder)
+ return Colors.color2
+ else
+ return Colors.folder
+ }
+ }
+
+ HoverHandler {
+ id: hoverHandler
+ }
+
+ TapHandler {
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onSingleTapped: (eventPoint, button) => {
+ switch (button) {
+ case Qt.LeftButton:
+ fileSystemTreeView.toggleExpanded(treeDelegate.row)
+ fileSystemTreeView.lastIndex = treeDelegate.index
+ // If this model item doesn't have children, it means it's
+ // representing a file.
+ if (!treeDelegate.hasChildren)
+ root.fileClicked(treeDelegate.filePath)
+ break;
+ case Qt.RightButton:
+ if (treeDelegate.hasChildren)
+ contextMenu.popup();
+ break;
+ }
+ }
+ }
+
+ MyMenu {
+ id: contextMenu
+ Action {
+ text: qsTr("Set as root index")
+ onTriggered: {
+ fileSystemTreeView.rootIndex = fileSystemTreeView.index(treeDelegate.row, 0)
+ }
+ }
+ Action {
+ text: qsTr("Reset root index")
+ onTriggered: fileSystemTreeView.rootIndex = undefined
+ }
+ }
+ }
+
+ // Provide our own custom ScrollIndicator for the TreeView.
+ ScrollIndicator.vertical: ScrollIndicator {
+ active: true
+ implicitWidth: 15
+
+ contentItem: Rectangle {
+ implicitWidth: 6
+ implicitHeight: 6
+
+ color: Colors.color1
+ opacity: fileSystemTreeView.movingVertically ? 0.5 : 0.0
+
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: 500
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenu.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenu.qml
new file mode 100644
index 000000000..1f1d30c56
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenu.qml
@@ -0,0 +1,45 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls.Basic
+import FileSystemModule
+
+Menu {
+ id: root
+
+ delegate: MenuItem {
+ id: menuItem
+ contentItem: Item {
+ Text {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+
+ text: menuItem.text
+ color: enabled ? Colors.text : Colors.disabledText
+ }
+ Rectangle {
+ id: indicator
+
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ width: 6
+ height: parent.height
+
+ visible: menuItem.highlighted
+ color: Colors.color2
+ }
+ }
+ background: Rectangle {
+ implicitWidth: 210
+ implicitHeight: 35
+ color: menuItem.highlighted ? Colors.active : "transparent"
+ }
+ }
+ background: Rectangle {
+ implicitWidth: 210
+ implicitHeight: 35
+ color: Colors.surface2
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenuBar.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenuBar.qml
new file mode 100644
index 000000000..4874a2c03
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenuBar.qml
@@ -0,0 +1,177 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls.Basic
+import FileSystemModule
+
+// The MenuBar also serves as a controller for our window as we don't use any decorations.
+MenuBar {
+ id: root
+
+ required property ApplicationWindow dragWindow
+ property alias infoText: windowInfo.text
+
+ // Customization of the top level menus inside the MenuBar
+ delegate: MenuBarItem {
+ id: menuBarItem
+
+ contentItem: Text {
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+
+ text: menuBarItem.text
+ font: menuBarItem.font
+ elide: Text.ElideRight
+ color: menuBarItem.highlighted ? Colors.textFile : Colors.text
+ opacity: enabled ? 1.0 : 0.3
+ }
+
+ background: Rectangle {
+ id: background
+
+ color: menuBarItem.highlighted ? Colors.selection : "transparent"
+ Rectangle {
+ id: indicator
+
+ width: 0; height: 3
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+
+ color: Colors.color1
+ states: State {
+ name: "active"
+ when: menuBarItem.highlighted
+ PropertyChanges {
+ indicator.width: background.width - 2
+ }
+ }
+ transitions: Transition {
+ NumberAnimation {
+ properties: "width"
+ duration: 175
+ }
+ }
+ }
+ }
+ }
+ // We use the contentItem property as a place to attach our window decorations. Beneath
+ // the usual menu entries within a MenuBar, it includes a centered information text, along
+ // with the minimize, maximize, and close buttons.
+ contentItem: RowLayout {
+ id: windowBar
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ spacing: root.spacing
+ Repeater {
+ id: menuBarItems
+
+ Layout.alignment: Qt.AlignLeft
+ model: root.contentModel
+ }
+
+ Item {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Text {
+ id: windowInfo
+
+ width: parent.width; height: parent.height
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ leftPadding: windowActions.width
+ color: Colors.text
+ clip: true
+ }
+ }
+
+ RowLayout {
+ id: windowActions
+
+ Layout.alignment: Qt.AlignRight
+ Layout.fillHeight: true
+
+ spacing: 0
+
+ component InteractionButton: Rectangle {
+ id: interactionButton
+
+ signal action()
+ property alias hovered: hoverHandler.hovered
+
+ Layout.fillHeight: true
+ Layout.preferredWidth: height
+
+ color: hovered ? Colors.background : "transparent"
+ HoverHandler {
+ id: hoverHandler
+ }
+ TapHandler {
+ id: tapHandler
+ onTapped: interactionButton.action()
+ }
+ }
+
+ InteractionButton {
+ id: minimize
+
+ onAction: root.dragWindow.showMinimized()
+ Rectangle {
+ anchors.centerIn: parent
+ color: parent.hovered ? Colors.iconIndicator : Colors.icon
+ height: 2
+ width: parent.height - 14
+ }
+ }
+
+ InteractionButton {
+ id: maximize
+
+ onAction: root.dragWindow.showMaximized()
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 7
+ border.color: parent.hovered ? Colors.iconIndicator : Colors.icon
+ border.width: 2
+ color: "transparent"
+ }
+ }
+
+ InteractionButton {
+ id: close
+
+ color: hovered ? "#ec4143" : "transparent"
+ onAction: root.dragWindow.close()
+ Rectangle {
+ anchors.centerIn: parent
+ width: parent.height - 8; height: 2
+
+ rotation: 45
+ antialiasing: true
+ transformOrigin: Item.Center
+ color: parent.hovered ? Colors.iconIndicator : Colors.icon
+
+ Rectangle {
+ anchors.centerIn: parent
+ width: parent.height
+ height: parent.width
+
+ antialiasing: true
+ color: parent.color
+ }
+ }
+ }
+ }
+ }
+
+ background: Rectangle {
+ color: Colors.surface2
+ // Make the empty space drag the specified root window.
+ WindowDragHandler {
+ dragWindow: root.dragWindow
+ }
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/ResizeButton.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/ResizeButton.qml
new file mode 100644
index 000000000..0df65bf82
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/ResizeButton.qml
@@ -0,0 +1,23 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick.Controls
+import FileSystemModule
+
+Button {
+ required property ApplicationWindow resizeWindow
+
+ icon.width: 20; icon.height: 20
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ rightPadding: 3
+ bottomPadding: 3
+
+ icon.source: "../icons/resize.svg"
+ icon.color: hovered ? Colors.iconIndicator : Colors.icon
+
+ background: null
+ checkable: false
+ display: AbstractButton.IconOnly
+ onPressed: resizeWindow.startSystemResize(Qt.BottomEdge | Qt.RightEdge)
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Sidebar.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Sidebar.qml
new file mode 100644
index 000000000..04880a55d
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Sidebar.qml
@@ -0,0 +1,146 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls.Basic
+import FileSystemModule
+
+Rectangle {
+ id: root
+
+ property alias currentTabIndex: topBar.currentIndex
+ required property ApplicationWindow dragWindow
+ readonly property int tabBarSpacing: 10
+
+ color: Colors.surface2
+
+ component SidebarEntry: Button {
+ id: sidebarButton
+
+ Layout.alignment: Qt.AlignHCenter
+ Layout.fillWidth: true
+
+ icon.color: down || checked ? Colors.iconIndicator : Colors.icon
+ icon.width: 27
+ icon.height: 27
+
+ topPadding: 0
+ rightPadding: 0
+ bottomPadding: 0
+ leftPadding: 0
+ background: null
+
+ Rectangle {
+ id: indicator
+
+ anchors.verticalCenter: parent.verticalCenter
+ x: 2
+ width: 4
+ height: sidebarButton.icon.height * 1.2
+
+ visible: sidebarButton.checked
+ color: Colors.color1
+ }
+ }
+
+ // TabBar is designed to be horizontal, whereas we need a vertical bar.
+ // We can easily achieve that by using a Container.
+ component TabBar: Container {
+ id: tabBarComponent
+
+ Layout.fillWidth: true
+ // ButtonGroup ensures that only one button can be checked at a time.
+ ButtonGroup {
+ buttons: tabBarComponent.contentChildren
+
+ // We have to manage the currentIndex ourselves, which we do by setting it to the index
+ // of the currently checked button. We use setCurrentIndex instead of setting the
+ // currentIndex property to avoid breaking bindings. See "Managing the Current Index"
+ // in Container's documentation for more information.
+ onCheckedButtonChanged: tabBarComponent.setCurrentIndex(
+ Math.max(0, buttons.indexOf(checkedButton)))
+ }
+
+ contentItem: ColumnLayout {
+ spacing: tabBarComponent.spacing
+ Repeater {
+ model: tabBarComponent.contentModel
+ }
+ }
+ }
+
+ ColumnLayout {
+ anchors.fill: root
+ anchors.topMargin: root.tabBarSpacing
+ anchors.bottomMargin: root.tabBarSpacing
+
+ spacing: root.tabBarSpacing
+ TabBar {
+ id: topBar
+
+ spacing: root.tabBarSpacing
+ // Shows help text when clicked.
+ SidebarEntry {
+ id: infoTab
+ icon.source: "../icons/light_bulb.svg"
+ checkable: true
+ checked: true
+ }
+
+ // Shows the file system when clicked.
+ SidebarEntry {
+ id: filesystemTab
+
+ icon.source: "../icons/read.svg"
+ checkable: true
+ }
+
+ // Shows the scheme switcher
+ SidebarEntry {
+ icon.source: "../icons/leaf.svg"
+ checkable: true
+
+ Layout.alignment: Qt.AlignHCenter
+ }
+ }
+
+ // This item acts as a spacer to expand between the checkable and non-checkable buttons.
+ Item {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ // Make the empty space drag our main window.
+ WindowDragHandler {
+ dragWindow: root.dragWindow
+ }
+ }
+
+ TabBar {
+ id: bottomBar
+
+ spacing: root.tabBarSpacing
+ // Opens the Qt website in the system's web browser.
+ SidebarEntry {
+ id: qtWebsiteButton
+ icon.source: "../icons/globe.svg"
+ checkable: false
+ onClicked: Qt.openUrlExternally("https://www.qt.io/")
+ }
+
+ // Opens the About Qt Window.
+ SidebarEntry {
+ id: aboutQtButton
+
+ icon.source: "../icons/info_sign.svg"
+ checkable: false
+ onClicked: aboutQtWindow.visible = !aboutQtWindow.visible
+ }
+ }
+ }
+
+ About {
+ id: aboutQtWindow
+ visible: false
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/WindowDragHandler.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/WindowDragHandler.qml
new file mode 100644
index 000000000..0e140aca3
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/WindowDragHandler.qml
@@ -0,0 +1,16 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+
+// Allows dragging the window when placed on an unused section of the UI.
+DragHandler {
+
+ required property ApplicationWindow dragWindow
+
+ target: null
+ onActiveChanged: {
+ if (active) dragWindow.startSystemMove()
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qmldir b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qmldir
new file mode 100644
index 000000000..e9c99b07b
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qmldir
@@ -0,0 +1,11 @@
+module FileSystemModule
+Main 1.0 Main.qml
+About 1.0 qml/About.qml
+Editor 1.0 qml/Editor.qml
+MyMenu 1.0 qml/MyMenu.qml
+Sidebar 1.0 qml/Sidebar.qml
+MyMenuBar 1.0 qml/MyMenuBar.qml
+ColorScheme 1.0 qml/ColorScheme.qml
+ResizeButton 1.0 qml/ResizeButton.qml
+FileSystemView 1.0 qml/FileSystemView.qml
+WindowDragHandler 1.0 qml/WindowDragHandler.qml
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/editormodels.py b/sources/pyside6/doc/tutorials/extendedexplorer/editormodels.py
new file mode 100644
index 000000000..688147726
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/editormodels.py
@@ -0,0 +1,116 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from PySide6.QtWidgets import QFileSystemModel
+from PySide6.QtQuick import QQuickTextDocument
+from PySide6.QtQml import QmlElement, QmlSingleton
+from PySide6.QtCore import (Qt, QDir, QAbstractListModel, Slot, QFile, QTextStream,
+ QMimeDatabase, QFileInfo, QStandardPaths, QModelIndex,
+ Signal, Property)
+
+QML_IMPORT_NAME = "FileSystemModule"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@QmlSingleton
+class FileSystemModel(QFileSystemModel):
+
+ rootIndexChanged = Signal()
+
+ def getDefaultRootDir():
+ return QStandardPaths.writableLocation(QStandardPaths.StandardLocation.HomeLocation)
+
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ self.mRootIndex = QModelIndex()
+ self.mDb = QMimeDatabase()
+ self.setFilter(QDir.Filter.AllEntries | QDir.Filter.Hidden | QDir.Filter.NoDotAndDotDot)
+ self.setInitialDirectory()
+
+ # check for the correct mime type and then read the file.
+ # returns the text file's content or an error message on failure
+ @Slot(str, result=str)
+ def readFile(self, path):
+ if path == "":
+ return ""
+
+ file = QFile(path)
+
+ mime = self.mDb.mimeTypeForFile(QFileInfo(file))
+ if ('text' in mime.comment().lower()
+ or any('text' in s.lower() for s in mime.parentMimeTypes())):
+ if file.open(QFile.OpenModeFlag.ReadOnly | QFile.OpenModeFlag.Text):
+ stream = QTextStream(file).readAll()
+ file.close()
+ return stream
+ else:
+ return self.tr("Error opening the file!")
+ return self.tr("File type not supported!")
+
+ @Slot(QQuickTextDocument, int, result=int)
+ def currentLineNumber(self, textDocument, cursorPosition):
+ td = textDocument.textDocument()
+ tb = td.findBlock(cursorPosition)
+ return tb.blockNumber()
+
+ def setInitialDirectory(self, path=getDefaultRootDir()):
+ dir = QDir(path)
+ if dir.makeAbsolute():
+ self.setRootPath(dir.path())
+ else:
+ self.setRootPath(self.getDefaultRootDir())
+ self.setRootIndex(self.index(dir.path()))
+
+ # we only need one column in this example
+ def columnCount(self, parent):
+ return 1
+
+ @Property(QModelIndex, notify=rootIndexChanged)
+ def rootIndex(self):
+ return self.mRootIndex
+
+ def setRootIndex(self, index):
+ if (index == self.mRootIndex):
+ return
+ self.mRootIndex = index
+ self.rootIndexChanged.emit()
+
+
+@QmlElement
+class LineNumberModel(QAbstractListModel):
+
+ lineCountChanged = Signal()
+
+ def __init__(self, parent=None):
+ self.mLineCount = 0
+ super().__init__(parent=parent)
+
+ @Property(int, notify=lineCountChanged)
+ def lineCount(self):
+ return self.mLineCount
+
+ @lineCount.setter
+ def lineCount(self, n):
+ if n < 0:
+ print("lineCount must be greater then zero")
+ return
+ if self.mLineCount == n:
+ return
+
+ if self.mLineCount < n:
+ self.beginInsertRows(QModelIndex(), self.mLineCount, n - 1)
+ self.mLineCount = n
+ self.endInsertRows()
+ else:
+ self.beginRemoveRows(QModelIndex(), n, self.mLineCount - 1)
+ self.mLineCount = n
+ self.endRemoveRows()
+
+ def rowCount(self, parent):
+ return self.mLineCount
+
+ def data(self, index, role):
+ if not self.checkIndex(index) or role != Qt.ItemDataRole.DisplayRole:
+ return
+ return index.row()
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.md b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.md
new file mode 100644
index 000000000..0ac7bec18
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.md
@@ -0,0 +1,210 @@
+# Extending the file system explorer example
+
+This tutorial shows how to extend the
+[Filesystem Explorer Example](filesystemexplorer_example)
+by adding a simple scheme manager. This feature will allow you to switch color
+schemes during the application's runtime. The color schemes will be declared in
+JSON format and made available through a custom Python-QML plugin.
+
+![Extended Explorer GIF](resources/extendedexplorer.gif)
+
+## Defining the color schemes
+
+To define your color scheme, you can use the same color names as the original
+example, so you don't have to rename every occurrence. The original colors are
+defined in the `Colors.qml` file as follows:
+
+```{literalinclude} resources/Colors.qml
+---
+language: QML
+caption: true
+linenos: true
+lines: 7-22
+---
+```
+
+The `schemes.json` file holds the color schemes. To start implementing this, you
+can use the [Catppuccin](https://github.com/catppuccin/catppuccin) scheme.
+
+```{literalinclude} schemes.json
+---json
+caption: true
+linenos: true
+start-at: "Catppuccin"
+end-at: "},"
+---
+```
+
+In addition to the "Catppuccin" color scheme, four other color schemes got
+implemented: Nordic, One Dark, Gruvbox, and Solarized. However, feel free to get
+creative and experiment with **your** schemes.
+
+To define a new color scheme, copy the structure from above and provide your
+color values
+
+## Implement the scheme manager
+
+After defining the color schemes, you can implement the actual scheme manager.
+The manager will read the `schemes.json` file and provide QML bindings to switch
+between schemes during runtime.
+
+To implement the scheme manager, create a Python-QML plugin that exposes the
+`SchemeManager` object to QML. This object will have methods to load the color
+schemes from the `schemes.json` file and switch between them.
+
+Create a new Python file called `schememanager.py` in your project directory. In
+this file, define the **SchemeManager** class:
+
+```{literalinclude} scheme_manager.py
+---
+language: python
+caption: true
+linenos: true
+start-at: "QML_IMPORT_NAME"
+end-at: "class SchemeManager"
+---
+```
+
+To integrate smoothly into the already existing code, attach the SchemeManager
+to the same QML module that's already present with
+`QML_IMPORT_NAME = "FileSystemModule"`. Additionally, use the`@QmlNamedElement`
+decorator to smoothly transition to using the custom plugin instead of the
+`Colors.qml` file. With these changes, we can avoid editing all previous
+assignments like:
+
+```QML
+import FileSystemModule
+...
+Rectangle {
+ color: Colors.background
+}
+```
+
+The constructor reads the `schemes.json` file once upon application start and
+then calls the `setTheme` member function.
+
+```{literalinclude} scheme_manager.py
+---
+language: python
+caption: true
+linenos: true
+lines: 18-24
+---
+```
+
+By adding the `SchemeManager` as a callable QML element named **Colors** to the
+FileSystemModule, the class is now accessible in the code without the need to
+import it each time or edit previous assignments. This, in turn, will streamline
+the workflow.
+
+After defining the schemes in the JSON format and making the `SchemeManager`
+class a callable element from QML under the name **Colors**, there are two
+remaining steps to fully integrate the new scheme manager in the example.
+
+The **first step** is to create a function in the `SchemeManager` class that
+loads a color scheme from the JSON file. The **second step** is to make the
+individual colors available in QML with the *same name* as used before with the
+syntax `Colors.<previousName>` as assignable properties.
+
+
+```{literalinclude} scheme_manager.py
+---
+language: python
+caption: true
+linenos: true
+lines: 26-31
+---
+```
+
+The `setScheme` method is responsible for switching between color schemes. To
+make this method accessible in QML, use the `@Slot(str)` decorator and specify
+that it takes a string as its input parameter. In this method, we populate a
+dictionary with the color values from the JSON file.
+
+> Note: For simplicity reasons no other error checking is performed.
+> You would probably want to validate the keys contained in the json.
+
+```{literalinclude} scheme_manager.py
+---
+language: python
+caption: true
+linenos: true
+start-at: "@Property(QColor"
+end-at: "return"
+---
+```
+
+To make the color property assignable in QML, use the `@Property` decorator.
+We simply return the corresponding color value from the dictionary for each
+property. This process is repeated for all other colors that are used in the
+application.
+At this point the application should start with the colors provided by the
+active scheme in the constructor.
+
+## Add the scheme switching to QML
+
+To visualize the current scheme and enable interactive scheme switching, start
+by adding a new entry to the `Sidebar.qml` file.
+
+```{literalinclude} FileSystemModule/qml/Sidebar.qml
+---
+language: QML
+caption: true
+linenos: true
+lines: 99-105
+---
+```
+
+To update the main content area of the application to display the `ColorScheme`,
+the logic that checks the active index from the Sidebar buttons needs to be
+modified. The necessary changes will be made to the Main.qml file:
+
+```{literalinclude} FileSystemModule/Main.qml
+---
+language: QML
+caption: true
+linenos: true
+lines: 170-187
+---
+```
+
+In addition, change the behavior of the application so that there are two
+`StackLayouts`: one for the resizable navigation and one for the main content
+area where we display our color scheme switching functionality. These changes
+will also be made to the Main.qml file.
+
+```{literalinclude} FileSystemModule/Main.qml
+---
+language: QML
+caption: true
+linenos: true
+lines: 147-150
+---
+```
+
+To complete our implementation, the `ColorScheme.qml` file needs to be created.
+The implementation is straightforward and follows the same principles as in the
+original example. If anything is unclear, please refer to the documentation
+provided there. To display all colors and scheme names, use a `Repeater`. The
+model for the Repeater is provided by our `scheme_manager.py`file as a
+`QStringList`.
+
+```{literalinclude} FileSystemModule/qml/ColorScheme.qml
+---
+language: QML
+caption: true
+linenos: true
+lines: 97-111
+---
+```
+
+When examining the code in more detail, you will notice that there are different
+ways to retrieve the models. The `getKeys()` method is defined as a **Slot** and
+therefore requires parentheses when called. On the other hand, the `currentColors`
+model is defined as a **property** and is therefore assigned as a property in QML.
+The reason for this is to receive notifications when the color scheme is switched
+so that the colors displayed in the application can be updated. The keys for the
+color schemes are loaded only once at application startup and do not rely on any
+notifications.
+
+![Extended Explorer GIF](resources/colorscheme.png)
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.pyproject b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.pyproject
new file mode 100644
index 000000000..77a3969ae
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.pyproject
@@ -0,0 +1,31 @@
+{
+ "files": [
+ "main.py",
+ "editormodels.py",
+ "scheme_manager.py",
+ "schemes.json",
+ "FileSystemModule/qmldir",
+ "FileSystemModule/app.qrc",
+ "FileSystemModule/icons.qrc",
+ "FileSystemModule/Main.qml",
+ "FileSystemModule/qml/About.qml",
+ "FileSystemModule/qml/ColorScheme.qml",
+ "FileSystemModule/qml/Editor.qml",
+ "FileSystemModule/qml/FileSystemView.qml",
+ "FileSystemModule/qml/MyMenu.qml",
+ "FileSystemModule/qml/MyMenuBar.qml",
+ "FileSystemModule/qml/ResizeButton.qml",
+ "FileSystemModule/qml/Sidebar.qml",
+ "FileSystemModule/qml/WindowDragHandler.qml",
+ "FileSystemModule/icons/app_icon.svg",
+ "FileSystemModule/icons/folder_closed.svg",
+ "FileSystemModule/icons/folder_open.svg",
+ "FileSystemModule/icons/generic_file.svg",
+ "FileSystemModule/icons/globe.svg",
+ "FileSystemModule/icons/info_sign.svg",
+ "FileSystemModule/icons/light_bulb.svg",
+ "FileSystemModule/icons/qt_logo.svg",
+ "FileSystemModule/icons/read.svg",
+ "FileSystemModule/icons/resize.svg"
+ ]
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/main.py b/sources/pyside6/doc/tutorials/extendedexplorer/main.py
new file mode 100644
index 000000000..f1e6e7d93
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/main.py
@@ -0,0 +1,50 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""
+This example shows how to customize Qt Quick Controls by implementing a simple filesystem explorer.
+"""
+
+# Compile both resource files app.qrc and icons.qrc and include them here if you wish
+# to load them from the resource system. Currently, all resources are loaded locally
+# import FileSystemModule.rc_icons
+# import FileSystemModule.rc_app
+
+from scheme_manager import SchemeManager
+from editormodels import FileSystemModel
+import PySide6
+from PySide6.QtGui import QGuiApplication, QIcon
+from PySide6.QtQml import QQmlApplicationEngine
+from PySide6.QtCore import QCommandLineParser
+
+import sys
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ app.setOrganizationName("QtProject")
+ app.setApplicationName("File System Explorer")
+ app.setApplicationVersion(PySide6.__version__)
+ app.setWindowIcon(QIcon("FileSystemModule/icons/app_icon.svg"))
+
+ parser = QCommandLineParser()
+ parser.setApplicationDescription("Qt Filesystemexplorer Example")
+ parser.addHelpOption()
+ parser.addVersionOption()
+ parser.addPositionalArgument("", "Initial directory", "[path]")
+ parser.process(app)
+ args = parser.positionalArguments()
+
+ engine = QQmlApplicationEngine()
+ # Include the path of this file to search for the 'qmldir' module
+ engine.addImportPath(sys.path[0])
+
+ engine.loadFromModule("FileSystemModule", "Main")
+
+ if not engine.rootObjects():
+ sys.exit(-1)
+
+ if (len(args) == 1):
+ fsm = engine.singletonInstance("FileSystemModule", "FileSystemModel")
+ fsm.setInitialDirectory(args[0])
+
+ sys.exit(app.exec())
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/resources/Colors.qml b/sources/pyside6/doc/tutorials/extendedexplorer/resources/Colors.qml
new file mode 100644
index 000000000..280f89286
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/resources/Colors.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+pragma Singleton
+import QtQuick
+
+QtObject {
+ readonly property color background: "#23272E"
+ readonly property color surface1: "#1E2227"
+ readonly property color surface2: "#090A0C"
+ readonly property color text: "#ABB2BF"
+ readonly property color textFile: "#C5CAD3"
+ readonly property color disabledText: "#454D5F"
+ readonly property color selection: "#2C313A"
+ readonly property color active: "#23272E"
+ readonly property color inactive: "#3E4452"
+ readonly property color folder: "#3D4451"
+ readonly property color icon: "#3D4451"
+ readonly property color iconIndicator: "#E5C07B"
+ readonly property color color1: "#E06B74"
+ readonly property color color2: "#62AEEF"
+}
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/resources/colorscheme.png b/sources/pyside6/doc/tutorials/extendedexplorer/resources/colorscheme.png
new file mode 100644
index 000000000..410538ca3
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/resources/colorscheme.png
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.gif b/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.gif
new file mode 100644
index 000000000..9e59f64aa
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.gif
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.webp b/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.webp
new file mode 100644
index 000000000..79a14f34c
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.webp
Binary files differ
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/scheme_manager.py b/sources/pyside6/doc/tutorials/extendedexplorer/scheme_manager.py
new file mode 100644
index 000000000..8d732093c
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/scheme_manager.py
@@ -0,0 +1,97 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import json
+from pathlib import Path
+from PySide6.QtCore import Slot, QObject, Property, Signal
+from PySide6.QtGui import QColor
+from PySide6.QtQml import QmlNamedElement, QmlSingleton
+
+QML_IMPORT_NAME = "FileSystemModule"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlNamedElement("Colors")
+@QmlSingleton
+class SchemeManager(QObject):
+
+ schemeChanged = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent=parent)
+ with open(Path(__file__).parent / "schemes.json", 'r') as f:
+ self.m_schemes = json.load(f)
+ self.m_activeScheme = {}
+ self.m_activeSchemeName = "Catppuccin"
+ self.setScheme(self.m_activeSchemeName)
+
+ @Slot(str)
+ def setScheme(self, theme):
+ for k, v in self.m_schemes[theme].items():
+ self.m_activeScheme[k] = QColor.fromString(v)
+ self.m_activeSchemeName = theme
+ self.schemeChanged.emit()
+
+ @Slot(result='QStringList')
+ def getKeys(self):
+ return self.m_schemes.keys()
+
+ @Property('QStringList', notify=schemeChanged)
+ def currentColors(self):
+ return self.m_schemes[self.m_activeSchemeName].values()
+
+ @Property(QColor, notify=schemeChanged)
+ def background(self):
+ return self.m_activeScheme["background"]
+
+ @Property(QColor, notify=schemeChanged)
+ def surface1(self):
+ return self.m_activeScheme["surface1"]
+
+ @Property(QColor, notify=schemeChanged)
+ def surface2(self):
+ return self.m_activeScheme["surface2"]
+
+ @Property(QColor, notify=schemeChanged)
+ def text(self):
+ return self.m_activeScheme["text"]
+
+ @Property(QColor, notify=schemeChanged)
+ def textFile(self):
+ return self.m_activeScheme["textFile"]
+
+ @Property(QColor, notify=schemeChanged)
+ def disabledText(self):
+ return self.m_activeScheme["disabledText"]
+
+ @Property(QColor, notify=schemeChanged)
+ def selection(self):
+ return self.m_activeScheme["selection"]
+
+ @Property(QColor, notify=schemeChanged)
+ def active(self):
+ return self.m_activeScheme["active"]
+
+ @Property(QColor, notify=schemeChanged)
+ def inactive(self):
+ return self.m_activeScheme["inactive"]
+
+ @Property(QColor, notify=schemeChanged)
+ def folder(self):
+ return self.m_activeScheme["folder"]
+
+ @Property(QColor, notify=schemeChanged)
+ def icon(self):
+ return self.m_activeScheme["icon"]
+
+ @Property(QColor, notify=schemeChanged)
+ def iconIndicator(self):
+ return self.m_activeScheme["iconIndicator"]
+
+ @Property(QColor, notify=schemeChanged)
+ def color1(self):
+ return self.m_activeScheme["color1"]
+
+ @Property(QColor, notify=schemeChanged)
+ def color2(self):
+ return self.m_activeScheme["color2"]
diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/schemes.json b/sources/pyside6/doc/tutorials/extendedexplorer/schemes.json
new file mode 100644
index 000000000..e4f2d8c81
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/extendedexplorer/schemes.json
@@ -0,0 +1,82 @@
+{
+ "Catppuccin": {
+ "background": "#1E1E2E",
+ "surface1": "#181825",
+ "surface2": "#11111B",
+ "text": "#CDD6F4",
+ "textFile": "#CDD6F4",
+ "disabledText": "#363659",
+ "selection": "#45475A",
+ "active": "#1E1E2E",
+ "inactive": "#6C7086",
+ "folder": "#6C7086",
+ "icon": "#6C7086",
+ "iconIndicator": "#FFCC66",
+ "color1": "#CBA6F7",
+ "color2": "#89DCEB"
+ },
+ "Nordic": {
+ "background": "#2E3440",
+ "surface1": "#2B2F3A",
+ "surface2": "#262A35",
+ "text": "#D8DEE9",
+ "textFile": "#D8DEE9",
+ "disabledText": "#4D556A",
+ "selection": "#495468",
+ "active": "#2E3440",
+ "inactive": "#555B6A",
+ "folder": "#495468",
+ "icon": "#495468",
+ "iconIndicator": "#FFC40D",
+ "color1": "#81B6C6",
+ "color2": "#5E81AC"
+ },
+ "One Dark": {
+ "background": "#23272E",
+ "surface1": "#1E2227",
+ "surface2": "#090A0C",
+ "text": "#ABB2BF",
+ "textFile": "#C5CAD3",
+ "disabledText": "#2B303B",
+ "selection": "#2C313A",
+ "active": "#23272E",
+ "inactive": "#3E4452",
+ "folder": "#3D4451",
+ "icon": "#3D4451",
+ "iconIndicator": "#E5C07B",
+ "color1": "#E06B74",
+ "color2": "#62AEEF"
+ },
+ "Gruvbox": {
+ "background": "#292828",
+ "surface1": "#171819",
+ "surface2": "#090A0C",
+ "text": "#D4BE98",
+ "textFile": "#E1D2B7",
+ "disabledText": "#2C313A",
+ "selection": "#333130",
+ "active": "#292828",
+ "inactive": "#383737",
+ "folder": "#383737",
+ "icon": "#383737",
+ "iconIndicator": "#FFCC66",
+ "color1": "#A7B464",
+ "color2": "#D3869B"
+ },
+ "Solarized": {
+ "background": "#FDF6E3",
+ "surface1": "#EEE8D5",
+ "surface2": "#DDD6C1",
+ "text": "#6D6D6D",
+ "textFile": "#333333",
+ "disabledText": "#ADADAD",
+ "selection": "#D1CBB8",
+ "active": "#FDF6E3",
+ "inactive": "#8C8364",
+ "folder": "#5F5944",
+ "icon": "#5F5944",
+ "iconIndicator": "#002B36",
+ "color1": "#B58900",
+ "color2": "#6B9E75"
+ }
+}
diff --git a/sources/pyside6/doc/tutorials/index.rst b/sources/pyside6/doc/tutorials/index.rst
index ae29da9d9..8a69a3c6f 100644
--- a/sources/pyside6/doc/tutorials/index.rst
+++ b/sources/pyside6/doc/tutorials/index.rst
@@ -1,5 +1,5 @@
-|project| Tutorials
-====================
+Tutorials
+=========
A collection of tutorials with walkthrough guides are
provided with |project| to help new users get started.
@@ -8,64 +8,6 @@ Some of these documents were ported from C++ to Python and cover a range of
topics, from basic use of widgets to step-by-step tutorials that show how an
application is put together.
-Before you start
-----------------
-
-Here you can find a couple of common questions and situations that will
-clarify questions before you start programming.
-If you have not installed PySide yet, remember to check the
-`Quick Start <../quickstart.html>`_ section.
-
-.. panels::
- :container: container-lg pb-1
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
-
- .. link-button:: pretutorial/whatisqt
- :type: ref
- :text: Qt, QML, Widgets... What is the difference?
- :classes: btn-link btn-block stretched-link
- ---
-
- .. link-button:: pretutorial/whichide
- :type: ref
- :text: Which IDEs are compatible with PySide?
- :classes: btn-link btn-block stretched-link
- ---
-
- .. link-button:: pretutorial/whatisshiboken
- :type: ref
- :text: Binding Generation: What is Shiboken?
- :classes: btn-link btn-block stretched-link
- ---
-
- .. link-button:: pretutorial/typesoffiles
- :type: ref
- :text: File Types in PySide
- :classes: btn-link btn-block stretched-link
- ---
-
- .. link-button:: pretutorial/distribution
- :type: ref
- :text: Distributing your application to other systems and platforms
- :classes: btn-link btn-block stretched-link
-
- ---
-
- .. link-button:: pretutorial/whyqtforpython
- :type: ref
- :text: As a Qt/C++ developer, why should I consider Qt for Python?
- :classes: btn-link btn-block stretched-link
-
-.. toctree::
- :hidden:
-
- pretutorial/whatisqt.rst
- pretutorial/whichide.rst
- pretutorial/whatisshiboken.rst
- pretutorial/typesoffiles.rst
- pretutorial/distribution.rst
- pretutorial/whyqtforpython.rst
-
Qt Widgets: Basic tutorials
---------------------------
@@ -73,86 +15,78 @@ If you want to see the available widgets in action, you can check the
`Qt Widget Gallery <https://doc.qt.io/qt-6/gallery.html>`_ to learn their
names and how they look like.
-.. panels::
- :container: container-lg pb-1
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
- :img-top-cls: d-flex align-self-center
-
- :img-top: basictutorial/widgets.png
-
- .. link-button:: basictutorial/widgets
- :type: ref
- :text: Your First QtWidgets Application
- :classes: btn-link btn-block stretched-link
- ---
- :img-top: basictutorial/clickablebutton.png
-
- .. link-button:: basictutorial/clickablebutton
- :type: ref
- :text: Using a Simple Button
- :classes: btn-link btn-block stretched-link
- ---
- :img-top: basictutorial/signals_slots.png
-
- .. link-button:: basictutorial/signals_and_slots
- :type: ref
- :text: Signals and Slots
- :classes: btn-link btn-block stretched-link
- ---
- :img-top: basictutorial/dialog.png
-
- .. link-button:: basictutorial/dialog
- :type: ref
- :text: Creating a Dialog Application
- :classes: btn-link btn-block stretched-link
- ---
- :img-top: basictutorial/tablewidget.png
-
- .. link-button:: basictutorial/tablewidget
- :type: ref
- :text: Displaying Data Using a Table Widget
- :classes: btn-link btn-block stretched-link
-
- ---
- :img-top: basictutorial/treewidget.png
-
- .. link-button:: basictutorial/treewidget
- :type: ref
- :text: Displaying Data Using a Tree Widget
- :classes: btn-link btn-block stretched-link
-
- ---
- :img-top: basictutorial/uifiles.png
-
- .. link-button:: basictutorial/uifiles
- :type: ref
- :text: Using .ui files from Designer or QtCreator with QUiLoader and pyside6-uic
- :classes: btn-link btn-block stretched-link
-
- ---
- :img-top: basictutorial/player-new.png
-
- .. link-button:: basictutorial/qrcfiles
- :type: ref
- :text: Using .qrc Files (pyside6-rcc)
- :classes: btn-link btn-block stretched-link
-
- ---
- :img-top: basictutorial/translations.png
-
- .. link-button:: basictutorial/translations
- :type: ref
- :text: Translating Applications
- :classes: btn-link btn-block stretched-link
-
- ---
- :img-top: basictutorial/widgetstyling-yes.png
-
- .. link-button:: basictutorial/widgetstyling
- :type: ref
- :text: Styling the Widgets Application
- :classes: btn-link btn-block stretched-link
+.. grid:: 1 3 3 3
+ :gutter: 2
+
+ .. grid-item-card:: Basic Widget
+ :class-item: cover-img
+ :link: basictutorial/widgets.html
+ :img-top: basictutorial/widgets.png
+
+ Your first QtWidgets Application
+
+ .. grid-item-card:: Basic Button
+ :class-item: cover-img
+ :link: basictutorial/clickablebutton.html
+ :img-top: basictutorial/clickablebutton.png
+
+ Using a Simple Button
+
+ .. grid-item-card:: Basic Connections
+ :class-item: cover-img
+ :link: basictutorial/signals_and_slots.html
+ :img-top: basictutorial/signals_slots.png
+
+ Signals and Slots
+
+ .. grid-item-card:: Basic Dialog
+ :class-item: cover-img
+ :link: basictutorial/dialog.html
+ :img-top: basictutorial/dialog.png
+
+ Creating a Dialog Application
+
+ .. grid-item-card:: Basic Table
+ :class-item: cover-img
+ :link: basictutorial/tablewidget.html
+ :img-top: basictutorial/tablewidget.png
+
+ Displaying Data Using a Table Widget
+
+ .. grid-item-card:: Basic Tree
+ :class-item: cover-img
+ :link: basictutorial/treewidget.html
+ :img-top: basictutorial/treewidget.png
+
+ Displaying Data Using a Tree Widget
+ .. grid-item-card:: Basic ``ui`` files
+ :class-item: cover-img
+ :link: basictutorial/uifiles.html
+ :img-top: basictutorial/uifiles.png
+
+ Using .ui files from Designer or QtCreator with QUiLoader and pyside6-uic
+
+ .. grid-item-card:: Basic ``qrc`` files
+ :class-item: cover-img
+ :link: basictutorial/qrcfiles.html
+ :img-top: basictutorial/player-new.png
+
+ Using .qrc Files (pyside6-rcc)
+
+ .. grid-item-card:: Basic Translations
+ :class-item: cover-img
+ :link: basictutorial/translations.html
+ :img-top: basictutorial/translations.png
+
+ Translating Applications
+
+ .. grid-item-card:: Basic Widget Style
+ :class-item: cover-img
+ :link: basictutorial/widgetstyling.html
+ :img-top: basictutorial/widgetstyling-yes.png
+
+ Styling the Widgets Application
.. toctree::
:hidden:
@@ -172,39 +106,43 @@ names and how they look like.
Quick/QML: Basic tutorials
--------------------------
-.. panels::
- :container: container-lg pb-1
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
- :img-top-cls: d-flex align-self-center
+.. grid:: 1 3 3 3
+ :gutter: 2
+
+ .. grid-item-card:: Basic Quick
+ :class-item: cover-img
+ :link: basictutorial/qml.html
+ :img-top: basictutorial/greenapplication.png
- :img-top: basictutorial/greenapplication.png
+ Your First QtQuick/QML Application
- .. link-button:: basictutorial/qml
- :type: ref
- :text: Your First QtQuick/QML Application
- :classes: btn-link btn-block stretched-link
- ---
- :img-top: qmlintegration/textproperties_material.png
+ .. grid-item-card:: Basic QML Integration
+ :class-item: cover-img
+ :link: qmlintegration/qmlintegration.html
+ :img-top: qmlintegration/textproperties_material.png
- .. link-button:: qmlintegration/qmlintegration
- :type: ref
- :text: Python-QML integration
- :classes: btn-link btn-block stretched-link
- ---
- :img-top: qmlapp/qmlapplication.png
+ Python-QML integration
- .. link-button:: qmlapp/qmlapplication
- :type: ref
- :text: QML Application Tutorial (QtCreator)
- :classes: btn-link btn-block stretched-link
- ---
- :img-top: qmlsqlintegration/example_list_view.png
+ .. grid-item-card:: QML Application
+ :class-item: cover-img
+ :link: qmlapp/qmlapplication.html
+ :img-top: qmlapp/qmlapplication.png
- .. link-button:: qmlsqlintegration/qmlsqlintegration
- :type: ref
- :text: QML, SQL and PySide Integration Tutorial
- :classes: btn-link btn-block stretched-link
+ QML Application Tutorial (QtCreator)
+ .. grid-item-card:: Advanced QML Integration
+ :class-item: cover-img
+ :link: qmlsqlintegration/qmlsqlintegration.html
+ :img-top: qmlsqlintegration/example_list_view.png
+
+ QML, SQL and PySide Integration Tutorial
+
+ .. grid-item-card:: Extended Explorer
+ :class-item: cover-img
+ :link: extendedexplorer/extendedexplorer.html
+ :img-top: extendedexplorer/resources/extendedexplorer.webp
+
+ Extending an Qt Quick Controls example
.. toctree::
:maxdepth: 1
@@ -214,28 +152,27 @@ Quick/QML: Basic tutorials
qmlintegration/qmlintegration.rst
qmlapp/qmlapplication.rst
qmlsqlintegration/qmlsqlintegration.rst
+ extendedexplorer/extendedexplorer.md
General Applications
--------------------
-.. panels::
- :container: container-lg pb-1
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
- :img-top-cls: d-flex align-self-center
+.. grid:: 1 3 3 3
+ :gutter: 2
+
+ .. grid-item-card:: Data Visualization
+ :class-item: cover-img
+ :link: datavisualize/index.html
+ :img-top: datavisualize/images/datavisualization_app.png
- :img-top: datavisualize/images/datavisualization_app.png
+ Data Visualization Tool
- .. link-button:: datavisualize/index
- :type: ref
- :text: Data Visualization Tool
- :classes: btn-link btn-block stretched-link
- ---
- :img-top: expenses/expenses_tool.png
+ .. grid-item-card:: Expenses Application
+ :class-item: cover-img
+ :link: expenses/expenses.html
+ :img-top: expenses/expenses_tool.png
- .. link-button:: expenses/expenses
- :type: ref
- :text: Expenses Tool
- :classes: btn-link btn-block stretched-link
+ Expenses administration tool
.. toctree::
:hidden:
@@ -243,6 +180,13 @@ General Applications
datavisualize/index.rst
expenses/expenses.rst
+Qt Overviews
+------------
+
+.. toctree::
+ :maxdepth: 1
+
+ ../overviews/overviews-main.rst
C++ and Python
--------------
@@ -258,4 +202,5 @@ Debug a PySide6 Application
:maxdepth: 1
debugging/mixed_debugging.rst
+ debugging/qml_debugging.rst
diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py b/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py
new file mode 100644
index 000000000..3a37cc0f3
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py
@@ -0,0 +1,137 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import sys
+
+from PySide6.QtWidgets import (QAbstractItemView, QApplication, QMainWindow,
+ QListView)
+from PySide6.QtCore import (QByteArray, QDataStream, QIODevice, QMimeData,
+ QModelIndex, QStringListModel, Qt)
+
+
+class DragDropListModel(QStringListModel):
+ """A simple model that uses a QStringList as its data source."""
+
+ def __init__(self, strings, parent=None):
+ super().__init__(strings, parent)
+
+#! [0]
+
+ def canDropMimeData(self, data, action, row, column, parent):
+ if not data.hasFormat("application/vnd.text.list"):
+ return False
+
+ if column > 0:
+ return False
+
+ return True
+#! [0]
+#! [1]
+ def dropMimeData(self, data, action, row, column, parent):
+ if not self.canDropMimeData(data, action, row, column, parent):
+ return False
+
+ if action == Qt.IgnoreAction:
+ return True
+#! [1]
+
+#! [2]
+ begin_row = 0
+
+ if row != -1:
+ begin_row = row
+#! [2] #! [3]
+ elif parent.isValid():
+ begin_row = parent.row()
+#! [3] #! [4]
+ else:
+ begin_row = self.rowCount(QModelIndex())
+#! [4]
+
+#! [5]
+ encoded_data = data.data("application/vnd.text.list")
+ stream = QDataStream(encoded_data, QIODevice.ReadOnly)
+ new_items = []
+ while not stream.atEnd():
+ new_items.append(stream.readQString())
+#! [5]
+
+#! [6]
+ self.insertRows(begin_row, len(new_items), QModelIndex())
+ for text in new_items:
+ idx = self.index(begin_row, 0, QModelIndex())
+ self.setData(idx, text)
+ begin_row += 1
+
+ return True
+#! [6]
+
+#! [7]
+ def flags(self, index):
+ default_flags = super().flags(index)
+ if index.isValid():
+ return Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled | default_flags
+ return Qt.ItemIsDropEnabled | default_flags
+#! [7]
+
+#! [8]
+ def mimeData(self, indexes):
+ mime_data = QMimeData()
+ encoded_data = QByteArray()
+ stream = QDataStream(encoded_data, QIODevice.WriteOnly)
+ for index in indexes:
+ if index.isValid():
+ text = self.data(index, Qt.DisplayRole)
+ stream.writeQString(text)
+
+ mime_data.setData("application/vnd.text.list", encoded_data)
+ return mime_data
+#! [8]
+
+#! [9]
+ def mimeTypes(self):
+ return ["application/vnd.text.list"]
+#! [9]
+
+#! [10]
+ def supportedDropActions(self):
+ return Qt.CopyAction | Qt.MoveAction
+#! [10]
+
+
+class MainWindow(QMainWindow):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ file_menu = self.menuBar().addMenu("&File")
+ quit_action = file_menu.addAction("E&xit")
+ quit_action.setShortcut("Ctrl+Q")
+
+#! [mainwindow0]
+ self._list_view = QListView(self)
+ self._list_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
+ self._list_view.setDragEnabled(True)
+ self._list_view.setAcceptDrops(True)
+ self._list_view.setDropIndicatorShown(True)
+#! [mainwindow0]
+
+ quit_action.triggered.connect(self.close)
+
+ self.setup_list_items()
+
+ self.setCentralWidget(self._list_view)
+ self.setWindowTitle("List View")
+
+ def setup_list_items(self):
+ items = ["Oak", "Fir", "Pine", "Birch", "Hazel", "Redwood", "Sycamore",
+ "Chestnut", "Mahogany"]
+ model = DragDropListModel(items, self)
+ self._list_view.setModel(model)
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ window = MainWindow()
+ window.show()
+ sys.exit(app.exec())
diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py b/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py
new file mode 100644
index 000000000..1bacfd829
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import sys
+
+from PySide6.QtWidgets import (QApplication, QFileSystemModel, QLabel,
+ QVBoxLayout, QWidget)
+from PySide6.QtGui import QPalette
+from PySide6.QtCore import QDir, Qt
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+ window = QWidget()
+ layout = QVBoxLayout(window)
+ title = QLabel("Some items from the directory model", window)
+ title.setBackgroundRole(QPalette.Base)
+ title.setMargin(8)
+ layout.addWidget(title)
+
+#! [0]
+ model = QFileSystemModel()
+ model.setRootPath(QDir.currentPath())
+
+ def on_directory_loaded(directory):
+ parent_index = model.index(directory)
+ num_rows = model.rowCount(parent_index)
+#! [1]
+ for row in range(num_rows):
+ index = model.index(row, 0, parent_index)
+#! [1]
+#! [2]
+ text = model.data(index, Qt.DisplayRole)
+#! [2]
+ label = QLabel(text, window)
+ layout.addWidget(label)
+
+ model.directoryLoaded.connect(on_directory_loaded)
+#! [0]
+
+ window.setWindowTitle("A simple model example")
+ window.show()
+ sys.exit(app.exec())
diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py b/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py
new file mode 100644
index 000000000..2c8493aa9
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py
@@ -0,0 +1,124 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import sys
+
+from PySide6.QtWidgets import (QApplication, QListView)
+from PySide6.QtCore import QAbstractListModel, QStringListModel, QModelIndex, Qt
+
+
+#! [0]
+class StringListModel(QAbstractListModel):
+ def __init__(self, strings, parent=None):
+ super().__init__(parent)
+ self._strings = strings
+
+#! [0]
+ def rowCount(self, parent=QModelIndex()):
+ """Returns the number of items in the string list as the number of rows
+ in the model."""
+ return len(self._strings)
+#! [0]
+
+#! [1]
+ def data(self, index, role):
+ """Returns an appropriate value for the requested data.
+ If the view requests an invalid index, an invalid variant is returned.
+ Any valid index that corresponds to a string in the list causes that
+ string to be returned."""
+ row = index.row()
+ if not index.isValid() or row >= len(self._strings):
+ return None
+ if role != Qt.DisplayRole and role != Qt.EditRole:
+ return None
+ return self._strings[row]
+#! [1]
+
+#! [2]
+ def headerData(self, section, orientation, role=Qt.DisplayRole):
+ """Returns the appropriate header string depending on the orientation of
+ the header and the section. If anything other than the display role is
+ requested, we return an invalid variant."""
+ if role != Qt.DisplayRole:
+ return None
+ if orientation == Qt.Horizontal:
+ return f"Column {section}"
+ return f"Row {section}"
+#! [2]
+
+#! [3]
+ def flags(self, index):
+ """Returns an appropriate value for the item's flags. Valid items are
+ enabled, selectable, and editable."""
+
+ if not index.isValid():
+ return Qt.ItemIsEnabled
+ return super().flags(index) | Qt.ItemIsEditable
+#! [3]
+
+ #! [4]
+ def setData(self, index, value, role=Qt.EditRole):
+ """Changes an item in the string list, but only if the following conditions
+ are met:
+
+ # The index supplied is valid.
+ # The index corresponds to an item to be shown in a view.
+ # The role associated with editing text is specified.
+
+ The dataChanged() signal is emitted if the item is changed."""
+
+ if index.isValid() and role == Qt.EditRole:
+ self._strings[index.row()] = value
+ self.dataChanged.emit(index, index, {role})
+ return True
+#! [4] #! [5]
+ return False
+#! [5]
+
+#! [6]
+ def insertRows(self, position, rows, parent):
+ """Inserts a number of rows into the model at the specified position."""
+ self.beginInsertRows(QModelIndex(), position, position + rows - 1)
+ for row in range(rows):
+ self._strings.insert(position, "")
+ self.endInsertRows()
+ return True
+#! [6] #! [7]
+#! [7]
+
+#! [8]
+ def removeRows(self, position, rows, parent):
+ """Removes a number of rows from the model at the specified position."""
+ self.beginRemoveRows(QModelIndex(), position, position + rows - 1)
+ for row in range(rows):
+ del self._strings[position]
+ self.endRemoveRows()
+ return True
+#! [8] #! [9]
+#! [9]
+
+
+#! [main0]
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+#! [main1]
+ numbers = ["One", "Two", "Three", "Four", "Five"]
+ model = StringListModel(numbers)
+#! [main0] #! [main1] #! [main2] #! [main3]
+ view = QListView()
+#! [main2]
+ view.setWindowTitle("View onto a string list model")
+#! [main4]
+ view.setModel(model)
+#! [main3] #! [main4]
+
+ model.insertRows(5, 7, QModelIndex())
+ for row in range(5, 12):
+ index = model.index(row, 0, QModelIndex())
+ model.setData(index, f"{row+1}")
+
+#! [main5]
+ view.show()
+ sys.exit(app.exec())
+#! [main5]
diff --git a/sources/pyside6/doc/tutorials/portingguide/chapter1/chapter1.rst b/sources/pyside6/doc/tutorials/portingguide/chapter1/chapter1.rst
index 2a3bd7079..87fb97660 100644
--- a/sources/pyside6/doc/tutorials/portingguide/chapter1/chapter1.rst
+++ b/sources/pyside6/doc/tutorials/portingguide/chapter1/chapter1.rst
@@ -26,7 +26,7 @@ the tables. Port these helper functions first. Here is how
the C++ and Python versions of these functions look like:
C++ version
-------------
+-----------
.. literalinclude:: initdb.h
:language: c++
@@ -34,7 +34,7 @@ C++ version
:lines: 9-33
Python version
----------------
+--------------
.. literalinclude:: createdb.py
:language: python
@@ -45,16 +45,16 @@ Now that the helper functions are in place, port ``initDb``.
Here is how the C++ and Python versions of this function
looks like:
-C++ version
-------------
+C++ version (initDb)
+--------------------
.. literalinclude:: initdb.h
:language: c++
:linenos:
:lines: 35-112
-Python version
----------------
+Python version (init_db)
+------------------------
.. literalinclude:: createdb.py
:language: python
@@ -77,7 +77,7 @@ test it, add the following code to ``main.py`` and run it:
Use the following command from the prompt to run:
-.. code-block::
+.. code-block:: bash
python main.py
diff --git a/sources/pyside6/doc/tutorials/portingguide/chapter2/chapter2.rst b/sources/pyside6/doc/tutorials/portingguide/chapter2/chapter2.rst
index fa6ef1116..83ba3357b 100644
--- a/sources/pyside6/doc/tutorials/portingguide/chapter2/chapter2.rst
+++ b/sources/pyside6/doc/tutorials/portingguide/chapter2/chapter2.rst
@@ -47,16 +47,16 @@ For example, painting stars to represent the rating for
each book in the table. Here is how the reimplemented
code looks like:
-C++ version
-------------
+C++ version (bookdelegate)
+--------------------------
.. literalinclude:: bookdelegate.cpp
:language: c++
:linenos:
:lines: 22-
-Python version
----------------
+Python version (bookdelegate)
+-----------------------------
.. literalinclude:: bookdelegate.py
:language: python
diff --git a/sources/pyside6/doc/tutorials/portingguide/chapter3/chapter3.rst b/sources/pyside6/doc/tutorials/portingguide/chapter3/chapter3.rst
index 1d48d4ea3..98d4d3982 100644
--- a/sources/pyside6/doc/tutorials/portingguide/chapter3/chapter3.rst
+++ b/sources/pyside6/doc/tutorials/portingguide/chapter3/chapter3.rst
@@ -21,9 +21,9 @@ and add the following imports to it:
To generate this Python code, run the following command on the
prompt:
-.. code-block::
+.. code-block:: bash
- pyside6-uic bookwindow.ui > ui_bookwindow.py
+ pyside6-uic bookwindow.ui -o ui_bookwindow.py
Try porting the remaining code now. To begin with, here is
how both the versions of the constructor code looks:
@@ -101,9 +101,9 @@ image only.
Now, run the ``pyside6-rcc`` tool on the ``books.qrc`` file
to generate ``rc_books.py``.
-.. code-block::
+.. code-block:: bash
- pyside6-rcc books.qrc > rc_books.py
+ pyside6-rcc books.qrc -o rc_books.py
Once you have the Python script generated, make the
following changes to ``bookdelegate.py`` and ``main.py``:
diff --git a/sources/pyside6/doc/tutorials/portingguide/index.rst b/sources/pyside6/doc/tutorials/portingguide/index.rst
index ed1a7a4f6..0b89c2ff8 100644
--- a/sources/pyside6/doc/tutorials/portingguide/index.rst
+++ b/sources/pyside6/doc/tutorials/portingguide/index.rst
@@ -8,7 +8,7 @@ to Python to understand this.
Before you start, ensure that all the prerequisites for
Qt for Python are met. See
-:doc:`Getting Started <../../gettingstarted>` for more
+:doc:`Getting Started <../../gettingstarted/index>` for more
information. In addition, familiarize yourself with the
basic differences between Qt in C++ and in Python.
@@ -63,7 +63,7 @@ C++ vs Python
doStuff(key, value)
In this example, ``func()`` would treat ``var`` as a local
-name without the ``global`` statement. This would lead to
+name without the ``global`` statement. This would lead to
a ``NameError`` in the ``value is None`` handling, on
accessing ``var``. For more information about this, see
`Python refernce documentation <python refdoc>`_.
diff --git a/sources/pyside6/doc/tutorials/qmlapp/qmlapplication.rst b/sources/pyside6/doc/tutorials/qmlapp/qmlapplication.rst
index b68a3686e..c6d72e742 100644
--- a/sources/pyside6/doc/tutorials/qmlapp/qmlapplication.rst
+++ b/sources/pyside6/doc/tutorials/qmlapp/qmlapplication.rst
@@ -15,15 +15,15 @@ defined in the QML file.
Before you begin, install the following prerequisites:
* The `PySide6 <https://pypi.org/project/PySide6/>`_ Python packages.
-* Qt Creator v4.9 beta1 or later from
+* *Qt Creator* from
`https://download.qt.io
- <https://download.qt.io/snapshots/qtcreator/4.9/4.9.0-beta1/>`_.
+ <https://download.qt.io/snapshots/qtcreator/>`_.
The following step-by-step instructions guide you through application
-development process using Qt Creator:
+development process using *Qt Creator*:
-#. Open Qt Creator and select **File > New File or Project..** menu item
+#. Open *Qt Creator* and select **File > New File or Project..** menu item
to open following dialog:
.. image:: newpyproject.png
diff --git a/sources/pyside6/doc/tutorials/qmlintegration/qmlintegration.rst b/sources/pyside6/doc/tutorials/qmlintegration/qmlintegration.rst
index d9de42ee2..ff6fe3e31 100644
--- a/sources/pyside6/doc/tutorials/qmlintegration/qmlintegration.rst
+++ b/sources/pyside6/doc/tutorials/qmlintegration/qmlintegration.rst
@@ -2,17 +2,17 @@ Python-QML integration
======================
This tutorial provides a quick walk-through of a python application that loads, and interacts with
-a QML file. QML is a declarative language that lets you design UIs faster than a traditional
-language, such as C++. The QtQml and QtQuick modules provides the necessary infrastructure for
+a QML file. QML is a declarative language that lets you design UIs faster than a traditional
+language, such as C++. The QtQml and QtQuick modules provides the necessary infrastructure for
QML-based UIs.
In this tutorial, you will learn how to integrate Python with a QML application.
This mechanism will help us to understand how to use Python as a backend for certain
-signals from the UI elements in the QML interface. Additionally, you will learn how to provide
+signals from the UI elements in the QML interface. Additionally, you will learn how to provide
a modern look to your QML application using one of the features from Qt Quick Controls 2.
The tutorial is based on an application that allow you to set many text properties, like increasing
-the font size, changing the color, changing the style, and so on. Before you begin, install the
+the font size, changing the color, changing the style, and so on. Before you begin, install the
`PySide6 <https://pypi.org/project/PySide6/>`_ Python packages.
The following step-by-step process will guide you through the key elements of the QML based
@@ -35,7 +35,7 @@ application and PySide6 integration:
Notice that we only need a :code:`QQmlApplicationEngine` to
:code:`load` the QML file.
-#. Define the `Bridge` class, containing all the logic for the element
+#. Define the ``Bridge`` class, containing all the logic for the element
that will be register in QML:
.. literalinclude:: main.py
@@ -48,7 +48,7 @@ application and PySide6 integration:
class and the variables :code:`QML_IMPORT_NAME` and
:code:`QML_IMPORT_MAJOR_VERSION`.
-#. Now, go back to the QML file and connect the signals to the slots defined in the `Bridge` class:
+#. Now, go back to the QML file and connect the signals to the slots defined in the ``Bridge`` class:
.. code:: js
@@ -68,7 +68,7 @@ application and PySide6 integration:
The properties *Italic*, *Bold*, and *Underline* are mutually
exclusive, this means only one can be active at any time.
- To achieve this each time we select one of these options, we
+ To achieve this each time we select one of these options, we
check the three properties via the QML element property as you can
see in the above snippet.
Only one of the three will return *True*, while the other two
@@ -95,22 +95,22 @@ application and PySide6 integration:
#. Now, for changing the look of our application, you have two options:
- 1. Use the command line: execute the python file adding the option, `--style`::
+ 1. Use the command line: execute the python file adding the option, ``--style``::
python main.py --style material
- 2. Use a `qtquickcontrols2.conf` file:
+ 2. Use a ``qtquickcontrols2.conf`` file:
.. literalinclude:: qtquickcontrols2.conf
:linenos:
- Then add it to your `.qrc` file:
+ Then add it to your ``.qrc`` file:
.. literalinclude:: style.qrc
:linenos:
- Generate the *rc* file running, `pyside6-rcc style.qrc > style_rc.py`
- And finally import it from your `main.py` script.
+ Generate the *rc* file running, ``pyside6-rcc style.qrc -o style_rc.py``
+ And finally import it from your ``main.py`` script.
.. literalinclude:: main.py
:linenos:
diff --git a/sources/pyside6/doc/tutorials/qmlsqlintegration/qmlsqlintegration.rst b/sources/pyside6/doc/tutorials/qmlsqlintegration/qmlsqlintegration.rst
index 4c0131f32..eee3f807e 100644
--- a/sources/pyside6/doc/tutorials/qmlsqlintegration/qmlsqlintegration.rst
+++ b/sources/pyside6/doc/tutorials/qmlsqlintegration/qmlsqlintegration.rst
@@ -14,9 +14,9 @@ name of our table, and define the global function ``createTable()`` that creates
doesn't already exist.
The database contains a single line to mock the beginning of a conversation.
- .. literalinclude:: sqlDialog.py
- :linenos:
- :lines: 3-42
+.. literalinclude:: sqlDialog.py
+ :linenos:
+ :lines: 4-43
The ``SqlConversationModel`` class offers the read-only data model required for the non-editable
contacts list. It derives from the :ref:`QSqlQueryModel` class, which is the logical choice for
@@ -26,25 +26,25 @@ Then, we proceed to create the table, set its name to the one defined previously
We add the necessary attributes to the table, to have a program that reflects the idea
of a chat application.
- .. literalinclude:: sqlDialog.py
- :linenos:
- :lines: 46-58
+.. literalinclude:: sqlDialog.py
+ :linenos:
+ :lines: 47-59
In ``setRecipient()``, you set a filter over the returned results from the database, and
emit a signal every time the recipient of the message changes.
- .. literalinclude:: sqlDialog.py
- :linenos:
- :lines: 60-69
+.. literalinclude:: sqlDialog.py
+ :linenos:
+ :lines: 61-70
The ``data()`` function falls back to ``QSqlTableModel``'s implementation if the role is not a
custom user role.
If you get a user role, we can subtract :meth:`~.QtCore.Qt.UserRole` from it to get the index of
that field, and then use that index to find the value to be returned.
- .. literalinclude:: sqlDialog.py
- :linenos:
- :lines: 71-78
+.. literalinclude:: sqlDialog.py
+ :linenos:
+ :lines: 72-79
In ``roleNames()``, we return a Python dictionary with our custom role and role names as key-values
@@ -53,27 +53,27 @@ Alternatively, it can be useful to declare an Enum to hold all of the role value
Note that ``names`` has to be a hash to be used as a dictionary key,
and that's why we're using the ``hash`` function.
- .. literalinclude:: sqlDialog.py
- :linenos:
- :lines: 80-94
+.. literalinclude:: sqlDialog.py
+ :linenos:
+ :lines: 81-95
The ``send_message()`` function uses the given recipient and message to insert a new record into
the database.
Using :meth:`~.QSqlTableModel.OnManualSubmit` requires you to also call ``submitAll()``,
since all the changes will be cached in the model until you do so.
- .. literalinclude:: sqlDialog.py
- :linenos:
- :lines: 96-115
+.. literalinclude:: sqlDialog.py
+ :linenos:
+ :lines: 97-116
chat.qml
--------
Let's look at the ``chat.qml`` file.
- .. literalinclude:: chat.qml
- :linenos:
- :lines: 3-5
+.. literalinclude:: chat.qml
+ :linenos:
+ :lines: 4-6
First, import the Qt Quick module.
This gives us access to graphical primitives such as Item, Rectangle, Text, and so on.
@@ -86,9 +86,9 @@ root type, Window:
Let's step through the ``chat.qml`` file.
- .. literalinclude:: chat.qml
- :linenos:
- :lines: 8-13
+.. literalinclude:: chat.qml
+ :linenos:
+ :lines: 9-14
``ApplicationWindow`` is a Window with some added convenience for creating a header and a footer.
It also provides the foundation for popups and supports some basic styling, such as the background
@@ -101,9 +101,9 @@ Once we've set these, we have a properly sized, empty window ready to be filled
Because we are exposing the :code:`SqlConversationModel` class to QML, we will
declare a component to access it:
- .. literalinclude:: chat.qml
- :linenos:
- :lines: 15-17
+.. literalinclude:: chat.qml
+ :linenos:
+ :lines: 16-18
There are two ways of laying out items in QML: `Item Positioners`_ and `Qt Quick Layouts`_.
@@ -113,13 +113,13 @@ There are two ways of laying out items in QML: `Item Positioners`_ and `Qt Quick
resizable user interfaces.
Below, we use `ColumnLayout`_ to vertically lay out a `ListView`_ and a `Pane`_.
- .. literalinclude:: chat.qml
- :linenos:
- :lines: 19-22
+ .. literalinclude:: chat.qml
+ :linenos:
+ :lines: 20-23
- .. literalinclude:: chat.qml
- :linenos:
- :lines: 71-73
+ .. literalinclude:: chat.qml
+ :linenos:
+ :lines: 72-74
Pane is basically a rectangle whose color comes from the application's style.
It's similar to `Frame`_, but it has no stroke around its border.
@@ -144,18 +144,16 @@ remaining space that is left after accommodating the Pane.
.. _attached properties: https://doc.qt.io/qt-5/qml-qtquick-layouts-layout.html
.. _Layout.fillWidth: https://doc.qt.io/qt-5/qml-qtquick-layouts-layout.html#fillWidth-attached-prop
.. _Layout.fillHeight: https://doc.qt.io/qt-5/qml-qtquick-layouts-layout.html#fillHeight-attached-prop
-.. _ListView: https://doc.qt.io/qt-5/qml-qtquick-listview.html
.. _Qt Quick QML Types: https://doc.qt.io/qt-5/qtquick-qmlmodule.html
Let's look at the ``Listview`` in detail:
- .. literalinclude:: chat.qml
- :linenos:
- :lines: 22-69
+.. literalinclude:: chat.qml
+ :linenos:
+ :lines: 23-70
After filling the ``width`` and ``height`` of its parent, we also set some margins on the view.
-
Next, we set `displayMarginBeginning`_ and `displayMarginEnd`_.
These properties ensure that the delegates outside the view don't disappear when you
scroll at the edges of the view.
@@ -179,9 +177,9 @@ At the bottom of the screen, we place a `TextArea`_ item to allow multi-line tex
button to send the message.
We use Pane to cover the area under these two items:
- .. literalinclude:: chat.qml
- :linenos:
- :lines: 71-95
+.. literalinclude:: chat.qml
+ :linenos:
+ :lines: 72-96
The `TextArea`_ should fill the available width of the screen.
We assign some placeholder text to provide a visual cue to the contact as to where they should begin
@@ -203,16 +201,16 @@ main.py
We use ``logging`` instead of Python's ``print()``, because it provides a better way to control the
messages levels that our application will generate (errors, warnings, and information messages).
- .. literalinclude:: main.py
- :linenos:
- :lines: 3-15
+.. literalinclude:: main.py
+ :linenos:
+ :lines: 4-16
``connectToDatabase()`` creates a connection with the SQLite database, creating the actual file
if it doesn't already exist.
- .. literalinclude:: main.py
- :linenos:
- :lines: 18-38
+.. literalinclude:: main.py
+ :linenos:
+ :lines: 19-39
A few interesting things happen in the ``main`` function:
@@ -227,8 +225,8 @@ A few interesting things happen in the ``main`` function:
Finally, the Qt application runs, and your program starts.
- .. literalinclude:: main.py
- :linenos:
- :lines: 41-51
+.. literalinclude:: main.py
+ :linenos:
+ :lines: 42-52
.. image:: example_list_view.png
diff --git a/sources/pyside6/doc/videos.rst b/sources/pyside6/doc/videos.rst
index 95172bda4..919c9ff38 100644
--- a/sources/pyside6/doc/videos.rst
+++ b/sources/pyside6/doc/videos.rst
@@ -1,186 +1,155 @@
.. _video-gallery:
-|project| Videos
-================
+Videos
+======
Tutorials
---------
-.. panels::
- :body: align-items-center jutify-content-center text-center
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
- :img-top-cls: d-flex align-self-center img-responsive card-img-top-main
+.. grid:: 1 3 3 3
+ :gutter: 2
- Resources overview
- ^^^^^^^^^^^^^^^^^^
- .. raw:: html
+ .. grid-item-card:: Resources overview
+ :img-top: https://img.youtube.com/vi/sywLvidNkbw/mqdefault.jpg
+ :link: https://www.youtube.com/embed/sywLvidNkbw
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/sywLvidNkbw" frameborder="0" allowfullscreen>
- </iframe>
- </div>
- ---
+ .. grid-item-card:: Repository overview
+ :img-top: https://img.youtube.com/vi/RP0K1B7fqMs/mqdefault.jpg
+ :link: https://www.youtube.com/embed/RP0K1B7fqMs
- Repository overview
- ^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: Shiboken overview
+ :img-top: https://img.youtube.com/vi/RUwV_sx_gBM/mqdefault.jpg
+ :link: https://www.youtube.com/embed/RUwV_sx_gBM
- .. raw:: html
+ .. grid-item-card:: Tutorial
+ :img-top: https://img.youtube.com/vi/Cqo0-EQmy1Q/mqdefault.jpg
+ :link: https://www.youtube.com/embed/Cqo0-EQmy1Q
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/RP0K1B7fqMs" frameborder="0" allowfullscreen>
- </iframe>
- </div>
- ---
+ How to create a simple Qt Widgets app with PySide6
- Introduction to the Shiboken Wizard
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: Tutorial
+ :img-top: https://img.youtube.com/vi/JxfiUx60Mbg/mqdefault.jpg
+ :link: https://www.youtube.com/embed/JxfiUx60Mbg
- .. raw:: html
+ Making a QML Application in Python
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/RUwV_sx_gBM" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ .. grid-item-card:: Tutorial
+ :img-top: https://img.youtube.com/vi/i-utZN_NP6c/mqdefault.jpg
+ :link: https://www.youtube.com/embed/i-utZN_NP6c
-Community events
-----------------
+ How to install PySide6 on a new virtual environment
-.. panels::
- :body: align-items-center jutify-content-center text-center
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
- :img-top-cls: d-flex align-self-center img-responsive card-img-top-main
- Akademy 2021 - Qt for Python
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Community events
+----------------
- .. raw:: html
+.. grid:: 1 3 3 3
+ :gutter: 2
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/Ftm68AzYvr8" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ .. grid-item-card:: Akademy 2021
+ :img-top: https://img.youtube.com/vi/Ftm68AzYvr8/mqdefault.jpg
+ :link: https://www.youtube.com/embed/Ftm68AzYvr8
+ Qt for Python
Webinars
--------
-.. panels::
- :body: align-items-center jutify-content-center text-center
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
- :img-top-cls: d-flex align-self-center img-responsive card-img-top-main
+.. grid:: 1 3 3 3
+ :gutter: 2
- Python and C++ interoperability with Shiboken
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: Online Webinar
+ :img-top: https://img.youtube.com/vi/eqHveQ5JTZU/mqdefault.jpg
+ :link: https://www.youtube.com/embed/eqHveQ5JTZU
- .. raw:: html
+ How your Python projects can benefit from Qt
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/wOMlDutOWXI" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ .. grid-item-card:: Online Webinar
+ :img-top: https://img.youtube.com/vi/wOMlDutOWXI/mqdefault.jpg
+ :link: https://www.youtube.com/embed/wOMlDutOWXI
- ---
+ Interoperability of Python and C++ using Shiboken
- Develop your first Qt for Python application
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. grid-item-card:: Online Webinar
+ :img-top: https://img.youtube.com/vi/HDBjmSiOBxY/mqdefault.jpg
+ :link: https://www.youtube.com/embed/HDBjmSiOBxY
- .. raw:: html
+ Developing your first Qt for Python application
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/HDBjmSiOBxY" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ .. grid-item-card:: Online Webinar
+ :img-top: https://img.youtube.com/vi/wKqLaNqxgas/mqdefault.jpg
+ :link: https://www.youtube.com/embed/wKqLaNqxgas
- ---
-
- Creating user interfaces with Qt for Python
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- .. raw:: html
-
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/wKqLaNqxgas" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ Creating user interfaces with Qt for Python
Conferences
-----------
-.. panels::
- :body: align-items-center jutify-content-center text-center
- :container: container-lg pb-3
- :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2
- :img-top-cls: d-flex align-self-center img-responsive card-img-top-main
-
- QtVirtualTechCon2020: From Prototypes to Hybrid Applications
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. grid:: 1 3 3 3
+ :gutter: 2
- .. raw:: html
+ .. grid-item-card:: PyConES 2023
+ :img-top: https://img.youtube.com/vi/XuqdTvisqkQ/mqdefault.jpg
+ :link: https://www.youtube.com/embed/XuqdTvisqkQ
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/Vb1dbLQafyM" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ Asynchronous programming with asyncio and Qt
- ---
+ .. grid-item-card:: QtWS 2022
+ :img-top: https://img.youtube.com/vi/8wcdN1Iw1Uk/mqdefault.jpg
+ :link: https://www.youtube.com/embed/8wcdN1Iw1Uk
- QtWS2019: Utilizing Shiboken to Enhance your Application
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ 5 Reasons Why You Should Use the Latest Qt for Python
- .. raw:: html
+ .. grid-item-card:: QtDeCon 2022
+ :img-top: https://img.youtube.com/vi/ZUNg19OlDeE/mqdefault.jpg
+ :link: https://www.youtube.com/embed/ZUNg19OlDeE
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/mAfEVPgHRt8" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ Hybrid Qt Development: Boosting Your Projects with Python
- ---
+ .. grid-item-card:: QtWS 2021
+ :img-top: https://img.youtube.com/vi/SylgpRc-Lrg/mqdefault.jpg
+ :link: https://www.youtube.com/embed/SylgpRc-Lrg
- QtWS2019: Introduction to Qt for Python
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Hybrid Qt Development: boosting Projects with Python
- .. raw:: html
+ .. grid-item-card:: QtWS 2020
+ :img-top: https://img.youtube.com/vi/Vb1dbLQafyM/mqdefault.jpg
+ :link: https://www.youtube.com/embed/Vb1dbLQafyM
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/214TWASZVgA" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ Prototypes to Hybrid Applications
- ---
+ .. grid-item-card:: QtWS 2019
+ :img-top: https://img.youtube.com/vi/mAfEVPgHRt8/mqdefault.jpg
+ :link: https://www.youtube.com/embed/mAfEVPgHRt8
- QtWS2019: How to bring your C++ project to Python land
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Using Shiboken to Enhance Application
- .. raw:: html
+ .. grid-item-card:: QtWS 2019
+ :img-top: https://img.youtube.com/vi/214TWASZVgA/mqdefault.jpg
+ :link: https://www.youtube.com/embed/214TWASZVgA
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/XmY-tWTi9gY" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ Intro to Qt for Python
- ---
+ .. grid-item-card:: QtWS 2019
+ :img-top: https://img.youtube.com/vi/XmY-tWTi9gY/mqdefault.jpg
+ :link: https://www.youtube.com/embed/XmY-tWTi9gY
- QtWS2018: Mastering Qt for Python in 20 min
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Using C++ project in Python
- .. raw:: html
+ .. grid-item-card:: QtWS 2019
+ :img-top: https://img.youtube.com/vi/rRDoToEOlbY/mqdefault.jpg
+ :link: https://www.youtube.com/embed/rRDoToEOlbY
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/IhxZ99usPqY" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ Using Qt for Python for embedded system development
- ---
+ .. grid-item-card:: QtWS 2018
+ :img-top: https://img.youtube.com/vi/IhxZ99usPqY/mqdefault.jpg
+ :link: https://www.youtube.com/embed/IhxZ99usPqY
- QtWS2017: Take a walk on the PySide
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ Qt for Python in 20 min
- .. raw:: html
+ .. grid-item-card:: QtWS 2017
+ :img-top: https://img.youtube.com/vi/Sb4FV6SdHHQ/mqdefault.jpg
+ :link: https://www.youtube.com/embed/Sb4FV6SdHHQ
- <div class='embed-container'>
- <iframe src="https://www.youtube.com/embed/Sb4FV6SdHHQ" frameborder="0" allowfullscreen>
- </iframe>
- </div>
+ A walk to PySide