Skip to content

feat(ui): reset a whole tab from its icon's context menu - #1117

Open
s6stkurz wants to merge 1 commit into
marcinz606:mainfrom
s6stkurz:feat/reset-tab-context-menu
Open

s6stkurz wants to merge 1 commit into
marcinz606:mainfrom
s6stkurz:feat/reset-tab-context-menu

Conversation

@s6stkurz

Copy link
Copy Markdown
Contributor

What this does

Right-click a tab icon in the right panel for Reset Setup to Defaults — every panel on that
tab returns to its defaults in one commit, and one Ctrl+Z walks the whole thing back.

Clearing Setup today means resetting Calibration, Demosaic, Normalization and Roll Analysis from
four separate panel headers, and undoing that costs four presses. The per-panel header resets are
unchanged; this is a second way in, for when the whole tab is what you want gone.

The five workflow tabs offer it: Setup, Geometry, Exposure, Lab & Toning, Finish.

  • Favorites and History hold no settings.
  • Export is mirrored into sticky settings that reach frames other than the one in front of
    you, and ExportConfig carries machine paths — a reset would re-point the destination for the
    session.
  • Metadata is archival content (capture date, GPS, roll and frame), not settings.
    MetadataConfig() wholesale would be a deletion wearing a reset's label, and the panel already
    has per-group clears with the right verb.
  • Scan drives the scanner and camera through global device settings, so a reset there would
    not be part of the frame's edit and would not be undoable.

None of those five gets a menu at all, rather than a menu with a dead row.

The item is shown and greyed when the tab is already at its defaults, matching the canvas
right-click menu. Whether it is enabled is read from the same fold the reset commits, not from
the modified counts, which trail a 150 ms debounce.

The part that needs your agreement

An aggregate reset has to produce one WorkspaceConfig and one update_config call, or the tab
costs N undo steps. The 14 per-panel resets existed only as lambdas in _connect_signals with
three different commit routes, so there was nothing to compose.

So what each panel owns now lives in one table, _SECTION_RESETS, that both the header reset and
the tab reset fold. That collapses SessionManager.reset_section,
AppController.clear_roll_baseline and four ControlsPanel helpers into it — a net deletion, but
it does touch working code. Two consequences worth your eyes:

  1. Every panel reset now commits through apply_config. It compares source_token and
    re-decodes when a reset moves a source input. Previously only the two source-baking helpers
    did this, so a Normalization reset that cleared linear_raw rendered the stale decode. That is
    fixed as a side effect rather than on purpose; say the word if you would rather see it on its
    own.
  2. Normalization still resets the whole ProcessConfig, as it does today, which also
    defaults the Calibration, Demosaic and Roll Analysis fields that live on it. I kept the
    existing behaviour rather than scoping it, because scoping is a visible change to a control
    that is not what this PR is about. It costs nothing here: a whole-config reset subsumes the
    three scoped siblings, so the Setup fold is order-independent either way.

If you would rather not take the refactor, I can rework this as additive code that leaves the 14
wirings alone — it duplicates the "what does Calibration own" knowledge, which is why I did not
lead with it.

Testing

tests/test_tab_reset.py, 16 tests over three layers:

  • the fold — a tab reset defaults every panel on it and nothing off it, a panel reset stays inside
    its own panel, the fold is identity on a clean tab, a roll reset drops the cached per-frame
    bounds and a lock_bounds frame keeps them
  • the commit — one apply_config for a whole tab, none for a clean one, and Dodge & Burn drops
    its mask selection
  • the menu — against the real tab strip, so the five workflow tabs produce their labels and the
    other five produce no menu; plus the greying, the trigger, and the keyboard route

test_clear_roll_baseline_resets_axes moved out of tests/test_controller.py with its subject.

make format, make lint, make type clean; full suite passes. One unrelated failure on my
machine, test_metadata_presets.py::test_load_tooltip_follows_a_rebinding, expects Ctrl+Shift+L
where macOS renders ⇧⌘L — it fails the same way on main with this branch stashed, and CI runs
Ubuntu.

Notes

  • reset_tab is registered with no default key: every Ctrl+<digit> is a tab already. One entry
    rather than five, since five unbound rows in the ? overlay for one concept reads badly. Bound
    by hand it takes the tab on screen, where the menu takes the tab under the pointer.
  • A tab spilled into the » overflow menu cannot be right-clicked — the spilled items are
    QActions. The bar pins the active tab, so selecting a tab first always brings its button back.
    I left build_overflow_menu alone rather than grow it a submenu here.
  • Filtration is hidden in B&W mode but is still reset by an Exposure-tab reset. Its fields are
    part of the edit and inert in that mode.
  • docs/USER_GUIDE.md gains two sentences on the existing panel-header line. No new
    <!-- panel: --> marker, and docs/CHANGELOG.md is untouched.

There is no open issue for this one, so it arrives unsolicited. Happy to close it, split it, or
rework it if this is not a direction you want.

🤖 Generated with Claude Code

Clearing the Setup tab meant resetting Calibration, Demosaic,
Normalization and Roll Analysis from four separate panel headers, and
walking that back cost four presses of Ctrl+Z. Right-click a tab icon
now offers "Reset Setup to Defaults", which defaults every panel on the
tab in one commit and one undo step.

The five workflow tabs offer it. Favorites and History hold no settings.
Export is mirrored into sticky settings that reach other frames, Metadata
is archival content rather than settings, and Scan drives the scanner and
camera through global device settings, so none of the three is part of
the frame's edit and none gets a menu. The item greys when the tab is
already at its defaults, read from the same fold the reset commits rather
than from the modified counts, which trail a debounce.

What a panel owns now lives in one table that both the header reset and
the tab reset fold, so the two cannot disagree. That collapses
SessionManager.reset_section, AppController.clear_roll_baseline and four
ControlsPanel helpers into it. Every panel reset consequently commits
through apply_config, so one that moves linear_raw or demosaic_preview
re-decodes instead of rendering the stale buffer; previously only the two
source-baking helpers did that.

reset_tab is registered unbound: every Ctrl+digit is a tab already. Bound
by hand it takes the tab on screen, where the menu takes the one under
the pointer. A tab spilled into the overflow menu cannot be right-clicked;
the bar pins the active tab, so selecting it first brings its button back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@s6stkurz
s6stkurz force-pushed the feat/reset-tab-context-menu branch from d628786 to 08bb94b Compare September 19, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant