[pitivi/wip-speed-control: 4/8] undo: Join successive similar operations on title clips
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi/wip-speed-control: 4/8] undo: Join successive similar operations on title clips
- Date: Wed, 27 Jan 2021 20:59:26 +0000 (UTC)
commit 313e8f071ae4f9ee076ad3758bf2c5cdbc6c7454
Author: Alexandru Băluț <alexandru balut gmail com>
Date: Sun Jan 24 20:44:25 2021 +0100
undo: Join successive similar operations on title clips
Fixes #2022
pitivi/clip_properties/title.py | 2 +-
pitivi/undo/timeline.py | 13 +++++++++
pitivi/undo/undo.py | 60 ++++++++++++++++++++++++++++++++++-------
3 files changed, 64 insertions(+), 11 deletions(-)
---
diff --git a/pitivi/clip_properties/title.py b/pitivi/clip_properties/title.py
index 7a612b7a0..00889ccea 100644
--- a/pitivi/clip_properties/title.py
+++ b/pitivi/clip_properties/title.py
@@ -115,7 +115,7 @@ class TitleProperties(Gtk.Expander, Loggable):
self.show_all()
def _set_child_property(self, name, value):
- with self.app.action_log.started("Title change property",
+ with self.app.action_log.started("Title change property %s" % name,
toplevel=True):
self._setting_props = True
try:
diff --git a/pitivi/undo/timeline.py b/pitivi/undo/timeline.py
index 1b478754d..6330ada01 100644
--- a/pitivi/undo/timeline.py
+++ b/pitivi/undo/timeline.py
@@ -77,6 +77,19 @@ class TrackElementPropertyChanged(UndoableAction):
st['value'] = GObject.Value(pspec.value_type, value)
return st
+ def expand(self, action):
+ if not isinstance(action, TrackElementPropertyChanged):
+ return False
+
+ if not action.track_element == self.track_element:
+ return False
+
+ if not action.property_name == self.property_name:
+ return False
+
+ self.new_value = action.new_value
+ return True
+
class TimelineElementObserver(Loggable):
"""Monitors the props of an element and all its children.
diff --git a/pitivi/undo/undo.py b/pitivi/undo/undo.py
index 39de7b247..e65fa428e 100644
--- a/pitivi/undo/undo.py
+++ b/pitivi/undo/undo.py
@@ -132,15 +132,40 @@ class UndoableActionStack(UndoableAction, Loggable):
self.done_actions = []
self.finalizing_action = finalizing_action
+ def __len__(self):
+ return len(self.done_actions)
+
def __repr__(self):
return "%s: %s" % (self.action_group_name, self.done_actions)
+ def attempt_merge(self, stack, action):
+ """Merges the action into the previous one if possible.
+
+ Returns:
+ bool: Whether the merge has been done.
+ """
+ if not self.done_actions:
+ return False
+
+ if not self.action_group_name == stack.action_group_name:
+ return False
+
+ return self.attempt_expand_action(action)
+
+ def attempt_expand_action(self, action):
+ """Expands the last action with the specified action if possible."""
+ if not self.done_actions:
+ return False
+
+ last_action = self.done_actions[-1]
+ return last_action.expand(action)
+
def push(self, action):
- if self.done_actions:
- last_action = self.done_actions[-1]
- if last_action.expand(action):
- # The action has been included in the previous one.
- return
+ """Adds an action unless it's possible to expand the previous."""
+ if self.attempt_expand_action(action):
+ # The action has been merged into the last one.
+ return
+
self.done_actions.append(action)
def _run_action(self, actions, method_name):
@@ -225,7 +250,7 @@ class UndoableActionLog(GObject.Object, Loggable):
self.emit("begin", stack)
def push(self, action):
- """Reports a change.
+ """Records a change noticed by the monitoring system.
Args:
action (Action): The action representing the change.
@@ -249,11 +274,24 @@ class UndoableActionLog(GObject.Object, Loggable):
try:
stack = self._get_last_stack()
except UndoWrongStateError as e:
- self.warning("Failed pushing '%s' because: %s", action, e)
+ self.warning("Failed pushing '%s' because no transaction started: %s", action, e)
return
- stack.push(action)
- self.debug("push action %s in action group %s",
- action, stack.action_group_name)
+
+ merged = False
+ if len(self.stacks[0]) == 0 and self.undo_stacks:
+ # The current undoable operation is empty, this is the first action.
+ # Check if it can be merged with the previous operation.
+ previous_operation = self.undo_stacks[-1]
+ if previous_operation.attempt_merge(stack, action):
+ self.debug("Merging undoable operations")
+ self.stacks = [self.undo_stacks.pop()]
+ merged = True
+
+ if not merged:
+ stack.push(action)
+ self.debug("push action %s in action group %s",
+ action, stack.action_group_name)
+
self.emit("push", stack, action)
def rollback(self, undo=True):
@@ -299,9 +337,11 @@ class UndoableActionLog(GObject.Object, Loggable):
stack = self._get_last_stack(pop=True)
if action_group_name != stack.action_group_name:
raise UndoWrongStateError("Unexpected commit", action_group_name, stack, self.stacks)
+
if not stack.done_actions:
self.debug("Ignore empty stack %s", stack.action_group_name)
return
+
if not self.stacks:
self.undo_stacks.append(stack)
stack.finish_operation()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]