Skip to content

refactor(desktop): split WindowLatexPdfMixin into compile + pdf-preview (Batch 10 Stage 3)#82

Merged
yilibinbin merged 2 commits into
mainfrom
fix/batch10-stage3
Jul 3, 2026
Merged

refactor(desktop): split WindowLatexPdfMixin into compile + pdf-preview (Batch 10 Stage 3)#82
yilibinbin merged 2 commits into
mainfrom
fix/batch10-stage3

Conversation

@yilibinbin

@yilibinbin yilibinbin commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Batch 10 — Stage 3: split WindowLatexPdfMixin (behavior-preserving)

The cleanest, lowest-risk split from the reviewed decomposition plan, backstopped
by the Stage 0 guardrails (merged in #81). Two commits:

1/2 — extract the two LaTeX QThread workers to workers_qt.py.
_TectonicInstallWorker and _LatexCompileWorker (+ their helpers:
_TECTONIC_STAGE_LABELS, _LatexEngineRun, _LatexCompileOutcome,
_looks_like_plain_tex_output) were the only workers defined inside a mixin file;
every other worker (CalcWorker, FitWorker, RootSolvingWorker, …) lives in
workers_qt.py. Moved for architectural consistency (Gemini review finding).

2/2 — split the mixin via the proven window_fitting_mixin shim pattern.

  • window_latex_compile_mixin.pyWindowLatexCompileMixin (open/save/reload,
    compile_latex_to_pdf, engine resolution, tectonic install).
  • window_pdf_preview_mixin.pyWindowPdfPreviewMixin (PDF render/zoom/image
    display, dark-mode inversion).
  • window_latex_pdf_mixin.py — now a 66-line shim (was 969): empty subclass
    composing the two (compile leftmost), re-exporting WindowLatexPdfMixin and
    the two workers, so all existing imports keep working unchanged.

Guardrails updated deliberately: _EXPECTED_MRO expands the shim into its two
sub-mixins; the 6 composition guardrails still pass (no mixin __init__, no Qt
event override, no cross-sibling duplicate names). window_latex_pdf_mixin.py
dropped from the file-size ratchet (969 → 66); workers_qt.py consciously
baselined at 807.

Test plan

  • Independently re-verified (not the subagent's self-report): ruff clean,
    public import + full MRO check pass.
  • Full suite: 3817 passed, 9 skipped, 0 failed.

Stage 1 (statistics, larger) is a possible future PR; Stage 2 (cross-family run
controller) and Stage 4 (Protocol) are NO-GO per the two-model review.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added LaTeX-to-PDF compilation from the desktop app, including open, save, reload, and open-generated-PDF actions.
    • Added a richer PDF preview with multi-page rendering, zoom controls, and dark-mode support.
    • Added guided setup for missing LaTeX tools, including Tectonic installation prompts and progress feedback.
  • Bug Fixes

    • Improved handling of compile cancellation, timeouts, and error states.
    • Added automatic fallback behavior when a compiler run fails in common cases.

Aaronhaohao and others added 2 commits July 2, 2026 11:50
… Stage 3, 1/2)

_TectonicInstallWorker and _LatexCompileWorker were the only QThread workers
defined inside a mixin file; every other worker (CalcWorker/FitWorker/
RootSolvingWorker/...) lives in workers_qt.py. Move both, plus their
tightly-coupled helpers used only by them (_TECTONIC_STAGE_LABELS,
_LatexEngineRun, _LatexCompileOutcome, _looks_like_plain_tex_output), to
workers_qt.py for architectural consistency.

They are re-imported into window_latex_pdf_mixin.py so that:
- compile_latex_to_pdf / _offer_tectonic_install keep resolving them as
  module globals (call-time lookup lets the desktop UI tests monkeypatch
  window_latex_pdf_mixin._LatexCompileWorker), and
- external imports (test_latex_compile_worker.py imports _LatexCompileWorker
  and _looks_like_plain_tex_output from window_latex_pdf_mixin) keep working.

Behavior-preserving pure move: no logic change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ew (Stage 3, 2/2)

Second half of Batch-10 Stage 3. Split the 759-line WindowLatexPdfMixin (after
the worker extraction) into two responsibility mixins via the proven
window_fitting_mixin shim pattern:
- window_latex_compile_mixin.py — WindowLatexCompileMixin (open/save/reload,
  compile_latex_to_pdf, engine resolution, tectonic install orchestration).
- window_pdf_preview_mixin.py — WindowPdfPreviewMixin (PDF render/zoom/image
  display, dark-mode inversion, preview-tool location).
- window_latex_pdf_mixin.py — now a 66-line shim: an empty subclass composing
  the two (compile leftmost, since it calls into preview after a successful
  compile), re-exporting WindowLatexPdfMixin AND the two workers so
  `from app_desktop.window_latex_pdf_mixin import WindowLatexPdfMixin /
  _LatexCompileWorker / _TectonicInstallWorker` keep working unchanged.

Behavior-identical (pure move + shim). Stage-0 guardrails updated deliberately:
_EXPECTED_MRO now expands the shim into its two sub-mixins; no mixin defines
__init__ or a Qt event handler; no cross-sibling duplicate method names. Dropped
window_latex_pdf_mixin.py from the file-size ratchet baseline (969 -> 66, now
well under the 800 soft limit).

Independently re-verified (not the subagent's self-report): ruff clean; the
public import + full MRO check pass; 53 latex/compile/pdf/installer/ratchet/
desktop tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d75209d2-22f6-4d94-b23b-4a7cdabb1978

📥 Commits

Reviewing files that changed from the base of the PR and between daa77fd and c412c11.

📒 Files selected for processing (8)
  • app_desktop/window_latex_compile_mixin.py
  • app_desktop/window_latex_pdf_mixin.py
  • app_desktop/window_pdf_preview_mixin.py
  • app_desktop/workers_qt.py
  • tests/test_desktop_latex_compile_ui.py
  • tests/test_file_size_ratchet.py
  • tests/test_qfiledialog_titles_bilingual.py
  • tests/test_window_mixin_composition_guardrails.py

📝 Walkthrough

Walkthrough

The monolithic window_latex_pdf_mixin.py is split into window_latex_compile_mixin.py (compilation orchestration, engine resolution, Tectonic install) and window_pdf_preview_mixin.py (PDF rendering, zoom, dark mode). Worker classes move to workers_qt.py. The original file becomes a thin composing shim. Tests and baselines are updated accordingly.

Changes

LaTeX compile/preview mixin split

Layer / File(s) Summary
LaTeX/Tectonic worker classes
app_desktop/workers_qt.py
Adds _TectonicInstallWorker, _LatexCompileWorker, _LatexEngineRun/_LatexCompileOutcome dataclasses, stage labels, and plain-TeX detection heuristic; exports them via __all__.
Compile orchestration and engine resolution
app_desktop/window_latex_compile_mixin.py
New WindowLatexCompileMixin with compile_latex_to_pdf, completion handling, open_compiled_pdf, editor persist/reload, engine resolution tiers, and Tectonic install prompting.
PDF preview rendering, zoom, dark mode
app_desktop/window_pdf_preview_mixin.py
New WindowPdfPreviewMixin with zoom management, base image generation via external tools, page display, and dark-mode inversion.
Composing shim
app_desktop/window_latex_pdf_mixin.py
Old inline implementation replaced with an empty class composing the two new mixins and re-exporting worker symbols for backward compatibility.
Test and baseline updates
tests/test_desktop_latex_compile_ui.py, tests/test_qfiledialog_titles_bilingual.py, tests/test_window_mixin_composition_guardrails.py, tests/test_file_size_ratchet.py
Patch targets, bilingual title checks, MRO expectations, and file-size baselines updated to match the new module layout.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CompileMixin as WindowLatexCompileMixin
  participant CompileWorker as _LatexCompileWorker
  participant TectonicWorker as _TectonicInstallWorker
  participant PreviewMixin as WindowPdfPreviewMixin

  User->>CompileMixin: compile_latex_to_pdf()
  CompileMixin->>CompileMixin: _persist_latex_editor()
  CompileMixin->>CompileMixin: _ensure_latex_engine()
  alt Tectonic missing
    CompileMixin->>TectonicWorker: _offer_tectonic_install()
    TectonicWorker-->>CompileMixin: EngineChoice or None
  end
  CompileMixin->>CompileWorker: start(engine)
  CompileWorker-->>CompileMixin: completed(outcome)
  CompileMixin->>PreviewMixin: _render_pdf_preview(force_reload=True)
  PreviewMixin-->>User: display rendered PDF pages
Loading

Related PRs: No related pull requests identified from the provided information.

Suggested labels: refactor, desktop-app, latex

Suggested reviewers: yilibinbin

🐰 A mixin split, tidy and neat,
Compile and preview, each finds its seat,
Workers now live in a shared little home,
Tectonic installs while the tests learn to roam,
A shim ties it all with a whisker-light thread. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main refactor: splitting WindowLatexPdfMixin into compile and PDF preview responsibilities.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/batch10-stage3

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@yilibinbin
yilibinbin merged commit 7f5e037 into main Jul 3, 2026
6 checks passed
@yilibinbin
yilibinbin deleted the fix/batch10-stage3 branch July 3, 2026 02:16
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.

2 participants