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,8 @@
use adw::prelude::*;
use crate::app::AppState;
use pixstrip_core::types::QualityPreset;
pub fn build_compress_page() -> adw::NavigationPage {
pub fn build_compress_page(state: &AppState) -> adw::NavigationPage {
let scrolled = gtk::ScrolledWindow::builder()
.hscrollbar_policy(gtk::PolicyType::Never)
.vexpand(true)
@@ -15,11 +17,13 @@ pub fn build_compress_page() -> adw::NavigationPage {
.margin_end(24)
.build();
let cfg = state.job_config.borrow();
// Enable toggle
let enable_row = adw::SwitchRow::builder()
.title("Enable Compression")
.subtitle("Reduce file size with quality control")
.active(true)
.active(cfg.compress_enabled)
.build();
let enable_group = adw::PreferencesGroup::new();
@@ -32,15 +36,22 @@ pub fn build_compress_page() -> adw::NavigationPage {
.description("Higher quality means larger files")
.build();
let initial_val = match cfg.quality_preset {
QualityPreset::WebOptimized => 1.0,
QualityPreset::Low => 2.0,
QualityPreset::Medium => 3.0,
QualityPreset::High => 4.0,
QualityPreset::Maximum => 5.0,
};
let quality_scale = gtk::Scale::builder()
.orientation(gtk::Orientation::Horizontal)
.adjustment(&gtk::Adjustment::new(3.0, 1.0, 5.0, 1.0, 1.0, 0.0))
.adjustment(&gtk::Adjustment::new(initial_val, 1.0, 5.0, 1.0, 1.0, 0.0))
.draw_value(false)
.hexpand(true)
.build();
quality_scale.set_round_digits(0);
// Add named marks
quality_scale.add_mark(1.0, gtk::PositionType::Bottom, Some("Web"));
quality_scale.add_mark(2.0, gtk::PositionType::Bottom, Some("Low"));
quality_scale.add_mark(3.0, gtk::PositionType::Bottom, Some("Medium"));
@@ -48,7 +59,7 @@ pub fn build_compress_page() -> adw::NavigationPage {
quality_scale.add_mark(5.0, gtk::PositionType::Bottom, Some("Maximum"));
let quality_label = gtk::Label::builder()
.label("Medium - Good balance of quality and size")
.label(quality_description(initial_val as u32))
.css_classes(["dim-label"])
.margin_top(4)
.build();
@@ -67,42 +78,28 @@ pub fn build_compress_page() -> adw::NavigationPage {
quality_group.add(&quality_box);
content.append(&quality_group);
// Size estimation placeholder
let estimate_group = adw::PreferencesGroup::builder()
.title("Size Estimation")
.description("Load images to see real compression results")
.build();
let estimate_row = adw::ActionRow::builder()
.title("Estimated savings")
.subtitle("Add images to see file size comparison")
.build();
estimate_row.add_prefix(&gtk::Image::from_icon_name("drive-harddisk-symbolic"));
estimate_group.add(&estimate_row);
content.append(&estimate_group);
// Advanced options
let advanced_group = adw::PreferencesGroup::builder()
.title("Advanced Options")
.title("Per-Format Quality")
.description("Fine-tune quality for each format individually")
.build();
let jpeg_row = adw::SpinRow::builder()
.title("JPEG Quality")
.subtitle("1-100, higher is better quality")
.adjustment(&gtk::Adjustment::new(85.0, 1.0, 100.0, 1.0, 10.0, 0.0))
.adjustment(&gtk::Adjustment::new(cfg.jpeg_quality as f64, 1.0, 100.0, 1.0, 10.0, 0.0))
.build();
let png_row = adw::SpinRow::builder()
.title("PNG Compression Level")
.subtitle("1-6, higher is slower but smaller")
.adjustment(&gtk::Adjustment::new(3.0, 1.0, 6.0, 1.0, 1.0, 0.0))
.adjustment(&gtk::Adjustment::new(cfg.png_level as f64, 1.0, 6.0, 1.0, 1.0, 0.0))
.build();
let webp_row = adw::SpinRow::builder()
.title("WebP Quality")
.subtitle("1-100, higher is better quality")
.adjustment(&gtk::Adjustment::new(80.0, 1.0, 100.0, 1.0, 10.0, 0.0))
.adjustment(&gtk::Adjustment::new(cfg.webp_quality as f64, 1.0, 100.0, 1.0, 10.0, 0.0))
.build();
advanced_group.add(&jpeg_row);
@@ -110,6 +107,50 @@ pub fn build_compress_page() -> adw::NavigationPage {
advanced_group.add(&webp_row);
content.append(&advanced_group);
drop(cfg);
// Wire signals
{
let jc = state.job_config.clone();
enable_row.connect_active_notify(move |row| {
jc.borrow_mut().compress_enabled = row.is_active();
});
}
{
let jc = state.job_config.clone();
let label = quality_label.clone();
quality_scale.connect_value_changed(move |scale| {
let val = scale.value().round() as u32;
let mut c = jc.borrow_mut();
c.quality_preset = match val {
1 => QualityPreset::WebOptimized,
2 => QualityPreset::Low,
3 => QualityPreset::Medium,
4 => QualityPreset::High,
_ => QualityPreset::Maximum,
};
label.set_label(&quality_description(val));
});
}
{
let jc = state.job_config.clone();
jpeg_row.connect_value_notify(move |row| {
jc.borrow_mut().jpeg_quality = row.value() as u8;
});
}
{
let jc = state.job_config.clone();
png_row.connect_value_notify(move |row| {
jc.borrow_mut().png_level = row.value() as u8;
});
}
{
let jc = state.job_config.clone();
webp_row.connect_value_notify(move |row| {
jc.borrow_mut().webp_quality = row.value() as u8;
});
}
scrolled.set_child(Some(&content));
let clamp = adw::Clamp::builder()
@@ -123,3 +164,13 @@ pub fn build_compress_page() -> adw::NavigationPage {
.child(&clamp)
.build()
}
fn quality_description(val: u32) -> String {
match val {
1 => "Web Optimized - smallest files, noticeable quality loss".into(),
2 => "Low - small files, some quality loss".into(),
3 => "Medium - good balance of quality and size".into(),
4 => "High - large files, minimal quality loss".into(),
_ => "Maximum - largest files, best possible quality".into(),
}
}