Skip to content

Export: default destination to a subfolder of the roll - #1111

Draft
PabloRuizCuevas wants to merge 3 commits into
marcinz606:mainfrom
PabloRuizCuevas:feat/pr-export-destination-default
Draft

PabloRuizCuevas wants to merge 3 commits into
marcinz606:mainfrom
PabloRuizCuevas:feat/pr-export-destination-default

Conversation

@PabloRuizCuevas

@PabloRuizCuevas PabloRuizCuevas commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Summary

A fresh export now lands in <roll folder>/export instead of one shared ~/Documents/NegPy/export every roll ever exported into.

  • ExportConfig.output_mode defaults to SUBFOLDER_OF_SOURCE with output_subfolder="export". ExportPreset's own default (a separate delivery-recipe destination) is untouched.
  • A virtual roll has no single folder to build a subfolder under, so its exports redirect to <data folder>/<roll name> instead — computed once per export dispatch, wired into current-file and batch export, contact sheet, and every export path. The redirect warns once via the status bar, since it departs from what the DESTINATION picker shows.
  • Migration for existing installs: output_mode/export_path are sticky across frames, so an install's saved destination already held the old literal default and would otherwise never let the new one win. migrate_legacy_export_destination() runs once at startup and drops the sticky destination only when it still exactly matches the old factory default — a destination the user actually chose is left alone.

Note: this PR is based on main but its branch includes #1109's commits (the virtual-roll redirect needs that PR's roll concept) -- please review/merge #1109 first. Once it lands, this diff will automatically shrink to just the export-destination changes.

Testing

make all (ruff check/format, full pytest) passes with only one known unrelated failure (test_load_tooltip_follows_a_rebinding, pre-existing).

🤖 Generated with Claude Code

PabloRuizCuevas and others added 3 commits September 17, 2026 17:13
… workflow

Rolls (negpy/services/assets/rolls.py) replace folders as the library's
primary listing: importing a folder recognizes it as a roll; Save as
Roll… turns any loaded batch into a reopenable virtual roll, not
necessarily from one folder. The Library tree lists every roll flat,
color-coded (folder amber, virtual coral, no left-side twisty gutter),
with Rename…, bulk Delete…, and an opt-in "rename the folder on disk"
checkbox that rehomes every loaded path when the renamed roll is the
active one.

Roll Settings dialog tags gear, capture, place, process and scanning
metadata for the current frame, a selection, or the whole roll in one
dialog, with a Load-preset flow to fill and tick fields.

New Roll moves off the toolbar onto the Film Strip section's own
header menu (CollapsibleSection.set_actions_menu), next to Reset Roll
to Defaults — a roll-wide reset (reused _asset_defaults, one frame's
worth of logic applied to every visible one) with its own confirm
dialog. The top-level toolbar is gone: actions live in the row of the
section they act on, Library's own corner row or the Film Strip row
next to the loaded frames. restore_session now recognizes the active
roll on restart too, the same "only when unambiguous" rule an
already-open multi-folder session uses.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t virtual rolls

ExportConfig.output_mode now defaults to SUBFOLDER_OF_SOURCE with
output_subfolder="export", so a fresh export lands in <roll folder>/export
instead of one shared ~/Documents/NegPy/export every roll ever exported
into. ExportPreset's own default (SAME_AS_SOURCE, a separate delivery-recipe
destination) is untouched.

resolve_output_dir gains an optional roll_export_root, threaded onto
ExportTask, that stands in for the source file's own directory under
Subfolder of Source. AppController._roll_export_root computes it once per
export dispatch from the active roll: None for a folder roll or no roll
(existing per-file behavior), or <data folder>/<roll name> for a virtual
roll, which has no single folder to build a subfolder under. The redirect
warns once via the status bar, since it departs from what the DESTINATION
picker shows. Wired into the current-file and batch export, contact sheet,
linear output and printing-notes destination paths; Export Presets keep
their existing per-file resolution untouched.

path_safe (renamed from templating._path_safe) sanitizes the roll name for
the folder path, reusing the filename sanitizer already used for metadata
template fields.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
output_mode/export_path are sticky (EXPORT_REMAINDER carries them
unconditionally across frames), so a user's last_export_config already
held the old literal ABSOLUTE default from before this feature, and the
new SUBFOLDER_OF_SOURCE default could never win against it.

migrate_legacy_export_destination() runs once at startup: if the sticky
destination still exactly matches the old factory default (mode ABSOLUTE,
path <user dir>/export), it is dropped from last_export_config so the
current default applies. A destination the user actually chose is left
alone -- it will never match that exact combination.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@PabloRuizCuevas
PabloRuizCuevas force-pushed the feat/pr-export-destination-default branch from 8b813fb to 2eecf6c Compare September 17, 2026 10:22
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