aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorDennis Oberst <dennis.oberst@qt.io>2024-01-08 17:27:18 +0100
committerDennis Oberst <dennis.oberst@qt.io>2024-01-23 15:50:39 +0100
commit13537fa1f0d4546b4001a9f61a70e9081cd9db7d (patch)
tree200009fd03c61e561be429216fff8ec192e718b0 /examples
parentfcf1d51c3d6e2d8afa02a2e69665b7df9a6a97ca (diff)
Filesystemexplorer-example: port v2
Since we're touching the example: improve the visualization of files inside the tree-view and provide a minimum width and height. Task-number: PYSIDE-2576 Task-number: QTBUG-119785 Change-Id: I47c6d3eb02436a9ab4213e9b8195b32eaaf37573 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/Main.qml226
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/app.qrc2
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/icons.qrc1
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/icons/app_icon.svg2
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/About.qml88
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Colors.qml29
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Editor.qml160
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/FileSystemView.qml117
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Icon.qml44
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenu.qml19
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenuBar.qml184
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/ResizeButton.qml10
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Sidebar.qml147
-rw-r--r--examples/quickcontrols/filesystemexplorer/FileSystemModule/qmldir2
-rw-r--r--examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.rst13
-rw-r--r--examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.webpbin83086 -> 47416 bytes
-rw-r--r--examples/quickcontrols/filesystemexplorer/editormodels.py116
-rw-r--r--examples/quickcontrols/filesystemexplorer/filesystemexplorer.py70
-rw-r--r--examples/quickcontrols/filesystemexplorer/filesystemexplorer.pyproject6
-rw-r--r--examples/quickcontrols/filesystemexplorer/main.py49
20 files changed, 834 insertions, 451 deletions
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/Main.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/Main.qml
index 3987acc9e..7f7798ed8 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/Main.qml
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/Main.qml
@@ -6,47 +6,68 @@ 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("Qt Quick Controls - File System Explorer")
+ title: qsTr("File System Explorer Example")
- property string currentFilePath: ""
- property bool expandPath: false
+ 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 {
- rootWindow: root
-
- infoText: currentFilePath
- ? (expandPath ? currentFilePath
- : currentFilePath.substring(currentFilePath.lastIndexOf("/") + 1, currentFilePath.length))
- : "File System Explorer"
-
+ dragWindow: root
+ infoText: root.getInfoText()
MyMenu {
title: qsTr("File")
Action {
text: qsTr("Increase Font")
shortcut: StandardKey.ZoomIn
- onTriggered: textArea.font.pixelSize += 1
+ onTriggered: editor.text.font.pixelSize += 1
}
Action {
text: qsTr("Decrease Font")
shortcut: StandardKey.ZoomOut
- onTriggered: textArea.font.pixelSize -= 1
+ onTriggered: editor.text.font.pixelSize -= 1
}
Action {
- text: expandPath ? qsTr("Toggle Short Path") : qsTr("Toggle Expand Path")
- enabled: currentFilePath
- onTriggered: expandPath = !expandPath
+ 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: "Ctrl+Q"
+ shortcut: StandardKey.Quit
}
}
@@ -56,134 +77,109 @@ ApplicationWindow {
Action {
text: qsTr("Cut")
shortcut: StandardKey.Cut
- enabled: textArea.selectedText.length > 0
- onTriggered: textArea.cut()
+ enabled: editor.text.selectedText.length > 0
+ onTriggered: editor.text.cut()
}
Action {
text: qsTr("Copy")
shortcut: StandardKey.Copy
- enabled: textArea.selectedText.length > 0
- onTriggered: textArea.copy()
+ enabled: editor.text.selectedText.length > 0
+ onTriggered: editor.text.copy()
}
Action {
text: qsTr("Paste")
shortcut: StandardKey.Paste
- enabled: textArea.canPaste
- onTriggered: textArea.paste()
+ enabled: editor.text.canPaste
+ onTriggered: editor.text.paste()
}
Action {
text: qsTr("Select All")
shortcut: StandardKey.SelectAll
- enabled: textArea.length > 0
- onTriggered: textArea.selectAll()
+ enabled: editor.text.length > 0
+ onTriggered: editor.text.selectAll()
}
Action {
text: qsTr("Undo")
shortcut: StandardKey.Undo
- enabled: textArea.canUndo
- onTriggered: textArea.undo()
+ enabled: editor.text.canUndo
+ onTriggered: editor.text.undo()
}
}
}
-
- Rectangle {
+ // Set up the layout of the main components in a row:
+ // [ Sidebar, Navigation, Editor ]
+ RowLayout {
anchors.fill: parent
- color: Colors.background
-
- RowLayout {
- anchors.fill: parent
- spacing: 0
-
- // Stores the buttons that navigate the application.
- Sidebar {
- id: sidebar
- rootWindow: root
-
- Layout.preferredWidth: 60
- Layout.fillHeight: true
- }
+ 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
-
- 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
- }
+ // 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
}
}
+ }
- // 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 {
- color: Colors.surface1
-
- SplitView.preferredWidth: 250
- SplitView.fillHeight: true
-
- StackLayout {
- currentIndex: 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
- }
+ 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
+
+ // 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
}
- }
-
- // The ScrollView that contains the TextArea which shows the file's content.
- ScrollView {
- leftPadding: 20
- topPadding: 20
- bottomPadding: 20
- clip: true
-
- SplitView.fillWidth: true
- SplitView.fillHeight: true
-
- property alias textArea: textArea
- MyTextArea {
- id: textArea
- text: FileSystemModel.readFile(root.currentFilePath)
+ // 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.
+ Editor {
+ id: editor
+ showLineNumbers: root.showLineNumbers
+ currentFilePath: root.currentFilePath
+ SplitView.fillWidth: true
+ SplitView.fillHeight: true
+ }
}
- ResizeButton {}
+ }
+
+ ResizeButton {
+ resizeWindow: root
}
}
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/app.qrc b/examples/quickcontrols/filesystemexplorer/FileSystemModule/app.qrc
index 05fc728e7..fec76fe67 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/app.qrc
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/app.qrc
@@ -3,9 +3,9 @@
<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>
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/icons.qrc b/examples/quickcontrols/filesystemexplorer/FileSystemModule/icons.qrc
index 5793a62cf..97d8a3d79 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/icons.qrc
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/icons.qrc
@@ -1,5 +1,6 @@
<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>
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/icons/app_icon.svg b/examples/quickcontrols/filesystemexplorer/FileSystemModule/icons/app_icon.svg
new file mode 100644
index 000000000..5aae4221f
--- /dev/null
+++ b/examples/quickcontrols/filesystemexplorer/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/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/About.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/About.qml
index b7bc0ac6f..178bf03e4 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/About.qml
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/About.qml
@@ -7,53 +7,87 @@ import FileSystemModule
ApplicationWindow {
id: root
- width: 500
- height: 360
+ width: 650
+ height: 550
flags: Qt.Window | Qt.FramelessWindowHint
color: Colors.surface1
menuBar: MyMenuBar {
id: menuBar
- implicitHeight: 20
- rootWindow: root
+
+ 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: Qt.size(80, 80)
+ sourceSize.width: 80
+ sourceSize.height: 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"
- }
+ 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
}
- ResizeButton {}
}
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Colors.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Colors.qml
index 280f89286..285667773 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Colors.qml
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Colors.qml
@@ -1,22 +1,23 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-pragma Singleton
import QtQuick
+pragma Singleton
+
QtObject {
- readonly property color background: "#23272E"
- readonly property color surface1: "#1E2227"
+ readonly property color background: "#292828"
+ readonly property color surface1: "#171819"
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"
+ readonly property color text: "#D4BE98"
+ readonly property color textFile: "#E1D2B7"
+ readonly property color disabledText: "#2C313A"
+ readonly property color selection: "#4B4A4A"
+ readonly property color active: "#292828"
+ readonly property color inactive: "#383737"
+ readonly property color folder: "#383737"
+ readonly property color icon: "#383737"
+ readonly property color iconIndicator: "#D5B35D"
+ readonly property color color1: "#A7B464"
+ readonly property color color2: "#D3869B"
}
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Editor.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Editor.qml
new file mode 100644
index 000000000..80f7c04c5
--- /dev/null
+++ b/examples/quickcontrols/filesystemexplorer/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/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/FileSystemView.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/FileSystemView.qml
index ade2e48c1..db955168c 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/FileSystemView.qml
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/FileSystemView.qml
@@ -2,26 +2,31 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
-import QtQuick.Layouts
+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
- property int lastIndex: -1
-
Component.onCompleted: fileSystemTreeView.toggleExpanded(0)
// The delegate represents a single entry in the filesystem.
@@ -31,50 +36,101 @@ Rectangle {
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: null
-
- contentItem: Item {
- anchors.fill: parent
+ indicator: Image {
+ id: directoryIcon
- Icon {
- id: directoryIcon
- x: leftMargin + (depth * indentation)
- anchors.verticalCenter: parent.verticalCenter
- path: treeDelegate.hasChildren
- ? (treeDelegate.expanded ? "../icons/folder_open.svg" : "../icons/folder_closed.svg")
+ 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"
- 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
- }
+ 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
+ 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)
+ // 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.
@@ -85,6 +141,7 @@ Rectangle {
contentItem: Rectangle {
implicitWidth: 6
implicitHeight: 6
+
color: Colors.color1
opacity: fileSystemTreeView.movingVertically ? 0.5 : 0.0
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Icon.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Icon.qml
deleted file mode 100644
index 25162d9d3..000000000
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Icon.qml
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenu.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenu.qml
index 99795b5e5..1f1d30c56 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenu.qml
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenu.qml
@@ -8,35 +8,38 @@ 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 {
+ 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/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenuBar.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenuBar.qml
index a2a3fea88..4874a2c03 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenuBar.qml
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/MyMenuBar.qml
@@ -6,130 +6,172 @@ 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.
+// The MenuBar also serves as a controller for our window as we don't use any decorations.
MenuBar {
id: root
- required property ApplicationWindow rootWindow
+ required property ApplicationWindow dragWindow
property alias infoText: windowInfo.text
- implicitHeight: 25
-
- // The top level menus on the left side
+ // Customization of the top level menus inside the MenuBar
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
+ 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
+ color: Colors.color1
states: State {
- name: "active"; when: menuBarItem.highlighted
- PropertyChanges { target: indicator; width: parent.width }
+ name: "active"
+ when: menuBarItem.highlighted
+ PropertyChanges {
+ indicator.width: background.width - 2
+ }
}
-
transitions: Transition {
NumberAnimation {
properties: "width"
- duration: 300
+ 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
- // 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 }
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ spacing: root.spacing
+ Repeater {
+ id: menuBarItems
- Text {
- id: windowInfo
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
- color: Colors.text
+ Layout.alignment: Qt.AlignLeft
+ model: root.contentModel
}
- component InteractionButton: Rectangle {
- signal action;
- property alias hovered: hoverHandler.hovered
+ 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
+ }
+ }
- width: root.height
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- color: hovered ? Colors.background : "transparent"
+ RowLayout {
+ id: windowActions
- HoverHandler { id: hoverHandler }
- TapHandler { onTapped: action() }
- }
+ Layout.alignment: Qt.AlignRight
+ Layout.fillHeight: true
- InteractionButton {
- id: minimize
+ spacing: 0
- anchors.right: maximize.left
- onAction: rootWindow.showMinimized()
- Rectangle {
- width: parent.height - 10; height: 2
- anchors.centerIn: parent
- color: parent.hovered ? Colors.iconIndicator : Colors.icon
+ 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: maximize
+ InteractionButton {
+ id: minimize
- 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
+ onAction: root.dragWindow.showMinimized()
+ Rectangle {
+ anchors.centerIn: parent
+ color: parent.hovered ? Colors.iconIndicator : Colors.icon
+ height: 2
+ width: parent.height - 14
+ }
}
- }
- InteractionButton {
- id: close
+ InteractionButton {
+ id: maximize
- 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
+ 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 {
- width: parent.height
- height: parent.width
anchors.centerIn: parent
- color: parent.color
+ 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/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/ResizeButton.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/ResizeButton.qml
index eb2e5bc02..0df65bf82 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/ResizeButton.qml
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/ResizeButton.qml
@@ -5,6 +5,8 @@ import QtQuick.Controls
import FileSystemModule
Button {
+ required property ApplicationWindow resizeWindow
+
icon.width: 20; icon.height: 20
anchors.right: parent.right
anchors.bottom: parent.bottom
@@ -12,12 +14,10 @@ Button {
bottomPadding: 3
icon.source: "../icons/resize.svg"
- icon.color: down || checked ? Colors.iconIndicator : Colors.icon
+ icon.color: hovered ? Colors.iconIndicator : Colors.icon
+ background: null
checkable: false
display: AbstractButton.IconOnly
- background: null
- onPressed: {
- root.startSystemResize(Qt.BottomEdge | Qt.RightEdge)
- }
+ onPressed: resizeWindow.startSystemResize(Qt.BottomEdge | Qt.RightEdge)
}
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Sidebar.qml b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Sidebar.qml
index 9d08562d9..aac530394 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Sidebar.qml
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qml/Sidebar.qml
@@ -8,77 +8,92 @@ import FileSystemModule
Rectangle {
id: root
+
+ property alias currentTabIndex: topBar.currentIndex
+ required property ApplicationWindow dragWindow
+ readonly property int tabBarSpacing: 10
+
color: Colors.surface2
- required property ApplicationWindow rootWindow
- property alias currentTabIndex: tabBar.currentIndex
+ component SidebarEntry: Button {
+ id: sidebarButton
- ColumnLayout {
- anchors.fill: root
- anchors.topMargin: 10
- anchors.bottomMargin: 10
- spacing: 10
+ Layout.alignment: Qt.AlignHCenter
+ Layout.fillWidth: true
- // TabBar is designed to be horizontal, whereas we need a vertical bar.
- // We can easily achieve that by using a Container.
- Container {
- id: tabBar
+ icon.color: down || checked ? Colors.iconIndicator : Colors.icon
+ icon.width: 27
+ icon.height: 27
- Layout.fillWidth: true
+ topPadding: 0
+ rightPadding: 0
+ bottomPadding: 0
+ leftPadding: 0
+ background: null
- // 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)))
- }
+ Rectangle {
+ id: indicator
- contentItem: ColumnLayout {
- spacing: tabBar.spacing
+ anchors.verticalCenter: parent.verticalCenter
+ x: 2
+ width: 4
+ height: sidebarButton.icon.height * 1.2
- Repeater {
- model: tabBar.contentModel
- }
- }
+ 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)))
+ }
- 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
- }
+ 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
-
- Layout.alignment: Qt.AlignHCenter
}
// Shows the file system when clicked.
SidebarEntry {
+ id: filesystemTab
+
icon.source: "../icons/read.svg"
checkable: true
-
- Layout.alignment: Qt.AlignHCenter
}
}
@@ -88,25 +103,31 @@ Rectangle {
Layout.fillWidth: true
// Make the empty space drag our main window.
- WindowDragHandler { dragWindow: rootWindow }
+ WindowDragHandler {
+ dragWindow: root.dragWindow
+ }
}
- // Opens the Qt website in the system's web browser.
- SidebarEntry {
- id: qtWebsiteButton
- icon.source: "../icons/globe.svg"
- checkable: false
+ TabBar {
+ id: bottomBar
- onClicked: Qt.openUrlExternally("https://www.qt.io/")
- }
+ 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
+ // Opens the About Qt Window.
+ SidebarEntry {
+ id: aboutQtButton
- onClicked: aboutQtWindow.visible = !aboutQtWindow.visible
+ icon.source: "../icons/info_sign.svg"
+ checkable: false
+ onClicked: aboutQtWindow.visible = !aboutQtWindow.visible
+ }
}
}
diff --git a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qmldir b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qmldir
index ff7ecb757..b1f684600 100644
--- a/examples/quickcontrols/filesystemexplorer/FileSystemModule/qmldir
+++ b/examples/quickcontrols/filesystemexplorer/FileSystemModule/qmldir
@@ -1,7 +1,7 @@
module FileSystemModule
Main 1.0 Main.qml
-Icon 1.0 qml/Icon.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
diff --git a/examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.rst b/examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.rst
index 0260928b6..b46cbec79 100644
--- a/examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.rst
+++ b/examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.rst
@@ -37,3 +37,16 @@ pleasing UIs.
.. image:: filesystemexplorer.webp
:target: filesystemexplorer.webp
:alt: QtQuickControls Filesystem Explorer Screenshot
+
+References
+----------
+
+If you're interested in the C++ version of this example, you can find it
+`here <https://doc-snapshots.qt.io/qt6-dev/qtquickcontrols-filesystemexplorer-example.html>`_.
+
+Additionally, there is a detailed
+`tutorial <https://doc.qt.io/qtforpython-6/tutorials/extendedexplorer/extendedexplorer.html>`_
+available that provides step-by-step instructions on how to extend this example
+with additional features. This tutorial can be helpful if you want to explore
+and learn more about building upon the existing functionality of the filesystem
+explorer.
diff --git a/examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.webp b/examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.webp
index cce7e1daf..10ad0d26e 100644
--- a/examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.webp
+++ b/examples/quickcontrols/filesystemexplorer/doc/filesystemexplorer.webp
Binary files differ
diff --git a/examples/quickcontrols/filesystemexplorer/editormodels.py b/examples/quickcontrols/filesystemexplorer/editormodels.py
new file mode 100644
index 000000000..688147726
--- /dev/null
+++ b/examples/quickcontrols/filesystemexplorer/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/examples/quickcontrols/filesystemexplorer/filesystemexplorer.py b/examples/quickcontrols/filesystemexplorer/filesystemexplorer.py
deleted file mode 100644
index 2bc733c37..000000000
--- a/examples/quickcontrols/filesystemexplorer/filesystemexplorer.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# 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 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/examples/quickcontrols/filesystemexplorer/filesystemexplorer.pyproject b/examples/quickcontrols/filesystemexplorer/filesystemexplorer.pyproject
index 1e1aa2ad8..8053cfab0 100644
--- a/examples/quickcontrols/filesystemexplorer/filesystemexplorer.pyproject
+++ b/examples/quickcontrols/filesystemexplorer/filesystemexplorer.pyproject
@@ -1,19 +1,21 @@
{
"files": [
- "filesystemexplorer.py",
+ "main.py",
+ "editormodels.py",
"FileSystemModule/qmldir",
"FileSystemModule/app.qrc",
"FileSystemModule/qmldir",
"FileSystemModule/Main.qml",
"FileSystemModule/qml/About.qml",
"FileSystemModule/qml/Colors.qml",
+ "FileSystemModule/qml/Editor.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/app_icon.svg",
"FileSystemModule/icons/folder_closed.svg",
"FileSystemModule/icons/folder_open.svg",
"FileSystemModule/icons/generic_file.svg",
diff --git a/examples/quickcontrols/filesystemexplorer/main.py b/examples/quickcontrols/filesystemexplorer/main.py
new file mode 100644
index 000000000..ebf196ca7
--- /dev/null
+++ b/examples/quickcontrols/filesystemexplorer/main.py
@@ -0,0 +1,49 @@
+# 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 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())