use adw::prelude::*; pub fn build_processing_page() -> adw::NavigationPage { let content = gtk::Box::builder() .orientation(gtk::Orientation::Vertical) .spacing(16) .margin_top(24) .margin_bottom(24) .margin_start(24) .margin_end(24) .vexpand(true) .build(); // Title let title = gtk::Label::builder() .label("Processing...") .css_classes(["title-1"]) .halign(gtk::Align::Start) .build(); // Progress info let progress_label = gtk::Label::builder() .label("0 / 0 images") .css_classes(["heading"]) .halign(gtk::Align::Start) .build(); let progress_bar = gtk::ProgressBar::builder() .fraction(0.0) .show_text(true) .text("0%") .build(); progress_bar.update_property(&[ gtk::accessible::Property::Label("Processing progress"), ]); let eta_label = gtk::Label::builder() .label("Estimating time remaining...") .css_classes(["dim-label"]) .halign(gtk::Align::Start) .build(); // Activity log let log_group = adw::PreferencesGroup::builder() .title("Activity") .build(); let log_scrolled = gtk::ScrolledWindow::builder() .hscrollbar_policy(gtk::PolicyType::Never) .vexpand(true) .min_content_height(200) .build(); let log_box = gtk::Box::builder() .orientation(gtk::Orientation::Vertical) .spacing(2) .build(); log_scrolled.set_child(Some(&log_box)); log_group.add(&log_scrolled); // Control buttons let button_box = gtk::Box::builder() .orientation(gtk::Orientation::Horizontal) .spacing(12) .halign(gtk::Align::Center) .margin_top(12) .build(); let pause_button = gtk::Button::builder() .label("Pause") .tooltip_text("Pause after current image") .build(); let cancel_button = gtk::Button::builder() .label("Cancel") .tooltip_text("Cancel processing") .build(); cancel_button.add_css_class("destructive-action"); button_box.append(&pause_button); button_box.append(&cancel_button); content.append(&title); content.append(&progress_label); content.append(&progress_bar); content.append(&eta_label); content.append(&log_group); content.append(&button_box); adw::NavigationPage::builder() .title("Processing") .tag("processing") .child(&content) .build() } pub fn build_results_page() -> adw::NavigationPage { let scrolled = gtk::ScrolledWindow::builder() .hscrollbar_policy(gtk::PolicyType::Never) .vexpand(true) .build(); let content = gtk::Box::builder() .orientation(gtk::Orientation::Vertical) .spacing(16) .margin_top(24) .margin_bottom(24) .margin_start(24) .margin_end(24) .build(); // Success icon and title let status_icon = gtk::Image::builder() .icon_name("emblem-ok-symbolic") .pixel_size(48) .halign(gtk::Align::Center) .css_classes(["success"]) .build(); status_icon.update_property(&[ gtk::accessible::Property::Label("Success"), ]); let title = gtk::Label::builder() .label("Processing Complete") .css_classes(["title-1"]) .halign(gtk::Align::Center) .build(); content.append(&status_icon); content.append(&title); // Stats let stats_group = adw::PreferencesGroup::builder() .title("Results") .build(); let images_row = adw::ActionRow::builder() .title("Images processed") .subtitle("0 images") .build(); images_row.add_prefix(>k::Image::from_icon_name("image-x-generic-symbolic")); let size_before_row = adw::ActionRow::builder() .title("Original size") .subtitle("0 B") .build(); size_before_row.add_prefix(>k::Image::from_icon_name("drive-harddisk-symbolic")); let size_after_row = adw::ActionRow::builder() .title("Output size") .subtitle("0 B") .build(); size_after_row.add_prefix(>k::Image::from_icon_name("drive-harddisk-symbolic")); let savings_row = adw::ActionRow::builder() .title("Space saved") .subtitle("0%") .build(); savings_row.add_prefix(>k::Image::from_icon_name("emblem-ok-symbolic")); let time_row = adw::ActionRow::builder() .title("Processing time") .subtitle("0s") .build(); time_row.add_prefix(>k::Image::from_icon_name("preferences-system-time-symbolic")); stats_group.add(&images_row); stats_group.add(&size_before_row); stats_group.add(&size_after_row); stats_group.add(&savings_row); stats_group.add(&time_row); content.append(&stats_group); // Errors section (initially hidden) let errors_group = adw::PreferencesGroup::builder() .title("Errors") .visible(false) .build(); let errors_expander = adw::ExpanderRow::builder() .title("0 errors occurred") .build(); errors_group.add(&errors_expander); content.append(&errors_group); // Action buttons let action_group = adw::PreferencesGroup::new(); let open_row = adw::ActionRow::builder() .title("Open Output Folder") .subtitle("View processed images in file manager") .activatable(true) .build(); open_row.add_prefix(>k::Image::from_icon_name("folder-open-symbolic")); open_row.add_suffix(>k::Image::from_icon_name("go-next-symbolic")); let process_more_row = adw::ActionRow::builder() .title("Process Another Batch") .subtitle("Start over with new images") .activatable(true) .build(); process_more_row.add_prefix(>k::Image::from_icon_name("view-refresh-symbolic")); process_more_row.add_suffix(>k::Image::from_icon_name("go-next-symbolic")); let save_preset_row = adw::ActionRow::builder() .title("Save as Preset") .subtitle("Save this workflow for future use") .activatable(true) .build(); save_preset_row.add_prefix(>k::Image::from_icon_name("document-save-symbolic")); save_preset_row.add_suffix(>k::Image::from_icon_name("go-next-symbolic")); let add_queue_row = adw::ActionRow::builder() .title("Add to Queue") .subtitle("Queue another batch with different images") .activatable(true) .build(); add_queue_row.add_prefix(>k::Image::from_icon_name("view-list-symbolic")); add_queue_row.add_suffix(>k::Image::from_icon_name("go-next-symbolic")); action_group.add(&open_row); action_group.add(&process_more_row); action_group.add(&add_queue_row); action_group.add(&save_preset_row); content.append(&action_group); scrolled.set_child(Some(&content)); adw::NavigationPage::builder() .title("Results") .tag("results") .child(&scrolled) .build() }