[pitivi] undo: Update the transitions map when recreating a transition



commit 70d40599856afb3e02da7dfbe65e75981ae1e6c8
Author: Alexandru Băluț <alexandru balut gmail com>
Date:   Wed Jun 22 14:24:53 2016 +0200

    undo: Update the transitions map when recreating a transition
    
    This allows undoable actions applied to transitions to work on the
    latest transition object when they are redone.
    
    Differential Revision: https://phabricator.freedesktop.org/D1104

 pitivi/undo/timeline.py     |   65 +++++++++++++++++++++++++++++++++++++-----
 tests/test_undo_timeline.py |   22 ++++++++++++++-
 2 files changed, 78 insertions(+), 9 deletions(-)
---
diff --git a/pitivi/undo/timeline.py b/pitivi/undo/timeline.py
index 50a5c02..8d18d16 100644
--- a/pitivi/undo/timeline.py
+++ b/pitivi/undo/timeline.py
@@ -307,7 +307,57 @@ class ClipRemoved(ExpandableUndoableAction):
         return st
 
 
-class TransitionClipRemovedAction(UndoableAction):
+class TransitionClipAction(UndoableAction):
+
+    def __init__(self, ges_layer, ges_clip, track_element):
+        UndoableAction.__init__(self)
+        self.ges_layer = ges_layer
+        self.start = ges_clip.props.start
+        self.duration = ges_clip.props.duration
+        self.track_element = track_element
+
+    @staticmethod
+    def get_video_element(ges_clip):
+        for track_element in ges_clip.get_children(True):
+            if isinstance(track_element, GES.VideoTransition):
+                return track_element
+        return None
+
+    def find_video_transition(self):
+        for ges_clip in self.ges_layer.get_clips():
+            if isinstance(ges_clip, GES.TransitionClip) and \
+                    ges_clip.props.start == self.start and \
+                    ges_clip.props.duration == self.duration:
+                # Got the transition clip, now find its video element, if any.
+                track_element = TransitionClipAction.get_video_element(ges_clip)
+                if not track_element:
+                    # Probably the audio transition clip.
+                    continue
+                # Double lucky!
+                return track_element
+
+
+class TransitionClipAddedAction(TransitionClipAction):
+
+    @classmethod
+    def new(cls, ges_layer, ges_clip):
+        track_element = cls.get_video_element(ges_clip)
+        if not track_element:
+            return None
+        return cls(ges_layer, ges_clip, track_element)
+
+    def do(self):
+        """Searches the transition clip created automatically to update it."""
+        track_element = self.find_video_transition()
+        assert track_element
+        UndoableAutomaticObjectAction.update_object(self.track_element, track_element)
+
+    def undo(self):
+        # The transition is being removed, nothing to do.
+        pass
+
+
+class TransitionClipRemovedAction(TransitionClipAction):
 
     def __init__(self, ges_layer, ges_clip, track_element):
         UndoableAction.__init__(self)
@@ -329,13 +379,6 @@ class TransitionClipRemovedAction(UndoableAction):
             return None
         return cls(ges_layer, ges_clip, track_element)
 
-    @staticmethod
-    def get_video_element(ges_clip):
-        for track_element in ges_clip.get_children(True):
-            if isinstance(track_element, GES.VideoTransition):
-                return track_element
-        return None
-
     def do(self):
         # The transition is being removed, nothing to do.
         pass
@@ -580,6 +623,12 @@ class LayerObserver(MetaContainerObserver, Loggable):
 
     def _connectToTrackElement(self, track_element):
         if isinstance(track_element, GES.VideoTransition):
+            ges_clip = track_element.get_toplevel_parent()
+            ges_layer = ges_clip.props.layer
+            action = TransitionClipAddedAction(ges_layer, ges_clip,
+                                               track_element)
+            self.action_log.push(action)
+
             observer = GObjectObserver(track_element, TRANSITION_PROPS,
                                        self.action_log)
             self.track_element_observers[track_element] = observer
diff --git a/tests/test_undo_timeline.py b/tests/test_undo_timeline.py
index efe180f..68ac3a1 100644
--- a/tests/test_undo_timeline.py
+++ b/tests/test_undo_timeline.py
@@ -355,7 +355,8 @@ class TestLayerObserver(BaseTestUndoTimeline):
         clip2 = asset.extract()
         clip2.set_start(clip1.props.duration / 2)
         clip2.set_duration(10 * Gst.SECOND)
-        self.layer.add_clip(clip2)
+        with self.action_log.started("add second clip"):
+            self.layer.add_clip(clip2)
 
         def get_transition_element(ges_layer):
             for clip in self.layer.get_clips():
@@ -408,6 +409,25 @@ class TestLayerObserver(BaseTestUndoTimeline):
                              "UndoableAutomaticObjectAction is not updated when "
                              "undoing clip remove.")
 
+        for unused_repeat in range(4):
+            # Undo the transition change.
+            self.action_log.undo()
+            # Undo adding the second clip.
+            self.action_log.undo()
+            # Redo adding the second clip.
+            self.action_log.redo()
+            transition_element = get_transition_element(self.layer)
+            self.assertEqual(transition_element.get_transition_type(),
+                             GES.VideoStandardTransitionType.CROSSFADE)
+            # Redo the transition change.
+            self.action_log.redo()
+            transition_element = get_transition_element(self.layer)
+            self.assertEqual(transition_element.get_transition_type(),
+                             GES.VideoStandardTransitionType.BAR_WIPE_LR,
+                             "The auto objects map in "
+                             "UndoableAutomaticObjectAction is not updated when "
+                             "redoing clip add.")
+
 
 class TestControlSourceObserver(BaseTestUndoTimeline):
 


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