From 3109f9778652be03d3dfdd6517d0027cbb839426 Mon Sep 17 00:00:00 2001 From: lashman Date: Fri, 6 Mar 2026 17:07:53 +0200 Subject: [PATCH] Add overwrite confirmation dialog and preset file drop import - When overwrite behavior is "Ask", show dialog before processing listing conflicting files with Overwrite/Skip/Auto-rename options - Workflow page accepts .pixstrip-preset file drag-and-drop for import - Split run_processing into two phases to support async dialog --- pixstrip-gtk/src/app.rs | 63 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/pixstrip-gtk/src/app.rs b/pixstrip-gtk/src/app.rs index 494ada6..74e6f30 100644 --- a/pixstrip-gtk/src/app.rs +++ b/pixstrip-gtk/src/app.rs @@ -1687,11 +1687,12 @@ fn run_processing(_window: &adw::ApplicationWindow, ui: &WizardUi) { job.preserve_directory_structure = cfg.preserve_dir_structure; job.output_dpi = cfg.output_dpi; + let ask_overwrite = cfg.overwrite_behavior == 0; job.overwrite_behavior = match cfg.overwrite_behavior { 1 => pixstrip_core::operations::OverwriteBehavior::AutoRename, 2 => pixstrip_core::operations::OverwriteBehavior::Overwrite, 3 => pixstrip_core::operations::OverwriteBehavior::Skip, - _ => pixstrip_core::operations::OverwriteBehavior::AutoRename, // 0 "Ask" defaults to auto-rename in batch + _ => pixstrip_core::operations::OverwriteBehavior::AutoRename, }; drop(cfg); @@ -1700,6 +1701,66 @@ fn run_processing(_window: &adw::ApplicationWindow, ui: &WizardUi) { job.add_source(file); } + // Check for existing output files when "Ask" overwrite behavior is set + if ask_overwrite { + let output_dir = ui.state.output_dir.borrow().clone() + .unwrap_or_else(|| { + files[0].parent() + .unwrap_or_else(|| std::path::Path::new(".")) + .join("processed") + }); + if output_dir.exists() { + let conflicts: Vec = files.iter() + .filter_map(|f| { + let name = f.file_name()?; + let out_path = output_dir.join(name); + if out_path.exists() { Some(name.to_string_lossy().into()) } else { None } + }) + .take(10) + .collect(); + + if !conflicts.is_empty() { + let msg = if conflicts.len() == 10 { + format!("{} files already exist in the output folder (showing first 10):\n\n{}", conflicts.len(), conflicts.join("\n")) + } else { + format!("{} files already exist in the output folder:\n\n{}", conflicts.len(), conflicts.join("\n")) + }; + + let confirm = adw::AlertDialog::builder() + .heading("Files Already Exist") + .body(&msg) + .build(); + confirm.add_response("rename", "Auto-rename"); + confirm.add_response("skip", "Skip Existing"); + confirm.add_response("overwrite", "Overwrite All"); + confirm.set_response_appearance("overwrite", adw::ResponseAppearance::Destructive); + confirm.set_default_response(Some("rename")); + confirm.set_close_response("rename"); + + let ui_c = ui.clone(); + let window_c = _window.clone(); + let mut job_c = job; + confirm.choose(Some(_window), gtk::gio::Cancellable::NONE, move |response| { + job_c.overwrite_behavior = match response.as_str() { + "overwrite" => pixstrip_core::operations::OverwriteBehavior::Overwrite, + "skip" => pixstrip_core::operations::OverwriteBehavior::Skip, + _ => pixstrip_core::operations::OverwriteBehavior::AutoRename, + }; + continue_processing(&window_c, &ui_c, job_c); + }); + return; + } + } + } + + continue_processing(_window, ui, job); +} + +fn continue_processing( + _window: &adw::ApplicationWindow, + ui: &WizardUi, + job: pixstrip_core::pipeline::ProcessingJob, +) { // Build processing UI inline in the nav_view let processing_page = crate::processing::build_processing_page(); ui.nav_view.push(&processing_page);