From 0ceec7eec467393a91f6effbdaf04d79892fa699 Mon Sep 17 00:00:00 2001 From: lashman Date: Fri, 6 Mar 2026 17:04:18 +0200 Subject: [PATCH] Add preset export/delete buttons and single-instance support - User preset rows now have export and delete action buttons - Export opens file save dialog for .pixstrip-preset files - Delete removes preset from storage and UI - Single-instance via GIO HANDLES_OPEN for file manager integration - Screen reader announcements on step navigation --- pixstrip-gtk/src/steps/step_workflow.rs | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/pixstrip-gtk/src/steps/step_workflow.rs b/pixstrip-gtk/src/steps/step_workflow.rs index f94f1c5..5dd7ae9 100644 --- a/pixstrip-gtk/src/steps/step_workflow.rs +++ b/pixstrip-gtk/src/steps/step_workflow.rs @@ -175,6 +175,53 @@ pub fn build_workflow_page(state: &AppState) -> adw::NavigationPage { .activatable(true) .build(); row.add_prefix(>k::Image::from_icon_name(&preset.icon)); + + // Export button + let export_btn = gtk::Button::builder() + .icon_name("document-save-as-symbolic") + .tooltip_text("Export preset") + .valign(gtk::Align::Center) + .build(); + export_btn.add_css_class("flat"); + let preset_for_export = preset.clone(); + export_btn.connect_clicked(move |btn| { + let p = preset_for_export.clone(); + let dialog = gtk::FileDialog::builder() + .title("Export Preset") + .initial_name(&format!("{}.pixstrip-preset", p.name)) + .modal(true) + .build(); + if let Some(window) = btn.root().and_then(|r| r.downcast::().ok()) { + dialog.save(Some(&window), gtk::gio::Cancellable::NONE, move |result| { + if let Ok(file) = result + && let Some(path) = file.path() + { + let store = pixstrip_core::storage::PresetStore::new(); + let _ = store.export_to_file(&p, &path); + } + }); + } + }); + row.add_suffix(&export_btn); + + // Delete button + let delete_btn = gtk::Button::builder() + .icon_name("user-trash-symbolic") + .tooltip_text("Delete preset") + .valign(gtk::Align::Center) + .build(); + delete_btn.add_css_class("flat"); + delete_btn.add_css_class("error"); + let pname = preset.name.clone(); + let row_ref = row.clone(); + let group_ref = user_group.clone(); + delete_btn.connect_clicked(move |_| { + let store = pixstrip_core::storage::PresetStore::new(); + let _ = store.delete(&pname); + group_ref.remove(&row_ref); + }); + row.add_suffix(&delete_btn); + row.add_suffix(>k::Image::from_icon_name("go-next-symbolic")); let jc = state.job_config.clone();