Add undo and redo to the interface

Ctrl+Z undoes, Ctrl+Y and Ctrl+Shift+Z redo, caught in the capture
phase so a focused entry or spin never undoes only its own text; both
are in the header-bar menu too. The history keeps whole snapshots of
the project (currentProject() plus the immutable source list itself,
so stepping back never decodes again), compared by their JSON.
requestRender() notes every edit, and a step is committed once the
controls have been still for half a second. New and Open start the
history over once the project's images are in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Si
2026-09-26 23:15:03 +02:00
co-authored by Claude Opus 5.5
parent f9fe6e0fa5
commit 5402a50742
5 changed files with 331 additions and 1 deletions
+10
View File
@@ -175,6 +175,16 @@ the `effector` application name on each entry; the GUI tests point
`XDG_DATA_HOME` at a temporary folder so they never touch the user's list. Opening one replaces the sources, so a decode still in flight
is discarded rather than mixed into the new project (`dropLoadedImages_`).
Undo and redo (Ctrl+Z, Ctrl+Y / Ctrl+Shift+Z, caught in the capture phase so
an entry never undoes its own text instead) keep whole snapshots of the
project: `captureState` is `currentProject()` plus the `sources_` list itself,
so stepping back never decodes again, compared by `projectToJson`. There is
nothing to call per edit: `requestRender()` calls `noteChange()`, which commits
a step once the controls have been still for `kHistoryPause`; an edit that
renders nothing (renaming a style) calls `noteChange()` itself. New and Open
start the history over, after the project's images are in
(`historyAfterLoad_`).
### Video projects
A project is a still or a clip: `VideoSettings` (`src/core/video.hpp`: enabled,