[pitivi] viewer: Add undo/redo support to the transformation box



commit 2a4e9ad013b64e8e2d8e31666a1712c04edb544c
Author: Thibault Saunier <tsaunier gnome org>
Date:   Fri Apr 1 11:34:38 2016 +0200

    viewer: Add undo/redo support to the transformation box
    
    + Add the notion of FinalizingAction to UndoableActionStack so that
      we can commit the timeline *only* once after all actions have been
      executed
    
    Differential Revision: https://phabricator.freedesktop.org/D844

 pitivi/undo/timeline.py             |   13 +++++++++++--
 pitivi/undo/undo.py                 |   22 +++++++++++++++++++---
 pitivi/viewer/move_scale_overlay.py |   16 +++++++++++++++-
 pitivi/viewer/overlay_stack.py      |    2 +-
 pre-commit.hook                     |    1 +
 5 files changed, 47 insertions(+), 7 deletions(-)
---
diff --git a/pitivi/undo/timeline.py b/pitivi/undo/timeline.py
index c4fbacd..1dc887f 100644
--- a/pitivi/undo/timeline.py
+++ b/pitivi/undo/timeline.py
@@ -24,10 +24,19 @@ from gi.repository import GES
 from gi.repository import GObject
 
 from pitivi.utils.loggable import Loggable
-from pitivi.undo.undo import PropertyChangeTracker, UndoableAction
+from pitivi.undo.undo import PropertyChangeTracker, UndoableAction,\
+    FinalizingAction
 from pitivi.effects import PROPS_TO_IGNORE
 
 
+class CommitTimelineFinalizingAction(FinalizingAction):
+    def __init__(self, pipeline):
+        self.__pipeline = pipeline
+
+    def do(self):
+        self.__pipeline.commit_timeline()
+
+
 class TrackElementPropertyChanged(UndoableAction):
 
     def __init__(self, track_element, property_name, old_value, new_value):
@@ -592,7 +601,7 @@ class TimelineLogObserver(Loggable):
                               self._controlBindingAddedCb)
         if isinstance(track_element, GES.BaseEffect):
             self.children_props_tracker.addTrackElement(track_element)
-        elif isinstance(track_element, GES.TitleSource):
+        elif isinstance(track_element, GES.VideoSource):
             self.children_props_tracker.addTrackElement(track_element)
 
     def _disconnectFromTrackElement(self, track_element):
diff --git a/pitivi/undo/undo.py b/pitivi/undo/undo.py
index c6f803f..ace492d 100644
--- a/pitivi/undo/undo.py
+++ b/pitivi/undo/undo.py
@@ -79,6 +79,15 @@ class UndoableAction(GObject.Object, Loggable):
         self.emit("undone")
 
 
+class FinalizingAction:
+    """
+    Base class for actions to happen when an UndoableActionStack is
+    done or undone.
+    """
+    def do(self):
+        raise NotImplementedError()
+
+
 class UndoableActionStack(UndoableAction):
 
     """
@@ -89,12 +98,13 @@ class UndoableActionStack(UndoableAction):
         "cleaned": (GObject.SIGNAL_RUN_LAST, None, ()),
     }
 
-    def __init__(self, action_group_name):
+    def __init__(self, action_group_name, finalizing_action=None):
         UndoableAction.__init__(self)
         self.action_group_name = action_group_name
         self.done_actions = []
         self.undone_actions = []
         self.actions = []
+        self.finalizing_action = finalizing_action
 
     def push(self, action):
         self.done_actions.append(action)
@@ -109,11 +119,17 @@ class UndoableActionStack(UndoableAction):
         self.done_actions = self.undone_actions[::-1]
         self.emit("done")
 
+        if self.finalizing_action:
+            self.finalizing_action.do()
+
     def undo(self):
         self._runAction(self.done_actions, "undo")
         self.undone_actions = self.done_actions[::-1]
         self.emit("undone")
 
+        if self.finalizing_action:
+            self.finalizing_action.do()
+
     def clean(self):
         actions = self.done_actions + self.undone_actions
         self.undone_actions = []
@@ -152,13 +168,13 @@ class UndoableActionLog(GObject.Object, Loggable):
         self.running = False
         self._checkpoint = self._takeSnapshot()
 
-    def begin(self, action_group_name):
+    def begin(self, action_group_name, finalizing_action=None):
         self.debug("Beginning %s", action_group_name)
         if self.running:
             self.debug("Abort because already running")
             return
 
-        stack = UndoableActionStack(action_group_name)
+        stack = UndoableActionStack(action_group_name, finalizing_action)
         nested = self._stackIsNested(stack)
         self.stacks.append(stack)
         self.debug("begin action group %s, nested %s",
diff --git a/pitivi/viewer/move_scale_overlay.py b/pitivi/viewer/move_scale_overlay.py
index b368656..2c9fac4 100644
--- a/pitivi/viewer/move_scale_overlay.py
+++ b/pitivi/viewer/move_scale_overlay.py
@@ -27,6 +27,8 @@ from math import pi
 
 from gi.repository import Gdk
 
+from pitivi.undo.timeline import CommitTimelineFinalizingAction
+from pitivi.utils.misc import disconnectAllByFunc
 from pitivi.viewer.overlay import Overlay
 
 
@@ -304,13 +306,14 @@ class MoveScaleOverlay(Overlay):
     """
     Viewer overlays class for GESVideoSource transformations
     """
-    def __init__(self, stack, source):
+    def __init__(self, stack, action_log, source):
         Overlay.__init__(self, stack, source)
 
         self.__clicked_handle = None
         self.__click_diagonal_sign = None
         self.__box_hovered = False
 
+        self.__action_log = action_log
         self.hovered_handle = None
 
         # Corner handles need to be ordered for drawing.
@@ -327,6 +330,7 @@ class MoveScaleOverlay(Overlay):
         for key in self.handles:
             self.handles[key].set_placement(key)
 
+        self._source.connect("deep-notify", self.__source_property_changed_cb)
         self.update_from_source()
 
     def __get_source_position(self):
@@ -410,9 +414,13 @@ class MoveScaleOverlay(Overlay):
         return size[0] / size[1]
 
     def on_button_press(self):
+        disconnectAllByFunc(self._source, self.__source_property_changed_cb)
         self.click_source_position = self.__get_source_position()
         self.__clicked_handle = None
 
+        self.__action_log.begin("Video position change",
+                                CommitTimelineFinalizingAction(
+                                    self._source.get_timeline().get_parent()))
         if self.hovered_handle:
             self.hovered_handle.on_click()
             self.__clicked_handle = self.hovered_handle
@@ -429,6 +437,7 @@ class MoveScaleOverlay(Overlay):
         self.update_from_source()
         self.on_hover(cursor_position)
 
+        self.__action_log.commit()
         if self.__clicked_handle:
             if not self.__clicked_handle.hovered:
                 self.stack.reset_cursor()
@@ -437,8 +446,13 @@ class MoveScaleOverlay(Overlay):
         elif self._is_hovered():
             self.stack.set_cursor("grab")
 
+        self._source.connect("deep-notify", self.__source_property_changed_cb)
         self.queue_draw()
 
+    def __source_property_changed_cb(self, unused_source, unused_gstelement,
+                                     unused_pspec):
+        self.update_from_source()
+
     def on_motion_notify(self, cursor_pos):
         click_to_cursor = self.stack.get_normalized_drag_distance(cursor_pos)
         if self.__clicked_handle:
diff --git a/pitivi/viewer/overlay_stack.py b/pitivi/viewer/overlay_stack.py
index ae7dfef..f2db4f8 100644
--- a/pitivi/viewer/overlay_stack.py
+++ b/pitivi/viewer/overlay_stack.py
@@ -60,7 +60,7 @@ class OverlayStack(Gtk.Overlay):
         if type(source) == GES.TitleSource:
             overlay = TitleOverlay(self, source)
         else:
-            overlay = MoveScaleOverlay(self, source)
+            overlay = MoveScaleOverlay(self, self.app.action_log, source)
         self.add_overlay(overlay)
         self.__overlays[source] = overlay
 
diff --git a/pre-commit.hook b/pre-commit.hook
index 54062a1..83e4243 100755
--- a/pre-commit.hook
+++ b/pre-commit.hook
@@ -67,6 +67,7 @@ pitivi/undo/undo.py \
 pitivi/undo/timeline.py \
 pitivi/render.py \
 pitivi/viewer/move_scale_overlay.py \
+pitivi/viewer/overlay_stack.py \
 "
 
 git-pylint-commit-hook --help |grep ignore > /dev/null 2>&1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]