Add the editor: page view, cut editing, discard, levels, metadata

QGraphicsView for the viewport, with cuts and the content rectangle
manipulated by hit-testing in the view rather than as movable items —
the geometry is normalised, so what the screen shows and what the
renderer uses are the same numbers at a different zoom.

Cuts are edited as polylines: double-click adds one, drag moves it,
Ctrl-click inserts a vertex, right-click deletes a vertex or the whole
cut. That is how a straight cut becomes the stepped cut Engel needs.

Slice boundaries are drawn, not just cut lines, so a trim anomaly is
visible before export rather than after. Discarded slices are shaded.

Pages preview at 1800px regardless of source resolution, cached per
page, because re-reading a 4959x7017 vector render on every slider move
is unusable.

Autosave is debounced at 800ms and also fires on close.

Closes #12
Closes #14
Closes #15
Closes #16
Closes #17
Closes #18
Closes #19
Closes #20
Closes #26
This commit is contained in:
Esa Kataja
2026-07-28 23:03:49 +03:00
parent 974c91a727
commit bc19eae111
3 changed files with 660 additions and 0 deletions
+11
View File
@@ -111,6 +111,12 @@ def _export(args: argparse.Namespace) -> int:
return 0
def _edit(args: argparse.Namespace) -> int:
from .editor import launch
return launch(Path(args.pdf), SourceType(args.type) if args.type else None)
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
prog="noteman-slicer",
@@ -148,6 +154,11 @@ def main(argv: list[str] | None = None) -> int:
exp.add_argument("--type", choices=[t.value for t in SourceType])
exp.set_defaults(func=_export)
ed = sub.add_parser("edit", help="open the editor")
ed.add_argument("pdf")
ed.add_argument("--type", choices=[t.value for t in SourceType])
ed.set_defaults(func=_edit)
args = parser.parse_args(argv)
return args.func(args)