168 lines
5.2 KiB
QML
168 lines
5.2 KiB
QML
// SPDX-FileCopyrightText: 2026, Shaun Reed <shaunrd0@gmail.com>
|
|
//
|
|
// SPDX-License-Identifier: GNU General Public License v3.0 or later
|
|
|
|
import QtQuick
|
|
import QtQuick.Effects
|
|
import QtQuick.Controls
|
|
|
|
import clide.module 1.0
|
|
import Logger 1.0
|
|
|
|
TreeView {
|
|
id: fileSystemTreeView
|
|
|
|
property int lastIndex: -1
|
|
required property string originalRootDirectory
|
|
property string rootDirectory
|
|
|
|
signal fileClicked(string filePath)
|
|
|
|
boundsBehavior: Flickable.StopAtBounds
|
|
boundsMovement: Flickable.StopAtBounds
|
|
clip: true
|
|
leftMargin: 25
|
|
model: FileSystem
|
|
rootIndex: FileSystem.setDirectory(fileSystemTreeView.rootDirectory)
|
|
|
|
// Provide our own custom ScrollIndicator for the TreeView.
|
|
ScrollIndicator.vertical: ScrollIndicator {
|
|
active: true
|
|
implicitWidth: 15
|
|
|
|
contentItem: Rectangle {
|
|
color: RustColors.scrollbar
|
|
implicitHeight: 6
|
|
implicitWidth: 6
|
|
opacity: fileSystemTreeView.movingVertically ? 0.5 : 0.0
|
|
|
|
Behavior on opacity {
|
|
OpacityAnimator {
|
|
duration: 500
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// The delegate represents a single entry in the filesystem.
|
|
delegate: TreeViewDelegate {
|
|
id: treeDelegate
|
|
|
|
required property string fileName
|
|
required property url filePath
|
|
required property int index
|
|
|
|
implicitHeight: 25
|
|
implicitWidth: fileSystemTreeView.width > 0 ? fileSystemTreeView.width : 250
|
|
indentation: 12
|
|
|
|
background: Rectangle {
|
|
color: current ? RustColors.explorer_folder_open : "transparent"
|
|
radius: 2.5
|
|
}
|
|
contentItem: Text {
|
|
anchors.left: directoryIcon.right
|
|
anchors.leftMargin: 5
|
|
color: RustColors.explorer_text
|
|
text: treeDelegate.fileName
|
|
}
|
|
indicator: Label {
|
|
id: directoryIcon
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
antialiasing: true
|
|
font.family: localFont.font.family
|
|
font.pixelSize: 18
|
|
smooth: true
|
|
text: fileSystemTreeView.model.icon(filePath)
|
|
x: treeDelegate.leftMargin + (treeDelegate.depth * treeDelegate.indentation) + (indicator.visible ? indicator.width : 0)
|
|
}
|
|
|
|
FontLoader {
|
|
id: localFont
|
|
|
|
source: "qrc:/fonts/saucecodepro-xlight.ttf"
|
|
}
|
|
Label {
|
|
id: indicator
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
font.family: localFont.font.family
|
|
font.pixelSize: 10
|
|
font.weight: localFont.font.weight
|
|
text: expanded ? "⮟" : "⮞"
|
|
visible: isTreeNode && hasChildren
|
|
x: padding + (depth * indentation)
|
|
}
|
|
MultiEffect {
|
|
id: iconOverlay
|
|
|
|
anchors.fill: directoryIcon
|
|
brightness: 1.0
|
|
colorization: 1.0
|
|
colorizationColor: {
|
|
const isFile = !treeDelegate.hasChildren;
|
|
if (isFile)
|
|
return Qt.lighter(RustColors.explorer_folder, 2);
|
|
const isExpandedFolder = treeDelegate.expanded && treeDelegate.hasChildren;
|
|
if (isExpandedFolder)
|
|
return Qt.darker(RustColors.explorer_folder, 2);
|
|
else
|
|
return RustColors.explorer_folder;
|
|
}
|
|
source: directoryIcon
|
|
}
|
|
HoverHandler {
|
|
id: hoverHandler
|
|
|
|
acceptedDevices: PointerDevice.Mouse
|
|
}
|
|
TapHandler {
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
|
|
onSingleTapped: (eventPoint, button) => {
|
|
switch (button) {
|
|
case Qt.LeftButton:
|
|
if (treeDelegate.hasChildren) {
|
|
fileSystemTreeView.toggleExpanded(treeDelegate.row);
|
|
} else {
|
|
// If this model item doesn't have children, it means it's representing a file.
|
|
fileSystemTreeView.fileClicked(treeDelegate.filePath);
|
|
}
|
|
break;
|
|
case Qt.RightButton:
|
|
contextMenu.popup();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
ClideMenu {
|
|
id: contextMenu
|
|
|
|
ClideMenuItem {
|
|
action: Action {
|
|
enabled: treeDelegate.hasChildren
|
|
text: qsTr("Set root")
|
|
|
|
onTriggered: {
|
|
Logger.debug("Setting new root directory: " + treeDelegate.filePath);
|
|
fileSystemTreeView.rootDirectory = treeDelegate.filePath;
|
|
}
|
|
}
|
|
}
|
|
ClideMenuItem {
|
|
action: Action {
|
|
text: qsTr("Reset root")
|
|
|
|
onTriggered: {
|
|
Logger.log("Resetting root directory: " + fileSystemTreeView.originalRootDirectory);
|
|
fileSystemTreeView.rootDirectory = fileSystemTreeView.originalRootDirectory;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
selectionModel: ItemSelectionModel {
|
|
}
|
|
}
|