diff --git a/qml/ClideEditor.qml b/qml/ClideEditor.qml index fc89e6e..8a14eb3 100644 --- a/qml/ClideEditor.qml +++ b/qml/ClideEditor.qml @@ -35,31 +35,36 @@ SplitView { // extend the available height. Flickable { id: lineNumbers - Layout.fillHeight: true Layout.fillWidth: false - - // Calculate the width based on the logarithmic scale. + // 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 - visible: true Column { anchors.fill: parent - topPadding: 6 + topPadding: textArea.topPadding Repeater { id: repeatedLineNumbers + // TODO: Bug where text wrapping shows as new line number. + model: textArea.lineCount - // Each line number in the gutter. + // This Item is used for each line number in the gutter. delegate: Item { - required property int index - - // Calculate the height of each line in the text area. + // Calculates the height of each line in the text area. height: textArea.contentHeight / textArea.lineCount width: parent.width + required property int index + + // Show the line number. Label { id: numbers @@ -69,8 +74,9 @@ SplitView { horizontalAlignment: Text.AlignLeft text: parent.index + 1 verticalAlignment: Text.AlignVCenter - width: parent.width + width: parent.width - indicator.width } + // Draw edge along the right side of the line number. Rectangle { id: indicator @@ -80,14 +86,11 @@ SplitView { width: 1 } } - // TODO: Bug where text wrapping shows as new line number. - model: textArea.lineCount } } } Flickable { id: editorFlickable - Layout.fillHeight: true Layout.fillWidth: true boundsBehavior: Flickable.StopAtBounds @@ -97,6 +100,7 @@ SplitView { } ScrollBar.vertical: MyScrollBar { } + TextArea.flickable: TextArea { id: textArea @@ -104,8 +108,8 @@ SplitView { focus: true persistentSelection: true selectByMouse: true - // selectedTextColor: RustColors.editor_highlighted_text - // selectionColor: RustColors.editor_highlight + selectedTextColor: RustColors.editor_highlighted_text + selectionColor: RustColors.editor_highlight textFormat: Qt.AutoText wrapMode: TextArea.Wrap text: FileSystem.readFile(root.filePath) diff --git a/src/colors.rs b/src/colors.rs index 815630e..d113109 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -77,7 +77,7 @@ impl Default for RustColorsImpl { active: QColor::try_from("#a9acb0").unwrap(), inactive: QColor::try_from("#FFF").unwrap(), editor_background: QColor::try_from("#2b2b2b").unwrap(), - editor_text: QColor::try_from("#ccced3").unwrap(), + editor_text: QColor::try_from("#acaea3").unwrap(), editor_highlighted_text: QColor::try_from("#ccced3").unwrap(), editor_highlight: QColor::try_from("#ccced3").unwrap(), gutter: QColor::try_from("#1e1f22").unwrap(), diff --git a/src/filesystem.rs b/src/filesystem.rs index 540bcbe..fc99f67 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -42,6 +42,8 @@ pub mod qobject { use cxx_qt_lib::{QModelIndex, QString}; use dirs; use std::fs; +use std::fs::FileType; +use log::warn; // TODO: Impleent a provider for QFileSystemModel::setIconProvider for icons. pub struct FileSystemImpl { @@ -64,11 +66,20 @@ impl qobject::FileSystem { if path.is_empty() { return QString::default(); } - // TODO: What if the file is binary or something horrible? - QString::from( - fs::read_to_string(path.to_string()) - .expect(format!("Failed to read file {}", path).as_str()), - ) + // TODO: Use syntect for syntax highlighting? + // https://github.com/trishume/syntect/blob/master/examples/syncat.rs + if fs::metadata(path.to_string()) + .expect(format!("Failed to get file metadata {}", path).as_str()) + .is_file() + { + QString::from( + fs::read_to_string(path.to_string()) + .expect(format!("Failed to read file {}", path).as_str()), + ) + } else { + warn!("Attempted to open file {} that is not a valid file", path); + QString::default() + } } // There will never be more than one column.