pub struct DicomViewerApp {Show 16 fields
pub paths: Paths,
pub config: Config,
pub ui_state: UiState,
pub studies: Vec<Study>,
pub raw_cache: HashMap<String, Arc<RawImage>>,
pub raw_failures: HashMap<String, String>,
pub metadata_cache: HashMap<String, Arc<Vec<TagRow>>>,
pub metadata_filter: String,
pub thumbnails: HashMap<String, ThumbnailState>,
pub grid: GridLayout,
pub cells: Vec<CellState>,
pub active_cell: usize,
pub annotation_store: AnnotationStore,
pub annotations_path: PathBuf,
pub last_error: Option<String>,
pub last_info: Option<String>,
/* private fields */
}Expand description
Fields§
§paths: PathsResolved data/log/exe paths. See Paths::resolve.
config: ConfigLoaded config.toml (or defaults on first run).
ui_state: UiStateTransient UI state — disclaimer/about dialogs, active tool, panel visibility, in-progress measurement, etc.
studies: Vec<Study>All loaded studies (metadata only; pixels live in Self::raw_cache).
raw_cache: HashMap<String, Arc<RawImage>>Decoded pixel buffers, keyed by SOP Instance UID. Filled lazily by
Self::raw_for; cleared on Self::open_folder.
raw_failures: HashMap<String, String>SOP UIDs whose decode failed and the reason — so we don’t retry every frame.
metadata_cache: HashMap<String, Arc<Vec<TagRow>>>Flattened DICOM tag rows for the metadata panel, keyed by SOP UID.
Lazily populated by Self::metadata_for.
metadata_filter: StringSubstring filter applied to the metadata panel.
thumbnails: HashMap<String, ThumbnailState>Sidebar previews. Lazily populated one-per-frame so the UI never stalls behind a chain of pixel decodes.
grid: GridLayoutActive grid layout (1×1 up to 4×4).
cells: Vec<CellState>One CellState per visible viewport cell. Length matches
grid.cell_count().
active_cell: usizeIndex into Self::cells receiving toolbar actions and keyboard
input.
annotation_store: AnnotationStorePer-SOP-UID annotation list, persisted to a JSON sidecar.
annotations_path: PathBufWhere Self::annotation_store is loaded from / saved to.
last_error: Option<String>Last error message — shown in the status bar.
last_info: Option<String>Last informational message — shown in the status bar.
Implementations§
Source§impl DicomViewerApp
impl DicomViewerApp
Sourcepub fn new(
cc: &CreationContext<'_>,
paths: Paths,
config: Config,
startup_folder: Option<PathBuf>,
) -> Self
pub fn new( cc: &CreationContext<'_>, paths: Paths, config: Config, startup_folder: Option<PathBuf>, ) -> Self
Build the app, install the theme, and load annotations from
<data_dir>/annotations.json.
startup_folder defers the actual folder scan to the first
update tick so the window paints before
the (potentially CD-slow) scan begins.
Sourcepub fn save_annotations(&self)
pub fn save_annotations(&self)
Persist Self::annotation_store to Self::annotations_path.
Failures are logged but not propagated — losing one annotation save
shouldn’t crash the viewer.
Sourcepub fn push_annotation(&mut self, sop_uid: &str, ann: Annotation)
pub fn push_annotation(&mut self, sop_uid: &str, ann: Annotation)
Append ann to the list for sop_uid and immediately save.
Sourcepub fn clear_annotations_for_active(&mut self)
pub fn clear_annotations_for_active(&mut self)
Drop every annotation on the instance currently shown by the active cell and immediately save.
Sourcepub fn undo_last_annotation_for_active(&mut self)
pub fn undo_last_annotation_for_active(&mut self)
Remove the most recently pushed annotation on the active cell’s instance and immediately save.
Sourcepub fn set_grid(&mut self, g: GridLayout)
pub fn set_grid(&mut self, g: GridLayout)
Switch grid layout, resizing Self::cells to match. Existing
cells are preserved in array order; extras (when shrinking) are
truncated. Resets Self::active_cell if it now falls out of range.
Sourcepub fn open_folder(&mut self, folder: &Path)
pub fn open_folder(&mut self, folder: &Path)
Scan a folder for DICOM files, replace Self::studies, and
auto-arrange the first one. Clears every per-instance cache (raw
pixels, metadata rows, thumbnails) and every CellState. Errors
are surfaced via Self::last_error for the status bar — they’re
not propagated to the caller.
Sourcepub fn open_file(&mut self, file: &Path)
pub fn open_file(&mut self, file: &Path)
Convenience: open the parent folder of a single file. We always load a folder — there is no single-file mode.
Sourcepub fn select_series(&mut self, study_idx: usize, series_idx: usize)
pub fn select_series(&mut self, study_idx: usize, series_idx: usize)
Click on a series in the sidebar. First tries the MG hanging protocol across the whole study (covers the 4-series-of-1-instance case). If that doesn’t apply, falls back to single-series MG (≥4 instances in this series) or assigning to the active cell.
Sourcepub fn try_arrange_mg_study(&mut self, study_idx: usize) -> bool
pub fn try_arrange_mg_study(&mut self, study_idx: usize) -> bool
Look across every MG series in the study and assemble a 2×2 layout when there’s at least one right-breast and one left-breast view.
Placement priority:
- Strict — RCC, LCC, RMLO, LMLO all present: place in that order.
- View-known — at least 2 R and 2 L with
ViewPositionset: sort each side’s queue by view (CC before MLO) so the top row is the cranio-caudal pair. - Laterality-only — at least 2 R and 2 L but
ViewPositionis missing (common in some PACS exports): pair in series/instance order.
Sourcepub fn drop_series_onto_cell(
&mut self,
cell_idx: usize,
series_ref: (usize, usize),
)
pub fn drop_series_onto_cell( &mut self, cell_idx: usize, series_ref: (usize, usize), )
Queue a drag-drop assignment. Validated now (so we don’t push garbage), applied next frame (so the cell’s current TextureHandle survives the rest of this frame’s GPU submission).
Sourcepub fn raw_for(&mut self, sop_uid: &str, path: &Path) -> Option<Arc<RawImage>>
pub fn raw_for(&mut self, sop_uid: &str, path: &Path) -> Option<Arc<RawImage>>
Get the decoded RawImage for an instance, decoding on first
miss. Returns None (and remembers the failure in
Self::raw_failures) when decode fails, so the viewport doesn’t
re-attempt every frame.
Sourcepub fn handle_dropped_files(&mut self, ctx: &Context)
pub fn handle_dropped_files(&mut self, ctx: &Context)
Pick up files dropped onto the egui window. A dropped folder
triggers Self::open_folder; a dropped file triggers
Self::open_file.
Sourcepub fn reset_active_cell(&mut self)
pub fn reset_active_cell(&mut self)
Apply CellState::reset_view to the active cell.
Sourcepub fn active_instance(&self) -> Option<&Instance>
pub fn active_instance(&self) -> Option<&Instance>
Return the instance the active cell is currently showing, if any.
Sourcepub fn thumbnail_for(&mut self, series_uid: &str) -> Option<TextureHandle>
pub fn thumbnail_for(&mut self, series_uid: &str) -> Option<TextureHandle>
Sidebar asks per row: “do you have a thumbnail for this series?”
We register a Pending entry on first miss; the per-frame pump in
Self::pump_thumbnails decodes one at a time.
Sourcepub fn pump_thumbnails(&mut self, ctx: &Context)
pub fn pump_thumbnails(&mut self, ctx: &Context)
Decode at most one pending sidebar thumbnail per frame, so the UI thread isn’t blocked by a long chain of MG-sized decodes.
Trait Implementations§
Source§impl App for DicomViewerApp
impl App for DicomViewerApp
Source§fn update(&mut self, ctx: &Context, _frame: &mut Frame)
fn update(&mut self, ctx: &Context, _frame: &mut Frame)
§fn save(&mut self, _storage: &mut dyn Storage)
fn save(&mut self, _storage: &mut dyn Storage)
§fn auto_save_interval(&self) -> Duration
fn auto_save_interval(&self) -> Duration
Self::save]§fn clear_color(&self, _visuals: &Visuals) -> [f32; 4]
fn clear_color(&self, _visuals: &Visuals) -> [f32; 4]
gl.clearColor. Read more§fn persist_egui_memory(&self) -> bool
fn persist_egui_memory(&self) -> bool
§fn raw_input_hook(&mut self, _ctx: &Context, _raw_input: &mut RawInput)
fn raw_input_hook(&mut self, _ctx: &Context, _raw_input: &mut RawInput)
Self::update]. Read moreAuto Trait Implementations§
impl Freeze for DicomViewerApp
impl !RefUnwindSafe for DicomViewerApp
impl Send for DicomViewerApp
impl Sync for DicomViewerApp
impl Unpin for DicomViewerApp
impl UnsafeUnpin for DicomViewerApp
impl !UnwindSafe for DicomViewerApp
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<D> OwoColorize for D
impl<D> OwoColorize for D
§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg] or
a color-specific method, such as [OwoColorize::green], Read more§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg] or
a color-specific method, such as [OwoColorize::on_yellow], Read more