Trigger save dialog via close_request

This simplifies the code and fixes that unsaved changes were only saved
for the active window and dropped for all others.

Part-of: <https://gitlab.gnome.org/GNOME/loupe/-/merge_requests/576>
This commit is contained in:
Sophie Herold 2026-06-22 14:45:51 +02:00 • committed by Marge Bot
parent aa4bdbb114
commit 6b4d057167
3 changed files with 60 additions and 62 deletions

View file

@ -25,7 +25,6 @@ use glycin::Operations;
use super::LpImage;
use super::edit::LpEditCrop;
use crate::LpApplication;
use crate::deps::*;
use crate::util::ErrorType;
use crate::util::gettext::*;
@ -490,19 +489,6 @@ impl LpEditWindow {
self.imp().is_save_sensitive()
}
pub fn save_as_and_quit(&self, app: LpApplication) {
glib::spawn_future_local(glib::clone!(
#[weak(rename_to=win)]
self,
#[strong]
app,
async move {
win.imp().save_overwrite().await;
app.quit()
}
));
}
pub fn add_operation(&self, operation: glycin::Operation) {
let imp = self.imp();
@ -517,4 +503,40 @@ impl LpEditWindow {
self.set_operations(Some(Arc::new(Operations::new(operations))));
}
/// Returns if the window should proceed with closing
pub async fn ensure_saved(&self) -> glib::Propagation {
if self.has_unsaved_changes() {
let dialog = adw::AlertDialog::new(
Some(&gettext("Unsaved Changes")),
Some(&gettext(
"Changes which are not lost will be permanently lost",
)),
);
dialog.add_response("cancel", &gettext("Cancel"));
dialog.add_response("discard", &gettext("Discard"));
dialog.add_response("save", &gettext("Save"));
dialog.set_response_appearance("discard", adw::ResponseAppearance::Destructive);
let res = dialog.choose_future(Some(self)).await;
match res.as_str() {
"cancel" => glib::Propagation::Stop,
"close" => glib::Propagation::Stop,
"discard" => glib::Propagation::Proceed,
"save" => {
self.imp().save_overwrite().await;
glib::Propagation::Proceed
}
res => {
tracing::error!("Invalid dialog result: {res}");
glib::Propagation::Stop
}
}
} else {
glib::Propagation::Proceed
}
}
}

View file

@ -129,6 +129,11 @@ mod imp {
// and keeps the others usable
gtk::WindowGroup::new().add_window(&*obj);
obj.connect_close_request(|win| {
win.imp().close_request();
glib::Propagation::Stop
});
glib::timeout_add_local_once(
std::time::Duration::from_millis(SHOW_WINDOW_AFTER),
glib::clone!(
@ -151,6 +156,22 @@ mod imp {
impl WindowImpl for LpWindow {}
impl ApplicationWindowImpl for LpWindow {}
impl AdwApplicationWindowImpl for LpWindow {}
impl LpWindow {
pub fn close_request(&self) {
let obj = self.obj().to_owned();
glib::MainContext::default().spawn_local(async move {
if let Some(edit_window) = obj.edit_window() {
if matches!(edit_window.ensure_saved().await, glib::Propagation::Proceed) {
obj.destroy();
}
} else {
// Without editing window, we can always close
obj.destroy();
}
});
}
}
}
glib::wrapper! {