Wire all wizard step controls to shared JobConfig state

All four configurable steps (resize, convert, compress, metadata) now
have signal handlers that update the shared JobConfig via AppState.
The run_processing function builds ProcessingJob from actual user
choices instead of hardcoded values. Fixed clippy warnings (collapsed
if-let chain, removed needless borrow).
This commit is contained in:
2026-03-06 11:51:01 +02:00
parent eeb418ccdd
commit b855955786
6 changed files with 333 additions and 161 deletions

View File

@@ -1,6 +1,7 @@
use adw::prelude::*;
use crate::app::AppState;
pub fn build_resize_page() -> adw::NavigationPage {
pub fn build_resize_page(state: &AppState) -> adw::NavigationPage {
let scrolled = gtk::ScrolledWindow::builder()
.hscrollbar_policy(gtk::PolicyType::Never)
.vexpand(true)
@@ -15,33 +16,34 @@ pub fn build_resize_page() -> adw::NavigationPage {
.margin_end(24)
.build();
let cfg = state.job_config.borrow();
// Enable toggle
let enable_row = adw::SwitchRow::builder()
.title("Enable Resize")
.subtitle("Resize images to new dimensions")
.active(true)
.active(cfg.resize_enabled)
.build();
let enable_group = adw::PreferencesGroup::new();
enable_group.add(&enable_row);
content.append(&enable_group);
// Resize mode selector
// Resize mode
let mode_group = adw::PreferencesGroup::builder()
.title("Resize Mode")
.build();
// Width/Height mode
let width_row = adw::SpinRow::builder()
.title("Width")
.subtitle("Target width in pixels")
.adjustment(&gtk::Adjustment::new(1200.0, 1.0, 10000.0, 1.0, 100.0, 0.0))
.adjustment(&gtk::Adjustment::new(cfg.resize_width as f64, 1.0, 10000.0, 1.0, 100.0, 0.0))
.build();
let height_row = adw::SpinRow::builder()
.title("Height")
.subtitle("Target height in pixels (0 = auto from aspect ratio)")
.adjustment(&gtk::Adjustment::new(0.0, 0.0, 10000.0, 1.0, 100.0, 0.0))
.adjustment(&gtk::Adjustment::new(cfg.resize_height as f64, 0.0, 10000.0, 1.0, 100.0, 0.0))
.build();
mode_group.add(&width_row);
@@ -58,24 +60,32 @@ pub fn build_resize_page() -> adw::NavigationPage {
.subtitle("Mastodon, Pixelfed, Bluesky, Lemmy")
.build();
let fedi_presets = [
("Mastodon Post", "1920 x 1080"),
("Mastodon Profile", "400 x 400"),
("Mastodon Header", "1500 x 500"),
("Pixelfed Post", "1080 x 1080"),
("Pixelfed Story", "1080 x 1920"),
("Bluesky Post", "1200 x 630"),
("Bluesky Profile", "400 x 400"),
("Lemmy Post", "1200 x 630"),
let fedi_presets: Vec<(&str, u32, u32)> = vec![
("Mastodon Post", 1920, 1080),
("Mastodon Profile", 400, 400),
("Mastodon Header", 1500, 500),
("Pixelfed Post", 1080, 1080),
("Pixelfed Story", 1080, 1920),
("Bluesky Post", 1200, 630),
("Bluesky Profile", 400, 400),
("Lemmy Post", 1200, 630),
];
for (name, dims) in &fedi_presets {
for (name, w, h) in &fedi_presets {
let row = adw::ActionRow::builder()
.title(*name)
.subtitle(*dims)
.subtitle(format!("{} x {}", w, h))
.activatable(true)
.build();
row.add_suffix(&gtk::Image::from_icon_name("go-next-symbolic"));
let width_row_c = width_row.clone();
let height_row_c = height_row.clone();
let w = *w;
let h = *h;
row.connect_activated(move |_| {
width_row_c.set_value(w as f64);
height_row_c.set_value(h as f64);
});
fedi_expander.add_row(&row);
}
@@ -84,22 +94,30 @@ pub fn build_resize_page() -> adw::NavigationPage {
.subtitle("Instagram, YouTube, LinkedIn, Pinterest")
.build();
let mainstream_presets = [
("Instagram Post", "1080 x 1080"),
("Instagram Story/Reel", "1080 x 1920"),
("Facebook Post", "1200 x 630"),
("YouTube Thumbnail", "1280 x 720"),
("LinkedIn Post", "1200 x 627"),
("Pinterest Pin", "1000 x 1500"),
let mainstream_presets: Vec<(&str, u32, u32)> = vec![
("Instagram Post", 1080, 1080),
("Instagram Story/Reel", 1080, 1920),
("Facebook Post", 1200, 630),
("YouTube Thumbnail", 1280, 720),
("LinkedIn Post", 1200, 627),
("Pinterest Pin", 1000, 1500),
];
for (name, dims) in &mainstream_presets {
for (name, w, h) in &mainstream_presets {
let row = adw::ActionRow::builder()
.title(*name)
.subtitle(*dims)
.subtitle(format!("{} x {}", w, h))
.activatable(true)
.build();
row.add_suffix(&gtk::Image::from_icon_name("go-next-symbolic"));
let width_row_c = width_row.clone();
let height_row_c = height_row.clone();
let w = *w;
let h = *h;
row.connect_activated(move |_| {
width_row_c.set_value(w as f64);
height_row_c.set_value(h as f64);
});
mainstream_expander.add_row(&row);
}
@@ -108,19 +126,27 @@ pub fn build_resize_page() -> adw::NavigationPage {
.subtitle("HD, Blog, Thumbnail")
.build();
let other_presets = [
("Full HD", "1920 x 1080"),
("Blog Image", "800 wide"),
("Thumbnail", "150 x 150"),
let other_presets: Vec<(&str, u32, u32)> = vec![
("Full HD", 1920, 1080),
("Blog Image", 800, 0),
("Thumbnail", 150, 150),
];
for (name, dims) in &other_presets {
for (name, w, h) in &other_presets {
let row = adw::ActionRow::builder()
.title(*name)
.subtitle(*dims)
.subtitle(if *h == 0 { format!("{} wide", w) } else { format!("{} x {}", w, h) })
.activatable(true)
.build();
row.add_suffix(&gtk::Image::from_icon_name("go-next-symbolic"));
let width_row_c = width_row.clone();
let height_row_c = height_row.clone();
let w = *w;
let h = *h;
row.connect_activated(move |_| {
width_row_c.set_value(w as f64);
height_row_c.set_value(h as f64);
});
other_expander.add_row(&row);
}
@@ -129,7 +155,7 @@ pub fn build_resize_page() -> adw::NavigationPage {
presets_group.add(&other_expander);
content.append(&presets_group);
// Basic adjustments (rotation/flip)
// Basic adjustments
let adjust_group = adw::PreferencesGroup::builder()
.title("Basic Adjustments")
.build();
@@ -152,28 +178,48 @@ pub fn build_resize_page() -> adw::NavigationPage {
adjust_group.add(&flip_row);
content.append(&adjust_group);
// Advanced options
// Advanced
let advanced_group = adw::PreferencesGroup::builder()
.title("Advanced Options")
.build();
let algo_row = adw::ComboRow::builder()
.title("Resize Algorithm")
.subtitle("Higher quality is slower")
.build();
let algo_model = gtk::StringList::new(&["Lanczos3 (Best)", "CatmullRom", "Bilinear", "Nearest"]);
algo_row.set_model(Some(&algo_model));
let upscale_row = adw::SwitchRow::builder()
.title("Allow Upscaling")
.subtitle("Enlarge images smaller than target size")
.active(false)
.active(cfg.allow_upscale)
.build();
advanced_group.add(&algo_row);
advanced_group.add(&upscale_row);
content.append(&advanced_group);
drop(cfg);
// Wire signals to update JobConfig
{
let jc = state.job_config.clone();
enable_row.connect_active_notify(move |row| {
jc.borrow_mut().resize_enabled = row.is_active();
});
}
{
let jc = state.job_config.clone();
width_row.connect_value_notify(move |row| {
jc.borrow_mut().resize_width = row.value() as u32;
});
}
{
let jc = state.job_config.clone();
height_row.connect_value_notify(move |row| {
jc.borrow_mut().resize_height = row.value() as u32;
});
}
{
let jc = state.job_config.clone();
upscale_row.connect_active_notify(move |row| {
jc.borrow_mut().allow_upscale = row.is_active();
});
}
scrolled.set_child(Some(&content));
let clamp = adw::Clamp::builder()