diff --git a/Cargo.lock b/Cargo.lock index 61ee8a12df..204b74a576 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -357,6 +357,17 @@ dependencies = [ "piper", ] +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "regex-automata 0.4.6", + "serde", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -746,6 +757,17 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + [[package]] name = "derive_builder" version = "0.11.2" @@ -1720,25 +1742,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "is-docker" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" -dependencies = [ - "once_cell", -] - -[[package]] -name = "is-wsl" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" -dependencies = [ - "is-docker", - "once_cell", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.0" @@ -1920,6 +1923,16 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "libloading" version = "0.8.3" @@ -2195,6 +2208,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "normpath" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5831952a9476f2fed74b77d74182fa5ddc4d21c72ec45a333b250e3ed0272804" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "notify" version = "6.1.1" @@ -2390,14 +2412,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "open" -version = "5.1.4" +name = "opener" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ca541f22b1c46d4bb9801014f234758ab4297e7870b904b6a8415b980a7388" +checksum = "f8df34be653210fbe9ffaff41d3b92721c56ce82dfee58ee684f9afb5e3a90c0" dependencies = [ - "is-wsl", - "libc", - "pathdiff", + "bstr", + "dbus", + "normpath", + "url", + "windows-sys 0.52.0", ] [[package]] @@ -2555,12 +2579,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "pathdiff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" - [[package]] name = "percent-encoding" version = "2.3.1" @@ -3000,7 +3018,7 @@ dependencies = [ "num-traits", "numeric-sort", "once_cell", - "open", + "opener", "palette", "parry2d-f64", "path-absolutize", @@ -3037,7 +3055,7 @@ dependencies = [ "dialoguer", "indicatif", "nalgebra", - "open", + "opener", "parry2d-f64", "rnote-compose", "rnote-engine", diff --git a/Cargo.toml b/Cargo.toml index 7ef4613972..aa8c783544 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ num-derive = "0.4.2" num-traits = "0.2.18" numeric-sort = "0.1.0" once_cell = "1.19" -open = "5.1" +opener = {version = "0.7.0", features=["reveal"]} palette = "0.7.5" parry2d-f64 = { version = "0.13.6", features = ["serde-serialize"] } path-absolutize = "3.1" diff --git a/crates/rnote-cli/Cargo.toml b/crates/rnote-cli/Cargo.toml index 01b99ddc91..658997b428 100644 --- a/crates/rnote-cli/Cargo.toml +++ b/crates/rnote-cli/Cargo.toml @@ -18,7 +18,7 @@ clap = { workspace = true } dialoguer = { workspace = true } indicatif = { workspace = true } nalgebra = { workspace = true } -open = { workspace = true } +opener = { workspace = true } parry2d-f64 = { workspace = true } smol = { workspace = true } tracing = { workspace = true } diff --git a/crates/rnote-cli/src/cli.rs b/crates/rnote-cli/src/cli.rs index f135bc5218..ddfa58ee05 100644 --- a/crates/rnote-cli/src/cli.rs +++ b/crates/rnote-cli/src/cli.rs @@ -272,7 +272,8 @@ pub(crate) async fn create_overwrite_file_w_bytes( } pub(crate) fn open_file_default_app(file_path: impl AsRef) -> anyhow::Result<()> { - open::that_detached(file_path.as_ref()).with_context(|| { + // this one may be problematic compared to open::that_detached + opener::open(file_path.as_ref()).with_context(|| { format!( "Failed to open output file/folder \"{}\".", file_path.as_ref().display() diff --git a/crates/rnote-ui/Cargo.toml b/crates/rnote-ui/Cargo.toml index 04d3e8e8ff..f5081bfb69 100644 --- a/crates/rnote-ui/Cargo.toml +++ b/crates/rnote-ui/Cargo.toml @@ -33,7 +33,7 @@ num-derive = { workspace = true } num-traits = { workspace = true } numeric-sort = { workspace = true } once_cell = { workspace = true } -open = { workspace = true } +opener = { workspace = true } palette = { workspace = true } parry2d-f64 = { workspace = true } path-absolutize = { workspace = true } diff --git a/crates/rnote-ui/data/ui/filerow.ui b/crates/rnote-ui/data/ui/filerow.ui index 767290916e..222076d08f 100644 --- a/crates/rnote-ui/data/ui/filerow.ui +++ b/crates/rnote-ui/data/ui/filerow.ui @@ -65,6 +65,10 @@ Open in Default App filerow.open-in-default-app + + Open in File Explorer + filerow.open-in-explorer + Rename filerow.rename-file diff --git a/crates/rnote-ui/data/ui/workspacebrowser.ui b/crates/rnote-ui/data/ui/workspacebrowser.ui index a952af41fd..4dc1bbcce4 100644 --- a/crates/rnote-ui/data/ui/workspacebrowser.ui +++ b/crates/rnote-ui/data/ui/workspacebrowser.ui @@ -164,6 +164,12 @@ workspacebrowser.create-folder +
+ + Open Workspace Folder + workspacebrowser.open-folder + +
diff --git a/crates/rnote-ui/src/dialogs/export.rs b/crates/rnote-ui/src/dialogs/export.rs index 80f4270b9c..5742087b40 100644 --- a/crates/rnote-ui/src/dialogs/export.rs +++ b/crates/rnote-ui/src/dialogs/export.rs @@ -235,18 +235,14 @@ pub(crate) async fn dialog_export_doc_w_prefs(appwindow: &RnAppWindow, canvas: & &gettext("Exported document successfully"), &gettext("View in file manager"), clone!(@weak canvas, @weak appwindow => move |_reload_toast| { - let Some(folder_path_string) = file - .parent() - .and_then(|p| - p.path()) - .and_then(|p| p.into_os_string().into_string().ok()) else { - tracing::error!("Failed to get the parent folder of the output file `{file:?}."); - appwindow.overlays().dispatch_toast_error(&gettext("Exporting document failed")); - return; - }; + let Some(file_path_string) = file.path().and_then(|p| p.into_os_string().into_string().ok()) else { + tracing::error!("Failed to get the path of the file `{file:?}."); + appwindow.overlays().dispatch_toast_error(&gettext("Exporting document failed")); + return; + }; - if let Err(e) = open::that(&folder_path_string) { - tracing::error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}"); + if let Err(e) = opener::reveal(&file_path_string) { + tracing::error!("Revealing the file '{file_path_string}' in the file manager failed, Err: {e:?}"); appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file manager")); } } @@ -546,7 +542,7 @@ pub(crate) async fn dialog_export_doc_pages_w_prefs(appwindow: &RnAppWindow, can return; }; - if let Err(e) = open::that(&folder_path_string) { + if let Err(e) = opener::open(&folder_path_string) { tracing::error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}"); appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file manager")); } @@ -818,7 +814,7 @@ pub(crate) async fn dialog_export_selection_w_prefs(appwindow: &RnAppWindow, can return; }; - if let Err(e) = open::that(&folder_path_string) { + if let Err(e) = opener::open(&folder_path_string) { tracing::error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}"); appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file manager")); } diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/actions/mod.rs b/crates/rnote-ui/src/workspacebrowser/filerow/actions/mod.rs index 7f3f50169c..cba0d52db9 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/actions/mod.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/actions/mod.rs @@ -2,6 +2,7 @@ mod duplicate; mod open; mod open_in_default_app; +mod open_in_explorer; mod rename; mod trash; @@ -9,5 +10,6 @@ mod trash; pub(crate) use duplicate::duplicate; pub(crate) use open::open; pub(crate) use open_in_default_app::open_in_default_app; +pub(crate) use open_in_explorer::open_in_explorer; pub(crate) use rename::rename; pub(crate) use trash::trash; diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_default_app.rs b/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_default_app.rs index e98fd3fde4..ad34efb738 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_default_app.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_default_app.rs @@ -14,7 +14,7 @@ pub(crate) fn open_in_default_app( let Some(current_file) = filerow.current_file() else { return; }; - if let Err(e) = open::that(current_file.uri()) { + if let Err(e) = opener::open(current_file.uri()) { appwindow.overlays().dispatch_toast_error(&gettext("Open the file in the default app failed")); tracing::debug!("Opening file {} with default app failed, Err: {e:?}", current_file.uri()); } diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_explorer.rs b/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_explorer.rs new file mode 100644 index 0000000000..49298f2048 --- /dev/null +++ b/crates/rnote-ui/src/workspacebrowser/filerow/actions/open_in_explorer.rs @@ -0,0 +1,29 @@ +// Imports +use crate::workspacebrowser::RnFileRow; +use crate::RnAppWindow; +use gettextrs::gettext; +use gtk4::{gio, gio::prelude::FileExt, glib, glib::clone}; + +/// Create a new `open-in-default-app` action. +pub(crate) fn open_in_explorer(filerow: &RnFileRow, appwindow: &RnAppWindow) -> gio::SimpleAction { + let action_open_in_default = gio::SimpleAction::new("open-in-explorer", None); + action_open_in_default.connect_activate( + clone!(@weak filerow, @weak appwindow => move |_action_open_in_default, _| { + if let Some(current_file) = filerow.current_file() { + // check if the path can be obtained + if let Some(path) = current_file.path() { + if let Err(e) = opener::reveal(path ) { + appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file explorer")); + tracing::debug!("opening file {} in the file explorer failed: {e:?}", current_file.uri()); + } + } + else { + appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file explorer")); + tracing::debug!("opening file {} in the file explorer failed, could not get the path", current_file.uri()); + } + } + }), + ); + + action_open_in_default +} diff --git a/crates/rnote-ui/src/workspacebrowser/filerow/mod.rs b/crates/rnote-ui/src/workspacebrowser/filerow/mod.rs index 9e9bd30c5e..d9cca2b964 100644 --- a/crates/rnote-ui/src/workspacebrowser/filerow/mod.rs +++ b/crates/rnote-ui/src/workspacebrowser/filerow/mod.rs @@ -230,6 +230,9 @@ impl RnFileRow { self.imp() .action_group .add_action(&actions::open_in_default_app(self, appwindow)); + self.imp() + .action_group + .add_action(&actions::open_in_explorer(self, appwindow)); self.imp() .action_group .add_action(&actions::rename(self, appwindow)); diff --git a/crates/rnote-ui/src/workspacebrowser/mod.rs b/crates/rnote-ui/src/workspacebrowser/mod.rs index 413add16eb..2a7fb6a90d 100644 --- a/crates/rnote-ui/src/workspacebrowser/mod.rs +++ b/crates/rnote-ui/src/workspacebrowser/mod.rs @@ -194,6 +194,9 @@ impl RnWorkspaceBrowser { self.imp() .action_group .add_action(&workspaceactions::create_folder(self, appwindow)); + self.imp() + .action_group + .add_action(&workspaceactions::open_folder(self, appwindow)); } fn setup_dir_controls(&self, appwindow: &RnAppWindow) { diff --git a/crates/rnote-ui/src/workspacebrowser/workspaceactions/mod.rs b/crates/rnote-ui/src/workspacebrowser/workspaceactions/mod.rs index d5c77d7e63..a0799af398 100644 --- a/crates/rnote-ui/src/workspacebrowser/workspaceactions/mod.rs +++ b/crates/rnote-ui/src/workspacebrowser/workspaceactions/mod.rs @@ -1,5 +1,7 @@ // Modules mod createfolder; +mod openfolder; // Re-exports pub(crate) use createfolder::create_folder; +pub(crate) use openfolder::open_folder; diff --git a/crates/rnote-ui/src/workspacebrowser/workspaceactions/openfolder.rs b/crates/rnote-ui/src/workspacebrowser/workspaceactions/openfolder.rs new file mode 100644 index 0000000000..d1c300f797 --- /dev/null +++ b/crates/rnote-ui/src/workspacebrowser/workspaceactions/openfolder.rs @@ -0,0 +1,26 @@ +use crate::{RnAppWindow, RnWorkspaceBrowser}; +use gettextrs::gettext; +use gtk4::{gio, glib, glib::clone, prelude::*}; + +pub(crate) fn open_folder( + workspacebrowser: &RnWorkspaceBrowser, + appwindow: &RnAppWindow, +) -> gio::SimpleAction { + let open_folder_action = gio::SimpleAction::new("open-folder", None); + + open_folder_action.connect_activate(clone!(@weak workspacebrowser, @weak appwindow => move |_, _| { + if let Some(parent_path) = workspacebrowser.dir_list_file().and_then(|f| f.path()) { + if let Err(e) = opener::open(&parent_path) { + let path_string = &parent_path.into_os_string().into_string().ok().unwrap_or(String::from("path not found")); + tracing::error!("Opening the parent folder '{path_string}' in the file manager failed, Err: {e:?}"); + appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file manager")); + } + } else { + tracing::warn!("No path found"); + appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file manager")); + } + } + )); + + open_folder_action +}