Name: filmstrip Version: 0.10.3 Release: 1%{?dist} Summary: Compose Instagram carousel and collage posts from local photos # Personal/local tool; MIT is just a permissive default -- change freely. License: MIT URL: https://github.com/example/filmstrip Source0: %{name}-%{version}.tar.gz BuildArch: noarch BuildRequires: desktop-file-utils BuildRequires: librsvg2-tools BuildRequires: python3 # For %check's unit test suite (tests/) -- mirrors the runtime Requires # below. %check runs in this build chroot, which only gets BuildRequires # installed, not Requires, so these need to be listed twice. BuildRequires: python3-pyside6 BuildRequires: python3-pillow # For %check's RAW/DNG integration test (tests/test_library.py's # RealExiftoolExtractionTests) to actually exercise exiftool during the # mock build rather than silently skip -- mirrors the runtime Requires # below, same "listed twice" reasoning as python3-pyside6/python3-pillow. BuildRequires: perl-Image-ExifTool Requires: python3 Requires: python3-pyside6 Requires: python3-pillow Requires: xdg-utils Requires: hicolor-icon-theme # RAW/DNG support (backend/library.py's extract_raw_preview_bytes) shells # out to exiftool to pull a raw file's embedded camera-JPEG preview -- this # app still never decodes a raw file itself (no darktable/rawpy), so # exiftool is the one new runtime dependency that buys that. Requires: perl-Image-ExifTool %description A personal, local-only Wayland desktop app for composing Instagram carousel and collage posts from local photos: pick a folder, arrange photos onto carousel slides using freeform or grid collage layouts, split one wide photo across multiple swipeable slides, drag/resize/crop/reorder, and export numbered, IG-ready images at a consistent aspect ratio. No filters or stickers, no cloud upload, no telemetry -- just the tedious layout/crop/ export part of building a good carousel post, made fast. No background service, no device watching, no database -- projects are plain JSON files. %prep %autosetup -n %{name}-%{version} %build # Pure Python + QML: nothing to compile. Rasterize the app icon from its # SVG source at the sizes the hicolor theme expects. mkdir -p render for size in 16 32 48 64 128 256 512; do rsvg-convert -w "${size}" -h "${size}" icons/%{name}.svg -o "render/%{name}-${size}.png" done %install install -Dm755 packaging/%{name} %{buildroot}%{_bindir}/%{name} install -d %{buildroot}%{_datadir}/%{name} cp -a main.py backend qml icons %{buildroot}%{_datadir}/%{name}/ desktop-file-install --dir=%{buildroot}%{_datadir}/applications \ --set-key=Exec --set-value=%{name} \ --set-key=Icon --set-value=%{name} \ %{name}.desktop install -Dm644 icons/%{name}.svg %{buildroot}%{_datadir}/icons/hicolor/scalable/apps/%{name}.svg for size in 16 32 48 64 128 256 512; do install -Dm644 "render/%{name}-${size}.png" \ "%{buildroot}%{_datadir}/icons/hicolor/${size}x${size}/apps/%{name}.png" done %check desktop-file-validate %{buildroot}%{_datadir}/applications/%{name}.desktop find %{buildroot}%{_datadir}/%{name} -name '*.py' -print0 | xargs -0 python3 -c ' import ast, sys for path in sys.argv[1:]: with open(path, encoding="utf-8") as fh: ast.parse(fh.read(), path) ' # tests/ self-isolates (every test points XDG_CONFIG_HOME/XDG_CACHE_HOME at # a fresh tempdir -- see tests/testutil.py), so this is safe to run as-is; # a failure here fails the whole build, same convention as photo-spool. python3 -m unittest discover -s tests -v %files %{_bindir}/%{name} %{_datadir}/%{name}/ %{_datadir}/applications/%{name}.desktop %{_datadir}/icons/hicolor/*/apps/%{name}.png %{_datadir}/icons/hicolor/scalable/apps/%{name}.svg %changelog * Mon Oct 26 2026 lacamar - 0.10.3-1 - Lint fixes * Tue Sep 01 2026 Filmstrip - 0.10.2-1 - Make a dragged photo's OS-level drag pixmap a little transparent (a new image://dragghost/ provider, composited to 70% opacity from the same small thumbnail cache) instead of fully opaque, so it reads as "picked up" rather than a solid duplicate sitting on top of the destination. - Fix the picker grid's drag pixmap showing visible letterbox padding around non-square photos -- it now sizes to the photo's own visible content, not the picker's square grid cell. - Fix panning/dragging a photo (or the resize handle, or a slide's reorder badge) on the continuous canvas also panning the whole canvas underneath it at the same time -- every in-canvas drag gesture now sets preventStealing so a Flickable can no longer take the gesture away mid-drag. * Tue Sep 01 2026 Filmstrip - 0.10.1-1 - Fix the continuous canvas's span-grow resize handle being too small and easy to miss (12x12, straddling the cell's own edge) -- a near-miss silently panned/zoomed the photo instead via the whole-cell gesture underneath, reading as "resizing doesn't work" rather than "missed the handle." Enlarged (20x20 visible, 40x40 hit target) and moved fully inside the cell's own bounds. - Restore the edge-drop-to-grow-into-a-grid gesture (drag a 2nd photo near a slide's edge, checkered overlay cue, drop to split into a multi-cell layout) on the continuous canvas -- the redesign's own freeform-drop assumption didn't actually cover the single-photo-slide case, since a full-bleed cell has no empty space beside it to drop into. - Add a leading (left) drop-to-prepend-a-slide zone on the canvas, mirroring the trailing one -- it previously only worked on the right. Both are now a small, subtle "+" glyph instead of a large dashed box. * Mon Aug 31 2026 Filmstrip - 0.10.0-1 - Replace the single-slide "stage" + small filmstrip strip + read-only "view all slides" toggle with one continuous, pan/zoomable canvas strip (CanvasView.qml) showing every slide side by side -- the only editing surface now. A cell's frame can be freely repositioned/resized within its slide (Shift+drag / a resize handle), not just chosen from a fixed template. - Add cross-slide photo spanning: drag a full-bleed single photo's resize handle past its slide's boundary to grow it seamlessly across one or more following slides, live -- a drag-driven generalization of the existing panorama-split feature (Cell.span_slides in project.py). A slide a span covers must always be an empty blank; restructuring a slide involved in an active span (template switch, reorder, duplicate) is rejected with a toast rather than silently corrupting which slides the span covers. - Fix a latent bug in duplicateSlide: duplicating a spanning photo's home slide could silently desync which slides its span actually covered, since inserting the clone shifts every later slide's index by one. The clone's own span now always resets to a single slide, the same treatment its panorama_group linkage already got. * Sat Aug 22 2026 Filmstrip - 0.9.12-1 - Fix the Shift+arrow precise-nudge gesture silently no-op'ing on raw (.dng/.cr2/etc.) photos, and nudging an EXIF-rotated non-raw photo by the wrong fraction: it read pixel size via QImageReader directly instead of the shared, raw-aware, orientation-corrected library.read_display_size every other crop-sizing call site already uses. - Fix a data race: full-resolution export now runs against a deep copy of the project rather than the live in-memory one, since the GUI thread stays fully responsive (and able to keep editing/autosaving) for the entire duration of an export running on its own background thread. - Fix adding a root folder, importing a project file, or exporting a copy of one to silently fail or resolve to the wrong path whenever the picked location had a space or other percent-encoded character in it -- these three dialogs were still stripping the "file://" prefix with a naive literal substring replace, the same bug already found and fixed for the export-folder field's dialog. * Fri Aug 21 2026 Filmstrip - 0.9.11-1 - Enforce a single running instance: a second launch pings the already-running instance (raising its window) via a QLocalServer/ QLocalSocket handshake and exits immediately, instead of opening a second window. Prevents two instances silently racing to overwrite the same project's debounced autosave, and prevents each instance fanning its own ThumbWorker batch out across up to 8 separate worker processes at once. * Fri Aug 21 2026 Filmstrip - 0.9.10-1 - Fix the actual remaining cause of thumbnail-generation hangs: Qt Quick was calling the thumb/preview/full image providers' requestImage() synchronously, on the GUI thread, for GridView delegates created inline during a picker folder-selection model reset -- despite every one of those Image elements having asynchronous: true. Confirmed live via cProfile: 11 cache-miss photos' worth of real decode+resize+save work accounted for 1.07s of a 1.09s addRootFolder() call. Neither of the two earlier thumbnail-hang fixes (ThumbWorker's ProcessPoolExecutor, PhotoSortWorker) touched this, since both addressed GIL contention between this app's own background threads, not Qt Quick calling directly into the image provider. Switched all three providers to QQuickAsyncImageProvider/QQuickImageResponse, Qt's own mechanism for making a synchronous-GUI-thread call structurally impossible rather than just unlikely. Verified fixed the same live way it was found: the same profiled call on the same photos now returns in ~20ms with zero GUI-thread stalls across the whole generation run. * Fri Aug 21 2026 Filmstrip - 0.9.9-1 - Fix filmstrip drag-to-reorder never snapping the dragged tile back into its actual grid slot on release (confirmed live with an in-process QQuickView + QTest mouse-event harness -- Drag.active only pauses the ListView's own repositioning of the dragged delegate, nothing re- triggered a layout pass for it specifically once the drag ended). - Fix arrow-key crop panning being silently dead until a photo was manually clicked first: switching the active slide always cleared the active cell instead of defaulting to the new slide's first cell. - Fix "Open folder" after export opening the user's home directory instead of the export folder: a FolderDialog-picked path could reach _resolve_local_path as a still file://-prefixed URL string, which Path().resolve() silently treated as a bogus relative path against cwd instead of the real folder. - Fix fullscreen preview sometimes not showing every slide's photos until a new slide was added and fullscreen reopened: its carousel model wasn't gated on window visibility, so slideAt()'s one-shot (non-live) snapshot went stale for any slide edited while fullscreen was closed. - Fix picker thumbnails staying visually shifted out of their grid cell after being dragged onto the canvas. - Change fullscreen preview to show zero peek of the next/previous slide -- only the current slide's photos are ever painted, with a solid black mask elsewhere, rather than partially revealing a neighboring slide's real photo content mid-swipe. - Change side-by-side (continuous) view: plain left-click-drag on a photo now pans/interacts with it directly (previously required Shift+drag); scrolling the strip is still available via wheel/ trackpad and dragging empty/unfilled space. - Add drop zones beside the single-slide canvas (when a slide is active) to start a brand new slide, matching the filmstrip's own flank drop target. - Add double-click on a picker thumbnail to open the photo preview popup, plus a fullscreen button inside that popup. - Add a selected-photos mini-strip in the picker, with a small X on each thumbnail to deselect it individually. - Add trackpad momentum scrolling to the folder tree and project browser lists (previously only the picker grid and a few other views had it). - Add PageUp/PageDown to step between slides and Tab/Shift+Tab to cycle which cell of a multi-cell slide is keyboard-active, on the single-slide canvas. * Thu Aug 20 2026 Filmstrip - 0.9.8-1 - Fix the picker still freezing the whole app for several seconds on a large raw-photo library with date-based sorting: the previous fix (0.9.7) reduced exiftool to one batched subprocess call instead of one per file, but that single call was still synchronous on the GUI thread -- live-measured at ~12s against a real ~935-photo raw folder. Date sorting now runs on its own background thread instead, verified with a live GUI-thread responsiveness check (max stall dropped from ~12s to ~0.06s against the same real folder). * Thu Aug 20 2026 Filmstrip - 0.9.7-1 - Fix the app hanging on launch for a project with date-based photo sorting and many raw photos: reading each raw file's capture time used to shell out to exiftool up to three times per file, synchronously, before the window even shows. Every raw file's date is now fetched in a single batched exiftool call for the whole folder instead. * Thu Aug 20 2026 Filmstrip - 0.9.6-1 - Add a picker preview modal: hover a grid thumbnail for a magnifier icon that opens a zoomable, pannable close-up (up to 4096px, sourced fresh rather than the on-canvas preview cache) to check focus or camera shake without leaving the app or adding the photo to the canvas. - Add trackpad scrolling momentum to the picker grid: a trackpad's real pixel deltas (including the decelerating ones libinput sends during kinetic scrolling) now drive the scroll directly, instead of every wheel tick being forced through the same fixed per-notch jump a mouse wheel needs. - Share the picker's added folders across every project; only which folders/subfolders are *selected* is per-project now. The folder tree also shows a dash (rather than an empty box) on a folder with some but not all of its subfolders selected. - Side-by-side (continuous) view: slides now sit flush against each other with only a thin divider, the bottom scrollbar no longer overlaps the images, photos can be dragged onto per-cell drop targets or the flanks to start a new slide, and panning a photo within a cell is now shift-drag/horizontal-wheel instead of fighting the view's own pan. - Fullscreen preview is now a swipeable carousel (left-click-drag to page between slides, mimicking Instagram's own carousel viewer) instead of a hard cut between slides. - Sort the photo picker by actual EXIF capture time instead of file modification time, and sort file names case-insensitively. - Invert arrow-key photo panning direction to match the on-screen drag direction. - Fix the project browser's rename pencil icon sitting well past the end of a short project name instead of right next to it, with a hover region that didn't line up with where it actually rendered either. - Restyle tooltips via a small custom Qt Quick Controls style instead of the default style's plain, unstyled box. * Thu Aug 20 2026 Filmstrip - 0.9.5-1 - Fullscreen preview now preloads every slide's media before showing anything, with a loading indicator and navigation blocked until it's done, instead of images visibly popping in as you browse. - Add a continuous view: a toolbar toggle switches the canvas between single-slide editing and every slide shown side by side in one scrollable strip; clicking a slide there jumps back to editing it. - Fix the app hanging when generating a lot of thumbnails: a large batch now fans out across a shared process pool instead of running sequentially in one thread, which was starving the GUI thread of Python's GIL. ~10x faster on a 200-photo batch, with GUI stalls down from multiple seconds to well under 150ms. - Tie the photo picker's folders to the project instead of a global setting: a new project starts with nothing selected, and opening a saved project restores exactly the folders it was using. - Add sorting options (name / newest / oldest) to the photo picker, applied across all selected folders together rather than grouping by folder. - Add a startup-behavior setting (ask each time / start empty / reopen most recent) to the Settings page -- the underlying logic already existed but had no UI to change it. - Fix the project browser's rename click target being far too large, making it easy to accidentally start renaming a project while trying to open it. * Thu Aug 20 2026 Filmstrip - 0.9.4-1 - Fix RAW/DNG photos rendering in the wrong orientation in the thumbnail grid, filmstrip, canvas, and export: the extracted embedded preview's own EXIF doesn't always carry an Orientation tag, even when the raw file itself does (confirmed against a real Nikon D7000 .dng) -- fall back to reading the tag off the raw file directly when the preview's own EXIF lacks one. - Actually fix the ratio dropdown's scrollbar overlapping its text (the 0.9.2 fix only reserved a gutter for the scrollbar; the popup itself was still sized off the *currently selected* entry rather than the widest one, so a longer entry like "1.91:1" still got hard-elided down to "1…" right against the scrollbar) -- widen the control to fit the widest entry in its model. * Thu Aug 20 2026 Filmstrip - 0.9.3-1 - Fix Ctrl+left-click-dragging a photo onto an already-filled cell silently discarding that cell's existing photo instead of swapping the two -- add a proper swap (backend/project.py's swap_cell_photos, AppController.swapCellPhotos). - Fix drag-to-reorder in the filmstrip strip: the crossing-detection logic hit-tested against the dragged tile's own current rect, so it always resolved back to itself and a reorder never actually fired via the drag gesture at all -- the tile just silently snapped back to its original slot on release. Replaced with direct slot-position arithmetic; also add auto-scroll while dragging a tile near either edge of the visible strip. - Speed up project-wide aspect-ratio changes on medium-size projects: the per-photo crop recompute was forcing a full pixel decode just to read a photo's (EXIF-corrected) size -- switch to a header/EXIF-only read (roughly 600x faster in measurement), and parallelize the still-inherently-slower raw/DNG path across a small thread pool. - Fix the fullscreen preview potentially opening on the wrong monitor; add mousewheel and clickable arrow-glyph navigation between slides while in fullscreen. - Verified (no change needed): the layout-growth drag zones and drag-to-create-a-new-slide already worked correctly for grid layouts and for Ctrl-dragged photos, not just plain picker-grid drags. * Thu Aug 20 2026 Filmstrip - 0.9.2-1 - Fix "system" theme mode never actually following the OS preference on Wayland compositors (e.g. niri) where Qt's styleHints() never reports anything but Unknown: fall back to reading the GNOME/GTK color-scheme gsetting directly, polling it when Qt's own change notification can't fire. - Fix the aspect-ratio dropdown's popup scrollbar overlapping the ratio text. - Fix the export dialog visibly growing/shrinking as export progress and the finished-output row appear. - Project browser: replace the separate Rename popup and two-click Delete button with inline click-to-rename (matching the header's own project-name control) and a trash-icon button with a proper confirm dialog. - Add a configurable startup behavior (always start empty, always reopen the most recent project, or prompt to choose) and persist the picker sidebar's and folder tree's collapsed/expanded state across restarts, including a new way to fully collapse the picker sidebar for more canvas room. * Wed Aug 19 2026 Filmstrip - 0.9.1-1 - Fix a critical bug where every pan/right-click-resize/wheel-zoom crop adjustment silently failed to save: the backend never actually received the updated crop from QML due to a type-marshaling mismatch, so the very next unrelated edit to the same slide would visibly "reset" the pan/zoom back to its last-saved position. This was very likely the real cause behind previously reported "pan/zoom resets" issues. * Wed Aug 19 2026 Filmstrip - 0.9.0-1 - Fix RAW/DNG photos rendering with the wrong orientation/aspect ratio on the canvas: two crop-computation functions opened the raw file directly (which Pillow can't decode), silently falling back to an uncropped full frame stretched into whatever cell shape it landed in. - Autosave every edit; the manual Save button is gone. The project title in the header is now click-to-rename (with a small pencil glyph hint) instead of needing the project browser for it. - Add a "New project" header button, and move "Add folder..." into the folder-tree panel as an icon button backed by a proper modal dialog. - Add export options: a "maximum size" mode that sizes the canvas from the actual source photos instead of the fixed baseline, and a configurable JPEG quality / PNG compression slider. Blank slides are now skipped on export instead of producing an empty numbered file. - Fix "Open folder" opening the user's home directory instead of the actual export folder (a relative/`~`-prefixed path produced a malformed file:// URL). - Fix Settings -> Theme -> "System" never actually reading the OS/desktop light-dark preference -- it silently behaved like "Light" always. Now tracks the live preference with no restart needed. - Fix aspect-ratio changes freezing the window on a medium-size project; the per-photo crop recompute now runs on a background thread with a small, unobtrusive "working" indicator instead of blocking the GUI. - Fix the filmstrip's drag-to-reorder reading as janky/unresponsive: a QML id typo silently broke the binding that tells the list to stop fighting the drag every frame. Reordering now also animates the other slides smoothly into place as a drag crosses them. - Add Ctrl+left-click-drag to move (not copy) a photo from one cell to another anywhere in the project, including dropping it into new-slide space to start a fresh slide. - Generalize the edge-drag layout-restructure gesture beyond single-photo slides to grid layouts too, and narrow its drop zone so it's less likely to trigger by accident when just replacing a cell's photo. - Every newly added slide is now focused immediately; repeatedly adding blank slides keeps focus on the first one instead of jumping to each new one in turn. - Flip the fine-resize drag direction to drag right to zoom in, left to zoom out. - Fix the filmstrip's scrollbar overlapping the bottom of the thumbnails. - Restyle the slide right-click context menu to match the rest of the app instead of the unstyled default. * Wed Aug 19 2026 Filmstrip - 0.8.0-1 - Add RAW/DNG support: recognized raw files (.dng/.cr2/.cr3/.nef/.arw/...) now show in the picker and work everywhere else, via exiftool extracting each file's embedded camera-JPEG preview (never a full raw decode) -- new hard dependency on exiftool (perl-Image-ExifTool). - Add a configurable thumbnail/preview disk cache size limit (Settings, default 1GB) with automatic oldest-first eviction once exceeded. - Add a "New project" header button and move "+ Add folder..." into the folder-tree panel as an icon button, now backed by a proper QML FolderDialog -- fixes it not behaving like a real modal window (it was the app's last remaining raw, unparented Python QFileDialog). - Add drag-to-reorder in the slide filmstrip (in addition to the existing nudge buttons), drag-to-new-slide onto the filmstrip's empty space, and a checkered-wireframe drop preview for restructuring a single-photo slide into a 2-cell grid by dropping near a stage edge. - Add a right-click context menu on filmstrip slide thumbnails: Duplicate slide, Split into panorama... (reintroducing an entry point for the existing, previously screen-orphaned panorama-split feature), Remove slide. - Add a fullscreen preview window for the active slide (arrow keys to step through slides, Esc to close). - Shift+arrow now nudges the active cell's crop by exactly one source- photo pixel (previously a bigger/coarser step -- the inverse of what the finer modifier key should do). - Custom vector glyphs for "Remove slide" and the new fullscreen-preview button, replacing the last remaining text-label toolbar buttons in the canvas view. * Wed Aug 19 2026 Filmstrip - 0.7.0-1 - Redesign the empty canvas stage and empty cells as a subtle dashed wireframe instead of a solid light rectangle, and make an empty stage a drop target: dragging a photo from the picker onto it creates a new single-photo slide. - Make the "+ Blank slide" button an icon-only glyph (IconAddSlide) instead of text. - Rewrite PhotoTile's pan/fine-resize/wheel-zoom gestures onto a single MouseArea (matching every other custom-drag interaction already in this codebase) instead of three separate DragHandler/WheelHandler/TapHandler pointer handlers, as a reliability fix for reported intermittent pan/zoom/resize failures. - Add a dedicated header Save button and a current-project-name indicator; saving a never-before-saved project now prompts for a name, prefilled with a ready-to-go non-clashing suggestion (AppController.suggestProjectName) so it can be a single Enter. - Add an "Open folder" button to the export popup once an export finishes, opening the output directory via the desktop's default file manager (QDesktopServices/xdg-open). * Wed Aug 19 2026 Filmstrip - 0.6.1-1 - Fix the folder tree's scrollbar overlapping a root folder's remove (x) button -- the earlier fix shrank the whole scrollable list, which moved the scrollbar and its overlapping content left together without actually separating them (both were still anchored to the same edge). Row content is now inset by a dedicated gutter instead. * Wed Aug 19 2026 Filmstrip - 0.6.0-1 - Fix the actual root cause behind pan resetting when adding a photo and intermittent right-click-resize/left-click-pan failures: the canvas's per-cell Repeater was bound to an array SlideListModel rebuilds on every edit, destroying and recreating every cell's gesture state on any unrelated cell's edit. Bound to a stable count instead. - Folder selection now cascades to subfolders (and back on deselect); the folder-tree panel is horizontally resizable; the picker's mouse wheel no longer stops short of the true bottom; scrollbars no longer overlap grid content; disabled buttons now visibly dim instead of just silently blocking clicks. - Redesign photo selection in the picker: a thin ring outside the photo instead of a border/tint on it, plus a "deselect all" overlay and a persisted thumbnail-size slider. - "Add as slide" is now a badge-counted icon button, greyed out until a photo is selected, offering only layouts that fully use the current selection; the confusing "Split..." button is removed from the UI (the panorama-split feature/tests are untouched, just not currently reachable from the UI). - Add a "+ Blank slide" button that focuses the slide it just created. - Add in-app project management: saved projects live under $XDG_DATA_HOME/filmstrip/projects/, browsable/renameable/deletable from a single "Projects..." popup, with manual import/export-a-copy for files elsewhere. Export now writes into a subdirectory named after the current project (whitespace-safe) instead of loose files in the picked folder. - Replace every emoji/text UI glyph with hand-drawn, theme-reactive vector icons. - The filmstrip strip reflects the project's actual aspect ratio (not a fixed box) and gets real corner rounding; the Settings page gains a "Clear cache" utility for the on-disk thumbnail cache. * Wed Aug 19 2026 Filmstrip - 0.5.0-1 - Fix cell resizing distorting the photo's aspect ratio when dragged too far in one direction (the wheel-zoom and right-click fine-resize gestures now clamp their shared zoom factor, not width/height independently, so the two can never drift apart). - Add multiple source folders: "+ Add folder..." adds another root rather than replacing the current one, automatically merging/absorbing any root that overlaps with (is the same as, or nested inside/around) one already added, with a per-root "x" to remove one outright. - Remember the selected source folders (and every selected subfolder) across restarts; migrates an existing pre-0.5.0 settings.json's old single-folder selection forward automatically. - Remove the header's light/dark toggle button -- theme is now set from the new Settings page only. - Add a Save/load project page: the header's new folder/disk icons open native file dialogs wired to the existing (previously UI-less) save/load project logic. - Add a "+ Blank slide" button for starting an empty slide to drag a photo onto later, rather than needing to pick a photo first. - Overhaul the export pipeline for best-practice Instagram output: color-managed conversion to sRGB (properly transforms a Display P3/ AdobeRGB-tagged photo's embedded color profile, not just a naive RGB mode change) with an explicit sRGB ICC profile embedded in every exported file; higher JPEG fidelity (quality 95, 4:4:4 chroma, no subsampling loss); and a higher (1440px-width) baseline resolution for feed/carousel ratios. The export pipeline has always read full- resolution source files directly rather than the on-screen preview cache -- documented that invariant explicitly given how easy it would be to regress by mistake. * Wed Aug 19 2026 Filmstrip - 0.4.0-1 - Remove the always-on rounded border overlay on canvas cells -- it never clipped the (square) photo underneath it to match, reading as a mismatched wireframe rather than a frame. - Add fine-grained cell adjustment: hold right-click and drag to gently resize (vs. the wheel's coarser per-tick zoom); arrow keys pan whichever cell was most recently clicked/adjusted, Shift for a bigger step. - Photos are now assigned to a cell by dragging one from the picker grid onto it, not a file dialog -- this also now works to replace an already-filled cell's photo, not just an empty one. - Add a resizable picker/canvas split (drag the divider) and bigger, faster mouse-wheel scroll steps in the picker grid. - Add a Settings page (theme selector, app version). - The filmstrip strip at the bottom now renders an accurate composite of each slide's actual layout instead of always showing just the first cell's photo stretched to fill the whole thumbnail. - Replace the "Add as slide" layout dropdown with a flyout of the same layout icons used in the canvas toolbar. * Wed Aug 19 2026 Filmstrip - 0.3.0-1 - Fix blurry canvas: the actively-edited slide's cell now loads a separate 2048px "preview" image cache (image://preview) instead of the picker grid's 320px thumbnail cache stretched up to fill the cell. - Fix photos still showing the wrong orientation after the 0.2.0 EXIF fix: the on-disk thumbnail cache is keyed purely by file stat, so an already- cached pre-fix (wrong-orientation) file kept being served after the upgrade. The cache key now folds in a format-version salt so upgrades can no longer serve stale cache entries. - Add a collapsible directory-tree sidebar to the photo picker: browse to a parent folder, then expand/multi-select any of its subdirectories -- every selected folder's photos merge into the picker grid. - Picker thumbnails are bigger and no longer center-cropped to a square; the full photo now shows letterboxed. - Add a 3-in-1 vertical stack layout (grid-1x3). - Theme ComboBox/TextField/SpinBox popups and controls (rounded corners, fade-in transitions, consistent sizing) -- previously unstyled default Qt Quick Controls widgets that looked and behaved inconsistently with the rest of the UI. * Wed Aug 19 2026 Filmstrip - 0.2.0-1 - Fix photos being stretched off-aspect when placed into a cell: every add/assign/template-switch/aspect-ratio-change path now fits a fresh centered crop to the cell's actual aspect ratio (compute_initial_crop / compute_cover_crop in project.py) instead of defaulting to the full, usually-mismatched photo. - Fix inconsistent photo orientation: apply EXIF Orientation correction (Pillow's ImageOps.exif_transpose) everywhere a photo is decoded -- thumbnails/picker/canvas preview, full-resolution export, and panorama split geometry -- so a portrait photo shot sideways no longer renders rotated in some views and not others. - Fix the photo picker's selection indicator: the selected-checkmark badge referenced a model role that didn't exist and silently never rendered; selection is now shown with a corrected checkmark, an accent-tinted overlay, and a thicker border. - Add a 9:16 Instagram Story/Reel aspect ratio option alongside the existing 1:1 / 4:5 / 1.91:1 carousel ratios. * Tue Aug 18 2026 Filmstrip - 0.1.0-1 - Initial release: folder-based photo picker, freeform/grid carousel canvas with drag-to-pan/wheel-to-zoom cropping per cell, five built-in layout templates (single, grid-2x1, grid-1x2, grid-2x2, grid-1-plus-2), panorama-style splitting of one photo across N carousel slides, drag-reorderable slide filmstrip, save/load projects as plain JSON, and slide-count-aware numbered export (01.jpg..NN.jpg) at a consistent aspect ratio (1:1 / 4:5 / 1.91:1) ready for Instagram upload. Light/dark theming ported from photo-spool's Theme.qml. No filters, no stickers, no cloud upload, no telemetry.