From 137bb77faa2a8191214503e796c41065e5ccc8fc Mon Sep 17 00:00:00 2001 From: lashman Date: Fri, 6 Mar 2026 13:33:06 +0200 Subject: [PATCH] Add Ctrl+A and Ctrl+Shift+A keyboard shortcuts for select/deselect all - Register select-all-images and deselect-all-images actions - Wire Ctrl+A to clear exclusion set, Ctrl+Shift+A to exclude all - Both shortcuts update checkbox state and count label in images step - Make set_all_checkboxes_in public for cross-module access --- pixstrip-gtk/src/app.rs | 50 +++++++++++++++++++++++++++ pixstrip-gtk/src/steps/step_images.rs | 8 ++--- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/pixstrip-gtk/src/app.rs b/pixstrip-gtk/src/app.rs index aa65395..3f7e448 100644 --- a/pixstrip-gtk/src/app.rs +++ b/pixstrip-gtk/src/app.rs @@ -128,6 +128,8 @@ fn setup_shortcuts(app: &adw::Application) { ); } app.set_accels_for_action("win.add-files", &["o"]); + app.set_accels_for_action("win.select-all-images", &["a"]); + app.set_accels_for_action("win.deselect-all-images", &["a"]); app.set_accels_for_action("app.quit", &["q"]); app.set_accels_for_action("win.show-settings", &["comma"]); app.set_accels_for_action("win.show-shortcuts", &["question", "F1"]); @@ -441,6 +443,54 @@ fn setup_window_actions(window: &adw::ApplicationWindow, ui: &WizardUi) { action_group.add_action(&action); } + // Select all images action + { + let ui = ui.clone(); + let action = gtk::gio::SimpleAction::new("select-all-images", None); + action.connect_activate(move |_, _| { + ui.state.excluded_files.borrow_mut().clear(); + // Update the images step UI + if let Some(page) = ui.pages.get(1) + && let Some(stack) = page.child().and_downcast::() + && let Some(loaded) = stack.child_by_name("loaded") + { + crate::steps::step_images::set_all_checkboxes_in(&loaded, true); + let files = ui.state.loaded_files.borrow(); + let count = files.len(); + drop(files); + update_images_count_label(&ui, count); + } + }); + action_group.add_action(&action); + } + + // Deselect all images action + { + let ui = ui.clone(); + let action = gtk::gio::SimpleAction::new("deselect-all-images", None); + action.connect_activate(move |_, _| { + { + let files = ui.state.loaded_files.borrow(); + let mut excl = ui.state.excluded_files.borrow_mut(); + for f in files.iter() { + excl.insert(f.clone()); + } + } + // Update the images step UI + if let Some(page) = ui.pages.get(1) + && let Some(stack) = page.child().and_downcast::() + && let Some(loaded) = stack.child_by_name("loaded") + { + crate::steps::step_images::set_all_checkboxes_in(&loaded, false); + let files = ui.state.loaded_files.borrow(); + let count = files.len(); + drop(files); + update_images_count_label(&ui, count); + } + }); + action_group.add_action(&action); + } + // Settings action - opens settings dialog { let window = window.clone(); diff --git a/pixstrip-gtk/src/steps/step_images.rs b/pixstrip-gtk/src/steps/step_images.rs index bb2659b..19d5b4e 100644 --- a/pixstrip-gtk/src/steps/step_images.rs +++ b/pixstrip-gtk/src/steps/step_images.rs @@ -437,7 +437,7 @@ fn build_loaded_state(state: &AppState) -> gtk::Box { && let Some(stack) = parent.downcast_ref::() && let Some(loaded_widget) = stack.child_by_name("loaded") { - set_all_checkboxes(&loaded_widget, true); + set_all_checkboxes_in(&loaded_widget, true); update_count_label(&loaded_widget, &loaded, &excl); } }); @@ -459,7 +459,7 @@ fn build_loaded_state(state: &AppState) -> gtk::Box { && let Some(stack) = parent.downcast_ref::() && let Some(loaded_widget) = stack.child_by_name("loaded") { - set_all_checkboxes(&loaded_widget, false); + set_all_checkboxes_in(&loaded_widget, false); update_count_label(&loaded_widget, &loaded, &excl); } }); @@ -498,14 +498,14 @@ fn build_loaded_state(state: &AppState) -> gtk::Box { } /// Set all CheckButton widgets within a container to a given state -fn set_all_checkboxes(widget: >k::Widget, active: bool) { +pub fn set_all_checkboxes_in(widget: >k::Widget, active: bool) { if let Some(check) = widget.downcast_ref::() { check.set_active(active); return; // Don't recurse into CheckButton children } let mut child = widget.first_child(); while let Some(c) = child { - set_all_checkboxes(&c, active); + set_all_checkboxes_in(&c, active); child = c.next_sibling(); } }