Deck - #103
Open
brokkoli71 wants to merge 10 commits into
Open
Conversation
A native slide editor in its own module deck.py, lazy-imported by sidemark.py via ☰ "New presentation", Ctrl+Alt+P, or --presentation/--deck: - 16:9 slides (1280×720 logical) stored as plain-JSON .smdeck - quick-start layouts: title slide, heading + text, blank - textboxes: inline editing, drag, resize handles, size/bold/alignment - images: clipboard paste, file drop, or picker; aspect-preserving - alignment snapping to slide center and sibling edges with guides - deck-owned undo/redo, delegated from the window's Ctrl+Z/Y - vector PDF export (960×540 pt, searchable text) Window integration mirrors text mode (_deck_mode/_deck_view/_deck_path); deck.py installed beside sidemark.py (PKGBUILD, aur, install.sh); bash completion, .desktop keywords, README section, ideas.csv #96; TestDeckMode suite (15 tests) — full suite 464 passed. Kept on an experimental branch: Deck may later ship as an extension or separate application rather than in the default install. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… slides, speaker notes, ink, presenter, autosave Deck becomes a third mode of Sidemark's one window UI (pdf/text/deck) instead of a self-contained widget. DocumentSession.doc_mode drives a declarative _MODE_CHROME table; DeckView is now only the slide canvas mounted in the paned's canvas_box, with all chrome supplied by the window (deck header cluster). Sidebar thumbnails go through the new _ThumbnailProvider interface (_PdfThumbnails/_DeckThumbnails) with capability-gated PDF-only DnD. Speaker notes edit slide["notes"] in the .smdeck; per-slide ink (pen/highlighter/eraser) renders in canvas, thumbs, presenter and PDF export; textboxes render inline math/Markdown. DeckPresenterWindow (F5) and deck autosave/recovery added. TestDeckMode grown to 23; full suite 472 passing. See ideas.csv row 97. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First-session guide to the project: what Sidemark is, the one-minute architecture (canvas/notes/text/deck modes, DocumentSession proxying, thumbnail provider interface), testing via run_tests.sh (headless Weston), the feature acceptance checklist, and conventions/gotchas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tes) Opening a .pptx now imports an editable Sidemark Deck instead of a flat PDF. _convert_pptx_then_open runs LibreOffice pptx→pdf, _rasterize_pdf_slides renders each page to a PNG (PyMuPDF, PPTX_IMPORT_WIDTH), and the new deck.deck_from_images builds a deck where each slide is one full-bleed picture (fit into 16:9, non-16:9 letterboxed) carrying its speaker notes from _extract_pptx_notes. _open_deck_model (factored out of _open_deck) mounts the in-memory deck untitled+dirty so the first save names the .smdeck. From there: reorder, ink/textbox annotation, F5 presenter, PDF export. The slides are pictures — original text isn't editable as text; that's a deliberate MVP (ideas.csv row 98), with structured text (row 99) and theme import so new slides match (Phase 2) as follow-ups. Removes the old pptx→PDF path and _apply_pptx_notes; cleans up the temp dir. TestPptxNotes covers deck_from_images fit/notes/empty, _rasterize_pdf_slides and _open_imported_deck. Full suite 474. Docs: README, CLAUDE.md, ideas.csv rows 98-100. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LibreOffice writes a tagged (accessibility) structure tree that MuPDF dislikes, so rasterizing each page of the converted PDF printed a harmless "No common ancestor in structure tree" to stderr per slide, flooding the terminal on import. The pixmaps are correct, so mute MuPDF's stderr display (fitz.TOOLS.mupdf_display_errors) around the rasterize loop and restore the prior setting afterward. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…button Presenting a deck now shows the next slide as a preview on the operator's canvas, matching the PDF presenter's PowerPoint-style stack look (it was deferred for decks in v2). DeckView gains set_stack_preview / _stack_layout / _draw_stack_peek: while presenting, the current slide shrinks and the next slide is drawn smaller and dimmed below it (or beside it on a wide/short canvas — whichever keeps the current slide larger, since slides are 16:9). Space is reserved even on the last slide so the slide size never jumps. Wired from _show_present_bar in deck mode. Also fixes a bug this surfaced: launching straight into deck mode (--presentation) showed no presenter button in the top-right corner. The wide deck bar lives in the scrollable start cluster but _calibrate_header measured its full width into every collapse breakpoint, forcing max collapse (level 3), which hides presenter/search/share. Calibration now measures with the deck bar hidden, so it scrolls instead of forcing collapse. Tests: next-slide preview (shrink + stable last slide), stack below/beside layout math, and a regression test that the deck bar can't hide the present button. README + ideas.csv row 101. Full suite 477. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Refresh CLAUDE.md "Current state" for the next session: PPTX import and the deck presenter next-slide preview + present-button fix are done and pushed; Phase 2 (deck themes + PowerPoint theme import) is the next step, and it also builds the OOXML placeholder-chain machinery structured text import needs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 2 of the deck roadmap. A deck now carries a *theme* (background, fonts, text colors, accent, and named-layout placeholder geometry) instead of being hardcoded Sans-on-white, and importing a .pptx synthesizes a theme from the file so slides added to an imported deck match the original design. Native themes (deck.py): - DeckModel.theme, serialized in the .smdeck; FORMAT_VERSION 1→2 with back-compat load (_normalize_theme: v1 files → DEFAULT_THEME, v1 textboxes get role='body' backfilled). - Textboxes carry a semantic role (title|subtitle|body); the old LAYOUTS lambdas became _BASE_LAYOUTS placeholder geometry; new_slide(layout, theme) materializes it. render_slide(cr, slide, theme, …) reads bg/fonts/colors, threaded through every caller (canvas, stack-peek, presenter, export, thumbnails). Inline text editor CSS now matches the theme (WYSIWYG). - Two built-in themes in deck.THEMES: Classic (default) and Midnight. - No colour-editing UI: a theme-picker dropdown in _build_deck_bar (labelled with the active theme, populated lazily) calls DeckView.set_theme (undoable). PowerPoint theme import: - sidemark._extract_pptx_theme parses the first slide master + theme part into a unit-free 'design' dict (colors resolved through <p:clrMap>, fonts from fontScheme, title/body geometry EMU→fraction), reusing the _extract_pptx_notes zip/rels walk; best-effort → None on any problem. - deck.build_imported_theme assembles it into a theme with per-field fallbacks, a contrast guard, and geometry over the content layout. - Wired through _convert_pptx_then_open → _open_imported_deck → deck_from_images(images, theme). Tests: +14 (theme model round-trip/back-compat/undo, theme-driven render, imported-theme assembly + contrast + geometry, pptx theme parse via a new make_themed_pptx helper, end-to-end parse→build→model). README, ideas.csv rows 102/103, and CLAUDE.md updated. Full suite green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JQHhGniyNw2Wz8cA37PGrA
Brings in two master features, both already correct for decks: - open launched file as a tab in the last-used window: decks ride along, since .smdeck/.pptx route through open_file → _do_open_file. - verbatim `code` spans + per-version instance id: the code-span change is in _notes_to_pango_markup (== deck.notes_to_markup), so slide textboxes render `code` verbatim too, no deck code changed. Conflicts (ideas.csv, sidemark.py, test_pdfeditor.py) resolved keeping both sides; master's ideas.csv rows renumbered 104–106 to avoid the deck rows. Full suite green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes two of row 103's limits. _extract_pptx_theme now resolves the page background with the real OOXML inheritance slide → layout → master (first part with a <p:bg> wins, via a nested _bg_spec) and extracts picture backgrounds: a blipFill resolves its r:embed through the part's rels to ppt/media/*, is converted to PNG with fitz.Pixmap (CMYK→RGB guarded, since cairo only reads PNG) and returned as design["bg_image"] (PNG bytes); a gradient is approximated by its first stop colour. deck.build_imported_theme base64-encodes bg_image into the theme; render_slide paints it full-bleed (EXTEND_PAD, no seam) behind objects via new deck._theme_bg_surface (caches under _bg_surface; to_json now cleans the theme so the cairo surface never reaches JSON). Tests: TestPptxNotes +4 (extract from master, layout-over-master + slide inheritance, none when solid; make_themed_pptx gained bg_image_png/bg_on), TestDeckMode +3 (build carries/omits bg_image, render paints it, save/load round-trip strips the cache). README + ideas.csv (107) updated. Note: the decks that triggered this carry no importable background (plain bg1 master) — their look is per-slide content already preserved as the slide picture; the real mismatch there was uninstalled source fonts. Built as the correct general fix for decks that do have picture/layout backgrounds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
No description provided.