Source code for madgui.util.history

"""
Utility for managing a simple history.
"""

__all__ = [
    'History',
]


from madgui.util.signal import Signal


[docs]class History: """ Simple class for tracking a value through a linear change history. This is basically a list with the additional notion of a ``current revision`` which can be incremented or decremented by "undoing" or "redoing". """ changed = Signal() def __init__(self): self.clear()
[docs] def clear(self): """Clear history.""" self._stack = [] # recorded revisions self._index = -1 # index of "current" value self.changed.emit()
[docs] def push(self, value): """Add a value at our history position and clear anything behind. Keeps the value unique in the stack by removing previous appearance of it in the stack.""" # check is so that we don't delete the history only by going back and # repushing the same value: if self() != value: self._index += 1 del self._stack[self._index:] self._remove(value) self._stack.append(value) self.changed.emit() return value
[docs] def undo(self): """Move backward in history.""" if self.can_undo(): self._index -= 1 self.changed.emit() return True
[docs] def redo(self): """Move forward in history.""" if self.can_redo(): self._index += 1 self.changed.emit() return True
[docs] def can_undo(self): """Check whether we can move backward in history.""" return self._index > 0
[docs] def can_redo(self): """Check whether we can move forward in history.""" return self._index < len(self._stack) - 1
def __call__(self): """Get the value at our current history position.""" return self._stack[self._index] if self._index >= 0 else None def __len__(self): """Total number of items in the history.""" return len(self._stack) def _remove(self, value): """Remove ``value`` from history.""" try: index = self._stack.index(value) except ValueError: return del self._stack[index] if self._index > index: self._index -= 1
[docs] def create_undo_action(self, parent): """Create a :class:`~PyQt5.QtWidgets.QAction` for an "Undo" button.""" from PyQt5.QtWidgets import QAction, QStyle from PyQt5.QtGui import QKeySequence icon = parent.style().standardIcon(QStyle.SP_ArrowBack) action = QAction(icon, "Undo", parent) action.setShortcut(QKeySequence.Undo) action.setStatusTip("Undo") action.triggered.connect(self.undo) action.setEnabled(self.can_undo()) self.changed.connect(lambda: action.setEnabled(self.can_undo())) return action
[docs] def create_redo_action(self, parent): """Create a :class:`~PyQt5.QtWidgets.QAction` for a "Redo" button.""" from PyQt5.QtWidgets import QAction, QStyle from PyQt5.QtGui import QKeySequence icon = parent.style().standardIcon(QStyle.SP_ArrowForward) action = QAction(icon, "Redo", parent) action.setShortcut(QKeySequence.Redo) action.setStatusTip("Redo") action.triggered.connect(self.redo) action.setEnabled(self.can_redo()) self.changed.connect(lambda: action.setEnabled(self.can_redo())) return action