Implement Save as, fixes #127

This commit is contained in:
Jeremy Soller 2024-02-15 15:09:32 -07:00
parent 9da0b4575e
commit 76c659fb21
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
4 changed files with 57 additions and 19 deletions

6
Cargo.lock generated
View file

@ -721,9 +721,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.14.0" version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f"
[[package]] [[package]]
name = "bytecount" name = "bytecount"
@ -1202,7 +1202,7 @@ dependencies = [
[[package]] [[package]]
name = "cosmic-files" name = "cosmic-files"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/pop-os/cosmic-files#91c4985d42806e6465726276685619d531355993" source = "git+https://github.com/pop-os/cosmic-files#a24983ca7fec2ba7b95d1153acfff8527c9882ff"
dependencies = [ dependencies = [
"chrono", "chrono",
"dirs", "dirs",

View file

@ -73,6 +73,7 @@ pub fn key_binds() -> HashMap<KeyBind, Action> {
bind!([Ctrl], Key::Character("q".into()), Quit); bind!([Ctrl], Key::Character("q".into()), Quit);
bind!([Ctrl, Shift], Key::Character("Z".into()), Redo); bind!([Ctrl, Shift], Key::Character("Z".into()), Redo);
bind!([Ctrl], Key::Character("s".into()), Save); bind!([Ctrl], Key::Character("s".into()), Save);
bind!([Ctrl, Shift], Key::Character("S".into()), SaveAsDialog);
bind!([Ctrl], Key::Character("a".into()), SelectAll); bind!([Ctrl], Key::Character("a".into()), SelectAll);
bind!([Ctrl], Key::Character("1".into()), TabActivate0); bind!([Ctrl], Key::Character("1".into()), TabActivate0);
bind!([Ctrl], Key::Character("2".into()), TabActivate1); bind!([Ctrl], Key::Character("2".into()), TabActivate1);

View file

@ -17,7 +17,7 @@ use cosmic::{
widget::{self, button, icon, nav_bar, segmented_button, view_switcher}, widget::{self, button, icon, nav_bar, segmented_button, view_switcher},
Application, ApplicationExt, Apply, Element, Application, ApplicationExt, Apply, Element,
}; };
use cosmic_files::dialog::{Dialog, DialogMessage, DialogResult}; use cosmic_files::dialog::{Dialog, DialogKind, DialogMessage, DialogResult};
use cosmic_text::{Cursor, Edit, Family, FontSystem, Selection, SwashCache, SyntaxSystem, ViMode}; use cosmic_text::{Cursor, Edit, Family, FontSystem, Selection, SwashCache, SyntaxSystem, ViMode};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
@ -180,6 +180,7 @@ pub enum Action {
Quit, Quit,
Redo, Redo,
Save, Save,
SaveAsDialog,
SelectAll, SelectAll,
TabActivate0, TabActivate0,
TabActivate1, TabActivate1,
@ -223,6 +224,7 @@ impl Action {
Self::Quit => Message::Quit, Self::Quit => Message::Quit,
Self::Redo => Message::Redo, Self::Redo => Message::Redo,
Self::Save => Message::Save, Self::Save => Message::Save,
Self::SaveAsDialog => Message::SaveAsDialog,
Self::SelectAll => Message::SelectAll, Self::SelectAll => Message::SelectAll,
Self::TabActivate0 => Message::TabActivateJump(0), Self::TabActivate0 => Message::TabActivateJump(0),
Self::TabActivate1 => Message::TabActivateJump(1), Self::TabActivate1 => Message::TabActivateJump(1),
@ -317,6 +319,8 @@ pub enum Message {
Quit, Quit,
Redo, Redo,
Save, Save,
SaveAsDialog,
SaveAsResult(segmented_button::Entity, DialogResult),
SelectAll, SelectAll,
SystemThemeModeChange(cosmic_theme::ThemeMode), SystemThemeModeChange(cosmic_theme::ThemeMode),
SyntaxTheme(usize, bool), SyntaxTheme(usize, bool),
@ -1526,8 +1530,12 @@ impl Application for App {
} }
Message::OpenFileDialog => { Message::OpenFileDialog => {
if self.dialog_opt.is_none() { if self.dialog_opt.is_none() {
let (dialog, command) = let (dialog, command) = Dialog::new(
Dialog::new(Message::DialogMessage, Message::OpenFileResult); DialogKind::OpenMultipleFiles,
None,
Message::DialogMessage,
Message::OpenFileResult,
);
self.dialog_opt = Some(dialog); self.dialog_opt = Some(dialog);
return command; return command;
} }
@ -1579,8 +1587,12 @@ impl Application for App {
} }
Message::OpenProjectDialog => { Message::OpenProjectDialog => {
if self.dialog_opt.is_none() { if self.dialog_opt.is_none() {
let (dialog, command) = let (dialog, command) = Dialog::new(
Dialog::new(Message::DialogMessage, Message::OpenProjectResult); DialogKind::OpenMultipleFolders,
None,
Message::DialogMessage,
Message::OpenProjectResult,
);
self.dialog_opt = Some(dialog); self.dialog_opt = Some(dialog);
return command; return command;
} }
@ -1742,10 +1754,8 @@ impl Application for App {
let mut title_opt = None; let mut title_opt = None;
if let Some(Tab::Editor(tab)) = self.active_tab_mut() { if let Some(Tab::Editor(tab)) = self.active_tab_mut() {
#[cfg(feature = "rfd")]
if tab.path_opt.is_none() { if tab.path_opt.is_none() {
//TODO: use async file dialog return self.update(Message::SaveAsDialog);
tab.path_opt = rfd::FileDialog::new().save_file();
} }
title_opt = Some(tab.title()); title_opt = Some(tab.title());
tab.save(); tab.save();
@ -1755,6 +1765,40 @@ impl Application for App {
self.tab_model.text_set(self.tab_model.active(), title); self.tab_model.text_set(self.tab_model.active(), title);
} }
} }
Message::SaveAsDialog => {
if self.dialog_opt.is_none() {
let entity = self.tab_model.active();
if let Some(Tab::Editor(tab)) = self.tab_model.data::<Tab>(entity) {
let (dialog, command) = Dialog::new(
DialogKind::SaveFile,
tab.path_opt.clone(),
Message::DialogMessage,
move |result| Message::SaveAsResult(entity, result),
);
self.dialog_opt = Some(dialog);
return command;
}
}
}
Message::SaveAsResult(entity, result) => {
self.dialog_opt = None;
match result {
DialogResult::Cancel => {}
DialogResult::Open(mut paths) => {
if !paths.is_empty() {
let mut title_opt = None;
if let Some(Tab::Editor(tab)) = self.tab_model.data_mut::<Tab>(entity) {
tab.path_opt = Some(paths.remove(0));
title_opt = Some(tab.title());
tab.save();
}
if let Some(title) = title_opt {
self.tab_model.text_set(entity, title);
}
}
}
}
}
Message::SelectAll => { Message::SelectAll => {
if let Some(Tab::Editor(tab)) = self.active_tab_mut() { if let Some(Tab::Editor(tab)) = self.active_tab_mut() {
let mut editor = tab.editor.lock().unwrap(); let mut editor = tab.editor.lock().unwrap();

View file

@ -143,13 +143,6 @@ pub fn menu_bar<'a>(
) )
}; };
let menu_key = |label, key, action: Action| {
MenuTree::new(
menu_button!(widget::text(label), horizontal_space(Length::Fill), key)
.on_press(action.message()),
)
};
let menu_tab_width = |tab_width: u16| { let menu_tab_width = |tab_width: u16| {
menu_checkbox( menu_checkbox(
fl!("tab-width", tab_width = tab_width), fl!("tab-width", tab_width = tab_width),
@ -199,7 +192,7 @@ pub fn menu_bar<'a>(
MenuTree::with_children(menu_folder(fl!("close-project")), close_projects), MenuTree::with_children(menu_folder(fl!("close-project")), close_projects),
MenuTree::new(horizontal_rule(1)), MenuTree::new(horizontal_rule(1)),
menu_item(fl!("save"), Action::Save), menu_item(fl!("save"), Action::Save),
menu_key(fl!("save-as"), "Ctrl + Shift + S", Action::Todo), menu_item(fl!("save-as"), Action::SaveAsDialog),
MenuTree::new(horizontal_rule(1)), MenuTree::new(horizontal_rule(1)),
menu_item(fl!("revert-all-changes"), Action::Todo), menu_item(fl!("revert-all-changes"), Action::Todo),
MenuTree::new(horizontal_rule(1)), MenuTree::new(horizontal_rule(1)),