Files
iccery-v2-mac/docs/22-settings-presets.md
gronodandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> b494b4fffd docs(m10): defaultInstrument seeds Spot Read; README floor is macOS 12
Refs #148

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-13 12:23:43 +01:00

7.0 KiB
Raw Permalink Blame History

22 — Settings and presets

Persisted at {app_data}/settings.json via load_settings / save_settings. Invalid JSON loads AppSettings::default(). save_settings calls validate() then writes pretty JSON and immediately applies log::set_max_level.

AppSettings (settings.rs)

Field Default Notes
argyll_binary_dir null Overrides bundled sidecars. resolve_binary checks this first.
default_instrument null Stored; seeds the Spot Read instrument picker when that instrument is present (#148). Never written into printtarg -i or targen argv. Stage 2 #instrumentSelect remains the printtarg instrument.
log_level null error / warn / info / debug / trace. null → Debug in debug builds, Info in release. Applied at startup and on save (#158).
delta_e_good_max 2.0 Stage 3 swatch traffic-light "Good". Must be ≥ 0.
delta_e_warning_max 5.0 Stage 3 "Warning" band. Must be strictly greater than good.
custom_presets [] User presets; built-ins are not stored here.
enable_i1pro2_leds false Adds chartread -Y l. Default off so stock Argyll still runs.
calibration_stale_days 30 Stage 0 / Stage 1 reminder.
default_install_location "user" "user" | "system" for Stage 5.
ask_before_overwrite_profile true
open_color_panel_after_install false

Validation error strings (surface in #deltaEThresholdError):

  • "ΔE thresholds cannot be negative."
  • "Good ΔE threshold must be strictly less than the warning threshold."

Saving dispatches a DOM settings-saved event so the live swatch grid reclassifies without a re-read.

Settings dialog ids: argyll_binary_dir, default_instrument, enable_i1pro2_leds, deltaEGoodMax, deltaEWarningMax, deltaEThresholdError, calibrationStaleDays, defaultInstallLocation, askBeforeOverwriteProfile, openColorPanelAfterInstall, logLevelSelect, btnOpenLogFolder, btnCopyLogPath, btnCopyLogExcerpt, logPathDisplay, saveSettingsBtn, closeSettingsBtn.

Log helpers: get_log_path, get_recent_log_excerpt, open_log_dir.

ProfilingPreset

Every field is optional-defaulted with #[serde(default)] except the required identity / Stage 12 core. applyPreset must set TIFF DPI (#113) — a historical bug left #tiffDpi at 300 when loading the 150 dpi draft preset.

Field Type Stage
id, name, description string identity. Names/descriptions go through textContent, never innerHTML (#114 XSS)
colour_space "rgb" | "cmyk" 1
patch_count, white_patches, black_patches u32 1
grey_steps, single_channel_steps, neutral_steps Option<u32> 1 advanced
preconditioning_profile Option<path> 1 -c
neutral_concentration Option<f64> 1 -N
ofps_high_quality Option<bool> 1 -G
ofps_adaptation Option<f64> 1 -A
full_spread_algorithm Option<string> 1 -t/-r/-R/-q/-Q/-i/-I
total_ink_limit Option<u32> 1 -l CMYK
dark_emphasis, device_power Option<f64> 1 -V / -p
instrument, page_size, bit_depth, dpi 2
random_seed, no_randomize 2 #printtargLayoutOrder
calibration_file, apply_calibration 0 / 2 -K
colprof_algorithm, colprof_quality, colprof_intent 4
colprof_fwa, colprof_illuminant, colprof_observer 4
colprof_input_viewing_cond, colprof_output_viewing_cond 4

Built-in presets (get_default_presets)

Built-ins cannot be deleted. Custom presets overlay by id. Import/export is JSON via export_preset_json / import_preset_json with schema validation (unknown keys ignored via serde default; missing required fields fail).

id Name Space Patches Page Bit DPI Quality Extra
preset-std-rgb Standard RGB Photo (800 patches) rgb 800, white 4 A4 8 300 m FWA D50, seed 1, instrument i1, alg l
preset-hq-cmyk High-Gamut CMYK Proofing (1500 patches) cmyk 1500, black 8 A3 16 300 h ink limit 320, FWA D50, seed 1
preset-draft-rgb Fast RGB Draft (400 patches) rgb 400 A4 8 150 l FWA D50, seed 1
preset-ultra-rgb Ultra Precision RGB (2500 patches) rgb 2500, white 6, black 6 A3 16 300 u ofps_high_quality=true (-G), FWA D50, seed 1

All four: instrument: "i1", colprof_algorithm: "l", random_seed: 1, no_randomize: false, colprof_fwa: "D50".

UI: #presetSelect, #btnSavePresetModal#savePresetDialog (savePresetName, savePresetDesc, btnConfirmSavePreset), #btnOpenPresetsDialog#managePresetsDialog (managePresetsList, btnExportActivePreset, btnImportPreset).

Media library (media_library.json)

Persisted at {app_data}/media_library.json — a sibling of settings.json, never a field inside it (issue #146). A MediaRecipe binds a CUPS queue + paper + ink set + optional .cal to a ProfilingPreset. Cap: 200 entries; the 201st is refused with an error, never silently evicted. Corrupt JSON → keep the file, load [], persistent warning banner.

Field Type Notes
id string recipe-<uuid>, never user-typed
name, notes string Rendered through Text only (#114)
printer_id string CUPS queue id (lpstat -e name)
printer_display_name string Human label; applied to wizard.printerName
paper_name, ink_set string Library metadata only — never written to targen flags
driver_media_type string? Last captured CUPS media_type (read-only)
colour_space "rgb" | "cmyk" Must match the bound preset
preset_id string ProfilingPreset.id (built-in or custom)
calibration_url string? Absolute .cal path, stored verbatim
apply_calibration bool Forced off for CAL_ stems or missing files
created, updated iso8601

Apply path: recipe → applyPreset (#82 mapping, no second Stage 1 form) → queue re-enumerated (lpstat -e) → printer_id absent from a non-empty list warns "not installed" and leaves the queue untouched; an empty list is indeterminate and never flags. CAL_ bound cal or a live CAL_ wizard basename forces applyCalibration off — printtarg -K can never see a CAL_ file (literal refusal; escape hatch is rename + re-capture). Staleness: .printer = absent from enumerated queues; .calibration = bound cal CREATED + calibration_stale_days < now.

Capture with no preset selected auto-snapshots the live form as a custom- preset and binds to it. UI: #mediaSelect (immediate apply, #presetSelect-style), #btnMediaLibraryCapture#saveMediaRecipeDialog, #btnMediaLibraryManage#manageMediaDialog (mediaLibraryList, mediaRow-{id}, btnMediaLibraryApply-{id}, btnMediaLibraryDelete-{id}), stale badge #mediaRecipeStale.