Export: default destination to a subfolder of the roll - #1111
Draft
PabloRuizCuevas wants to merge 3 commits into
Draft
PabloRuizCuevas wants to merge 3 commits into
PabloRuizCuevas wants to merge 3 commits into
Conversation
… 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
force-pushed
the
feat/pr-export-destination-default
branch
from
September 17, 2026 10:22
8b813fb to
2eecf6c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A fresh export now lands in
<roll folder>/exportinstead of one shared~/Documents/NegPy/exportevery roll ever exported into.ExportConfig.output_modedefaults toSUBFOLDER_OF_SOURCEwithoutput_subfolder="export".ExportPreset's own default (a separate delivery-recipe destination) is untouched.<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.output_mode/export_pathare 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
mainbut 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