diff options
author | Dennis Oberst <dennis.oberst@qt.io> | 2023-01-26 12:35:32 +0100 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-03-30 12:09:44 +0000 |
commit | c65128387e82b997efa9840943d1bf1cc0ca5ec3 (patch) | |
tree | 179bdae33ebbb93146be1a98bfc123f6e5550385 /sources | |
parent | 7c5fe1f178a62a54e88d26f945004161cfbc7145 (diff) |
docs: add extendedexplorer tutorial
Extended the filesystemexplorer example with interactive scheme
switching and wrote a tutorial about it. This tutorial uses Qml
features from 6.5. The tutorial is intended to provide users with
an overview of how to create modern applications with PySide/QtQuick
Task-number: QTBUG-108289
Task-number: PYSIDE-2224
Change-Id: I114824680156d0eacbbfe3363c67d1d5784a2219
Reviewed-by: Adrian Herrmann <adrian.herrmann@qt.io>
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit 3813faa6dac1377e390c9b89fff236bbc0bf8bbb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'sources')
33 files changed, 1732 insertions, 0 deletions
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..b699720dd --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/Main.qml @@ -0,0 +1,203 @@ +// 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 + +ApplicationWindow { + id: root + width: 1100 + height: 600 + visible: true + flags: Qt.Window | Qt.FramelessWindowHint + title: qsTr("Qt Quick Controls - File System Explorer") + + property string currentFilePath: "" + property bool expandPath: false + + menuBar: MyMenuBar { + rootWindow: root + + infoText: currentFilePath + ? (expandPath ? currentFilePath + : currentFilePath.substring(currentFilePath.lastIndexOf("/") + 1, currentFilePath.length)) + : "File System Explorer" + + MyMenu { + title: qsTr("File") + + Action { + text: qsTr("Increase Font") + shortcut: "Ctrl++" + onTriggered: textArea.font.pixelSize += 1 + } + Action { + text: qsTr("Decrease Font") + shortcut: "Ctrl+-" + onTriggered: textArea.font.pixelSize -= 1 + } + Action { + text: expandPath ? qsTr("Toggle Short Path") : qsTr("Toggle Expand Path") + enabled: currentFilePath + onTriggered: expandPath = !expandPath + } + Action { + text: qsTr("Exit") + onTriggered: Qt.exit(0) + } + } + + MyMenu { + title: qsTr("Edit") + + Action { + text: qsTr("Cut") + shortcut: StandardKey.Cut + enabled: textArea.selectedText.length > 0 + onTriggered: textArea.cut() + } + Action { + text: qsTr("Copy") + shortcut: StandardKey.Copy + enabled: textArea.selectedText.length > 0 + onTriggered: textArea.copy() + } + Action { + text: qsTr("Paste") + shortcut: StandardKey.Paste + enabled: textArea.canPaste + onTriggered: textArea.paste() + } + Action { + text: qsTr("Select All") + shortcut: StandardKey.SelectAll + enabled: textArea.length > 0 + onTriggered: textArea.selectAll() + } + Action { + text: qsTr("Undo") + shortcut: StandardKey.Undo + enabled: textArea.canUndo + onTriggered: textArea.undo() + } + } + } + + Rectangle { + anchors.fill: parent + color: Colors.background + + RowLayout { + anchors.fill: parent + spacing: 0 + + // Stores the buttons that navigate the application. + Sidebar { + id: sidebar + z: 2 + rootWindow: root + + Layout.preferredWidth: 60 + Layout.fillHeight: true + } + + // Allows resizing parts of the UI. + SplitView { + Layout.fillWidth: true + Layout.fillHeight: true + + handle: Rectangle { + implicitWidth: 10 + color: SplitHandle.pressed ? Colors.color2 : Colors.background + border.color: Colors.color2 + opacity: SplitHandle.hovered || SplitHandle.pressed ? 1.0 : 0.0 + + Behavior on opacity { + OpacityAnimator { + duration: 900 + } + } + } + + // We use an inline component to make a reusable TextArea component. + // This is convenient when the component is only used in one file. + component MyTextArea: TextArea { + antialiasing: true + color: Colors.textFile + selectedTextColor: Colors.textFile + selectionColor: Colors.selection + renderType: Text.QtRendering + textFormat: TextEdit.PlainText + + background: null + } + + Rectangle { + z: 1 + color: Colors.surface1 + + SplitView.preferredWidth: 250 + SplitView.fillHeight: true + + StackLayout { + currentIndex: sidebar.currentTabIndex > 1 ? 1 : sidebar.currentTabIndex + + anchors.fill: parent + + // Shows the help text. + MyTextArea { + readOnly: true + 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 + } + + // Shows the files on the file system. + FileSystemView { + id: fileSystemView + color: Colors.surface1 + + onFileClicked: (path) => root.currentFilePath = path + } + } + } + + // The ScrollView that contains the TextArea which shows the file's content. + StackLayout { + currentIndex: sidebar.currentTabIndex > 1 ? 1 : 0 + + SplitView.fillWidth: true + SplitView.fillHeight: true + // TextArea is the first element inside the stack + ScrollView { + Layout.fillWidth: true + Layout.fillHeight: true + + leftPadding: 20 + topPadding: 20 + bottomPadding: 20 + + clip: true + + property alias textArea: textArea + + MyTextArea { + id: textArea + text: FileSystemModel.readFile(root.currentFilePath) + } + } + // The ColorScheme is the second element in the stack + ColorScheme { + Layout.fillWidth: true + Layout.fillHeight: true + } + } + } + } + ResizeButton {} + } +} 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..7303ced8f --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/app.qrc @@ -0,0 +1,15 @@ +<RCC> + <qresource prefix="/qt/qml/FileSystemModule"> + <file>qmldir</file> + <file>Main.qml</file> + <file>qml/About.qml</file> + <file>qml/ColorScheme.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..61323cef1 --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/icons.qrc @@ -0,0 +1,14 @@ +<RCC> + <qresource> + <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/light_bulb.svg</file> + <file>icons/qt_logo.svg</file> + <file>icons/read.svg</file> + <file>icons/resize.svg</file> + <file>icons/leaf.svg</file> + </qresource> +</RCC> 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..b7bc0ac6f --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/About.qml @@ -0,0 +1,59 @@ +// 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: 500 + height: 360 + flags: Qt.Window | Qt.FramelessWindowHint + color: Colors.surface1 + + menuBar: MyMenuBar { + id: menuBar + implicitHeight: 20 + rootWindow: root + 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: Qt.size(80, 80) + fillMode: Image.PreserveAspectFit + smooth: true + antialiasing: true + asynchronous: true + } + + TextArea { + anchors.top: logo.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 20 + antialiasing: true + wrapMode: Text.WrapAnywhere + color: Colors.textFile + horizontalAlignment: Text.AlignHCenter + readOnly: true + selectionColor: Colors.selection + text: qsTr("Qt Group (Nasdaq Helsinki: QTCOM) is a global software company with a strong \ +presence in more than 70 industries and is the leading independent technology behind 1+ billion \ +devices and applications. Qt is used by major global companies and developers worldwide, and the \ +technology enables its customers to deliver exceptional user experiences and advance their digital \ +transformation initiatives. Qt achieves this through its cross-platform software framework for the \ +development of apps and devices, under both commercial and open-source licenses.") + background: Rectangle { + color: "transparent" + } + } + ResizeButton {} +} 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/FileSystemView.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/FileSystemView.qml new file mode 100644 index 000000000..ade2e48c1 --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/FileSystemView.qml @@ -0,0 +1,99 @@ +// 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 + +// This is the file system view which gets populated by the C++ model. +Rectangle { + id: root + + signal fileClicked(string filePath) + + TreeView { + id: fileSystemTreeView + anchors.fill: parent + model: FileSystemModel + boundsBehavior: Flickable.StopAtBounds + boundsMovement: Flickable.StopAtBounds + clip: true + + property int lastIndex: -1 + + 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 + + required property int index + required property url filePath + + indicator: null + + contentItem: Item { + anchors.fill: parent + + Icon { + id: directoryIcon + x: leftMargin + (depth * indentation) + anchors.verticalCenter: parent.verticalCenter + path: treeDelegate.hasChildren + ? (treeDelegate.expanded ? "../icons/folder_open.svg" : "../icons/folder_closed.svg") + : "../icons/generic_file.svg" + iconColor: (treeDelegate.expanded && treeDelegate.hasChildren) ? Colors.color2 : Colors.folder + } + Text { + anchors.left: directoryIcon.right + anchors.verticalCenter: parent.verticalCenter + width: parent.width + text: model.fileName + color: Colors.text + } + } + + background: Rectangle { + color: treeDelegate.index === fileSystemTreeView.lastIndex + ? Colors.selection + : (hoverHandler.hovered ? Colors.active : "transparent") + } + + TapHandler { + onSingleTapped: { + fileSystemTreeView.toggleExpanded(row) + fileSystemTreeView.lastIndex = index + // If this model item doesn't have children, it means it's representing a file. + if (!treeDelegate.hasChildren) + root.fileClicked(filePath) + } + } + HoverHandler { + id: hoverHandler + } + } + + // 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/Icon.qml b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Icon.qml new file mode 100644 index 000000000..25162d9d3 --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Icon.qml @@ -0,0 +1,44 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +import QtQuick +import QtQuick.Effects + +// Custom Component for displaying Icons +Item { + id: root + + required property url path + property real padding: 5 + property real size: 30 + property alias iconColor: overlay.colorizationColor + property alias hovered: mouse.hovered + + width: size + height: size + + Image { + id: icon + anchors.fill: root + anchors.margins: padding + source: path + sourceSize: Qt.size(size, size) + fillMode: Image.PreserveAspectFit + smooth: true + antialiasing: true + asynchronous: true + } + + MultiEffect { + id: overlay + anchors.fill: icon + source: icon + colorization: 1.0 + brightness: 1.0 + } + + HoverHandler { + id: mouse + acceptedDevices: PointerDevice.Mouse + } +} 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..99795b5e5 --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenu.qml @@ -0,0 +1,42 @@ +// 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 + + background: Rectangle { + implicitWidth: 200 + implicitHeight: 40 + color: Colors.surface2 + } + + delegate: MenuItem { + id: menuItem + implicitWidth: 200 + implicitHeight: 40 + contentItem: Item { + Text { + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 5 + text: menuItem.text + color: enabled ? Colors.text : Colors.disabledText + } + Rectangle { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + width: 6 + height: parent.height + visible: menuItem.highlighted + color: Colors.color2 + } + } + background: Rectangle { + color: menuItem.highlighted ? Colors.active : "transparent" + } + } +} 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..a2a3fea88 --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/MyMenuBar.qml @@ -0,0 +1,135 @@ +// 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 rootWindow + property alias infoText: windowInfo.text + + implicitHeight: 25 + + // The top level menus on the left side + delegate: MenuBarItem { + id: menuBarItem + implicitHeight: 25 + + contentItem: Text { + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + color: menuBarItem.highlighted ? Colors.textFile : Colors.text + opacity: enabled ? 1.0 : 0.3 + text: menuBarItem.text + elide: Text.ElideRight + font: menuBarItem.font + } + + background: Rectangle { + 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 { target: indicator; width: parent.width } + } + + transitions: Transition { + NumberAnimation { + properties: "width" + duration: 300 + } + } + + } + } + } + + // The background property contains an information text in the middle as well as the + // Minimize, Maximize and Close Buttons. + background: Rectangle { + color: Colors.surface2 + // Make the empty space drag the specified root window. + WindowDragHandler { dragWindow: rootWindow } + + Text { + id: windowInfo + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: Colors.text + } + + component InteractionButton: Rectangle { + signal action; + property alias hovered: hoverHandler.hovered + + width: root.height + anchors.top: parent.top + anchors.bottom: parent.bottom + color: hovered ? Colors.background : "transparent" + + HoverHandler { id: hoverHandler } + TapHandler { onTapped: action() } + } + + InteractionButton { + id: minimize + + anchors.right: maximize.left + onAction: rootWindow.showMinimized() + Rectangle { + width: parent.height - 10; height: 2 + anchors.centerIn: parent + color: parent.hovered ? Colors.iconIndicator : Colors.icon + } + } + + InteractionButton { + id: maximize + + anchors.right: close.left + onAction: rootWindow.showMaximized() + Rectangle { + anchors.fill: parent + anchors.margins: 5 + border.width: 2 + color: "transparent" + border.color: parent.hovered ? Colors.iconIndicator : Colors.icon + } + } + + InteractionButton { + id: close + + color: hovered ? "#ec4143" : "transparent" + anchors.right: parent.right + onAction: rootWindow.close() + Rectangle { + width: parent.height - 8; height: 2 + anchors.centerIn: parent + color: parent.hovered ? Colors.iconIndicator : Colors.icon + rotation: 45 + transformOrigin: Item.Center + antialiasing: true + Rectangle { + width: parent.height + height: parent.width + anchors.centerIn: parent + color: parent.color + antialiasing: true + } + } + } + } + +} 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..eb2e5bc02 --- /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 { + 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: down || checked ? Colors.iconIndicator : Colors.icon + + checkable: false + display: AbstractButton.IconOnly + background: null + onPressed: { + root.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..29062a9bb --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qml/Sidebar.qml @@ -0,0 +1,124 @@ +// 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 + color: Colors.surface2 + + required property ApplicationWindow rootWindow + property alias currentTabIndex: tabBar.currentIndex + + ColumnLayout { + anchors.fill: root + anchors.topMargin: 10 + anchors.bottomMargin: 10 + spacing: 10 + + // TabBar is designed to be horizontal, whereas we need a vertical bar. + // We can easily achieve that by using a Container. + Container { + id: tabBar + + Layout.fillWidth: true + + // ButtonGroup ensures that only one button can be checked at a time. + ButtonGroup { + buttons: tabBar.contentItem.children + // 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: tabBar.setCurrentIndex(Math.max(0, buttons.indexOf(checkedButton))) + } + + contentItem: ColumnLayout { + spacing: tabBar.spacing + + Repeater { + model: tabBar.contentModel + } + } + + component SidebarEntry: Button { + id: sidebarButton + icon.color: down || checked ? Colors.iconIndicator : Colors.icon + icon.width: 35 + icon.height: 35 + leftPadding: 8 + indicator.width + + background: null + + Rectangle { + id: indicator + x: 4 + anchors.verticalCenter: parent.verticalCenter + width: 4 + height: sidebarButton.icon.width + color: Colors.color1 + visible: sidebarButton.checked + } + } + + // Shows help text when clicked. + SidebarEntry { + icon.source: "../icons/light_bulb.svg" + checkable: true + checked: true + + Layout.alignment: Qt.AlignHCenter + } + + // Shows the file system when clicked. + SidebarEntry { + icon.source: "../icons/read.svg" + checkable: true + + Layout.alignment: Qt.AlignHCenter + } + // 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: rootWindow } + } + + // 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..6c9e3ed9b --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/FileSystemModule/qmldir @@ -0,0 +1,11 @@ +module FileSystemModule +Main 1.0 Main.qml +Icon 1.0 qml/Icon.qml +About 1.0 qml/About.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/extendedexplorer.md b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.md new file mode 100644 index 000000000..7e265a7ef --- /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: 83-90 +--- +``` + +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: 169-198 +--- +``` + +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: 144-145 +--- +``` + +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.py b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.py new file mode 100644 index 000000000..6ad6e926c --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.py @@ -0,0 +1,70 @@ +# Copyright (C) 2023 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 PySide6.QtWidgets import QFileSystemModel +from PySide6.QtGui import QGuiApplication +from PySide6.QtQml import (QQmlApplicationEngine, QmlElement, QmlSingleton) +from PySide6.QtCore import (Slot, QFile, QTextStream, QMimeDatabase, QFileInfo, QStandardPaths) + +import sys + + +QML_IMPORT_NAME = "FileSystemModule" +QML_IMPORT_MAJOR_VERSION = 1 + + +@QmlElement +@QmlSingleton +class FileSystemModel(QFileSystemModel): + def __init__(self, parent=None): + super().__init__(parent=parent) + self.setRootPath(QStandardPaths.writableLocation(QStandardPaths.HomeLocation)) + self.db = QMimeDatabase() + + # we only need one column in this example + def columnCount(self, parent): + return 1 + + # 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.db.mimeTypeForFile(QFileInfo(file)) + if 'text' in mime.comment().lower() or any('text' in s.lower() for s in mime.parentMimeTypes()): + if file.open(QFile.ReadOnly | QFile.Text): + stream = QTextStream(file).readAll() + return stream + else: + return self.tr("Error opening the file!") + return self.tr("File type not supported!") + + +if __name__ == '__main__': + app = QGuiApplication(sys.argv) + app.setOrganizationName("QtProject") + app.setApplicationName("File System Explorer") + 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) + + sys.exit(app.exec()) diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.pyproject b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.pyproject new file mode 100644 index 000000000..f6f2e4e89 --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/extendedexplorer.pyproject @@ -0,0 +1,29 @@ +{ + "files": [ + "extendedexplorer.py", + "color_scheme.py", + "FileSystemModule/qmldir", + "FileSystemModule/app.qrc", + "FileSystemModule/icons.qrc", + "FileSystemModule/qmldir", + "FileSystemModule/Main.qml", + "FileSystemModule/qml/About.qml", + "FileSystemModule/qml/ColorScheme.qml", + "FileSystemModule/qml/FileSystemView.qml", + "FileSystemModule/qml/Icon.qml", + "FileSystemModule/qml/MyMenu.qml", + "FileSystemModule/qml/MyMenuBar.qml", + "FileSystemModule/qml/ResizeButton.qml", + "FileSystemModule/qml/Sidebar.qml", + "FileSystemModule/qml/WindowDragHandler.qml", + "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/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 Binary files differnew file mode 100644 index 000000000..410538ca3 --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/resources/colorscheme.png diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.gif b/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.gif Binary files differnew file mode 100644 index 000000000..9e59f64aa --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.gif diff --git a/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.webp b/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.webp Binary files differnew file mode 100644 index 000000000..1f4e2cfa7 --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/resources/extendedexplorer.webp 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..e6ecb8d2a --- /dev/null +++ b/sources/pyside6/doc/tutorials/extendedexplorer/scheme_manager.py @@ -0,0 +1,99 @@ +# 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): + + 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() + + @Signal + def schemeChanged(self): + pass + + @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 85466937f..920e646c4 100644 --- a/sources/pyside6/doc/tutorials/index.rst +++ b/sources/pyside6/doc/tutorials/index.rst @@ -137,6 +137,12 @@ Quick/QML: Basic tutorials 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 @@ -146,6 +152,7 @@ Quick/QML: Basic tutorials qmlintegration/qmlintegration.rst qmlapp/qmlapplication.rst qmlsqlintegration/qmlsqlintegration.rst + extendedexplorer/extendedexplorer.md General Applications -------------------- |