Under the UI Hood - setiastro/setiastrosuitepro GitHub Wiki
How it all works together: DocManager Γ SubWindows Γ MDI Γ Shortcuts Γ Drag-and-Drop
The cast
- DocManager (
DocManager) β Owns allImageDocuments, emitsdocumentAdded/Removed, tracks the active doc, and knows how to open, duplicate, save, and apply edits (undo/redo recorded on the document). - ImageDocument β Holds the image array, metadata (incl. header snapshot), mask layers, and an undo/redo history. Emits
changedwhenever the visible state should refresh. - Subwindow (
ImageSubWindow) β Widget that shows oneImageDocumentinside the MDI. Handles zoom/pan, display-stretch (normal/hard + optional Link RGB), mask overlay, and per-view titles/rename. - MDI Workspace (
QMdiAreaviaMdiArea) β Desktop containing all image subwindows. Determines the topmost window under the cursor for drops; double-click background opens files. - Shortcut system (
ShortcutManager,ShortcutCanvas,ShortcutButton) β Overlay on the MDI viewport with draggable βdesktopβ buttons for registered actions. Supports presets, multi-select, rubber-band, headless drag-apply.
Lifecycle at a glance
File path / slot / array
β
βΌ
DocManager.open_* β ImageDocument β documentAdded
β
ββ MainWindow spawns ImageSubWindow bound to that document
β
ββ DocManager.set_mdi_area hooks subwindow activation β tracks active doc
- Edits: Tools call
DocManager.update_active_document(...)(or aliases). This pushes to the docβs undo stack and emitsImageDocument.changedβ subwindow re-renders. - Save:
DocManager.save_document(doc, path, bit_depth_override?)validates bit-depth per format and updates doc metadata.
Active document plumbing
- On MDI activation,
DocManager._on_subwindow_activatedmaps the subwindow back to itsImageDocumentand updates the active pointer. DocManager.get_active_document()falls back to asking MDI or βlast opened.β
Subwindow specifics
- Rendering: Linear view or Display-Stretch (normal/hard; Link RGB ignored for mono). Converts to 8-bit RGB for display; optional red mask overlay.
- View/Title: Keeps zoom/scroll/autostretch; can copy/paste view state; title shows β when a mask is active. Quick rename: F2 (view) or rename the document (propagates to peers).
- Close guard: Warns on unsaved edits (based on undo) unless the app is force-closing.
Drag-and-Drop channels
1) View State (zoom/pan/stretch)
- Start: Drag the β§ tab on a subwindow.
- Payload:
MIME_VIEWSTATEβ{ doc_ptr, scale, hval, vval, autostretch, autostretch_target }. - Drop: On another subwindow (copy view) or MDI background (duplicate view).
- Handled by:
ImageSubWindow.apply_view_state(...)orMdiArea.viewStateDropped.
2) Command (+ optional preset)
-
Start: Alt+Drag a
ShortcutButton(or other action sources). -
Payload:
MIME_CMDβ{ command_id, preset }. -
Drop: Front-most subwindow under the cursor.
-
Handled by:
- Canvas:
ShortcutCanvasfinds the target and callsShortcutManager.apply_command_to_subwindow(...). - That method prefers main-window
_handle_command_drop(...), else triestarget.apply_command(...), elsemw.run_command(...), else activates the subwindow and triggers the registeredQAction.
- Canvas:
3) Mask
- Start: Shift+Drag the β§ tab from a subwindow.
- Payload:
MIME_MASKβ{ mask_doc_ptr, mode, invert, feather, name }. - Drop: Target subwindow.
- Handled by: Main window
_handle_mask_drop(...). Title shows β when a mask is active; overlay toggle via UI/shortcut.
4) Astrometry (WCS/SIP)
- Start: Ctrl+Drag the β§ tab.
- Payload:
MIME_ASTROMETRYβ{ wcs_from_doc_ptr, name }. - Drop: Target subwindow.
- Handled by: Main window
_on_astrometry_drop(...).
5) Files & Folders
- Start: Drag from OS into the ShortcutCanvas.
- Handled by: Canvas collects local files (recursing folders by allowed endings) and asks main window/
DocManagerto open, then spawns subwindows.
Shortcuts overlay (on the MDI viewport)
-
Register actions:
ShortcutManager.register_action(command_id, QAction). -
Create instances:
add_shortcut(command_id, pos, label?)β aShortcutButtonwith its own SID and preset (stored inQSettings). -
Use:
- Double-click β run action (opens UI if interactive).
- Alt+Drag (single selected) β headless apply to a subwindow via
MIME_CMD. - Ctrl/Shift or rubber-band to multi-select; move as a group; Delete to remove.
- Right-click β Run / Edit Preset (built-in dialogs or JSON) / Clear Preset / Rename / Delete.
-
Persistence: Positions, labels, and presets saved as a v2 JSON blob in
QSettings(v1 auto-migrates).
MDI coordination
- Accepts drops for viewstate/command/mask/astrometry and uses StackingOrder to find the topmost subwindow under the cursor.
- Background double-click emits
backgroundDoubleClickedβ open files. - Falls back to default Qt behavior for unknown drops.
Undo/Redo model
- Each
ImageDocumentrecords edits with astep_name. apply_edit()pushes current image/metadata to undo, clears redo, updates metadata, then emitschanged.- Subwindows listen and re-render; layer composites refresh as needed.
Persistence & safety notes
- QSettings stores: theme, linked-stretch default, panel layout, shortcut positions/labels/presets.
- Save As: filename hardening + extension normalization; format-specific bit-depth validation.
- FITS/MEF bonus: on open, known rejection layers (
REJ_LOW/HIGH/COMB) auto-open as sibling read-only docs with friendly names.
Quick scenarios
- Headless stretch to a view: create a Statistical Stretch shortcut with preset β Alt+Drag onto the target subwindow.
- Copy Aβs zoom to B: drag β§ from A, drop on B.
- Move a mask from A to B: Shift+Drag β§ from A, drop on B; toggle overlay to visualize.