From 4bb4ce18821da66057f99052f4a299f897a7bf07 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Sun, 8 Feb 2026 14:26:26 -0500 Subject: [PATCH] Clean up GUI. --- build.rs | 3 +- qml/ClideApplicationView.qml | 46 +++++++ qml/ClideEditor.qml | 202 ++++++++++++++-------------- qml/ClideEditorView.qml | 50 +++---- qml/ClideExplorerView.qml | 62 +++++++++ qml/ClideLogger.qml | 11 +- qml/ClideProjectView.qml | 81 ----------- qml/ClideTreeView.qml | 81 ++++++----- qml/Components/ClideBreadCrumbs.qml | 68 +++++----- qml/Components/ClideScrollBar.qml | 7 +- qml/main.qml | 4 +- 11 files changed, 322 insertions(+), 293 deletions(-) create mode 100644 qml/ClideApplicationView.qml create mode 100644 qml/ClideExplorerView.qml delete mode 100644 qml/ClideProjectView.qml diff --git a/build.rs b/build.rs index 1636fbc..2fefd4d 100644 --- a/build.rs +++ b/build.rs @@ -5,7 +5,8 @@ fn main() { "qml/main.qml", "qml/ClideAboutWindow.qml", "qml/ClideTreeView.qml", - "qml/ClideProjectView.qml", + "qml/ClideApplicationView.qml", + "qml/ClideExplorerView.qml", "qml/ClideEditor.qml", "qml/ClideEditorView.qml", "qml/ClideMenuBar.qml", diff --git a/qml/ClideApplicationView.qml b/qml/ClideApplicationView.qml new file mode 100644 index 0000000..dd88e48 --- /dev/null +++ b/qml/ClideApplicationView.qml @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2026, Shaun Reed +// +// SPDX-License-Identifier: GNU General Public License v3.0 or later + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import clide.module 1.0 +import Logger 1.0 + +SplitView { + id: root + + // Path to the directory of the project opened in clide. + required property string projectDir + + anchors.fill: parent + + // Customized handle to drag between the Navigation and the Editor. + handle: ClideHandle { + hovered: SplitHandle.hovered + pressed: SplitHandle.pressed + } + + ClideExplorerView { + SplitView.fillHeight: true + SplitView.preferredWidth: 200 + projectDir: root.projectDir + + // Open files when clicked in the explorer. + onFileClicked: path => { + Logger.trace("Setting editor path from ClideExplorerView signal: " + path) + clideEditorView.filePath = path; + } + } + ClideEditorView { + id: clideEditorView + + SplitView.fillHeight: true + SplitView.fillWidth: true + // Provide a path to the file currently open in the text editor. + // Initialized using the Default trait in Rust QML singleton FileSystem. + filePath: FileSystem.filePath + } +} diff --git a/qml/ClideEditor.qml b/qml/ClideEditor.qml index df221a3..9ab7f5e 100644 --- a/qml/ClideEditor.qml +++ b/qml/ClideEditor.qml @@ -9,128 +9,130 @@ import QtQuick.Layouts import clide.module 1.0 import Logger 1.0 -RowLayout { - // 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 +Rectangle { + color: "transparent" - Layout.fillHeight: true - Layout.fillWidth: false - // Calculating the width correctly is important as the number grows. - // We need to ensure space required to show N line number digits. - // We use log10 to find how many digits are needed in a line number. - // log10(9) ~= .95; log10(10) = 1.0; log10(100) = 2.0 ...etc - // We +1 to ensure space for at least 1 digit, as floor(1.95) = 1. - // The +10 is additional spacing and can be adjusted. - Layout.preferredWidth: fontMetrics.averageCharacterWidth * (Math.floor(Math.log10(textArea.lineCount)) + 1) + 10 - contentY: editorFlickable.contentY - interactive: false + RowLayout { + anchors.fill: parent - Column { - anchors.fill: parent - topPadding: textArea.topPadding + // 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 - Repeater { - id: repeatedLineNumbers + Layout.fillHeight: true + Layout.fillWidth: false + // Calculating the width correctly is important as the number grows. + // We need to ensure space required to show N line number digits. + // We use log10 to find how many digits are needed in a line number. + // log10(9) ~= .95; log10(10) = 1.0; log10(100) = 2.0 ...etc + // We +1 to ensure space for at least 1 digit, as floor(1.95) = 1. + // The +10 is additional spacing and can be adjusted. + Layout.preferredWidth: fontMetrics.averageCharacterWidth * (Math.floor(Math.log10(textArea.lineCount)) + 1) + 10 + contentY: editorFlickable.contentY + interactive: false - // TODO: Bug where text wrapping shows as new line number. - model: textArea.lineCount + Column { + anchors.fill: parent + topPadding: textArea.topPadding - // This Item is used for each line number in the gutter. - delegate: Item { - required property int index + Repeater { + id: repeatedLineNumbers - // Calculates the height of each line in the text area. - height: textArea.contentHeight / textArea.lineCount - width: parent.width + // TODO: Bug where text wrapping shows as new line number. + model: textArea.lineCount - // Show the line number. - Label { - id: numbers + // This Item is used for each line number in the gutter. + delegate: Item { + required property int index - color: RustColors.linenumber - font: textArea.font - height: parent.height - horizontalAlignment: Text.AlignLeft - text: parent.index + 1 - verticalAlignment: Text.AlignVCenter - width: parent.width - indicator.width + // Calculates the height of each line in the text area. + height: textArea.contentHeight / textArea.lineCount + width: parent.width - background: Rectangle { - color: RustColors.terminal_background + // Show the line number. + Label { + id: numbers + + color: RustColors.linenumber + font: textArea.font + height: parent.height + horizontalAlignment: Text.AlignLeft + text: parent.index + 1 + verticalAlignment: Text.AlignVCenter + width: parent.width - indicator.width } - } - // Draw edge along the right side of the line number. - Rectangle { - id: indicator + // Draw an edge along the right side of the line number. + Rectangle { + id: indicator - anchors.left: numbers.right - color: RustColors.linenumber - height: parent.height - width: 1 + anchors.left: numbers.right + color: RustColors.linenumber + height: parent.height + width: 1 + } } } } } - } - Flickable { - id: editorFlickable + Flickable { + id: editorFlickable - Layout.fillHeight: true - Layout.fillWidth: true - boundsBehavior: Flickable.StopAtBounds - height: 650 + Layout.fillHeight: true + Layout.fillWidth: true + boundsBehavior: Flickable.StopAtBounds + height: 650 - ScrollBar.horizontal: ClideScrollBar { - } - ScrollBar.vertical: ClideScrollBar { - } - TextArea.flickable: TextArea { - id: textArea + ScrollBar.horizontal: ClideScrollBar { + } + ScrollBar.vertical: ClideScrollBar { + } + TextArea.flickable: TextArea { + id: textArea - antialiasing: true - focus: true - persistentSelection: true - selectByMouse: true - selectedTextColor: RustColors.editor_highlighted_text - selectionColor: RustColors.editor_highlight - text: FileSystem.readFile(root.filePath) - textFormat: Qt.AutoText - wrapMode: TextArea.Wrap + antialiasing: true + focus: true + persistentSelection: true + selectByMouse: true + selectedTextColor: RustColors.editor_highlighted_text + selectionColor: RustColors.editor_highlight + text: FileSystem.readFile(root.filePath) + textFormat: Qt.AutoText + wrapMode: TextArea.Wrap - onLinkActivated: function (link) { - Qt.openUrlExternally(link); + onLinkActivated: function (link) { + Qt.openUrlExternally(link); + } + + // TODO: Handle saving + // Component.onCompleted: { + // if (Qt.application.arguments.length === 2) + // textDocument.source = "file:" + Qt.application.arguments[1] + // else + // textDocument.source = "qrc:/texteditor.html" + // } + // textDocument.onStatusChanged: { + // // a message lookup table using computed properties: + // // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer + // const statusMessages = { + // [ TextDocument.ReadError ]: qsTr("Failed to load “%1”"), + // [ TextDocument.WriteError ]: qsTr("Failed to save “%1”"), + // [ TextDocument.NonLocalFileError ]: qsTr("Not a local file: “%1”"), + // } + // const err = statusMessages[textDocument.status] + // if (err) { + // errorDialog.text = err.arg(textDocument.source) + // errorDialog.open() + // } + // } } - // TODO: Handle saving - // Component.onCompleted: { - // if (Qt.application.arguments.length === 2) - // textDocument.source = "file:" + Qt.application.arguments[1] - // else - // textDocument.source = "qrc:/texteditor.html" - // } - // textDocument.onStatusChanged: { - // // a message lookup table using computed properties: - // // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer - // const statusMessages = { - // [ TextDocument.ReadError ]: qsTr("Failed to load “%1”"), - // [ TextDocument.WriteError ]: qsTr("Failed to save “%1”"), - // [ TextDocument.NonLocalFileError ]: qsTr("Not a local file: “%1”"), - // } - // const err = statusMessages[textDocument.status] - // if (err) { - // errorDialog.text = err.arg(textDocument.source) - // errorDialog.open() - // } - // } - } + FontMetrics { + id: fontMetrics - FontMetrics { - id: fontMetrics - - font: textArea.font + font: textArea.font + } } } } diff --git a/qml/ClideEditorView.qml b/qml/ClideEditorView.qml index 9d1325f..58d7208 100644 --- a/qml/ClideEditorView.qml +++ b/qml/ClideEditorView.qml @@ -9,38 +9,40 @@ import QtQuick.Layouts import clide.module 1.0 import Logger 1.0 -SplitView { +Rectangle { id: root // The path to the file to show in the text editor. - // This is updated by a signal caught within ClideProjectView. - // Initialized by the Default trait for the Rust QML singleton FileSystem. + // This is updated by a signal caught within ClideApplicationView. required property string filePath - Layout.fillHeight: true - Layout.fillWidth: true - orientation: Qt.Vertical + clip: true + color: "transparent" + radius: 20 - // Customized handle to drag between the Editor and the Console. - handle: ClideHandle { - pressed: SplitHandle.pressed - hovered: SplitHandle.hovered - } + SplitView { + anchors.fill: parent + orientation: Qt.Vertical - Component.onCompleted: { - // Show logging is working. - Logger.info("Info logs"); - Logger.warn("Warning logs"); - Logger.debug("Debug logs"); - Logger.error("Error logs"); - Logger.trace("Trace logs"); - } + // Customized handle to drag between the Editor and the Console. + handle: ClideHandle { + hovered: SplitHandle.hovered + pressed: SplitHandle.pressed + } - ClideEditor{ - id: clideEditor - } - ClideLogger { - id: areaConsole + Component.onCompleted: { + // Show logging is working. + Logger.info("Info logs"); + Logger.warn("Warning logs"); + Logger.debug("Debug logs"); + Logger.error("Error logs"); + Logger.trace("Trace logs"); + } + ClideEditor { + SplitView.preferredHeight: 650 + } + ClideLogger { + } } } diff --git a/qml/ClideExplorerView.qml b/qml/ClideExplorerView.qml new file mode 100644 index 0000000..7c49cf0 --- /dev/null +++ b/qml/ClideExplorerView.qml @@ -0,0 +1,62 @@ +// SPDX-FileCopyrightText: 2026, Shaun Reed +// +// SPDX-License-Identifier: GNU General Public License v3.0 or later + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import clide.module 1.0 +import Logger 1.0 + +Rectangle { + id: root + + required property string projectDir + + clip: true + color: RustColors.explorer_background + radius: 20 + + signal fileClicked(string path) + + ColumnLayout { + anchors.fill: parent + spacing: 5 + + ClideBreadCrumbs { + id: breadCrumb + + Layout.fillWidth: true + Layout.leftMargin: 15 + Layout.rightMargin: 15 + Layout.topMargin: 10 + path: clideTreeView.rootDirectory + + onCrumbClicked: path => { + Logger.trace("Crumb clicked: " + path); + clideTreeView.rootDirectory = path; + } + onResetRoot: { + clideTreeView.rootDirectory = clideTreeView.originalRootDirectory; + } + } + ClideTreeView { + id: clideTreeView + + Layout.fillHeight: true + Layout.fillWidth: true + + // Path to the directory opened in the file explorer. + originalRootDirectory: root.projectDir + rootDirectory: root.projectDir + + // Pass the signal to the parent component using another signal. + onFileClicked: path => root.fileClicked(path) + onRootDirectoryChanged: { + Logger.log("Setting root directory: " + clideTreeView.rootDirectory); + breadCrumb.path = clideTreeView.rootDirectory; + } + } + } +} diff --git a/qml/ClideLogger.qml b/qml/ClideLogger.qml index 3282b0a..b6b2948 100644 --- a/qml/ClideLogger.qml +++ b/qml/ClideLogger.qml @@ -8,14 +8,12 @@ import QtQuick.Controls import clide.module 1.0 import Logger 1.0 -Item { +Rectangle { + color: "#111" + radius: 10 + ListModel { id: model - - } - Rectangle { - anchors.fill: parent - color: "#111" } ListView { id: listView @@ -38,7 +36,6 @@ Item { } anchors.fill: parent - clip: true model: model delegate: Text { diff --git a/qml/ClideProjectView.qml b/qml/ClideProjectView.qml deleted file mode 100644 index cf043f4..0000000 --- a/qml/ClideProjectView.qml +++ /dev/null @@ -1,81 +0,0 @@ -// SPDX-FileCopyrightText: 2026, Shaun Reed -// -// SPDX-License-Identifier: GNU General Public License v3.0 or later - -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts - -import clide.module 1.0 -import Logger 1.0 - -SplitView { - id: root - - // Path to the directory of the project opened in clide. - required property string projectDir - - anchors.fill: parent - - // Customized handle to drag between the Navigation and the Editor. - handle: ClideHandle { - id: verticalSplitHandle - - hovered: SplitHandle.hovered - pressed: SplitHandle.pressed - } - - Rectangle { - id: navigationView - - SplitView.fillHeight: true - SplitView.maximumWidth: 250 - SplitView.minimumWidth: 0 - SplitView.preferredWidth: 200 - color: RustColors.explorer_background - radius: 20 - - ColumnLayout { - spacing: 2 - - ClideBreadCrumbs { - id: breadCrumb - - Layout.bottomMargin: 5 - Layout.leftMargin: 15 - Layout.topMargin: 5 - path: clideTreeView.rootDirectory - - onCrumbClicked: path => { - Logger.trace("Crumb clicked: " + path); - clideTreeView.rootDirectory = path; - } - } - ClideTreeView { - id: clideTreeView - - height: navigationView.height - - // Path to the directory opened in the file explorer. - originalRootDirectory: root.projectDir - rootDirectory: root.projectDir - width: navigationView.width - - onFileClicked: path => clideEditor.filePath = path - onRootDirectoryChanged: { - Logger.log("Setting root directory: " + clideTreeView.rootDirectory); - breadCrumb.path = clideTreeView.rootDirectory; - } - } - } - } - ClideEditorView { - id: clideEditor - - SplitView.fillWidth: true - - // Provide a path to the file currently open in the text editor. - // Initialized using the Default trait in Rust QML singleton FileSystem. - filePath: FileSystem.filePath - } -} diff --git a/qml/ClideTreeView.qml b/qml/ClideTreeView.qml index 4f70afe..b1f6415 100644 --- a/qml/ClideTreeView.qml +++ b/qml/ClideTreeView.qml @@ -10,38 +10,30 @@ import clide.module 1.0 import Logger 1.0 TreeView { - id: fileSystemTreeView + id: root property int lastIndex: -1 required property string originalRootDirectory property string rootDirectory + property int rootIndent: 25 signal fileClicked(string filePath) boundsBehavior: Flickable.StopAtBounds boundsMovement: Flickable.StopAtBounds clip: true - leftMargin: 25 + + // The model is implemented in filesystem.rs model: FileSystem - rootIndex: FileSystem.setDirectory(fileSystemTreeView.rootDirectory) + // 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) // 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 - } - } - } + ScrollBar.horizontal: ClideScrollBar { + sizeModifier: 3 + } + ScrollBar.vertical: ClideScrollBar { + sizeModifier: 3 } // The delegate represents a single entry in the filesystem. @@ -53,38 +45,40 @@ TreeView { required property int index implicitHeight: 25 - implicitWidth: fileSystemTreeView.width > 0 ? fileSystemTreeView.width : 250 + implicitWidth: root.width indentation: 12 background: Rectangle { color: current ? RustColors.explorer_folder_open : "transparent" - radius: 2.5 + radius: 20 + width: root.width - 15 } + // Item name. contentItem: Text { - anchors.left: directoryIcon.right + anchors.left: itemIcon.right anchors.leftMargin: 5 color: RustColors.explorer_text text: treeDelegate.fileName } + // Item Icon. indicator: Label { - id: directoryIcon + id: itemIcon anchors.verticalCenter: parent.verticalCenter antialiasing: true + enabled: false + focus: false 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) + // Get the icon from Rust implementation. + text: root.model.icon(filePath) + x: root.rootIndent + (treeDelegate.depth * treeDelegate.indentation) + (carrotIndicator.visible ? carrotIndicator.width : 0) } - FontLoader { - id: localFont - - source: "qrc:/fonts/saucecodepro-xlight.ttf" - } + // Directory carrot indicator. Label { - id: indicator + id: carrotIndicator anchors.verticalCenter: parent.verticalCenter font.family: localFont.font.family @@ -92,12 +86,11 @@ TreeView { font.weight: localFont.font.weight text: expanded ? "⮟" : "⮞" visible: isTreeNode && hasChildren - x: padding + (depth * indentation) + x: (root.rootIndent - implicitWidth) + (depth * indentation) } + // Apply colorization effects to the icon for the item. MultiEffect { - id: iconOverlay - - anchors.fill: directoryIcon + anchors.fill: itemIcon brightness: 1.0 colorization: 1.0 colorizationColor: { @@ -110,7 +103,7 @@ TreeView { else return RustColors.explorer_folder; } - source: directoryIcon + source: itemIcon } HoverHandler { id: hoverHandler @@ -124,10 +117,10 @@ TreeView { switch (button) { case Qt.LeftButton: if (treeDelegate.hasChildren) { - fileSystemTreeView.toggleExpanded(treeDelegate.row); + root.toggleExpanded(treeDelegate.row); } else { // If this model item doesn't have children, it means it's representing a file. - fileSystemTreeView.fileClicked(treeDelegate.filePath); + root.fileClicked(treeDelegate.filePath); } break; case Qt.RightButton: @@ -146,7 +139,7 @@ TreeView { onTriggered: { Logger.debug("Setting new root directory: " + treeDelegate.filePath); - fileSystemTreeView.rootDirectory = treeDelegate.filePath; + root.rootDirectory = treeDelegate.filePath; } } } @@ -155,8 +148,8 @@ TreeView { text: qsTr("Reset root") onTriggered: { - Logger.log("Resetting root directory: " + fileSystemTreeView.originalRootDirectory); - fileSystemTreeView.rootDirectory = fileSystemTreeView.originalRootDirectory; + Logger.log("Resetting root directory: " + root.originalRootDirectory); + root.rootDirectory = root.originalRootDirectory; } } } @@ -164,4 +157,10 @@ TreeView { } selectionModel: ItemSelectionModel { } + + FontLoader { + id: localFont + + source: "qrc:/fonts/saucecodepro-xlight.ttf" + } } diff --git a/qml/Components/ClideBreadCrumbs.qml b/qml/Components/ClideBreadCrumbs.qml index bb28fc5..7562904 100644 --- a/qml/Components/ClideBreadCrumbs.qml +++ b/qml/Components/ClideBreadCrumbs.qml @@ -5,7 +5,7 @@ import QtQuick.Layouts 1.15 import clide.module 1.0 import Logger 1.0 -Item { +Rectangle { id: root property var fullPaths: [] @@ -13,36 +13,32 @@ Item { property var segments: [] signal crumbClicked(string path) + signal resetRoot - function rebuildSegments() { - var cleaned = path; + function rebuildSegments(): string { + let 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); - } + segments = []; + fullPaths = []; + segments.push("/"); + fullPaths.push("/"); + let parts = cleaned.split("/"); + let current = ""; + // We already pushed the root `/` path above, so skip index 0. + for (let i = 1; i < parts.length; ++i) { + current += "/" + parts[i]; + Logger.trace("Pushing path: " + parts[i] + " Current: " + current); + segments.push(parts[i]); + fullPaths.push(current); } - rep.model = root.segments; + // Update the model used in the Repeater to show the new segments. + repeater.model = segments; } - anchors.leftMargin: 20 - height: breadcrumbRow.implicitHeight + color: "transparent" + implicitHeight: breadcrumbRow.implicitHeight width: parent.width Component.onCompleted: rebuildSegments() @@ -51,28 +47,32 @@ Item { Flow { id: breadcrumbRow + anchors.fill: parent + spacing: 2 + width: parent.width + Repeater { - id: rep + id: repeater model: root.segments delegate: Text { - id: linkText - + required property int index required property string modelData - function getText() { + function getText(): string { if (modelData === "/") { return modelData; } - Logger.trace("Getting valid text:" + modelData); return modelData + "/"; } + // Show blue underlined hyperlink text if the mouse is hovering a segment. color: mouseArea.containsMouse ? "#2a7fff" : RustColors.explorer_text font.underline: mouseArea.containsMouse text: getText() + // Click events for each path segment call signal so the parent can set the file explorer root path. MouseArea { id: mouseArea @@ -80,8 +80,8 @@ Item { hoverEnabled: true onClicked: { - console.log("Breadcrumb clicked:", root.fullPaths[root.segments.indexOf(modelData)]); - root.crumbClicked(root.fullPaths[root.segments.indexOf(modelData)]); + Logger.info(index + "] Breadcrumb clicked:" + root.fullPaths[index]); + crumbClicked(root.fullPaths[index]); } } } @@ -90,7 +90,7 @@ Item { TapHandler { acceptedButtons: Qt.RightButton - onSingleTapped: (eventPoint, button) => contextMenu.popup() + onSingleTapped: contextMenu.popup() } ClideMenu { id: contextMenu @@ -100,8 +100,8 @@ Item { text: qsTr("Reset root") onTriggered: { - Logger.log("Resetting root directory: " + clideTreeView.originalRootDirectory); - clideTreeView.rootDirectory = clideTreeView.originalRootDirectory; + Logger.info("Resetting root directory from ClideBreadCrumbs"); + resetRoot(); } } } diff --git a/qml/Components/ClideScrollBar.qml b/qml/Components/ClideScrollBar.qml index 614bb3c..d06601c 100644 --- a/qml/Components/ClideScrollBar.qml +++ b/qml/Components/ClideScrollBar.qml @@ -11,9 +11,10 @@ ScrollBar { id: scrollBar // Height, opacitiy, width - property int h: scrollBar.interactive ? 4 * 2 : 4 + property int h: scrollBar.interactive ? sizeModifier * 2 : sizeModifier property int o: scrollBar.active && scrollBar.size < 1.0 ? 1.0 : 0.0 - property int w: scrollBar.interactive ? 4 * 2 : 4 + property int sizeModifier: 4 + property int w: scrollBar.interactive ? sizeModifier * 2 : sizeModifier // Scroll bar gutter background: Rectangle { @@ -25,6 +26,7 @@ ScrollBar { // Fade the scrollbar gutter when inactive. opacity: scrollBar.o + radius: 20 Behavior on opacity { OpacityAnimator { @@ -55,6 +57,7 @@ ScrollBar { // Fade the scrollbar when inactive. opacity: scrollBar.o + radius: 20 // Smooth transition between color changes based on the state above. Behavior on color { diff --git a/qml/main.qml b/qml/main.qml index 83458cd..de53192 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -22,9 +22,7 @@ ApplicationWindow { menuBar: ClideMenuBar { } - ClideProjectView { - id: clideProjectView - + ClideApplicationView { projectDir: appWindow.appContextPath } }