-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🪲 Fix history lost by manual history creation
- Loading branch information
1 parent
4b592c6
commit ebd26aa
Showing
5 changed files
with
203 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# Pyflow an open-source tool for modular visual programing in python | ||
# Copyright (C) 2021-2022 Bycelium <https://www.gnu.org/licenses/> | ||
|
||
""" Module for the handling an history of operations. """ | ||
|
||
from typing import Any, List | ||
|
||
|
||
class History: | ||
"""Helper object to handle undo/redo operations. | ||
Args: | ||
max_stack: Maximum size of the history stack (number of available undo). | ||
""" | ||
|
||
def __init__(self, max_stack: int = 50): | ||
self.history_stack: List[Any] = [] | ||
self.current: int = -1 | ||
self.max_stack: int = max_stack | ||
|
||
def undo(self) -> None: | ||
"""Undo the last action by moving the current stamp backward and restoring.""" | ||
if len(self.history_stack) > 0 and self.current > 0: | ||
self.current -= 1 | ||
self.restore() | ||
|
||
def redo(self) -> None: | ||
"""Redo the last undone action by moving the current stamp forward and restoring.""" | ||
if len(self.history_stack) > 0 and self.current + 1 < len(self.history_stack): | ||
self.current += 1 | ||
self.restore() | ||
|
||
def store(self, data: Any) -> None: | ||
"""Store new data in the history stack, updating current checkpoint. | ||
Remove data that would be forward in the history stack. | ||
Args: | ||
data: Data to store in the history stack. | ||
""" | ||
if self.current + 1 < len(self.history_stack): | ||
self.history_stack = self.history_stack[0 : self.current + 1] | ||
|
||
self.history_stack.append(data) | ||
|
||
if len(self.history_stack) > self.max_stack: | ||
self.history_stack.pop(0) | ||
|
||
self.current = min(self.current + 1, len(self.history_stack) - 1) | ||
|
||
def restored_data(self) -> Any: | ||
""" | ||
Return the snapshot pointed by current in the history stack. | ||
Return None if there is nothing pointed to. | ||
""" | ||
if len(self.history_stack) >= 0 and self.current >= 0: | ||
data = self.history_stack[self.current] | ||
return data | ||
return None | ||
|
||
def restore(self) -> None: | ||
""" | ||
Empty function to be overriden | ||
Contains the behavior to be adopted when a state is restored | ||
""" | ||
# data: Any = self.restored_data() | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Pyflow an open-source tool for modular visual programing in python | ||
# Copyright (C) 2021-2022 Bycelium <https://www.gnu.org/licenses/> | ||
|
||
""" Module for the Python Editor. """ | ||
|
||
from pyflow.core.pyeditor.pyeditor import PythonEditor, POINT_SIZE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Pyflow an open-source tool for modular visual programing in python | ||
# Copyright (C) 2021-2022 Bycelium <https://www.gnu.org/licenses/> | ||
|
||
""" Module for the handling a PythonEditor history. """ | ||
|
||
from typing import TYPE_CHECKING, Optional, OrderedDict, Tuple | ||
|
||
from pyflow.core.history import History | ||
|
||
if TYPE_CHECKING: | ||
from pyflow.core.pyeditor import PythonEditor | ||
|
||
|
||
class EditorHistory(History): | ||
""" | ||
Helper object to handle undo/redo operations on a PythonEditor. | ||
Args: | ||
editor: PythonEditor reference. | ||
max_stack: Maximum size of the history stack (number of available undo). | ||
""" | ||
|
||
def __init__(self, editor: "PythonEditor", max_stack: int = 50): | ||
self.editor = editor | ||
self.is_writing = False | ||
super().__init__(max_stack) | ||
|
||
def start_sequence(self): | ||
""" | ||
Start a new writing sequence if it was not already the case, and save the current state. | ||
""" | ||
if not self.is_writing: | ||
self.is_writing = True | ||
self.checkpoint() | ||
|
||
def end_sequence(self): | ||
""" | ||
End the writing sequence if it was not already the case. | ||
Do not save at this point because the writing parameters to be saved (cursor pos, etc) | ||
are the one of the beginning of the next sequence. | ||
""" | ||
self.is_writing = False | ||
|
||
def checkpoint(self): | ||
""" | ||
Store a snapshot of the editor's text and parameters in the history stack | ||
(only if the text has changed). | ||
""" | ||
text: str = self.editor.text() | ||
old_data = self.restored_data() | ||
if old_data is not None and old_data["text"] == text: | ||
return | ||
|
||
cursor_pos: Tuple[int, int] = self.editor.getCursorPosition() | ||
scroll_pos: int = self.editor.verticalScrollBar().value() | ||
self.store( | ||
{ | ||
"text": text, | ||
"cursor_pos": cursor_pos, | ||
"scroll_pos": scroll_pos, | ||
} | ||
) | ||
|
||
def restore(self): | ||
""" | ||
Restore the editor's text and parameters | ||
using the snapshot pointed by current in the history stack. | ||
""" | ||
data: Optional[OrderedDict] = self.restored_data() | ||
|
||
if data is not None: | ||
self.editor.setText(data["text"]) | ||
self.editor.setCursorPosition(*data["cursor_pos"]) | ||
self.editor.verticalScrollBar().setValue(data["scroll_pos"]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters