ddennedy's Description of Work
This pull request significantly improves the undo/redo system for timeline editing commands by making undo operations more efficient and context-aware. The changes focus on capturing only the affected tracks or clips for undo, rather than restoring entire tracks unnecessarily. This results in faster, more reliable undos and better user experience. Additionally, command descriptions are now copied to UndoHelper to show on a progress dialogs when things are slow. Things are usually slow on big projects especially when Ripple All Tracks is on.
Undo/Redo System Improvements
Most timeline commands now call
m_undoHelper.recordBeforeState()with a set of affected track indices, instead of always restoring whole tracks. This enables more efficient, fine-grained undo operations.For commands that can affect multiple tracks (such as ripple edits or move/align commands), logic was added to determine the precise scope of affected tracks and fall back to whole-track restores only when necessary (e.g., ripple-all-tracks is enabled).
Here's the complete picture of every timeline command's undo strategy on the branch now.
Fine-grained (fast per-clip undo β no RestoreTracks)
Use UndoHelper with NoHints/SkipXML:
Command
Notes
AppendCommand
NoHints
OverwriteCommand
NoHints (snapshots the replaced/split span)
LiftCommand
NoHints (snapshots lifted clip)
RemoveCommand
NoHints when not ripple-all
MergeCommand
NoHints
SplitCommand
NoHints (snapshots split clip)
InsertCommand
NoHints when not ripple-all (snapshots split clip)
AddTransitionCommand
NoHints when not ripple-all (snapshots mixed clips)
TrimClipInCommand
NoHints when not ripple
TrimClipOutCommand
SkipXML when not ripple
UpdateCommand
NoHints
DetachAudioCommand
NoHints
ReplaceCommand
NoHints
Still RestoreTracks (whole-track rebuild)
These are the genuinely track-wide or cross-track cases where fine-grained doesn't apply:
Command
When
Why it needs it
MoveClipCommand
always
can move across tracks / reorder
RemoveTrackCommand
always
the whole track is cleared
AlignClipsCommand
always
repositions many clips (lift+overwrite loop)
InsertCommand
ripple-all-tracks
shifts clips on other tracks
RemoveCommand
ripple-all-tracks
shifts other tracks
AddTransitionCommand
ripple-all-tracks
shifts other tracks
TrimClipInCommand
ripple
ripple shifts the track (and others if ripple-all)
Don't use UndoHelper at all (own inverse logic)
GroupCommand, UngroupCommand, NameTrackCommand, MuteTrackCommand, HideTrackCommand, CompositeTrackCommand, LockTrackCommand, FadeInCommand, FadeOutCommand, TrimTransitionInCommand, TrimTransitionOutCommand, ResizeTransitionCommand, AddTransitionByTrimInCommand, AddTransitionByTrimOutCommand, RemoveTransitionByTrimInCommand, RemoveTransitionByTrimOutCommand, AddTrackCommand, InsertTrackCommand, MoveTrackCommand, ChangeBlendModeCommand, ChangeTransitionPropertyCommand, ApplyFiltersCommand, ChangeGainCommand.
Progress Dialog
- All timeline commands now propagate their undo/redo text label via
m_undoHelper.setText(text())to show descriptions in the progress dialogs.
Improved Undo Data Capture
- For commands that split, overwrite, or otherwise modify clips, the system now snapshots only the affected clipsβ XML, enabling cheap and accurate restoration without parsing the entire track.
Refactoring for Move/Align Commands
- The
MoveClipCommandandAlignClipsCommandnow defer the call torecordBeforeState()until the redo step, after the set of affected clips/tracks is known, further optimizing the undo scope.