Project View ↔ NewRawScan Integration

Overview

The Project View is updated reactively when new raw scans are loaded into the project model. This interaction is mediated through an event-driven architecture centered on the RawScanAppendEvent.

The flow is:

  1. Backend loads raw scans

  2. Model emits RawScanAppendEvent

  3. Presenter listens and transforms the event

  4. View updates the Project Tree

This decouples data ingestion from UI concerns.

Architecture

The interaction spans three layers:

  • Model: Owns raw scan data and emits events

  • Presenter: Subscribes to events and updates the view

  • View (Project Tree): Displays scans hierarchically

Data Flow

Loading raw scans triggers the following sequence:

FileMenuPresenter
    ↓
TaviProjectModel.load_raw_scan_from_folder
    ↓
RawScanLoadController.load_folder
    ↓
(returns List[RawScan])
    ↓
TaviProjectModel
    - stores scans in TaviData
    - emits RawScanAppendEvent per scan
    ↓
EventBroker
    ↓
LoadRawScanPresenter.update_treeview_data
    ↓
ProjectView.add_raw_scan
    ↓
TreeViewWidget.add_raw_scan

Model Responsibilities

The TaviProjectModel is responsible for:

  • Persisting scans in TaviData.raw_scans

  • Emitting a RawScanAppendEvent per scan

Each event contains:

  • uuid: Unique identifier

  • friendly_name: Display name

  • friendly_path: Logical grouping path

Implementation detail:

  • Events are emitted after scans are stored

  • One event is emitted per scan (not batched)

Event Definition

RawScanAppendEvent is a typed model event:

class RawScanAppendEvent(Event):
    uuid: UUID
    friendly_name: str
    friendly_path: str

This event is the sole contract between backend data loading and UI updates.

Presenter Responsibilities

The LoadRawScanPresenter:

  • Registers with the EventBroker for RawScanAppendEvent

  • Maintains a local inventory of loaded scans

  • Translates events into view updates

On event:

self._view.add_raw_scan(event.uuid,
                        event.friendly_name,
                        event.friendly_path)

The presenter does no transformation beyond forwarding metadata.

View Responsibilities (Project Tree)

The Project View is implemented via TreeViewWidget and is responsible for:

  • Maintaining hierarchical structure via path_map

  • Tracking nodes via uuid_map

  • Rendering scan entries under a /Raw root

Adding a Scan

All raw scans are inserted under a fixed root:

/Raw/<friendly_path>/<friendly_name>

The method:

add_raw_scan(uuid, name, path)

normalizes input by:

  • Stripping leading / from path

  • Prefixing with /Raw

Tree Construction

Tree nodes are created incrementally:

  • Each path segment becomes a node if not already present

  • Leaf nodes represent scans

  • Duplicate names are allowed (UUID enforces uniqueness)

Key constraints:

  • Duplicate UUID insertion raises an error

  • Path structure is cached in path_map for O(1) lookup

Example

Given:

  • friendly_name = "scan1"

  • friendly_path = "/experiment/runA"

The resulting tree:

/Raw
  └── experiment
        └── runA
              └── scan1

Key Design Decisions

Event-driven UI updates

The UI does not poll or directly query the model. Instead:

  • The model pushes updates via events

  • The presenter reacts asynchronously

This ensures:

  • Loose coupling

  • Easier extensibility (e.g., progress events, deletion events)

Per-scan event emission

Each scan generates its own event rather than batching.

Pros:

  • Simpler UI updates

  • Incremental rendering possible

Cons:

  • Higher event volume for large loads

Strict UUID ownership

The view enforces uniqueness via uuid_map:

  • Prevents duplicate insertion bugs

  • Enables future direct lookup (e.g., selection sync)

Summary

The Project View does not directly depend on the loading mechanism. Instead, it subscribes to RawScanAppendEvent and incrementally builds a hierarchical representation of scans under the /Raw namespace.

This pattern cleanly separates:

  • Data ingestion (controller + model)

  • Event propagation (event broker)

  • Presentation logic (presenter)

  • Rendering (view)