Skip to content

refactor(page_numbers): split scan+prompt from background apply#37

Merged
nelsonduarte merged 1 commit into
mainfrom
refactor/page-numbers-background
May 6, 2026
Merged

refactor(page_numbers): split scan+prompt from background apply#37
nelsonduarte merged 1 commit into
mainfrom
refactor/page-numbers-background

Conversation

@nelsonduarte
Copy link
Copy Markdown
Owner

Summary

Migrate page_numbers from synchronous UI-thread work to a two-phase design that survives the mid-flow Yes/No/Cancel prompt about replacing existing page numbers. With this PR, the migration list from feedback_background_tasks.md is complete except for import_pdf (which has 8 paths each shelling into a different third-party lib and needs per-converter review).

How the split works

Phase 1 (main thread) — validate input, scan the chosen margin band for existing numbers (thin band per target page, fast enough to stay on the main thread), prompt Yes/No/Cancel if hits are found. The scanned bboxes are carried forward as plain (x0,y0,x1,y1) tuples so no fitz.Rect objects escape the with block.

Phase 2 (worker thread) — re-open the doc + authenticate, optionally apply redactions over the existing-number bboxes, loop target pages adding new numbers via page.insert_text, emit per-page progress, save. worker.is_cancelled() is checked at every iteration so the dialog's Cancel button actually aborts.

Changes

  • app/tools/page_numbers.py — refactored _run into pre-flight scan + prompt + _run_background apply.
  • app/translations.json — 3 new i18n keys × 8 languages:
    • progress.page_numbers.applying (dialog label)
    • progress.page_numbers.page (per-page status with {current}/{total})
    • tool.page_numbers.no_targets (replaces a previous silent no-op when the page range matched zero pages)

Test plan

  • Smoke test on Ubuntu 26.04 + Py3.14.4 (offscreen): three cases all pass —
    • Clean PDF → no prompt, output appears, on_done on main thread (2,858 B for a 5-page doc).
    • Pre-numbered PDF + user-Yes → prompt shown, redactions applied, fresh numbers added (3,047 B).
    • Pre-numbered PDF + user-Cancel → prompt shown, no output produced, no work runs.
  • Live GUI on Windows + Py3.14: Cancel button on the progress dialog actually aborts mid-document; large-document numbering no longer freezes the UI.
  • Encrypted-source path: viewer prompts password, page-numbers in compact mode reuses it without re-prompting.

Remaining background-task TODO

After this lands, only import_pdf.py (8 conversion paths via python-docx / python-pptx / openpyxl / BeautifulSoup / ebooklib) is still synchronous. Each path has its own progress shape and dep set; deferred to per-converter PRs.

🤖 Generated with Claude Code

Page-numbers was the last tool in TODO.txt's background-task migration
list. Direct migration was awkward because of the mid-flow
QMessageBox.question that asks the user whether to replace existing
page numbers it detects in the chosen margin band.

Split into two phases:

Phase 1 (main thread):
- Validate input, resolve out_path, gather UI parameters.
- Open the doc once and scan the chosen margin band for existing
  numbers. The scan reads only a thin band per target page, so it
  stays fast enough not to need its own worker.
- If hits are found, prompt Yes/No/Cancel. Cancel aborts cleanly.
- Bail out with a localized warning when the page-target spec
  resolves to zero pages (new tool.page_numbers.no_targets key).

Phase 2 (worker thread):
- Re-open the doc, authenticate if encrypted.
- If replace=True, apply redactions over the existing numbers'
  bboxes (carried as plain (x0,y0,x1,y1) tuples — no fitz.Rect
  objects leak past the Phase-1 with-block).
- Loop target pages adding new numbers, emit per-page progress,
  honour worker.is_cancelled() at every iteration.
- Save with garbage=4, deflate=True.

Add 3 new i18n keys × 8 languages: progress.page_numbers.applying
(dialog label), progress.page_numbers.page (per-page status with
{current}/{total}), tool.page_numbers.no_targets (clearer warning
than the previous silent no-op when the page range matched nothing).

Verified on Ubuntu 26.04 + Py3.14.4 with three smoke-test cases:
clean PDF (no prompt), pre-numbered PDF with user-Yes-replace,
pre-numbered PDF with user-Cancel. All three behave correctly:
on_done fires on the main thread, output appears only on success
paths, the Cancel path produces no output file.

Background-task migration is now complete except for import_pdf.py,
which has 8 paths each shelling into a different third-party lib —
that warrants per-converter review rather than a single mechanical
pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@nelsonduarte nelsonduarte merged commit 826802c into main May 6, 2026
3 checks passed
@nelsonduarte nelsonduarte deleted the refactor/page-numbers-background branch May 6, 2026 13:37
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