diff --git a/build.rs b/build.rs index 1eeab13..1636fbc 100644 --- a/build.rs +++ b/build.rs @@ -14,6 +14,7 @@ fn main() { "qml/Components/ClideHandle.qml", "qml/Components/ClideMenu.qml", "qml/Components/ClideMenuItem.qml", + "qml/Components/ClideBreadCrumbs.qml", "qml/Logger/Logger.qml", ])) // Link Qt's Network library diff --git a/qml/ClideProjectView.qml b/qml/ClideProjectView.qml index 0129d9a..00d1170 100644 --- a/qml/ClideProjectView.qml +++ b/qml/ClideProjectView.qml @@ -48,40 +48,17 @@ SplitView { ColumnLayout { spacing: 2 - // TODO: Make a ClideBreadCrumb element to support select parent paths as root - Rectangle { - color: RustColors.explorer_background - height: 25 - width: navigationView.width + ClideBreadCrumbs { + id: breadCrumb - Text { - id: breadCrumb + Layout.bottomMargin: 5 + Layout.leftMargin: 15 + Layout.topMargin: 5 + path: clideTreeView.rootDirectory - anchors.fill: parent - color: RustColors.explorer_text - elide: Text.ElideLeft - horizontalAlignment: Text.AlignHCenter - text: clideTreeView.rootDirectory - verticalAlignment: Text.AlignVCenter - } - TapHandler { - acceptedButtons: Qt.RightButton - - onSingleTapped: (eventPoint, button) => contextMenu.popup() - } - ClideMenu { - id: contextMenu - - ClideMenuItem { - action: Action { - text: qsTr("Reset root") - - onTriggered: { - Logger.log("Resetting root directory: " + clideTreeView.originalRootDirectory); - clideTreeView.rootDirectory = clideTreeView.originalRootDirectory; - } - } - } + onCrumbClicked: path => { + Logger.trace("Crumb clicked: " + path); + clideTreeView.rootDirectory = path; } } ClideTreeView { @@ -97,7 +74,7 @@ SplitView { onFileClicked: path => clideEditor.filePath = path onRootDirectoryChanged: { Logger.log("Setting root directory: " + clideTreeView.rootDirectory); - breadCrumb.text = clideTreeView.rootDirectory; + breadCrumb.path = clideTreeView.rootDirectory; } } } diff --git a/qml/Components/ClideBreadCrumbs.qml b/qml/Components/ClideBreadCrumbs.qml new file mode 100644 index 0000000..bb28fc5 --- /dev/null +++ b/qml/Components/ClideBreadCrumbs.qml @@ -0,0 +1,109 @@ +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import clide.module 1.0 +import Logger 1.0 + +Item { + id: root + + property var fullPaths: [] + required property string path + property var segments: [] + + signal crumbClicked(string path) + + function rebuildSegments() { + var cleaned = path; + if (cleaned.endsWith("/")) + cleaned = cleaned.slice(0, -1); + var parts = cleaned.split("/"); + root.segments = []; + root.fullPaths = []; + var current = ""; + Logger.trace("Building segments for path: " + cleaned); + for (var i = 0; i < parts.length; ++i) { + if (parts[i] === "") { + current = "/"; + root.segments.push("/"); + root.fullPaths.push("/"); + } else { + if (current === "/") + current += parts[i]; + else + current += "/" + parts[i]; + Logger.trace("Pushing path: " + parts[i] + " Current: " + current); + root.segments.push(parts[i]); + root.fullPaths.push(current); + } + } + rep.model = root.segments; + } + + anchors.leftMargin: 20 + height: breadcrumbRow.implicitHeight + width: parent.width + + Component.onCompleted: rebuildSegments() + onPathChanged: rebuildSegments() + + Flow { + id: breadcrumbRow + + Repeater { + id: rep + + model: root.segments + + delegate: Text { + id: linkText + + required property string modelData + + function getText() { + if (modelData === "/") { + return modelData; + } + Logger.trace("Getting valid text:" + modelData); + return modelData + "/"; + } + + color: mouseArea.containsMouse ? "#2a7fff" : RustColors.explorer_text + font.underline: mouseArea.containsMouse + text: getText() + + MouseArea { + id: mouseArea + + anchors.fill: parent + hoverEnabled: true + + onClicked: { + console.log("Breadcrumb clicked:", root.fullPaths[root.segments.indexOf(modelData)]); + root.crumbClicked(root.fullPaths[root.segments.indexOf(modelData)]); + } + } + } + } + } + TapHandler { + acceptedButtons: Qt.RightButton + + onSingleTapped: (eventPoint, button) => contextMenu.popup() + } + ClideMenu { + id: contextMenu + + ClideMenuItem { + action: Action { + text: qsTr("Reset root") + + onTriggered: { + Logger.log("Resetting root directory: " + clideTreeView.originalRootDirectory); + clideTreeView.rootDirectory = clideTreeView.originalRootDirectory; + } + } + } + } +} diff --git a/qml/Components/ClideMenu.qml b/qml/Components/ClideMenu.qml index cc297a2..6fd076e 100644 --- a/qml/Components/ClideMenu.qml +++ b/qml/Components/ClideMenu.qml @@ -5,9 +5,10 @@ import clide.module 1.0 Menu { background: Rectangle { - border.color: Qt.darker(RustColors.menubar, 2) + border.color: RustColors.hovered + border.width: 10 color: RustColors.menubar implicitWidth: 100 - radius: 2 + radius: 5 } } diff --git a/qml/Components/qmldir b/qml/Components/qmldir index 5a7b322..f071afa 100644 --- a/qml/Components/qmldir +++ b/qml/Components/qmldir @@ -2,3 +2,4 @@ ClideScrollBar ClideScrollBar.qml ClideHandle ClideHandle.qml ClideMenu ClideMenu.qml ClideMenuItem ClideMenuItem.qml +ClideBreadCrumbs ClideBreadCrumbs.qml diff --git a/resources/SauceCodeProNerdFont-Black.ttf b/resources/SauceCodeProNerdFont-Black.ttf new file mode 100644 index 0000000..bbfc2b5 Binary files /dev/null and b/resources/SauceCodeProNerdFont-Black.ttf differ diff --git a/resources/SauceCodeProNerdFont-ExtraLight.ttf b/resources/SauceCodeProNerdFont-ExtraLight.ttf new file mode 100644 index 0000000..0df0cdc Binary files /dev/null and b/resources/SauceCodeProNerdFont-ExtraLight.ttf differ diff --git a/resources/SauceCodeProNerdFont-Light.ttf b/resources/SauceCodeProNerdFont-Light.ttf new file mode 100644 index 0000000..431684e Binary files /dev/null and b/resources/SauceCodeProNerdFont-Light.ttf differ