Replace custom shortcuts dialog with GtkShortcutsWindow, fix Process More button

- Use proper GtkShortcutsWindow with ShortcutsSection/Group/Shortcut widgets
  instead of custom AdwDialog with ActionRows
- Hide step indicator during processing and results screens
- Fix "Process More" button re-triggering processing instead of resetting wizard
- Add accessible label to resize step size preview DrawingArea
This commit is contained in:
2026-03-06 14:46:54 +02:00
parent 6dd81e5900
commit 3aeb05c9a0
2 changed files with 84 additions and 64 deletions

View File

@@ -642,7 +642,12 @@ fn setup_window_actions(window: &adw::ApplicationWindow, ui: &WizardUi) {
ui.next_button.connect_clicked({ ui.next_button.connect_clicked({
let action_group = action_group.clone(); let action_group = action_group.clone();
let ui = ui.clone(); let ui = ui.clone();
move |_| { move |btn| {
// If the button says "Process More", reset the wizard
if btn.label().as_deref() == Some("Process More") {
reset_wizard(&ui);
return;
}
let s = ui.state.wizard.borrow(); let s = ui.state.wizard.borrow();
if s.is_last_step() { if s.is_last_step() {
drop(s); drop(s);
@@ -1252,9 +1257,10 @@ fn run_processing(_window: &adw::ApplicationWindow, ui: &WizardUi) {
let processing_page = crate::processing::build_processing_page(); let processing_page = crate::processing::build_processing_page();
ui.nav_view.push(&processing_page); ui.nav_view.push(&processing_page);
// Hide bottom nav buttons during processing // Hide bottom nav buttons and step indicator during processing
ui.back_button.set_visible(false); ui.back_button.set_visible(false);
ui.next_button.set_visible(false); ui.next_button.set_visible(false);
ui.step_indicator.widget().set_visible(false);
ui.title.set_subtitle("Processing..."); ui.title.set_subtitle("Processing...");
// Get references to progress widgets inside the page // Get references to progress widgets inside the page
@@ -1367,6 +1373,7 @@ fn show_results(
ui.nav_view.push(&results_page); ui.nav_view.push(&results_page);
ui.title.set_subtitle("Processing Complete"); ui.title.set_subtitle("Processing Complete");
ui.step_indicator.widget().set_visible(false);
ui.back_button.set_visible(false); ui.back_button.set_visible(false);
ui.next_button.set_label("Process More"); ui.next_button.set_label("Process More");
ui.next_button.set_visible(true); ui.next_button.set_visible(true);
@@ -1660,6 +1667,7 @@ fn reset_wizard(ui: &WizardUi) {
// Reset nav // Reset nav
ui.nav_view.replace(&ui.pages[..1]); ui.nav_view.replace(&ui.pages[..1]);
ui.step_indicator.set_current(0); ui.step_indicator.set_current(0);
ui.step_indicator.widget().set_visible(true);
ui.title.set_subtitle("Batch Image Processor"); ui.title.set_subtitle("Batch Image Processor");
ui.back_button.set_visible(false); ui.back_button.set_visible(false);
ui.next_button.set_label("Next"); ui.next_button.set_label("Next");
@@ -2176,78 +2184,87 @@ fn walk_widgets(widget: &Option<gtk::Widget>, f: &dyn Fn(&gtk::Widget)) {
fn show_shortcuts_window(window: &adw::ApplicationWindow) { fn show_shortcuts_window(window: &adw::ApplicationWindow) {
let dialog = adw::Dialog::builder() let shortcuts_window = gtk::ShortcutsWindow::builder()
.title("Keyboard Shortcuts") .transient_for(window)
.content_width(400) .modal(true)
.content_height(500)
.build(); .build();
let toolbar_view = adw::ToolbarView::new(); // Wizard Navigation section
let header = adw::HeaderBar::new(); let wizard_group = gtk::ShortcutsGroup::builder()
toolbar_view.add_top_bar(&header); .title("Wizard Navigation")
let scrolled = gtk::ScrolledWindow::builder()
.hscrollbar_policy(gtk::PolicyType::Never)
.vexpand(true)
.build(); .build();
let content = gtk::Box::builder() let shortcuts_nav: &[(&str, &str)] = &[
.orientation(gtk::Orientation::Vertical) ("<Alt>Right", "Next step"),
.spacing(0) ("<Alt>Left", "Previous step"),
.margin_start(12) ("<Alt>1", "Jump to step 1"),
.margin_end(12) ("<Alt>2", "Jump to step 2"),
.margin_top(12) ("<Alt>3", "Jump to step 3"),
.margin_bottom(12) ("<Control>Return", "Process images"),
.build();
let sections: &[(&str, &[(&str, &str)])] = &[
("Wizard Navigation", &[
("Alt + Right", "Next step"),
("Alt + Left", "Previous step"),
("Alt + 1...9", "Jump to step by number"),
("Ctrl + Enter", "Process images"),
("Escape", "Cancel or go back"), ("Escape", "Cancel or go back"),
]),
("File Management", &[
("Ctrl + O", "Add files"),
("Ctrl + V", "Paste image from clipboard"),
("Ctrl + A", "Select all images"),
("Ctrl + Shift + A", "Deselect all images"),
("Delete", "Remove selected images"),
]),
("Application", &[
("Ctrl + ,", "Settings"),
("F1", "Keyboard shortcuts"),
("Ctrl + Z", "Undo last batch"),
("Ctrl + Q", "Quit"),
]),
]; ];
for (title, shortcuts) in sections { for (accel, title) in shortcuts_nav {
let group = adw::PreferencesGroup::builder() let shortcut = gtk::ShortcutsShortcut::builder()
.accelerator(*accel)
.title(*title) .title(*title)
.build(); .build();
wizard_group.add_shortcut(&shortcut);
for (accel, desc) in *shortcuts {
let row = adw::ActionRow::builder()
.title(*desc)
.build();
let label = gtk::Label::builder()
.label(*accel)
.css_classes(["monospace", "dim-label"])
.valign(gtk::Align::Center)
.build();
row.add_suffix(&label);
group.add(&row);
} }
content.append(&group); // File Management section
let files_group = gtk::ShortcutsGroup::builder()
.title("File Management")
.build();
let shortcuts_files: &[(&str, &str)] = &[
("<Control>o", "Add files"),
("<Control>v", "Paste image from clipboard"),
("<Control>a", "Select all images"),
("<Control><Shift>a", "Deselect all images"),
("Delete", "Remove selected images"),
];
for (accel, title) in shortcuts_files {
let shortcut = gtk::ShortcutsShortcut::builder()
.accelerator(*accel)
.title(*title)
.build();
files_group.add_shortcut(&shortcut);
} }
scrolled.set_child(Some(&content)); // Application section
toolbar_view.set_content(Some(&scrolled)); let app_group = gtk::ShortcutsGroup::builder()
dialog.set_child(Some(&toolbar_view)); .title("Application")
dialog.present(Some(window)); .build();
let shortcuts_app: &[(&str, &str)] = &[
("<Control>comma", "Settings"),
("F1", "Keyboard shortcuts"),
("<Control>z", "Undo last batch"),
("<Control>q", "Quit"),
];
for (accel, title) in shortcuts_app {
let shortcut = gtk::ShortcutsShortcut::builder()
.accelerator(*accel)
.title(*title)
.build();
app_group.add_shortcut(&shortcut);
}
let section = gtk::ShortcutsSection::builder()
.title("Keyboard Shortcuts")
.build();
#[allow(deprecated)]
{
section.add_group(&wizard_group);
section.add_group(&files_group);
section.add_group(&app_group);
shortcuts_window.add_section(&section);
}
shortcuts_window.present();
} }
fn apply_accessibility_settings() { fn apply_accessibility_settings() {

View File

@@ -242,6 +242,9 @@ pub fn build_resize_page(state: &AppState) -> adw::NavigationPage {
.margin_top(8) .margin_top(8)
.margin_bottom(8) .margin_bottom(8)
.build(); .build();
drawing.update_property(&[
gtk::accessible::Property::Label("Visual comparison of original and target image dimensions"),
]);
let pw = preview_width.clone(); let pw = preview_width.clone();
let ph = preview_height.clone(); let ph = preview_height.clone();