Source code for rekordbox_set_list_manager.controllers.undo_stack

"""Generic JSON-snapshot undo/redo stack."""

from __future__ import annotations

_DEFAULT_MAX = 50


[docs] class UndoStack[T]: """Undo/redo stack that stores serialised snapshots of type *T*. Usage:: stack: UndoStack[str] = UndoStack() # Before a mutation: stack.push(current_snapshot) # Undo: prev = stack.undo(current_snapshot) # Redo: next_ = stack.redo(current_snapshot) """ def __init__(self, max_size: int = _DEFAULT_MAX) -> None: """Initialise an empty undo/redo stack with *max_size* capacity.""" self._max = max_size self._undo: list[T] = [] self._redo: list[T] = [] # ---------------------------------------------------------------- public @property
[docs] def can_undo(self) -> bool: """Return True if there are undo steps available.""" return bool(self._undo)
@property
[docs] def can_redo(self) -> bool: """Return True if there are redo steps available.""" return bool(self._redo)
[docs] def push(self, snapshot: T) -> None: """Record *snapshot* before a mutation. Clears the redo stack. Parameters ---------- snapshot : T The serialised project state to push onto the undo history. """ if self._undo and self._undo[-1] == snapshot: return # no-op: nothing changed self._undo.append(snapshot) if len(self._undo) > self._max: self._undo.pop(0) self._redo.clear()
[docs] def undo(self, current: T) -> T | None: """Undo one step. Returns the previous snapshot, or *None* if empty. The caller must pass the *current* snapshot so it can be pushed to the redo stack. Parameters ---------- current : T The current serialised state, saved to the redo stack. Returns ------- T | None The previous snapshot to restore, or ``None`` if the undo stack is empty. """ if not self._undo: return None self._redo.append(current) return self._undo.pop()
[docs] def redo(self, current: T) -> T | None: """Redo one step. Returns the next snapshot, or *None* if empty. The caller must pass the *current* snapshot so it can be pushed back to the undo stack. Parameters ---------- current : T The current serialised state, saved back to the undo stack. Returns ------- T | None The next snapshot to restore, or ``None`` if the redo stack is empty. """ if not self._redo: return None self._undo.append(current) return self._redo.pop()
[docs] def clear(self) -> None: """Discard all undo and redo history.""" self._undo.clear() self._redo.clear()