Compare commits

..

No commits in common. "4cc43916cbb55030a4df9482311b1180109d6f0e" and "0fac2b71ab777a3e4d4cd9627eae4cd59a66b147" have entirely different histories.

5 changed files with 77 additions and 86 deletions

View File

@ -153,13 +153,12 @@ SplitView {
id: areaConsole id: areaConsole
height: 100 height: 100
width: parent.width placeholderText: qsTr("Placeholder for bash terminal.")
placeholderText: qsTr("shaun@pc:~/Code/clide$ ")
placeholderTextColor: "white" placeholderTextColor: "white"
readOnly: true readOnly: true
wrapMode: TextArea.Wrap wrapMode: TextArea.Wrap
background: Rectangle { background: Rectangle {
color: RustColors.terminal_background color: RustColors.editor_background
implicitHeight: 100 implicitHeight: 100
// border.color: control.enabled ? RustColors.active : RustColors.inactive // border.color: control.enabled ? RustColors.active : RustColors.inactive
} }

View File

@ -45,40 +45,31 @@ SplitView {
ColumnLayout { ColumnLayout {
spacing: 2 spacing: 2
// TODO: Make a ClideBreadCrumb element to support select parent paths as root
Rectangle { Rectangle {
width: navigationView.width width: navigationView.width
height: 25 height: breadCrumb.height + 5
color: RustColors.explorer_background
color: RustColors.explorer_text
Text { Text {
id: breadCrumb id: breadCrumb
anchors.fill: parent
text: clideTreeView.rootDirectory text: clideTreeView.rootDirectory
color: RustColors.explorer_text
elide: Text.ElideLeft elide: Text.ElideLeft
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
} }
} }
ClideTreeView { ClideTreeView {
id: clideTreeView id: clideTreeView
onFileClicked: path => clideEditor.filePath = path onFileClicked: path => root.projectDir = path
width: navigationView.width width: navigationView.width
height: navigationView.height height: navigationView.height
// Path to the directory opened in the file explorer. // Path to the directory opened in the file explorer.
originalRootDirectory: root.projectDir
rootDirectory: root.projectDir rootDirectory: root.projectDir
onRootDirectoryChanged: {
console.log(clideTreeView.rootDirectory)
breadCrumb.text = clideTreeView.rootDirectory
}
} }
} }
} }
ClideEditor { ClideEditor {
id: clideEditor
SplitView.fillWidth: true SplitView.fillWidth: true
// Provide a path to the file currently open in the text editor. // Provide a path to the file currently open in the text editor.

View File

@ -14,21 +14,25 @@ TreeView {
property int lastIndex: -1 property int lastIndex: -1
required property string originalRootDirectory required property string rootDirectory
property string rootDirectory
signal fileClicked(string filePath) signal fileClicked(string filePath)
rootIndex: FileSystem.setDirectory(fileSystemTreeView.rootDirectory)
rootIndex: FileSystem.rootIndex
leftMargin: 5 leftMargin: 5
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
boundsMovement: Flickable.StopAtBounds boundsMovement: Flickable.StopAtBounds
clip: true clip: true
Component.onCompleted: {
FileSystem.rootIndex = FileSystem.setDirectory(fileSystemTreeView.rootDirectory)
}
// The delegate represents a single entry in the filesystem. // The delegate represents a single entry in the filesystem.
delegate: TreeViewDelegate { delegate: TreeViewDelegate {
id: treeDelegate id: treeDelegate
indentation: 8 indentation: 6
implicitWidth: fileSystemTreeView.width > 0 ? fileSystemTreeView.width : 250 implicitWidth: fileSystemTreeView.width > 0 ? fileSystemTreeView.width : 250
implicitHeight: 25 implicitHeight: 25
@ -115,13 +119,15 @@ TreeView {
switch (button) { switch (button) {
case Qt.LeftButton: case Qt.LeftButton:
fileSystemTreeView.toggleExpanded(treeDelegate.row) fileSystemTreeView.toggleExpanded(treeDelegate.row)
fileSystemTreeView.lastIndex = treeDelegate.index
// If this model item doesn't have children, it means it's // If this model item doesn't have children, it means it's
// representing a file. // representing a file.
if (!treeDelegate.hasChildren) if (!treeDelegate.hasChildren)
fileSystemTreeView.fileClicked(treeDelegate.filePath) root.fileClicked(treeDelegate.filePath)
break; break;
case Qt.RightButton: case Qt.RightButton:
contextMenu.popup(); if (treeDelegate.hasChildren)
contextMenu.popup();
break; break;
} }
} }
@ -131,17 +137,16 @@ TreeView {
id: contextMenu id: contextMenu
Action { Action {
text: qsTr("Set as root index") text: qsTr("Set as root index")
enabled: treeDelegate.hasChildren
onTriggered: { onTriggered: {
console.log("Setting new root directory: " + treeDelegate.filePath) console.log("Setting directory: " + treeDelegate.filePath)
fileSystemTreeView.rootDirectory = treeDelegate.filePath FileSystem.rootIndex = FileSystem.setDirectory(treeDelegate.filePath)
} }
} }
Action { Action {
text: qsTr("Reset root index") text: qsTr("Reset root index")
onTriggered: { onTriggered: {
console.log("Resetting root directory: " + fileSystemTreeView.originalRootDirectory) console.log("Reset root index")
fileSystemTreeView.rootDirectory = fileSystemTreeView.originalRootDirectory FileSystem.rootIndex = FileSystem.setDirectory(fileSystemTreeView.rootDirectory)
} }
} }
} }

View File

@ -36,7 +36,6 @@ pub mod qobject {
#[qproperty(QColor, explorer_background)] #[qproperty(QColor, explorer_background)]
#[qproperty(QColor, explorer_folder)] #[qproperty(QColor, explorer_folder)]
#[qproperty(QColor, explorer_folder_open)] #[qproperty(QColor, explorer_folder_open)]
#[qproperty(QColor, terminal_background)]
type RustColors = super::RustColorsImpl; type RustColors = super::RustColorsImpl;
} }
} }
@ -66,7 +65,6 @@ pub struct RustColorsImpl {
explorer_background: QColor, explorer_background: QColor,
explorer_folder: QColor, explorer_folder: QColor,
explorer_folder_open: QColor, explorer_folder_open: QColor,
terminal_background: QColor,
} }
impl Default for RustColorsImpl { impl Default for RustColorsImpl {
@ -89,12 +87,11 @@ impl Default for RustColorsImpl {
editor_highlight: QColor::try_from("#ccced3").unwrap(), editor_highlight: QColor::try_from("#ccced3").unwrap(),
gutter: QColor::try_from("#1e1f22").unwrap(), gutter: QColor::try_from("#1e1f22").unwrap(),
explorer_hovered: QColor::try_from("#4c5053").unwrap(), explorer_hovered: QColor::try_from("#4c5053").unwrap(),
explorer_text: QColor::try_from("#FFF").unwrap(), explorer_text: QColor::try_from("#3b3b3b").unwrap(),
explorer_text_selected: QColor::try_from("#262626").unwrap(), explorer_text_selected: QColor::try_from("#262626").unwrap(),
explorer_background: QColor::try_from("#1E1F22").unwrap(), explorer_background: QColor::try_from("#1E1F22").unwrap(),
explorer_folder: QColor::try_from("#54585b").unwrap(), explorer_folder: QColor::try_from("#54585b").unwrap(),
explorer_folder_open: QColor::try_from("#2b2b2b").unwrap(), explorer_folder_open: QColor::try_from("#2b2b2b").unwrap(),
terminal_background: QColor::try_from("#2C2E32").unwrap(),
} }
} }
} }

View File

@ -2,19 +2,6 @@
// //
// SPDX-License-Identifier: GNU General Public License v3.0 or later // SPDX-License-Identifier: GNU General Public License v3.0 or later
use cxx_qt_lib::{QModelIndex, QString};
use dirs;
use log::warn;
use std::fs;
use std::path::Path;
use syntect::easy::HighlightLines;
use syntect::highlighting::ThemeSet;
use syntect::html::{
IncludeBackground, append_highlighted_html_for_styled_line, start_highlighted_html_snippet,
};
use syntect::parsing::SyntaxSet;
use syntect::util::LinesWithEndings;
#[cxx_qt::bridge] #[cxx_qt::bridge]
pub mod qobject { pub mod qobject {
unsafe extern "C++" { unsafe extern "C++" {
@ -34,6 +21,7 @@ pub mod qobject {
#[qml_element] #[qml_element]
#[qml_singleton] #[qml_singleton]
#[qproperty(QString, file_path, cxx_name = "filePath")] #[qproperty(QString, file_path, cxx_name = "filePath")]
#[qproperty(QModelIndex, root_index, cxx_name = "rootIndex")]
type FileSystem = super::FileSystemImpl; type FileSystem = super::FileSystemImpl;
#[inherit] #[inherit]
@ -55,9 +43,22 @@ pub mod qobject {
} }
} }
// TODO: Implement a provider for QFileSystemModel::setIconProvider for icons. use cxx_qt_lib::{QModelIndex, QString};
use dirs;
use log::warn;
use std::fs;
use std::io::BufRead;
use syntect::easy::HighlightFile;
use syntect::highlighting::ThemeSet;
use syntect::html::{
IncludeBackground, append_highlighted_html_for_styled_line, start_highlighted_html_snippet,
};
use syntect::parsing::SyntaxSet;
// TODO: Impleent a provider for QFileSystemModel::setIconProvider for icons.
pub struct FileSystemImpl { pub struct FileSystemImpl {
file_path: QString, file_path: QString,
root_index: QModelIndex,
} }
// Default is explicit to make the editor open this source file initially. // Default is explicit to make the editor open this source file initially.
@ -65,6 +66,7 @@ impl Default for FileSystemImpl {
fn default() -> Self { fn default() -> Self {
Self { Self {
file_path: QString::from(file!()), file_path: QString::from(file!()),
root_index: Default::default(),
} }
} }
} }
@ -74,46 +76,42 @@ impl qobject::FileSystem {
if path.is_empty() { if path.is_empty() {
return QString::default(); return QString::default();
} }
let meta = fs::metadata(path.to_string()) if !fs::metadata(path.to_string())
.expect(format!("Failed to get file metadata {path:?}").as_str()); .expect(format!("Failed to get file metadata {path:?}").as_str())
if !meta.is_file() { .is_file()
{
warn!(target:"FileSystem", "Attempted to open file {path:?} that is not a valid file"); warn!(target:"FileSystem", "Attempted to open file {path:?} that is not a valid file");
return QString::default(); return QString::default();
} }
let path_str = path.to_string(); let ss = SyntaxSet::load_defaults_nonewlines();
if let Ok(lines) = fs::read_to_string(path_str.as_str()) { let ts = ThemeSet::load_defaults();
let ss = SyntaxSet::load_defaults_nonewlines(); let theme = &ts.themes["base16-ocean.dark"];
let ts = ThemeSet::load_defaults();
let theme = &ts.themes["base16-ocean.dark"];
let lang = ss
.find_syntax_by_extension(
Path::new(path_str.as_str())
.extension()
.map(|s| s.to_str())
.unwrap_or_else(|| Some("md"))
.expect("Failed to get file extension"),
)
.unwrap_or_else(|| ss.find_syntax_plain_text());
let mut highlighter = HighlightLines::new(lang, theme);
let (mut output, _bg) = start_highlighted_html_snippet(theme);
for line in LinesWithEndings::from(lines.as_str()) {
let regions = highlighter
.highlight_line(line, &ss)
.expect("Failed to highlight");
append_highlighted_html_for_styled_line( let mut highlighter =
&regions[..], HighlightFile::new(path.to_string(), &ss, theme).expect("Failed to create highlighter");
IncludeBackground::Yes, let (mut output, _bg) = start_highlighted_html_snippet(theme);
&mut output, let mut line = String::new();
) while highlighter
.expect("Failed to insert highlighted html"); .reader
} .read_line(&mut line)
.expect("Failed to read file.")
> 0
{
let regions = highlighter
.highlight_lines
.highlight_line(&line, &ss)
.expect("Failed to highlight");
output.push_str("</pre>\n"); append_highlighted_html_for_styled_line(
QString::from(output) &regions[..],
} else { IncludeBackground::Yes,
return QString::default(); &mut output,
)
.expect("Failed to insert highlighted html");
line.clear();
} }
output.push_str("</pre>\n");
QString::from(output)
} }
// There will never be more than one column. // There will never be more than one column.
@ -130,13 +128,14 @@ impl qobject::FileSystem {
self.set_root_path(path) self.set_root_path(path)
} else { } else {
// If the initial directory can't be opened, attempt to find the home directory. // If the initial directory can't be opened, attempt to find the home directory.
let homedir = dirs::home_dir() self.set_root_path(&QString::from(
.expect("Failed to get home directory") dirs::home_dir()
.as_path() .expect("Failed to get home directory")
.to_str() .as_path()
.unwrap() .to_str()
.to_string(); .unwrap()
self.set_root_path(&QString::from(homedir)) .to_string(),
))
} }
} }
} }