feat(sort): multi-tag target dirs, skip already-placed moves, modal progress (#40, #50, #80) #125

Merged
ValleyGeek merged 3 commits from 0.1.43/issue-40-50-80-sort-into-folders into main 2026-06-22 01:44:08 +00:00
Member

Summary

  • #40plan_sort_moves() now skips images already directly inside their target tag-named subfolder — no move, no DB write, no shutil call for files that are already correctly placed.
  • #80 — new "Create Multi-Tag Directories" checkbox in the Sort into Folders dialog (off by default — existing single-tag behavior unchanged, see DR-024). When enabled, images with more than one panel tag become eligible too, moving into a folder named after every tag, sorted alphabetically and comma-joined (e.g. "Beach, Mountain").
  • #50 — new modal SortProgressDialog (same pattern as the existing subdir-tag-build dialog) replaces the indeterminate toolbar progress bar for this operation, with a Cancel button now wired to actually take effect mid-move (previously cancellation only took effect between planning and execution). The completion summary also reports how many images were already in their target folder (#40).

Test plan

  • ruff check / ruff format --check
  • pytest
  • PR-prep version bump 0.1.43 → 0.1.44

Refs #40, #50, #80.

Stacked on #124 — part of the 11-PR sequential chain into main.

## Summary - **#40** — `plan_sort_moves()` now skips images already directly inside their target tag-named subfolder — no move, no DB write, no `shutil` call for files that are already correctly placed. - **#80** — new "Create Multi-Tag Directories" checkbox in the Sort into Folders dialog (off by default — existing single-tag behavior unchanged, see DR-024). When enabled, images with more than one panel tag become eligible too, moving into a folder named after every tag, sorted alphabetically and comma-joined (e.g. "Beach, Mountain"). - **#50** — new modal `SortProgressDialog` (same pattern as the existing subdir-tag-build dialog) replaces the indeterminate toolbar progress bar for this operation, with a Cancel button now wired to actually take effect mid-move (previously cancellation only took effect between planning and execution). The completion summary also reports how many images were already in their target folder (#40). ## Test plan - [x] `ruff check` / `ruff format --check` - [x] `pytest` - [x] PR-prep version bump 0.1.43 → 0.1.44 Refs #40, #50, #80. Stacked on #124 — part of the 11-PR sequential chain into `main`.
#40: plan_sort_moves() now skips images already directly inside their target
tag-named subfolder — no move, no DB write, no shutil call for files that are
already correctly placed.

#80: New "Create Multi-Tag Directories" checkbox in the Sort into Folders
dialog (off by default — DR-010 behavior unchanged). When enabled, images
with more than one panel tag become eligible too, moving into a folder named
after every tag sorted alphabetically and comma-joined (e.g. "Beach,
Mountain"). is_sort_eligible()/single_sort_tag()/sort_exclusion_reason()
(core/sort_into_folders.py) and the matching WorkingDB query methods take a
new multi_tag keyword; SortWorker forwards it. See DR-024.

#50: New modal SortProgressDialog (ui/sort_progress_dialog.py, same pattern
as SubdirTagBuildDialog) replaces the indeterminate toolbar progress bar for
this operation — shown on confirm, updated via the existing progress signal,
closed right before the completion summary dialog. Its Cancel button is
wired to SortWorker.cancel(); execute_sort_moves() now takes an is_cancelled
callback checked once per move (previously cancellation only took effect
between planning and execution, so a Cancel button during the actual file
moves would have done nothing). The completion summary now also reports how
many images were already in their target folder (#40).

Threading notes: SortWorker is unchanged as IO + plain-data-signals only;
the new is_cancelled callback is the same _cancelled flag already read from
the worker thread, just polled more often. SortProgressDialog only runs on
the main thread, driven by the existing queued progress/finished signals —
no new cross-thread access.

Fixes #40, #50, #80
SortIntoFoldersDialog._rebuild_list() clears the old tag-group widgets via
deleteLater(), which only takes effect on the next event-loop iteration. The
multi-tag checkbox test never gave Qt a chance to process that before the
test (and the dialog) ended, leaving a stale deferred-deletion event in the
queue that could later crash an unrelated test when some other test's event
loop finally got around to it. A short qtbot.wait() after toggling the
checkbox flushes it immediately instead.
docs: PR-prep for issues 40, 50, 80 - bump to 0.1.44
All checks were successful
CI / lint (push) Successful in 8s
CI / test (push) Successful in 1m57s
CI / appimage (push) Successful in 8m52s
CI / build-appimage (push) Successful in 0s
CI / windows-exe (push) Successful in 9m21s
CI / build-windows-exe (push) Successful in 0s
2a2fc04803
ValleyGeek changed target branch from 0.1.42/issue-64-thumbnail-threads to main 2026-06-22 01:42:34 +00:00
Claude force-pushed 0.1.43/issue-40-50-80-sort-into-folders from 2a2fc04803
All checks were successful
CI / lint (push) Successful in 8s
CI / test (push) Successful in 1m57s
CI / appimage (push) Successful in 8m52s
CI / build-appimage (push) Successful in 0s
CI / windows-exe (push) Successful in 9m21s
CI / build-windows-exe (push) Successful in 0s
to 4f6ea62c67 2026-06-22 01:43:38 +00:00
Compare
ValleyGeek deleted branch 0.1.43/issue-40-50-80-sort-into-folders 2026-06-22 01:44:09 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ai-collab/bulk-image-organizer!125
No description provided.