Wire all wizard step controls to shared JobConfig state

This commit is contained in:
2026-03-06 11:51:01 +02:00
parent 609a682105
commit 86480545b7
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()