From a936cd4a6d8bca958350fe6b02e1ec003ad0a675 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 26 Feb 2024 14:11:45 -0700 Subject: [PATCH] Return item open to tab handler --- examples/dialog.rs | 52 +++++++++++++++++++++---------------- justfile | 3 +-- src/app.rs | 47 +++++++++++++++++++++++---------- src/dialog.rs | 34 ++++++++++++++++++------ src/lib.rs | 1 + src/tab.rs | 65 +++++++--------------------------------------- src/util.rs | 37 ++++++++++++++++++++++++++ 7 files changed, 137 insertions(+), 102 deletions(-) create mode 100644 src/util.rs diff --git a/examples/dialog.rs b/examples/dialog.rs index 8abba19..09c9b27 100644 --- a/examples/dialog.rs +++ b/examples/dialog.rs @@ -17,9 +17,8 @@ fn main() -> Result<(), Box> { #[derive(Clone, Debug)] pub enum Message { DialogMessage(DialogMessage), - DialogOpen, + DialogOpen(DialogKind), DialogResult(DialogResult), - DialogSave, } pub struct App { @@ -61,10 +60,10 @@ impl Application for App { return dialog.update(dialog_message); } } - Message::DialogOpen => { + Message::DialogOpen(dialog_kind) => { if self.dialog_opt.is_none() { let (dialog, command) = Dialog::new( - DialogKind::OpenFile, + dialog_kind, None, Message::DialogMessage, Message::DialogResult, @@ -77,20 +76,6 @@ impl Application for App { self.dialog_opt = None; self.result_opt = Some(result); } - Message::DialogSave => { - if self.dialog_opt.is_none() { - let (dialog, command) = Dialog::new( - DialogKind::SaveFile { - filename: "README.md".to_string(), - }, - None, - Message::DialogMessage, - Message::DialogResult, - ); - self.dialog_opt = Some(dialog); - return command; - } - } } Command::none() @@ -106,16 +91,39 @@ impl Application for App { fn view(&self) -> Element { let mut column = widget::column().spacing(8); { - let mut button = widget::button::standard("Open Dialog"); + let mut button = widget::button::standard("Open File"); if self.dialog_opt.is_none() { - button = button.on_press(Message::DialogOpen); + button = button.on_press(Message::DialogOpen(DialogKind::OpenFile)); } column = column.push(button); } { - let mut button = widget::button::standard("Save Dialog"); + let mut button = widget::button::standard("Open Multiple Files"); if self.dialog_opt.is_none() { - button = button.on_press(Message::DialogSave); + button = button.on_press(Message::DialogOpen(DialogKind::OpenMultipleFiles)); + } + column = column.push(button); + } + { + let mut button = widget::button::standard("Open Folder"); + if self.dialog_opt.is_none() { + button = button.on_press(Message::DialogOpen(DialogKind::OpenFolder)); + } + column = column.push(button); + } + { + let mut button = widget::button::standard("Open Multiple Folders"); + if self.dialog_opt.is_none() { + button = button.on_press(Message::DialogOpen(DialogKind::OpenMultipleFolders)); + } + column = column.push(button); + } + { + let mut button = widget::button::standard("Save File"); + if self.dialog_opt.is_none() { + button = button.on_press(Message::DialogOpen(DialogKind::SaveFile { + filename: "test".to_string() + })); } column = column.push(button); } diff --git a/justfile b/justfile index 0eb89eb..99cdc63 100644 --- a/justfile +++ b/justfile @@ -50,8 +50,7 @@ check-json: (check '--message-format=json') dev *args: cargo fmt cargo test - cargo build --profile release-with-debug - env RUST_LOG=cosmic_files=debug RUST_BACKTRACE=full target/release-with-debug/cosmic-files {{args}} + just run {{args}} # Run with debug logs run *args: diff --git a/src/app.rs b/src/app.rs index fa3b37f..8cca3d1 100644 --- a/src/app.rs +++ b/src/app.rs @@ -30,6 +30,7 @@ use crate::{ fl, home_dir, key_bind::{key_binds, KeyBind}, menu, + util, operation::Operation, tab::{self, ItemMetadata, Location, Tab}, }; @@ -850,29 +851,47 @@ impl Application for App { Message::TabMessage(entity_opt, tab_message) => { let entity = entity_opt.unwrap_or_else(|| self.tab_model.active()); + //TODO: move to Command? if let tab::Message::ContextMenu(_point_opt) = tab_message { // Disable side context page self.core.window.show_context = false; } - let tab_command = match self.tab_model.data_mut::(entity) { + let tab_commands = match self.tab_model.data_mut::(entity) { Some(tab) => tab.update(tab_message, self.modifiers), - _ => tab::Command::None, + _ => Vec::new(), }; - match tab_command { - tab::Command::None => {} - tab::Command::Action(action) => { - return self.update(action.message(Some(entity))); - } - tab::Command::ChangeLocation(tab_title, tab_path) => { - self.tab_model.text_set(entity, tab_title); - return Command::batch([ - self.update_title(), - self.update_watcher(), - self.rescan_tab(entity, tab_path), - ]); + + let mut commands = Vec::new(); + for tab_command in tab_commands { + match tab_command { + tab::Command::Action(action) => { + commands.push(self.update(action.message(Some(entity)))); + } + tab::Command::ChangeLocation(tab_title, tab_path) => { + self.tab_model.text_set(entity, tab_title); + commands.push(Command::batch([ + self.update_title(), + self.update_watcher(), + self.rescan_tab(entity, tab_path), + ])); + } + tab::Command::OpenFile(item_path) => { + let mut command = util::open_command(&item_path); + match command.spawn() { + Ok(_) => (), + Err(err) => { + log::warn!( + "failed to open {:?}: {}", + item_path, + err + ); + } + } + } } } + return Command::batch(commands); } Message::TabNew => { let active = self.tab_model.active(); diff --git a/src/dialog.rs b/src/dialog.rs index 59fac89..d752bb0 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -53,6 +53,10 @@ impl DialogKind { } } + pub fn is_dir(&self) -> bool { + matches!(self, Self::OpenFolder | Self::OpenMultipleFolders) + } + pub fn multiple(&self) -> bool { matches!(self, Self::OpenMultipleFiles | Self::OpenMultipleFolders) } @@ -456,6 +460,14 @@ impl Application for App { if !paths.is_empty() { self.result_opt = Some(DialogResult::Open(paths)); return window::close(self.main_window_id()); + } else if self.flags.kind.is_dir() { + match &self.tab.location { + Location::Path(tab_path) => { + self.result_opt = Some(DialogResult::Open(vec![tab_path.clone()])); + return window::close(self.main_window_id()); + }, + _ => {} + } } } Message::Save => { @@ -479,7 +491,7 @@ impl Application for App { _ => None, }; - let tab_command = self.tab.update(tab_message, self.modifiers); + let tab_commands = self.tab.update(tab_message, self.modifiers); // Update filename box when anything is selected if let DialogKind::SaveFile { filename } = &mut self.flags.kind { @@ -494,15 +506,21 @@ impl Application for App { } } - match tab_command { - tab::Command::None => {} - tab::Command::Action(action) => { - log::warn!("Action {:?} not supported in dialog", action); - } - tab::Command::ChangeLocation(_tab_title, _tab_path) => { - return Command::batch([self.update_watcher(), self.rescan_tab()]); + let mut commands = Vec::new(); + for tab_command in tab_commands { + match tab_command { + tab::Command::Action(action) => { + log::warn!("Action {:?} not supported in dialog", action); + } + tab::Command::ChangeLocation(_tab_title, _tab_path) => { + commands.push(Command::batch([self.update_watcher(), self.rescan_tab()])); + } + tab::Command::OpenFile(_item_path) => { + commands.push(self.update(Message::Open)); + } } } + return Command::batch(commands); } Message::TabRescan(mut items) => { // Select based on filename diff --git a/src/lib.rs b/src/lib.rs index 555e6ca..dc9d666 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ mod mime_icon; mod mouse_area; mod operation; mod tab; +mod util; pub fn home_dir() -> PathBuf { match dirs::home_dir() { diff --git a/src/tab.rs b/src/tab.rs index 10ca22f..74e3ec4 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -162,42 +162,6 @@ fn hidden_attribute(metadata: &Metadata) -> bool { metadata.file_attributes() & FILE_ATTRIBUTE_HIDDEN == FILE_ATTRIBUTE_HIDDEN } -#[cfg(target_os = "linux")] -fn open_command(path: &PathBuf) -> process::Command { - let mut command = process::Command::new("xdg-open"); - command.arg(path); - command -} - -#[cfg(target_os = "macos")] -fn open_command(path: &PathBuf) -> process::Command { - let mut command = process::Command::new("open"); - command.arg(path); - command -} - -#[cfg(target_os = "redox")] -fn open_command(path: &PathBuf) -> process::Command { - let mut command = process::Command::new("launcher"); - command.arg(path); - command -} - -#[cfg(target_os = "windows")] -fn open_command(path: &PathBuf) -> process::Command { - use std::os::windows::process::CommandExt; - - let mut command = process::Command::new("cmd"); - - command - .arg("/c") - .arg("start") - .raw_arg("\"\"") - .arg(path) - .creation_flags(0x08000000); - command -} - pub fn scan_path(tab_path: &PathBuf, sizes: IconSizes) -> Vec { let mut items = Vec::new(); match fs::read_dir(tab_path) { @@ -392,9 +356,9 @@ impl Location { #[derive(Clone, Debug)] pub enum Command { - None, Action(Action), ChangeLocation(String, Location), + OpenFile(PathBuf), } #[derive(Clone, Debug)] @@ -612,7 +576,8 @@ impl Tab { } } - pub fn update(&mut self, message: Message, modifiers: Modifiers) -> Command { + pub fn update(&mut self, message: Message, modifiers: Modifiers) -> Vec { + let mut commands = Vec::new(); let mut cd = None; let mut history_i_opt = None; match message { @@ -626,19 +591,10 @@ impl Tab { match self.location { Location::Path(_) => { if item.path.is_dir() { + //TODO: allow opening multiple tabs? cd = Some(Location::Path(item.path.clone())); - } else if !self.dialog.is_some() { - let mut command = open_command(&item.path); - match command.spawn() { - Ok(_) => (), - Err(err) => { - log::warn!( - "failed to open {:?}: {}", - item.path, - err - ); - } - } + } else { + commands.push(Command::OpenFile(item.path.clone())); } } Location::Trash => { @@ -669,7 +625,7 @@ impl Tab { // Close context menu self.context_menu = None; - return Command::Action(action); + commands.push(Command::Action(action)); } Message::ContextMenu(point_opt) => { self.context_menu = point_opt; @@ -795,13 +751,10 @@ impl Tab { self.history_i = self.history.len(); self.history.push(location.clone()); } - Command::ChangeLocation(self.title(), location) - } else { - Command::None + commands.push(Command::ChangeLocation(self.title(), location)); } - } else { - Command::None } + commands } pub fn location_view(&self, core: &Core) -> Element { diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..37877c6 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,37 @@ +use std::{path::PathBuf, process}; + +#[cfg(target_os = "linux")] +pub fn open_command(path: &PathBuf) -> process::Command { + let mut command = process::Command::new("xdg-open"); + command.arg(path); + command +} + +#[cfg(target_os = "macos")] +pub fn open_command(path: &PathBuf) -> process::Command { + let mut command = process::Command::new("open"); + command.arg(path); + command +} + +#[cfg(target_os = "redox")] +pub fn open_command(path: &PathBuf) -> process::Command { + let mut command = process::Command::new("launcher"); + command.arg(path); + command +} + +#[cfg(target_os = "windows")] +pub fn open_command(path: &PathBuf) -> process::Command { + use std::os::windows::process::CommandExt; + + let mut command = process::Command::new("cmd"); + + command + .arg("/c") + .arg("start") + .raw_arg("\"\"") + .arg(path) + .creation_flags(0x08000000); + command +}