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

@@ -10,12 +10,39 @@ use crate::wizard::WizardState;
pub const APP_ID: &str = "live.lashman.Pixstrip";
/// User's choices from the wizard steps, used to build the ProcessingJob
#[derive(Clone, Debug)]
pub struct JobConfig {
pub resize_enabled: bool,
pub resize_width: u32,
pub resize_height: u32,
pub allow_upscale: bool,
pub convert_enabled: bool,
pub convert_format: Option<pixstrip_core::types::ImageFormat>,
pub compress_enabled: bool,
pub quality_preset: pixstrip_core::types::QualityPreset,
pub jpeg_quality: u8,
pub png_level: u8,
pub webp_quality: u8,
pub metadata_enabled: bool,
pub metadata_mode: MetadataMode,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub enum MetadataMode {
#[default]
StripAll,
Privacy,
KeepAll,
}
/// Shared app state accessible from all UI callbacks
#[derive(Clone)]
pub struct AppState {
pub wizard: Rc<RefCell<WizardState>>,
pub loaded_files: Rc<RefCell<Vec<std::path::PathBuf>>>,
pub output_dir: Rc<RefCell<Option<std::path::PathBuf>>>,
pub job_config: Rc<RefCell<JobConfig>>,
}
#[derive(Clone)]
@@ -59,6 +86,21 @@ fn build_ui(app: &adw::Application) {
wizard: Rc::new(RefCell::new(WizardState::new())),
loaded_files: Rc::new(RefCell::new(Vec::new())),
output_dir: Rc::new(RefCell::new(None)),
job_config: Rc::new(RefCell::new(JobConfig {
resize_enabled: true,
resize_width: 1200,
resize_height: 0,
allow_upscale: false,
convert_enabled: false,
convert_format: None,
compress_enabled: true,
quality_preset: pixstrip_core::types::QualityPreset::Medium,
jpeg_quality: 85,
png_level: 3,
webp_quality: 80,
metadata_enabled: true,
metadata_mode: MetadataMode::StripAll,
})),
};
// Header bar
@@ -84,7 +126,7 @@ fn build_ui(app: &adw::Application) {
nav_view.set_vexpand(true);
// Build wizard pages
let pages = crate::wizard::build_wizard_pages();
let pages = crate::wizard::build_wizard_pages(&app_state);
for page in &pages {
nav_view.add(page);
}
@@ -573,12 +615,41 @@ fn run_processing(_window: &adw::ApplicationWindow, ui: &WizardUi) {
.clone()
.unwrap_or_else(|| input_dir.join("processed"));
// Build job - for now use default settings (resize off, compress high, strip metadata)
// Build job from wizard settings
let mut job = pixstrip_core::pipeline::ProcessingJob::new(&input_dir, &output_dir);
job.compress = Some(pixstrip_core::operations::CompressConfig::Preset(
pixstrip_core::types::QualityPreset::High,
));
job.metadata = Some(pixstrip_core::operations::MetadataConfig::StripAll);
let cfg = ui.state.job_config.borrow();
if cfg.resize_enabled && cfg.resize_width > 0 {
let target_w = cfg.resize_width;
let target_h = cfg.resize_height;
if target_h == 0 {
job.resize = Some(pixstrip_core::operations::ResizeConfig::ByWidth(target_w));
} else {
job.resize = Some(pixstrip_core::operations::ResizeConfig::FitInBox {
max: pixstrip_core::types::Dimensions { width: target_w, height: target_h },
allow_upscale: cfg.allow_upscale,
});
}
}
if cfg.convert_enabled && let Some(fmt) = cfg.convert_format {
job.convert = Some(pixstrip_core::operations::ConvertConfig::SingleFormat(fmt));
}
if cfg.compress_enabled {
job.compress = Some(pixstrip_core::operations::CompressConfig::Preset(cfg.quality_preset));
}
if cfg.metadata_enabled {
job.metadata = Some(match cfg.metadata_mode {
MetadataMode::StripAll => pixstrip_core::operations::MetadataConfig::StripAll,
MetadataMode::Privacy => pixstrip_core::operations::MetadataConfig::Privacy,
MetadataMode::KeepAll => pixstrip_core::operations::MetadataConfig::KeepAll,
});
}
drop(cfg);
for file in &files {
job.add_source(file);