diff --git a/src/util/gettext.rs b/src/util/gettext.rs index 9686cbb..9fad997 100644 --- a/src/util/gettext.rs +++ b/src/util/gettext.rs @@ -15,21 +15,28 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +use std::fmt::Display; + pub use gettextrs::gettext; -fn freplace(mut s: String, args: impl IntoIterator>) -> String { +fn freplace(mut s: String, args: impl IntoIterator) -> String { for arg in args { - s = s.replacen("{}", arg.as_ref(), 1); + s = s.replacen("{}", &arg.to_string(), 1); } s } -pub fn gettext_f(format: &str, args: impl IntoIterator>) -> String { +pub fn gettext_f(format: &str, args: impl IntoIterator) -> String { let s = ugettext(format); freplace(s, args) } +pub fn ngettext(format: &str, format_plural: &str, n: u32) -> String { + let s = gettextrs::ngettext(format, format_plural, n); + freplace(apply_unicode_escapes(&s).unwrap_or(s), [n]) +} + /// Same as `gettext` but evaluates unicode escape sequences pub fn ugettext(msgid: &str) -> String { let msg = gettext(msgid); diff --git a/src/widgets/edit/crop_selection.rs b/src/widgets/edit/crop_selection.rs index 87b0eee..3b981ce 100644 --- a/src/widgets/edit/crop_selection.rs +++ b/src/widgets/edit/crop_selection.rs @@ -152,9 +152,8 @@ trait RectExt: Into { impl RectExt for graphene::Rect {} mod imp { - use crate::widgets::LpImage; - use super::*; + use crate::widgets::LpImage; #[derive(Debug, Default, gtk::CompositeTemplate, glib::Properties)] #[properties(wrapper_type = super::LpEditCropSelection)] diff --git a/src/widgets/edit_window.rs b/src/widgets/edit_window.rs index b796832..e1ed7ca 100644 --- a/src/widgets/edit_window.rs +++ b/src/widgets/edit_window.rs @@ -137,7 +137,53 @@ mod imp { if let Some(current_file) = obj.original_image().file() { let file_dialog = gtk::FileDialog::new(); - file_dialog.set_initial_file(Some(¤t_file)); + let suggested_file = if let Some(path) = current_file.path() { + if let Some(basename) = path.file_stem() { + let mut suggested_file = None; + for i in 1..20 { + let mut new_path = path.clone(); + let mut new_filename = basename.to_os_string(); + + if i == 1 { + // Translators: Filename suffix + new_filename.push(gettext(" (Edited)")); + } else { + // Translators: Filename suffix, {} is replaced by a number + new_filename.push(ngettext(" (Edited)", " (Edited {})", i)); + } + + if let Some(ext) = path.extension() { + new_filename.push("."); + new_filename.push(ext); + } + + new_path.set_file_name(new_filename); + + let file = gio::File::for_path(&new_path); + let file_exists = file + .query_info_future( + gio::FILE_ATTRIBUTE_STANDARD_NAME, + gio::FileQueryInfoFlags::NONE, + glib::Priority::DEFAULT, + ) + .await + .is_ok(); + + if !file_exists { + suggested_file = Some(file); + break; + } + } + + suggested_file.unwrap_or_else(|| current_file.clone()) + } else { + current_file.clone() + } + } else { + current_file.clone() + }; + + file_dialog.set_initial_file(Some(&suggested_file)); match file_dialog.save_future(Some(&obj.window())).await { Err(err) => { diff --git a/src/widgets/error_details.rs b/src/widgets/error_details.rs index ec0091b..b1bc493 100644 --- a/src/widgets/error_details.rs +++ b/src/widgets/error_details.rs @@ -1,4 +1,5 @@ // Copyright (c) 2024 Sophie Herold +// Copyright (c) 2025 Rafael Fontenelle // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/src/widgets/image_view.rs b/src/widgets/image_view.rs index ecd14bc..15a477c 100644 --- a/src/widgets/image_view.rs +++ b/src/widgets/image_view.rs @@ -692,8 +692,6 @@ impl LpImageView { } } - dbg!(file_event); - let Some(current_file) = self.current_file() else { return; };