[pitivi] undo: Extract LayerObserver out of TimelineObserver



commit 1cb9da19ad04288845aa38a7815b39274fff35eb
Author: Alexandru Băluț <alexandru balut gmail com>
Date:   Tue Jun 14 22:59:55 2016 +0200

    undo: Extract LayerObserver out of TimelineObserver
    
    Also reorganize the /undo/timeline tests and remove a not very useful
    connect test.
    
    Differential Revision: https://phabricator.freedesktop.org/D1086

 pitivi/timeline/layer.py        |    2 +-
 pitivi/undo/project.py          |    4 +-
 pitivi/undo/timeline.py         |   93 ++++----
 tests/test_timeline_elements.py |    4 +-
 tests/test_undo_timeline.py     |  556 ++++++++++++++++++---------------------
 5 files changed, 314 insertions(+), 345 deletions(-)
---
diff --git a/pitivi/timeline/layer.py b/pitivi/timeline/layer.py
index 9b555f1..a3fbb8a 100644
--- a/pitivi/timeline/layer.py
+++ b/pitivi/timeline/layer.py
@@ -183,7 +183,7 @@ class LayerControls(Gtk.EventBox, Loggable):
         self.ges_layer.disconnect_by_func(self.__layerPriorityChangedCb)
         self.ges_timeline.disconnect_by_func(self.__timelineLayerAddedCb)
         self.ges_timeline.disconnect_by_func(self.__timelineLayerRemovedCb)
-        super(LayerControls, self).__del__()
+        super().__del__()
 
     def __layer_rename_cb(self, unused_ges_layer, item, value):
         if not item == "video::name":
diff --git a/pitivi/undo/project.py b/pitivi/undo/project.py
index 0b2f30e..5989cc4 100644
--- a/pitivi/undo/project.py
+++ b/pitivi/undo/project.py
@@ -77,8 +77,8 @@ class ProjectObserver(MetaContainerObserver):
         MetaContainerObserver.__init__(self, project, action_log)
         project.connect("asset-added", self._assetAddedCb)
         project.connect("asset-removed", self._assetRemovedCb)
-        self.timeline_observer = TimelineObserver(action_log)
-        self.timeline_observer.startObserving(project.ges_timeline)
+        self.timeline_observer = TimelineObserver(project.ges_timeline,
+                                                  action_log)
 
     def _assetAddedCb(self, project, asset):
         action = AssetAddedAction(project, asset)
diff --git a/pitivi/undo/timeline.py b/pitivi/undo/timeline.py
index c75c0e8..dc15e8e 100644
--- a/pitivi/undo/timeline.py
+++ b/pitivi/undo/timeline.py
@@ -447,57 +447,37 @@ class ControlSourceSetAction(SimpleUndoableAction):
         return st
 
 
-class TimelineObserver(Loggable):
-    """Monitors a project's timeline and reports UndoableActions.
+class LayerObserver(MetaContainerObserver, Loggable):
+    """Monitors a Layer and reports UndoableActions.
+
+    Args:
+        ges_layer (GES.Layer): The layer to observe.
 
     Attributes:
         action_log (UndoableActionLog): The action log where to report actions.
     """
 
-    def __init__(self, action_log):
+    def __init__(self, ges_layer, action_log):
+        MetaContainerObserver.__init__(self, ges_layer, action_log)
         Loggable.__init__(self)
         self.action_log = action_log
-        self.clip_property_trackers = {}
-        self.layer_observers = {}
-        self.keyframe_observers = {}
-        self.track_element_observers = {}
-        self._layers_priorities = {}
-
-    def startObserving(self, ges_timeline):
-        """Starts monitoring the specified timeline.
-
-        Args:
-            ges_timeline (GES.Timeline): The timeline to be monitored.
-        """
-        for ges_layer in ges_timeline.get_layers():
-            self._connect_to_layer(ges_layer)
-
-        ges_timeline.connect("layer-added", self._layerAddedCb)
-        ges_timeline.connect("layer-removed", self._layerRemovedCb)
+        self.priority = ges_layer.props.priority
 
-    def _connect_to_layer(self, ges_layer):
-        self._layers_priorities[ges_layer] = ges_layer.props.priority
         ges_layer.connect("clip-added", self._clipAddedCb)
         ges_layer.connect("clip-removed", self._clipRemovedCb)
-        ges_layer.connect("notify::priority", self._layer_moved_cb)
-        layer_observer = MetaContainerObserver(ges_layer, self.action_log)
-        self.layer_observers[ges_layer] = layer_observer
+        ges_layer.connect("notify::priority", self.__layer_moved_cb)
 
+        self.clip_observers = {}
         for ges_clip in ges_layer.get_clips():
             self._connectToClip(ges_clip)
 
-    def _disconnect_from_layer(self, ges_layer):
-        del self._layers_priorities[ges_layer]
-        ges_layer.disconnect_by_func(self._clipAddedCb)
-        ges_layer.disconnect_by_func(self._clipRemovedCb)
-        ges_layer.disconnect_by_func(self._layer_moved_cb)
-        self.layer_observers.pop(ges_layer).release()
+        self.keyframe_observers = {}
+        self.track_element_observers = {}
 
     def _connectToClip(self, ges_clip):
-        tracker = GObjectObserver(ges_clip,
-            ["start", "duration", "in-point", "priority"],
-            self.action_log)
-        self.clip_property_trackers[ges_clip] = tracker
+        props = ["start", "duration", "in-point", "priority"]
+        clip_observer = GObjectObserver(ges_clip, props, self.action_log)
+        self.clip_observers[ges_clip] = clip_observer
 
         ges_clip.connect("child-added", self._clipTrackElementAddedCb)
         ges_clip.connect("child-removed", self._clipTrackElementRemovedCb)
@@ -513,8 +493,8 @@ class TimelineObserver(Loggable):
 
         clip.disconnect_by_func(self._clipTrackElementAddedCb)
         clip.disconnect_by_func(self._clipTrackElementRemovedCb)
-        tracker = self.clip_property_trackers.pop(clip)
-        tracker.release()
+        clip_observer = self.clip_observers.pop(clip)
+        clip_observer.release()
 
     def _controlBindingAddedCb(self, track_element, binding):
         self._connectToControlSource(track_element, binding)
@@ -586,19 +566,42 @@ class TimelineObserver(Loggable):
         action = ActivePropertyChanged(add_effect_action, active)
         self.action_log.push(action)
 
-    def _layer_moved_cb(self, ges_layer, unused_param):
-        previous = self._layers_priorities[ges_layer]
+    def __layer_moved_cb(self, ges_layer, unused_param):
         current = ges_layer.props.priority
-        self._layers_priorities[ges_layer] = current
-        action = LayerMoved(ges_layer, previous, current)
+        action = LayerMoved(ges_layer, self.priority, current)
         self.action_log.push(action)
+        self.priority = current
+
 
-    def _layerAddedCb(self, ges_timeline, ges_layer):
+class TimelineObserver(Loggable):
+    """Monitors a project's timeline and reports UndoableActions.
+
+    Attributes:
+        ges_timeline (GES.Timeline): The timeline to be monitored.
+        action_log (UndoableActionLog): The action log where to report actions.
+    """
+
+    def __init__(self, ges_timeline, action_log):
+        Loggable.__init__(self)
+        self.ges_timeline = ges_timeline
+        self.action_log = action_log
+
+        self.layer_observers = {}
+        for ges_layer in ges_timeline.get_layers():
+            self._connect_to_layer(ges_layer)
+
+        ges_timeline.connect("layer-added", self.__layer_added_cb)
+        ges_timeline.connect("layer-removed", self.__layer_removed_cb)
+
+    def __layer_added_cb(self, ges_timeline, ges_layer):
         self._connect_to_layer(ges_layer)
-        action = LayerAdded(ges_timeline, ges_layer)
+
+    def _connect_to_layer(self, ges_layer):
+        action = LayerAdded(self.ges_timeline, ges_layer)
         self.action_log.push(action)
+        layer_observer = LayerObserver(ges_layer, self.action_log)
+        self.layer_observers[ges_layer] = layer_observer
 
-    def _layerRemovedCb(self, ges_timeline, ges_layer):
-        self._disconnect_from_layer(ges_layer)
+    def __layer_removed_cb(self, ges_timeline, ges_layer):
         action = LayerRemoved(ges_timeline, ges_layer)
         self.action_log.push(action)
diff --git a/tests/test_timeline_elements.py b/tests/test_timeline_elements.py
index fa82c5b..9aa240e 100644
--- a/tests/test_timeline_elements.py
+++ b/tests/test_timeline_elements.py
@@ -21,10 +21,10 @@ from unittest import mock
 from gi.repository import GES
 
 from tests import common
-from tests import test_timeline_timeline
+from tests.test_timeline_timeline import BaseTestTimeline
 
 
-class TestKeyframeCurve(test_timeline_timeline.BaseTestTimeline):
+class TestKeyframeCurve(BaseTestTimeline):
 
     def test_keyframe_toggle(self):
         timeline = self.createTimeline()
diff --git a/tests/test_undo_timeline.py b/tests/test_undo_timeline.py
index 4a1418b..4f0c60d 100644
--- a/tests/test_undo_timeline.py
+++ b/tests/test_undo_timeline.py
@@ -32,65 +32,14 @@ from pitivi.undo.project import AssetAddedAction
 from pitivi.undo.timeline import ClipAdded
 from pitivi.undo.timeline import ClipRemoved
 from pitivi.undo.timeline import EffectAddedAction
-from pitivi.undo.timeline import TimelineObserver
 from pitivi.undo.undo import PropertyChangedAction
-from pitivi.undo.undo import UndoableActionLog
 from pitivi.utils.ui import CONTROL_WIDTH
 from pitivi.utils.ui import LAYER_HEIGHT
 from pitivi.utils.ui import URI_TARGET_ENTRY
 from tests import common
 
 
-class TimelineObserverSpy(TimelineObserver):
-
-    def _connectToClip(self, clip):
-        TimelineObserver._connectToClip(self, clip)
-        clip.connected = True
-
-    def _disconnectFromClip(self, clip):
-        TimelineObserver._disconnectFromClip(self, clip)
-        clip.connected = False
-
-    def _connectToTrackElement(self, track_element):
-        TimelineObserver._connectToTrackElement(self, track_element)
-        track_element.connected = True
-
-    def _disconnectFromTrackElement(self, track_element):
-        TimelineObserver._disconnectFromTrackElement(self, track_element)
-        track_element.connected = False
-
-
-class TestTimelineLogObserver(TestCase):
-
-    def setUp(self):
-        self.action_log = UndoableActionLog()
-        self.observer = TimelineObserverSpy(self.action_log)
-
-    def testConnectionAndDisconnection(self):
-        timeline = GES.Timeline.new_audio_video()
-        layer = GES.Layer()
-        timeline.add_layer(layer)
-        self.observer.startObserving(timeline)
-
-        clip1 = GES.TitleClip()
-
-        layer.add_clip(clip1)
-        track_element1 = clip1.get_children(False)[0]
-        self.assertTrue(clip1.connected)
-        self.assertTrue(track_element1.connected)
-
-        layer.remove_clip(clip1)
-        self.assertFalse(clip1.connected)
-        self.assertFalse(track_element1.connected)
-
-        layer.add_clip(clip1)
-        track_element2 = clip1.get_children(False)[0]
-        self.assertTrue(clip1.connected)
-        self.assertFalse(track_element1.connected)
-        self.assertTrue(track_element2.connected)
-
-
-class TestTimelineUndo(TestCase):
+class BaseTestUndoTimeline(TestCase):
 
     def setUp(self):
         self.app = common.create_pitivi()
@@ -106,10 +55,13 @@ class TestTimelineUndo(TestCase):
                 yield clip
 
     @staticmethod
-    def commitCb(action_log, stack, stacks):
+    def commit_cb(action_log, stack, stacks):
         stacks.append(stack)
 
-    def testLayerRemoved(self):
+
+class TestTimelineObserver(BaseTestUndoTimeline):
+
+    def test_layer_removed(self):
         timeline_ui = Timeline(container=None, app=None)
         timeline_ui.setProject(self.app.project_manager.current_project)
 
@@ -137,6 +89,9 @@ class TestTimelineUndo(TestCase):
         self.assertEqual([l.props.priority for l in [layer1, layer3]],
                         list(range(2)))
 
+
+class TestLayerObserver(BaseTestUndoTimeline):
+
     def testLayerMoved(self):
         layer1 = self.layer
         layer2 = self.timeline.append_layer()
@@ -183,6 +138,175 @@ class TestTimelineUndo(TestCase):
         self.action_log.redo()
         self.assertEqual(layer._nameIfSet(), "Beautiful name")
 
+    def testAddClip(self):
+        stacks = []
+        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+
+        clip1 = GES.TitleClip()
+        with self.action_log.started("add clip"):
+            self.layer.add_clip(clip1)
+
+        self.assertEqual(1, len(stacks))
+        stack = stacks[0]
+        self.assertEqual(2, len(stack.done_actions), stack.done_actions)
+        self.assertTrue(isinstance(stack.done_actions[0], ClipAdded))
+        self.assertTrue(isinstance(stack.done_actions[1], AssetAddedAction))
+        self.assertTrue(clip1 in self.getTimelineClips())
+
+        self.action_log.undo()
+        self.assertFalse(clip1 in self.getTimelineClips())
+
+        self.action_log.redo()
+        self.assertTrue(clip1 in self.getTimelineClips())
+
+    def testRemoveClip(self):
+        stacks = []
+        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+
+        clip1 = GES.TitleClip()
+        self.layer.add_clip(clip1)
+        with self.action_log.started("remove clip"):
+            self.layer.remove_clip(clip1)
+
+        self.assertEqual(1, len(stacks))
+        stack = stacks[0]
+        self.assertEqual(1, len(stack.done_actions))
+        action = stack.done_actions[0]
+        self.assertTrue(isinstance(action, ClipRemoved))
+        self.assertFalse(clip1 in self.getTimelineClips())
+
+        self.action_log.undo()
+        self.assertTrue(clip1 in self.getTimelineClips())
+
+        self.action_log.redo()
+        self.assertFalse(clip1 in self.getTimelineClips())
+
+    def testUngroup(self):
+        uri = common.get_sample_uri("tears_of_steel.webm")
+        asset = GES.UriClipAsset.request_sync(uri)
+        clip1 = asset.extract()
+        self.layer.add_clip(clip1)
+
+        clip1.set_start(5 * Gst.SECOND)
+        clip1.set_duration(0.5 * Gst.SECOND)
+        timeline_clips = list(self.getTimelineClips())
+        self.assertEqual(1, len(timeline_clips), timeline_clips)
+        self.assertEqual(5 * Gst.SECOND, timeline_clips[0].get_start())
+        self.assertEqual(0.5 * Gst.SECOND, timeline_clips[0].get_duration())
+
+        with self.action_log.started("ungroup"):
+            ungrouped = GES.Container.ungroup(clip1, False)
+            self.assertEqual(2, len(ungrouped), ungrouped)
+        timeline_clips = list(self.getTimelineClips())
+        self.assertEqual(2, len(timeline_clips), timeline_clips)
+        self.assertEqual(5 * Gst.SECOND, timeline_clips[0].get_start())
+        self.assertEqual(0.5 * Gst.SECOND, timeline_clips[0].get_duration())
+        self.assertEqual(5 * Gst.SECOND, timeline_clips[1].get_start())
+        self.assertEqual(0.5 * Gst.SECOND, timeline_clips[1].get_duration())
+
+        self.action_log.undo()
+        timeline_clips = list(self.getTimelineClips())
+        self.assertEqual(1, len(timeline_clips))
+        self.assertEqual(5 * Gst.SECOND, timeline_clips[0].get_start())
+        self.assertEqual(0.5 * Gst.SECOND, timeline_clips[0].get_duration())
+
+    def testSplitClip(self):
+        clip = GES.TitleClip()
+        clip.set_start(0 * Gst.SECOND)
+        clip.set_duration(20 * Gst.SECOND)
+
+        self.layer.add_clip(clip)
+
+        with self.action_log.started("split clip"):
+            clip1 = clip.split(10 * Gst.SECOND)
+            self.assertEqual(2, len(self.layer.get_clips()))
+
+        with self.action_log.started("split clip"):
+            clip2 = clip1.split(15 * Gst.SECOND)
+            self.assertEqual(3, len(self.layer.get_clips()))
+
+        self.action_log.undo()
+        self.assertEqual(2, len(self.layer.get_clips()))
+        self.action_log.undo()
+        self.assertEqual(1, len(self.layer.get_clips()))
+
+        self.action_log.redo()
+        self.assertEqual(2, len(self.layer.get_clips()))
+        self.action_log.redo()
+        self.assertEqual(3, len(self.layer.get_clips()))
+
+    def testAddEffectToClip(self):
+        stacks = []
+        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+
+        clip1 = GES.TitleClip()
+        self.layer.add_clip(clip1)
+
+        effect1 = GES.Effect.new("agingtv")
+        with self.action_log.started("add effect"):
+            clip1.add(effect1)
+
+        self.assertEqual(1, len(stacks))
+        stack = stacks[0]
+        self.assertEqual(1, len(stack.done_actions), stack.done_actions)
+        action = stack.done_actions[0]
+        self.assertTrue(isinstance(action, EffectAddedAction))
+
+        self.assertTrue(effect1 in clip1.get_children(True))
+        self.assertEqual(1, len([effect for effect in
+                                 clip1.get_children(True)
+                                 if isinstance(effect, GES.Effect)]))
+
+        self.action_log.undo()
+        self.assertFalse(effect1 in clip1.get_children(True))
+
+        self.action_log.redo()
+        self.assertEqual(1, len([effect for effect in
+                                 clip1.get_children(True)
+                                 if isinstance(effect, GES.Effect)]))
+
+    def testRemoveEffectFromClip(self):
+        stacks = []
+        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+
+        clip1 = GES.TitleClip()
+        self.layer.add_clip(clip1)
+
+        effect1 = GES.Effect.new("agingtv")
+        with self.action_log.started("add effect"):
+            clip1.add(effect1)
+
+        self.assertEqual(1, len(stacks))
+        stack = stacks[0]
+        self.assertEqual(1, len(stack.done_actions), stack.done_actions)
+        action = stack.done_actions[0]
+        self.assertTrue(isinstance(action, EffectAddedAction))
+
+        self.assertTrue(effect1 in clip1.get_children(True))
+        self.assertEqual(1, len([effect for effect in
+                                 clip1.get_children(True)
+                                 if isinstance(effect, GES.Effect)]))
+
+        with self.action_log.started("remove effect"):
+            clip1.remove(effect1)
+
+        self.assertEqual(0, len([effect for effect in
+                                 clip1.get_children(True)
+                                 if isinstance(effect, GES.Effect)]))
+
+        self.action_log.undo()
+        self.assertEqual(1, len([effect for effect in
+                                 clip1.get_children(True)
+                                 if isinstance(effect, GES.Effect)]))
+
+        self.action_log.redo()
+        self.assertEqual(0, len([effect for effect in
+                                 clip1.get_children(True)
+                                 if isinstance(effect, GES.Effect)]))
+
+
+class TestControlSourceObserver(BaseTestUndoTimeline):
+
     def testControlSourceValueAdded(self):
         uri = common.get_sample_uri("tears_of_steel.webm")
         asset = GES.UriClipAsset.request_sync(uri)
@@ -254,26 +378,99 @@ class TestTimelineUndo(TestCase):
         self.action_log.redo()
         self.assertEqual(0.9, control_source.get_all()[0].value)
 
-    def testAddClip(self):
+
+class TestTimelineElementObserver(BaseTestUndoTimeline):
+
+    def testTrackElementPropertyChanged(self):
+        clip1 = GES.TitleClip()
+        self.layer.add_clip(clip1)
+
+        with self.action_log.started("Title text change"):
+            source = clip1.get_children(False)[0]
+            source.set_child_property("text", "pigs fly!")
+            self.assertEqual(source.get_child_property("text")[1], "pigs fly!")
+
+        self.action_log.undo()
+        self.assertEqual(source.get_child_property("text")[1], "")
+        self.action_log.redo()
+        self.assertEqual(source.get_child_property("text")[1], "pigs fly!")
+
+    def testChangeEffectProperty(self):
         stacks = []
-        self.action_log.connect("commit", TestTimelineUndo.commitCb, stacks)
+        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
 
         clip1 = GES.TitleClip()
-        with self.action_log.started("add clip"):
-            self.layer.add_clip(clip1)
+        self.layer.add_clip(clip1)
+
+        effect1 = GES.Effect.new("agingtv")
+        with self.action_log.started("add effect"):
+            clip1.add(effect1)
 
         self.assertEqual(1, len(stacks))
         stack = stacks[0]
-        self.assertEqual(2, len(stack.done_actions), stack.done_actions)
-        self.assertTrue(isinstance(stack.done_actions[0], ClipAdded))
-        self.assertTrue(isinstance(stack.done_actions[1], AssetAddedAction))
-        self.assertTrue(clip1 in self.getTimelineClips())
+        self.assertEqual(1, len(stack.done_actions), stack.done_actions)
+        action = stack.done_actions[0]
+        self.assertTrue(isinstance(action, EffectAddedAction))
+
+        self.assertTrue(effect1 in clip1.get_children(True))
+        self.assertEqual(1, len([effect for effect in
+                                 clip1.get_children(True)
+                                 if isinstance(effect, GES.Effect)]))
+
+        with self.action_log.started("change child property"):
+            effect1.set_child_property("scratch-lines", 0)
 
+        self.assertEqual(effect1.get_child_property("scratch-lines")[1], 0)
         self.action_log.undo()
-        self.assertFalse(clip1 in self.getTimelineClips())
+        self.assertEqual(effect1.get_child_property("scratch-lines")[1], 7)
+        self.action_log.redo()
+        self.assertEqual(effect1.get_child_property("scratch-lines")[1], 0)
+        self.action_log.undo()
+        self.assertTrue(effect1 in clip1.get_children(True))
+        self.action_log.undo()
+        self.assertFalse(effect1 in clip1.get_children(True))
+
 
+class TestGObjectObserver(BaseTestUndoTimeline):
+
+    def testClipPropertyChange(self):
+        stacks = []
+        self.action_log.connect("commit", BaseTestUndoTimeline.commit_cb, stacks)
+
+        # We are not dropping clips here...
+        self.app.gui.timeline_ui.timeline.dropping_clips = False
+
+        clip1 = GES.TitleClip()
+        clip1.set_start(5 * Gst.SECOND)
+        clip1.set_duration(20 * Gst.SECOND)
+        self.layer.add_clip(clip1)
+        with self.action_log.started("modify clip"):
+            clip1.set_start(10 * Gst.SECOND)
+
+        self.assertEqual(1, len(stacks))
+        stack = stacks[0]
+        self.assertEqual(1, len(stack.done_actions))
+        action = stack.done_actions[0]
+        self.assertTrue(isinstance(action, PropertyChangedAction))
+        self.assertEqual(10 * Gst.SECOND, clip1.get_start())
+
+        self.action_log.undo()
+        self.assertEqual(5 * Gst.SECOND, clip1.get_start())
         self.action_log.redo()
-        self.assertTrue(clip1 in self.getTimelineClips())
+        self.assertEqual(10 * Gst.SECOND, clip1.get_start())
+
+        clip1.set_priority(10)
+        with self.action_log.started("priority change"):
+            clip1.set_priority(20)
+
+        self.assertEqual(20, clip1.get_priority())
+        self.action_log.undo()
+        self.assertEqual(10, clip1.get_priority())
+        self.action_log.redo()
+        self.assertEqual(20, clip1.get_priority())
+
+
+class TestDragDropUndo(BaseTestUndoTimeline):
 
     def test_clip_dragged_to_create_layer(self):
         layers = self.timeline.get_layers()
@@ -396,234 +593,3 @@ class TestTimelineUndo(TestCase):
         self.assertEqual(layers[0], self.layer)
         self.assertEqual(layers[0].get_clips(), [])
         self.assertEqual(len(layers[1].get_clips()), 1)
-
-    def testTrackElementPropertyChanged(self):
-        clip1 = GES.TitleClip()
-        self.layer.add_clip(clip1)
-
-        with self.action_log.started("Title text change"):
-            source = clip1.get_children(False)[0]
-            source.set_child_property("text", "pigs fly!")
-            self.assertEqual(source.get_child_property("text")[1], "pigs fly!")
-
-        self.action_log.undo()
-        self.assertEqual(source.get_child_property("text")[1], "")
-        self.action_log.redo()
-        self.assertEqual(source.get_child_property("text")[1], "pigs fly!")
-
-    def testRemoveClip(self):
-        stacks = []
-        self.action_log.connect("commit", TestTimelineUndo.commitCb, stacks)
-
-        clip1 = GES.TitleClip()
-        self.layer.add_clip(clip1)
-        with self.action_log.started("remove clip"):
-            self.layer.remove_clip(clip1)
-
-        self.assertEqual(1, len(stacks))
-        stack = stacks[0]
-        self.assertEqual(1, len(stack.done_actions))
-        action = stack.done_actions[0]
-        self.assertTrue(isinstance(action, ClipRemoved))
-        self.assertFalse(clip1 in self.getTimelineClips())
-
-        self.action_log.undo()
-        self.assertTrue(clip1 in self.getTimelineClips())
-
-        self.action_log.redo()
-        self.assertFalse(clip1 in self.getTimelineClips())
-
-    def testAddEffectToClip(self):
-        stacks = []
-        self.action_log.connect("commit", TestTimelineUndo.commitCb, stacks)
-
-        clip1 = GES.TitleClip()
-        self.layer.add_clip(clip1)
-
-        effect1 = GES.Effect.new("agingtv")
-        with self.action_log.started("add effect"):
-            clip1.add(effect1)
-
-        self.assertEqual(1, len(stacks))
-        stack = stacks[0]
-        self.assertEqual(1, len(stack.done_actions), stack.done_actions)
-        action = stack.done_actions[0]
-        self.assertTrue(isinstance(action, EffectAddedAction))
-
-        self.assertTrue(effect1 in clip1.get_children(True))
-        self.assertEqual(1, len([effect for effect in
-                                 clip1.get_children(True)
-                                 if isinstance(effect, GES.Effect)]))
-
-        self.action_log.undo()
-        self.assertFalse(effect1 in clip1.get_children(True))
-
-        self.action_log.redo()
-        self.assertEqual(1, len([effect for effect in
-                                 clip1.get_children(True)
-                                 if isinstance(effect, GES.Effect)]))
-
-    def testRemoveEffectFromClip(self):
-        stacks = []
-        self.action_log.connect("commit", TestTimelineUndo.commitCb, stacks)
-
-        clip1 = GES.TitleClip()
-        self.layer.add_clip(clip1)
-
-        effect1 = GES.Effect.new("agingtv")
-        with self.action_log.started("add effect"):
-            clip1.add(effect1)
-
-        self.assertEqual(1, len(stacks))
-        stack = stacks[0]
-        self.assertEqual(1, len(stack.done_actions), stack.done_actions)
-        action = stack.done_actions[0]
-        self.assertTrue(isinstance(action, EffectAddedAction))
-
-        self.assertTrue(effect1 in clip1.get_children(True))
-        self.assertEqual(1, len([effect for effect in
-                                 clip1.get_children(True)
-                                 if isinstance(effect, GES.Effect)]))
-
-        with self.action_log.started("remove effect"):
-            clip1.remove(effect1)
-
-        self.assertEqual(0, len([effect for effect in
-                                 clip1.get_children(True)
-                                 if isinstance(effect, GES.Effect)]))
-
-        self.action_log.undo()
-        self.assertEqual(1, len([effect for effect in
-                                 clip1.get_children(True)
-                                 if isinstance(effect, GES.Effect)]))
-
-        self.action_log.redo()
-        self.assertEqual(0, len([effect for effect in
-                                 clip1.get_children(True)
-                                 if isinstance(effect, GES.Effect)]))
-
-    def testChangeEffectProperty(self):
-        stacks = []
-        self.action_log.connect("commit", TestTimelineUndo.commitCb, stacks)
-
-        clip1 = GES.TitleClip()
-        self.layer.add_clip(clip1)
-
-        effect1 = GES.Effect.new("agingtv")
-        with self.action_log.started("add effect"):
-            clip1.add(effect1)
-
-        self.assertEqual(1, len(stacks))
-        stack = stacks[0]
-        self.assertEqual(1, len(stack.done_actions), stack.done_actions)
-        action = stack.done_actions[0]
-        self.assertTrue(isinstance(action, EffectAddedAction))
-
-        self.assertTrue(effect1 in clip1.get_children(True))
-        self.assertEqual(1, len([effect for effect in
-                                 clip1.get_children(True)
-                                 if isinstance(effect, GES.Effect)]))
-
-        with self.action_log.started("change child property"):
-            effect1.set_child_property("scratch-lines", 0)
-
-        self.assertEqual(effect1.get_child_property("scratch-lines")[1], 0)
-        self.action_log.undo()
-        self.assertEqual(effect1.get_child_property("scratch-lines")[1], 7)
-        self.action_log.redo()
-        self.assertEqual(effect1.get_child_property("scratch-lines")[1], 0)
-        self.action_log.undo()
-        self.assertTrue(effect1 in clip1.get_children(True))
-        self.action_log.undo()
-        self.assertFalse(effect1 in clip1.get_children(True))
-
-    def testClipPropertyChange(self):
-        stacks = []
-        self.action_log.connect("commit", TestTimelineUndo.commitCb, stacks)
-
-        # We are not dropping clips here...
-        self.app.gui.timeline_ui.timeline.dropping_clips = False
-
-        clip1 = GES.TitleClip()
-        self.layer.add_clip(clip1)
-        clip1.set_start(5 * Gst.SECOND)
-        clip1.set_duration(20 * Gst.SECOND)
-        self.layer.add_clip(clip1)
-        with self.action_log.started("modify clip"):
-            clip1.set_start(10 * Gst.SECOND)
-
-        self.assertEqual(1, len(stacks))
-        stack = stacks[0]
-        self.assertEqual(1, len(stack.done_actions))
-        action = stack.done_actions[0]
-        self.assertTrue(isinstance(action, PropertyChangedAction))
-        self.assertEqual(10 * Gst.SECOND, clip1.get_start())
-
-        self.action_log.undo()
-        self.assertEqual(5 * Gst.SECOND, clip1.get_start())
-        self.action_log.redo()
-        self.assertEqual(10 * Gst.SECOND, clip1.get_start())
-
-        clip1.set_priority(10)
-        with self.action_log.started("priority change"):
-            clip1.set_priority(20)
-
-        self.assertEqual(20, clip1.get_priority())
-        self.action_log.undo()
-        self.assertEqual(10, clip1.get_priority())
-        self.action_log.redo()
-        self.assertEqual(20, clip1.get_priority())
-
-    def testUngroup(self):
-        uri = common.get_sample_uri("tears_of_steel.webm")
-        asset = GES.UriClipAsset.request_sync(uri)
-        clip1 = asset.extract()
-        self.layer.add_clip(clip1)
-
-        clip1.set_start(5 * Gst.SECOND)
-        clip1.set_duration(0.5 * Gst.SECOND)
-        timeline_clips = list(self.getTimelineClips())
-        self.assertEqual(1, len(timeline_clips), timeline_clips)
-        self.assertEqual(5 * Gst.SECOND, timeline_clips[0].get_start())
-        self.assertEqual(0.5 * Gst.SECOND, timeline_clips[0].get_duration())
-
-        with self.action_log.started("ungroup"):
-            ungrouped = GES.Container.ungroup(clip1, False)
-            self.assertEqual(2, len(ungrouped), ungrouped)
-        timeline_clips = list(self.getTimelineClips())
-        self.assertEqual(2, len(timeline_clips), timeline_clips)
-        self.assertEqual(5 * Gst.SECOND, timeline_clips[0].get_start())
-        self.assertEqual(0.5 * Gst.SECOND, timeline_clips[0].get_duration())
-        self.assertEqual(5 * Gst.SECOND, timeline_clips[1].get_start())
-        self.assertEqual(0.5 * Gst.SECOND, timeline_clips[1].get_duration())
-
-        self.action_log.undo()
-        timeline_clips = list(self.getTimelineClips())
-        self.assertEqual(1, len(timeline_clips))
-        self.assertEqual(5 * Gst.SECOND, timeline_clips[0].get_start())
-        self.assertEqual(0.5 * Gst.SECOND, timeline_clips[0].get_duration())
-
-    def testSplitClip(self):
-        clip = GES.TitleClip()
-        clip.set_start(0 * Gst.SECOND)
-        clip.set_duration(20 * Gst.SECOND)
-
-        self.layer.add_clip(clip)
-
-        with self.action_log.started("split clip"):
-            clip1 = clip.split(10 * Gst.SECOND)
-            self.assertEqual(2, len(self.layer.get_clips()))
-
-        with self.action_log.started("split clip"):
-            clip2 = clip1.split(15 * Gst.SECOND)
-            self.assertEqual(3, len(self.layer.get_clips()))
-
-        self.action_log.undo()
-        self.assertEqual(2, len(self.layer.get_clips()))
-        self.action_log.undo()
-        self.assertEqual(1, len(self.layer.get_clips()))
-
-        self.action_log.redo()
-        self.assertEqual(2, len(self.layer.get_clips()))
-        self.action_log.redo()
-        self.assertEqual(3, len(self.layer.get_clips()))


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