From f8e64d9805ab88c9020fc6bfa029b5c083275329 Mon Sep 17 00:00:00 2001 From: Sophie Herold Date: Thu, 9 Mar 2023 04:13:48 +0100 Subject: [PATCH] trash: Use non-existing name when restoring image We usually use the original path of the image. For the rare case the original file name exists we create one that is not used yet. Closes #66 Part-of: --- src/util.rs | 31 +++++++++++++++++++++++++++++-- src/window.rs | 2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/util.rs b/src/util.rs index c6880a6..02d3523 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,7 @@ use crate::deps::*; use crate::i18n::*; -use anyhow::{anyhow, Context}; +use anyhow::{anyhow, bail, Context}; use gio::prelude::*; use once_cell::sync::Lazy; @@ -96,15 +96,42 @@ pub async fn untrash(path: &Path) -> anyhow::Result<()> { if original_path == path { let trash_file = trash.child(file_info.name()); let original_file = gio::File::for_path(original_path); + let mut target_file = original_file.clone(); + + // Find available filename if original is used + for i in 1.. { + if !target_file.query_exists(gio::Cancellable::NONE) { + break; + } + + // Construct new name of the form " (i)." + let Some(path) = original_file.path() else { bail!("File without path") }; + let mut name = path + .file_stem() + .map(|x| x.to_os_string()) + .unwrap_or_default(); + name.push(format!(" ({i})")); + + // Construct new path + let mut new_path = path.clone(); + new_path.set_file_name(name); + if let Some(ext) = path.extension() { + new_path.set_extension(ext); + } + + target_file = gio::File::for_path(new_path); + } + error = trash_file .move_future( - &original_file, + &target_file, gio::FileCopyFlags::NOFOLLOW_SYMLINKS, glib::Priority::default(), ) .0 .await .context(i18n("Failed to restore image from trash")); + break; } } diff --git a/src/window.rs b/src/window.rs index bc3bdb8..22ad0df 100644 --- a/src/window.rs +++ b/src/window.rs @@ -533,7 +533,7 @@ impl LpWindow { /// Permanently delete image /// - /// Fallback for when trash no available + /// Fallback for when trash not available async fn delete(&self, path: &Path) { let dialog = adw::MessageDialog::builder() .modal(true)