# Architecture ## Overview ScanSlicer is a Qt desktop app split into UI mixins, controller mixins, canvas subsystems, and image-processing/autotune engines. Top-level startup path: 1. `scanslicer.entry:main` 2. Backend/environment resolution and validation 3. `scanslicer.main:run_app` 4. `QtScanSlicer` window composition ## Module Map - `scanslicer/entry.py` - CLI parsing - Wayland/X11 backend selection - Qt platform environment configuration - `scanslicer/main.py` - `QtScanSlicer` main window lifecycle - Theme handling and app icon resolution - App bootstrap (`run_app`) - `scanslicer/controller*.py` - UI action handlers split by responsibility - `scanslicer/ui_builders*.py` - Widget construction for control panel, preview panel, and shared UI helpers - `scanslicer/canvas*.py` - Interactive image canvas for box display/editing - `scanslicer/autoslicer.py` - Detection/export engine wrapper - `scanslicer/autoslicer_detection.py` - Detection pipelines and contour-to-box extraction - `scanslicer/autoslicer_feedback.py` - Auto-tune profiles, candidate scoring, and feedback persistence - `scanslicer/params.py` - Parameter model, defaults, and user presets - `scanslicer/slices.py` - Box geometry model and polygon IoU helper ## UI Composition `QtScanSlicer` inherits: - `ScanSlicerUiBuilderMixin` (UI construction) - `ScanSlicerControllerMixin` (behavior) Controller mixin composition: - `ScanSlicerStatusMixin` (status/logging/busy state) - `ScanSlicerCanvasActionsMixin` (box operations and preview toggles) - `ScanSlicerDetectionMixin` (worker orchestration) - `ScanSlicerImageIOMixin` (directory/image loading and save/export) - `ScanSlicerParamsMixin` (parameter/default/preset/autotune interactions) ## Detection Execution Flow 1. User action triggers `update_preview()`. 2. Detection starts in `DetectionTask` (`QRunnable`) on `QThreadPool` (single worker). 3. Worker runs `Autoslicer.autodetect_slices(...)`. 4. On completion: - Cache normal preview image - Cache filter preview image - Update canvas image - Merge/update boxes 5. Toolbar status and box state are refreshed. Key properties: - One detection worker at a time. - Busy state disables controls during processing. - Task IDs prevent stale callbacks from old tasks mutating UI. ## Auto-Tune Execution Flow 1. User clicks `Auto-tune`. 2. `AutotuneTask` runs in the same single-thread pool. 3. `autotune_for_current_image()`: - Builds candidate parameter sets - Ranks by current-image + prior feedback similarity - Coarse pass on downscaled image (`fast_mode=True`) - Fine pass on top finalists - Applies best candidate to parameter model 4. UI controls sync from model and detection re-runs. ## Canvas System - `QtSlicingCanvas` = interaction + rendering + state mixins - Stores: - image and zoom/pan state - list of `PhotoSlice` objects - active slice index - drag modes (corner, side, rotation, box drag, panning) - Emits `active_slice_changed` signal to keep toolbar state synchronized. ## Geometry Model `PhotoSlice` stores 4-point quadrilateral and flags: - `locked` - `side_handles_enabled` It supports: - top-left normalization and winding correction - rectangle detection (`is_perfect_rectangle`) - squarize while preserving tilt - reset to axis-aligned orientation ## Persistence Model Paths are runtime-dependent (host vs container), with environment overrides: - Defaults JSON - Presets JSON - Auto-tune feedback JSON - Session status log Persistence writes are performed through explicit actions (save defaults/preset, save slices with feedback, status updates). ## Export Pipeline For each locked box: 1. Compute output width/height from opposing edge lengths. 2. Build perspective transform from box quad to rectangle. 3. Warp source image with `cv2.warpPerspective`. 4. Save with format-specific encoding params. ## Packaging Surfaces - Python package/CLI (`pyproject.toml`, script `scanslicer`) - Docker runtime (`Dockerfile`, `docker-compose.yml`) - AppImage (`packaging/appimage/`)