Files
clide/qml/ClideTreeView.qml

167 lines
5.1 KiB
QML
Raw Normal View History

2026-01-31 08:02:16 -05:00
// SPDX-FileCopyrightText: 2026, Shaun Reed <shaunrd0@gmail.com>
//
// SPDX-License-Identifier: GNU General Public License v3.0 or later
2026-01-25 20:57:36 +00:00
import QtQuick
2026-02-01 15:35:40 -05:00
import QtQuick.Effects
2026-01-25 20:57:36 +00:00
import QtQuick.Controls
import clide.module 1.0
2026-02-01 20:20:39 -05:00
import Logger 1.0
2026-01-25 20:57:36 +00:00
2026-02-01 15:35:40 -05:00
TreeView {
2026-02-08 14:26:26 -05:00
id: root
2026-02-01 15:35:40 -05:00
property int lastIndex: -1
required property string originalRootDirectory
property string rootDirectory
2026-02-08 14:26:26 -05:00
property int rootIndent: 25
2026-01-31 04:25:14 +00:00
2026-01-25 20:57:36 +00:00
signal fileClicked(string filePath)
2026-02-01 15:35:40 -05:00
boundsBehavior: Flickable.StopAtBounds
boundsMovement: Flickable.StopAtBounds
clip: true
2026-02-08 14:26:26 -05:00
// The model is implemented in filesystem.rs
2026-02-02 18:08:37 -05:00
model: FileSystem
2026-02-08 14:26:26 -05:00
// Set the root directory on the Rust model, returning the QModeIndex to use for the root of the tree view widget.
rootIndex: FileSystem.setDirectory(root.rootDirectory)
2026-02-02 18:08:37 -05:00
// Provide our own custom ScrollIndicator for the TreeView.
2026-02-08 14:26:26 -05:00
ScrollBar.horizontal: ClideScrollBar {
sizeModifier: 3
}
ScrollBar.vertical: ClideScrollBar {
sizeModifier: 3
2026-02-02 18:08:37 -05:00
}
2026-01-25 20:57:36 +00:00
2026-02-01 15:35:40 -05:00
// The delegate represents a single entry in the filesystem.
delegate: TreeViewDelegate {
id: treeDelegate
required property string fileName
2026-02-02 18:08:37 -05:00
required property url filePath
required property int index
implicitHeight: 25
2026-02-08 14:26:26 -05:00
implicitWidth: root.width
2026-02-02 18:08:37 -05:00
indentation: 12
2026-02-01 15:35:40 -05:00
2026-02-02 18:08:37 -05:00
background: Rectangle {
2026-02-07 12:42:56 -05:00
color: current ? RustColors.explorer_folder_open : "transparent"
2026-02-08 14:26:26 -05:00
radius: 20
2026-02-08 15:21:06 -05:00
width: root.width
2026-02-02 18:08:37 -05:00
}
2026-02-08 14:26:26 -05:00
// Item name.
2026-02-02 18:08:37 -05:00
contentItem: Text {
2026-02-08 14:26:26 -05:00
anchors.left: itemIcon.right
2026-02-07 12:42:56 -05:00
anchors.leftMargin: 5
2026-02-02 18:08:37 -05:00
color: RustColors.explorer_text
text: treeDelegate.fileName
}
2026-02-08 14:26:26 -05:00
// Item Icon.
indicator: Label {
2026-02-08 14:26:26 -05:00
id: itemIcon
2026-02-01 15:35:40 -05:00
anchors.verticalCenter: parent.verticalCenter
antialiasing: true
2026-02-08 14:26:26 -05:00
enabled: false
focus: false
font.family: localFont.font.family
font.pixelSize: 18
2026-02-02 18:08:37 -05:00
smooth: true
2026-02-08 14:26:26 -05:00
// Get the icon from Rust implementation.
text: root.model.icon(filePath)
x: root.rootIndent + (treeDelegate.depth * treeDelegate.indentation) + (carrotIndicator.visible ? carrotIndicator.width : 0)
2026-02-01 15:35:40 -05:00
}
2026-01-25 20:57:36 +00:00
2026-02-08 14:26:26 -05:00
// Directory carrot indicator.
2026-02-07 12:42:56 -05:00
Label {
2026-02-08 14:26:26 -05:00
id: carrotIndicator
2026-02-07 12:42:56 -05:00
anchors.verticalCenter: parent.verticalCenter
font.family: localFont.font.family
2026-02-07 12:42:56 -05:00
font.pixelSize: 10
font.weight: localFont.font.weight
2026-02-07 12:42:56 -05:00
text: expanded ? "⮟" : "⮞"
visible: isTreeNode && hasChildren
2026-02-08 14:26:26 -05:00
x: (root.rootIndent - implicitWidth) + (depth * indentation)
2026-02-07 12:42:56 -05:00
}
2026-02-08 14:26:26 -05:00
// Apply colorization effects to the icon for the item.
2026-02-01 15:35:40 -05:00
MultiEffect {
2026-02-08 14:26:26 -05:00
anchors.fill: itemIcon
2026-02-01 15:35:40 -05:00
brightness: 1.0
2026-02-02 18:08:37 -05:00
colorization: 1.0
2026-02-01 15:35:40 -05:00
colorizationColor: {
const isFile = !treeDelegate.hasChildren;
if (isFile)
2026-02-02 18:08:37 -05:00
return Qt.lighter(RustColors.explorer_folder, 2);
2026-02-01 15:35:40 -05:00
const isExpandedFolder = treeDelegate.expanded && treeDelegate.hasChildren;
if (isExpandedFolder)
2026-02-02 18:08:37 -05:00
return Qt.darker(RustColors.explorer_folder, 2);
2026-02-01 15:35:40 -05:00
else
2026-02-02 18:08:37 -05:00
return RustColors.explorer_folder;
2026-01-25 20:57:36 +00:00
}
2026-02-08 14:26:26 -05:00
source: itemIcon
2026-02-01 15:35:40 -05:00
}
HoverHandler {
id: hoverHandler
2026-02-02 18:08:37 -05:00
2026-02-01 15:35:40 -05:00
acceptedDevices: PointerDevice.Mouse
}
TapHandler {
acceptedButtons: Qt.LeftButton | Qt.RightButton
2026-02-02 18:08:37 -05:00
2026-02-01 15:35:40 -05:00
onSingleTapped: (eventPoint, button) => {
switch (button) {
2026-02-02 18:08:37 -05:00
case Qt.LeftButton:
if (treeDelegate.hasChildren) {
2026-02-08 14:26:26 -05:00
root.toggleExpanded(treeDelegate.row);
} else {
2026-02-07 12:42:56 -05:00
// If this model item doesn't have children, it means it's representing a file.
2026-02-08 14:26:26 -05:00
root.fileClicked(treeDelegate.filePath);
}
2026-02-02 18:08:37 -05:00
break;
case Qt.RightButton:
contextMenu.popup();
break;
2026-01-25 20:57:36 +00:00
}
}
2026-02-01 15:35:40 -05:00
}
2026-02-07 12:59:44 -05:00
ClideMenu {
2026-02-01 15:35:40 -05:00
id: contextMenu
2026-02-02 18:08:37 -05:00
2026-02-07 12:59:44 -05:00
ClideMenuItem {
action: Action {
enabled: treeDelegate.hasChildren
text: qsTr("Set root")
2026-02-02 18:08:37 -05:00
2026-02-07 12:59:44 -05:00
onTriggered: {
Logger.debug("Setting new root directory: " + treeDelegate.filePath);
2026-02-08 14:26:26 -05:00
root.rootDirectory = treeDelegate.filePath;
2026-02-07 12:59:44 -05:00
}
2026-01-25 20:57:36 +00:00
}
2026-02-01 15:35:40 -05:00
}
2026-02-07 12:59:44 -05:00
ClideMenuItem {
action: Action {
text: qsTr("Reset root")
2026-01-25 20:57:36 +00:00
2026-02-07 12:59:44 -05:00
onTriggered: {
2026-02-08 14:26:26 -05:00
Logger.log("Resetting root directory: " + root.originalRootDirectory);
root.rootDirectory = root.originalRootDirectory;
2026-02-07 12:59:44 -05:00
}
2026-01-25 20:57:36 +00:00
}
}
}
}
selectionModel: ItemSelectionModel {
}
2026-02-08 14:26:26 -05:00
FontLoader {
id: localFont
source: "qrc:/fonts/saucecodepro-xlight.ttf"
}
2026-01-25 20:57:36 +00:00
}