[pitivi] pitivi: Reimplement undo redo



commit 7216b12d891a9cbf36479ac05a8a8aff4fec26b1
Author: Thibault Saunier <tsaunier gnome org>
Date:   Wed Apr 2 03:44:40 2014 +0200

    pitivi: Reimplement undo redo
    
    Rebased, reviewed and fixed by Mathieu Duponchelle
    <mathieu duponchelle opencreed com>
    
    + Fix unit tests
    
    https://bugzilla.gnome.org/show_bug.cgi?id=709471

 pitivi/application.py    |    8 +++-
 pitivi/mainwindow.py     |    1 +
 pitivi/project.py        |   49 +++++++++++++++++-
 pitivi/undo/Makefile.am  |    3 +-
 pitivi/undo/effect.py    |   81 +++++++++---------------------
 pitivi/undo/timeline.py  |  123 ++++++++++++++++++++++------------------------
 pitivi/utils/timeline.py |   27 +---------
 tests/test_project.py    |   19 ++++++--
 8 files changed, 156 insertions(+), 155 deletions(-)
---
diff --git a/pitivi/application.py b/pitivi/application.py
index 3fdaa39..8f87d86 100644
--- a/pitivi/application.py
+++ b/pitivi/application.py
@@ -35,6 +35,7 @@ from pitivi.utils.threads import ThreadMaster
 from pitivi.mainwindow import PitiviMainWindow
 from pitivi.project import ProjectManager, ProjectLogObserver
 from pitivi.undo.undo import UndoableActionLog, DebugActionLogObserver
+from pitivi.undo.timeline import TimelineLogObserver
 from pitivi.dialogs.startupwizard import StartUpWizard
 
 from pitivi.utils.misc import quote_uri
@@ -104,6 +105,7 @@ class Pitivi(Gtk.Application, Loggable):
         self.action_log.connect("cleaned", self._actionLogCleaned)
         self.debug_action_log_observer = DebugActionLogObserver()
         self.debug_action_log_observer.startObserving(self.action_log)
+        self.timeline_log_observer = TimelineLogObserver(self.action_log)
         self.project_log_observer = ProjectLogObserver(self.action_log)
 
         self.project_manager.connect("new-project-loaded", self._newProjectLoaded)
@@ -182,10 +184,12 @@ class Pitivi(Gtk.Application, Loggable):
 
     def _newProjectLoaded(self, unused_project_manager, project, unused_fully_loaded):
         self.action_log.clean()
+        self.timeline_log_observer.startObserving(project.timeline)
         self.project_log_observer.startObserving(project)
 
     def _projectClosed(self, unused_project_manager, project):
         self.project_log_observer.stopObserving(project)
+        self.timeline_log_observer.stopObserving(project.timeline)
 
     def _checkVersion(self):
         """
@@ -273,4 +277,6 @@ class Pitivi(Gtk.Application, Loggable):
 
         dirty = action_log.dirty()
         self.project_manager.current_project.setModificationState(dirty)
-        self.gui.showProjectStatus()
+        # In the tests we do not want to create any gui
+        if self.gui is not None:
+            self.gui.showProjectStatus()
diff --git a/pitivi/mainwindow.py b/pitivi/mainwindow.py
index 1e2bdde..f5081da 100644
--- a/pitivi/mainwindow.py
+++ b/pitivi/mainwindow.py
@@ -980,6 +980,7 @@ class PitiviMainWindow(Gtk.ApplicationWindow, Loggable):
         self.app.project_manager.current_project.connect("rendering-settings-changed", 
self._renderingSettingsChangedCb)
 
         self.viewer.setPipeline(self.app.project_manager.current_project.pipeline)
+        self.app.timeline_log_observer.setPipeline(self.app.project_manager.current_project.pipeline)
         self._renderingSettingsChangedCb(self.app.project_manager.current_project)
         if self.timeline_ui:
             self.clipconfig.project = self.app.project_manager.current_project
diff --git a/pitivi/project.py b/pitivi/project.py
index a5b6461..d9765e8 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -62,6 +62,30 @@ DEFAULT_AUDIO_ENCODER = "vorbisenc"
 #------------------ Backend classes ------------------------------------------#
 
 
+class AssetRemovedAction(UndoableAction):
+    def __init__(self, project, asset):
+        self.project = project
+        self.asset = asset
+
+    def undo(self):
+        self.project.add_asset(self.asset)
+
+    def do(self):
+        self.project.remove_asset(self.asset)
+
+
+class AssetAddedAction(UndoableAction):
+    def __init__(self, project, asset):
+        self.project = project
+        self.asset = asset
+
+    def undo(self):
+        self.project.remove_asset(self.asset)
+
+    def do(self):
+        self.project.add_asset(self.asset)
+
+
 class ProjectSettingsChanged(UndoableAction):
 
     def __init__(self, project, old, new):
@@ -85,10 +109,14 @@ class ProjectLogObserver(UndoableAction):
 
     def startObserving(self, project):
         project.connect("notify-meta", self._settingsChangedCb)
+        project.connect("asset-added", self._assetAddedCb)
+        project.connect("asset-removed", self._assetRemovedCb)
 
     def stopObserving(self, project):
         try:
             project.disconnect_by_func(self._settingsChangedCb)
+            project.disconnect_by_func(self._assetAddedCb)
+            project.disconnect_by_func(self._assetRemovedCb)
         except Exception:
             # This can happen when we interrupt the loading of a project,
             # such as in mainwindow's _projectManagerMissingUriCb
@@ -104,6 +132,14 @@ class ProjectLogObserver(UndoableAction):
         """
         pass
 
+    def _assetAddedCb(self, project, asset):
+        action = AssetAddedAction(project, asset)
+        self.log.push(action)
+
+    def _assetRemovedCb(self, project, asset):
+        action = AssetRemovedAction(project, asset)
+        self.log.push(action)
+
 
 class ProjectManager(Signallable, Loggable):
     """
@@ -164,7 +200,7 @@ class ProjectManager(Signallable, Loggable):
             self.debug('Loading project from backup: %s', uri)
 
         # Load the project:
-        self.current_project = Project(uri=uri)
+        self.current_project = Project(self.app, uri=uri)
         # For backup files and legacy formats, force the user to use "Save as"
         if use_backup or path.endswith(".xptv"):
             self.debug("Enforcing read-only mode")
@@ -423,7 +459,7 @@ class ProjectManager(Signallable, Loggable):
         if emission:
             self.emit("new-project-loading", None)
         # We don't have a URI here, None means we're loading a new project
-        project = Project(_("New Project"))
+        project = Project(self.app, _("New Project"))
 
         # setting default values for project metadata
         project.author = getpwuid(os.getuid()).pw_gecos.split(",")[0]
@@ -536,7 +572,7 @@ class Project(Loggable, GES.Project):
                                         GObject.TYPE_PYOBJECT,))
     }
 
-    def __init__(self, name="", uri=None, **unused_kwargs):
+    def __init__(self, app, name="", uri=None, **unused_kwargs):
         """
         @param name: the name of the project
         @param uri: the uri of the project
@@ -548,6 +584,8 @@ class Project(Loggable, GES.Project):
         self.timeline = None
         self.seeker = Seeker()
         self.uri = uri
+        self.loaded = False
+        self.app = app
 
         # Follow imports
         self._dirty = False
@@ -825,6 +863,9 @@ class Project(Loggable, GES.Project):
                 GObject.type_is_a(asset.get_extractable_type(), GES.UriClip)])
         if self.nb_remaining_file_to_import == 0:
             self.nb_imported_files = 0
+            # We do not take into account asset comming from project
+            if self.loaded is True:
+                self.app.action_log.commit()
             self._emitChange("done-importing")
 
     def do_asset_added(self, asset):
@@ -840,6 +881,7 @@ class Project(Loggable, GES.Project):
 
     def do_loaded(self, unused_timeline):
         """ vmethod, get called on "loaded" """
+        self.loaded = True
         self._ensureTracks()
         #self._ensureLayer()
 
@@ -914,6 +956,7 @@ class Project(Loggable, GES.Project):
         The uris will be analyzed before being added.
         """
         # Do not try to reload URIS that we already have loaded
+        self.app.action_log.begin("Adding assets")
         for uri in uris:
             self.create_asset(quote_uri(uri), GES.UriClip)
         self._calculateNbLoadingAssets()
diff --git a/pitivi/undo/Makefile.am b/pitivi/undo/Makefile.am
index 9be4f5d..cda9c06 100644
--- a/pitivi/undo/Makefile.am
+++ b/pitivi/undo/Makefile.am
@@ -4,8 +4,7 @@ undo_PYTHON =    \
        __init__.py  \
        undo.py      \
        timeline.py  \
-       effect.py    \
-       medialibrary.py
+       effect.py
 
 clean-local:
        rm -rf *.pyc *.pyo
diff --git a/pitivi/undo/effect.py b/pitivi/undo/effect.py
index 49e2f74..3e8322e 100644
--- a/pitivi/undo/effect.py
+++ b/pitivi/undo/effect.py
@@ -21,7 +21,7 @@
 # the Free Software Foundation; either version 3, or (at your option)
 # any later version.
 
-from gi.repository import GObject
+from gi.repository import GObject, GES
 
 from pitivi.undo.undo import UndoableAction
 from pitivi.effects import PROPS_TO_IGNORE
@@ -101,97 +101,66 @@ class EffectAdded(UndoableAction):
     # doing again. We have to keep all EffectPropertyChanged object that refers
     # to the Effect when undoing so we reset theirs gst_element when
     # doing it again. The way of doing it is the same with EffectRemoved
-    def __init__(self, clip, track_element, properties_watcher):
+    def __init__(self, clip, effect, properties_watcher):
         self.clip = clip
-        self.track_element = track_element
-        self.factory = track_element.factory
+        self.effect = effect
+        self.asset = effect.get_asset()
         self.effect_props = []
         self.gnl_obj_props = []
         self._properties_watcher = properties_watcher
         self._props_changed = []
 
     def do(self):
-        timeline = self.clip.timeline
-        clip_track_element = timeline.addEffectFactoryOnObject(self.factory,
-                                            clips=[self.clip])
-
-        self.track_element = clip_track_element[0][1]
-        element = self.track_element.getElement()
+        self.effect = self.clip.add_asset(self.asset)
         for prop_name, prop_value in self.effect_props:
-            element.set_property(prop_name, prop_value)
-        for prop_name, prop_value in self.gnl_obj_props:
-            self.track_element.gnl_object.set_property(prop_name, prop_value)
-        for prop_changed in self._props_changed:
-            prop_changed.gst_element = self.track_element.getElement()
+            self.effect.set_child_property(prop_name, prop_value)
+        self.clip.get_layer().get_timeline().commit()
         self._props_changed = []
         self._done()
 
     def undo(self):
-        element = self.track_element.getElement()
-        props = GObject.list_properties(element)
-        self.effect_props = [(prop.name, element.get_property(prop.name))
+        props = self.effect.list_children_properties()
+        self.effect_props = [(prop.name, self.effect.get_child_property(prop.name)[1])
                           for prop in props
                           if prop.flags & GObject.PARAM_WRITABLE
                           and prop.name not in PROPS_TO_IGNORE]
-        gnl_props = GObject.list_properties(self.track_element.gnl_object)
-        gnl_obj = self.track_element.gnl_object
-        self.gnl_obj_props = [(prop.name, gnl_obj.get_property(prop.name))
-                          for prop in gnl_props
-                          if prop.flags & GObject.PARAM_WRITABLE]
-
-        self.clip.removeTrackElement(self.track_element)
-        self.track_element.track.removeTrackElement(self.track_element)
+        self.clip.remove(self.effect)
         self._props_changed =\
-            self._properties_watcher.getPropChangedFromTrackObj(self.track_element)
-        del self.track_element
-        self.track_element = None
+            self._properties_watcher.getPropChangedFromTrackObj(self.effect)
+        del self.effect
+        self.effect = None
         self._undone()
 
 
 class EffectRemoved(UndoableAction):
-    def __init__(self, clip, track_element, properties_watcher):
-        self.track_element = track_element
+    def __init__(self, clip, effect, properties_watcher):
+        self.effect = effect
         self.clip = clip
-        self.factory = track_element.factory
+        self.asset = effect.get_asset()
         self.effect_props = []
         self.gnl_obj_props = []
         self._properties_watcher = properties_watcher
         self._props_changed = []
 
     def do(self):
-        element = self.track_element.getElement()
-        props = GObject.list_properties(element)
-        self.effect_props = [(prop.name, element.get_property(prop.name))
+        props = self.effect.list_children_properties()
+        self.effect_props = [(prop.name, self.effect.get_child_property(prop.name)[1])
                           for prop in props
                           if prop.flags & GObject.PARAM_WRITABLE
                           and prop.name not in PROPS_TO_IGNORE]
 
-        gnl_props = GObject.list_properties(self.track_element.gnl_object)
-        gnl_obj = self.track_element.gnl_object
-        self.gnl_obj_props = [(prop.name, gnl_obj.get_property(prop.name))
-                          for prop in gnl_props
-                          if prop.flags & GObject.PARAM_WRITABLE]
+        self.clip.remove(self.effect)
 
-        self.clip.removeTrackElement(self.track_element)
-        self.track_element.track.removeTrackElement(self.track_element)
         self._props_changed =\
-            self._properties_watcher.getPropChangedFromTrackObj(self.track_element)
-        del self.track_element
-        self.track_element = None
+            self._properties_watcher.getPropChangedFromTrackObj(self.effect)
+        del self.effect
+        self.effect = None
         self._done()
 
     def undo(self):
-        timeline = self.clip.timeline
-        clip_track_element = timeline.addEffectFactoryOnObject(self.factory,
-                                            clips=[self.clip])
-
-        self.track_element = clip_track_element[0][1]
-        element = self.track_element.getElement()
+        self.effect = self.clip.add_asset(self.asset)
         for prop_name, prop_value in self.effect_props:
-            element.set_property(prop_name, prop_value)
-        for prop_name, prop_value in self.gnl_obj_props:
-            self.track_element.gnl_object.set_property(prop_name, prop_value)
-        for prop_changed in self._props_changed:
-            prop_changed.gst_element = self.track_element.getElement()
+            self.effect.set_child_property(prop_name, prop_value)
+        self.clip.get_layer().get_timeline().commit()
         self._props_changed = []
         self._undone()
diff --git a/pitivi/undo/timeline.py b/pitivi/undo/timeline.py
index 4d39360..3149f6e 100644
--- a/pitivi/undo/timeline.py
+++ b/pitivi/undo/timeline.py
@@ -19,43 +19,32 @@
 # Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 # Boston, MA 02110-1301, USA.
 
+from gi.repository import GES
 from pitivi.utils.signal import Signallable
 from pitivi.undo.undo import PropertyChangeTracker, UndoableAction
 from pitivi.undo.effect import EffectAdded, EffectRemoved
-from pitivi.undo.effects import EffectGstElementPropertyChangeTracker
+from pitivi.undo.effect import EffectGstElementPropertyChangeTracker
 
 
 class ClipPropertyChangeTracker(PropertyChangeTracker):
     # no out-point
-    property_names = ["start", "duration", "in-point",
-            "media-duration", "priority", "selected"]
-
-    _disabled = False
+    property_names = ["start", "duration", "in-point", "priority"]
 
     def connectToObject(self, obj):
         PropertyChangeTracker.connectToObject(self, obj)
         self.timeline = obj.timeline
-        self.timeline.connect("disable-updates", self._timelineDisableUpdatesCb)
+        self.timeline.connect("commited", self._timelineCommitedCb)
 
     def disconnectFromObject(self, obj):
-        return
-        self.timeline.disconnect_by_func(self._timelineDisableUpdatesCb)
+        self.timeline.disconnect_by_func(self._timelineCommitedCb)
         PropertyChangeTracker.disconnectFromObject(self, obj)
 
-    def _timelineDisableUpdatesCb(self, timeline, disabled):
-        if self._disabled and not disabled:
-            self._disabled = disabled
-            properties = self._takeCurrentSnapshot(self.obj)
-            for property_name, property_value in properties.items():
-                old_value = self.properties[property_name]
-                if old_value != property_value:
-                    self._propertyChangedCb(self.obj, property_value, property_name)
-        else:
-            self._disabled = disabled
-
-    def _propertyChangedCb(self, clip, value, property_name):
-        if not self._disabled:
-            PropertyChangeTracker._propertyChangedCb(self, clip, value, property_name)
+    def _timelineCommitedCb(self, timeline):
+        properties = self._takeCurrentSnapshot(self.obj)
+        for property_name, property_value in properties.items():
+            old_value = self.properties[property_name]
+            if old_value != property_value:
+                self._propertyChangedCb(self.obj, property_value, property_name)
 
 
 class KeyframeChangeTracker(Signallable):
@@ -109,49 +98,41 @@ class ClipPropertyChanged(UndoableAction):
         self.new_value = new_value
 
     def do(self):
-        setattr(self.clip, self.property_name.replace("-", "_"), self.new_value)
+        self.clip.set_property(self.property_name.replace("-", "_"), self.new_value)
         self._done()
 
     def undo(self):
-        setattr(self.clip, self.property_name.replace("-", "_"), self.old_value)
+        self.clip.set_property(self.property_name.replace("-", "_"), self.old_value)
         self._undone()
 
 
 class ClipAdded(UndoableAction):
-    def __init__(self, timeline, clip):
-        self.timeline = timeline
+    def __init__(self, layer, clip):
+        self.layer = layer
         self.clip = clip
-        self.tracks = dict((track_element, track_element.get_track())
-                for track_element in clip.get_children(False))
 
     def do(self):
-        for track_element, track in self.tracks.items():
-            track.addTrackElement(track_element)
-
-        self.timeline.addClip(self.clip)
+        self.layer.add_clip(self.clip)
+        self.layer.get_timeline().commit()
         self._done()
 
     def undo(self):
-        self.timeline.removeClip(self.clip, deep=True)
+        self.layer.remove_clip(self.clip)
         self._undone()
 
 
 class ClipRemoved(UndoableAction):
-    def __init__(self, timeline, clip):
-        self.timeline = timeline
+    def __init__(self, layer, clip):
+        self.layer = layer
         self.clip = clip
-        self.tracks = dict((track_element, track_element.get_track())
-                for track_element in clip.get_children(False))
 
     def do(self):
-        self.timeline.removeClip(self.clip, deep=True)
+        self.layer.remove_clip(self.clip)
         self._done()
 
     def undo(self):
-        for track_element, track in self.tracks.items():
-            track.addTrackElement(track_element)
-
-        self.timeline.addClip(self.clip)
+        self.layer.add_clip(self.clip)
+        self.layer.get_timeline().commit()
         self._undone()
 
 
@@ -254,29 +235,39 @@ class TimelineLogObserver(object):
         for layer in timeline.get_layers():
             for clip in layer.get_clips():
                 self._connectToClip(clip)
-                for track_element in clip.track_elements:
+                for track_element in clip.get_children(True):
                     self._connectToTrackElement(track_element)
 
     def stopObserving(self, timeline):
         self._disconnectFromTimeline(timeline)
-        for clip in timeline.clips:
-            self._disconnectFromClip(clip)
-            for track_element in clip.track_elements:
-                self._disconnectFromTrackElement(track_element)
+        for layer in timeline.layers:
+            for clip in layer.get_clips():
+                self._disconnectFromClip(clip)
+                for track_element in clip.get_children(True):
+                    self._disconnectFromTrackElement(track_element)
 
     def _connectToTimeline(self, timeline):
         for layer in timeline.get_layers():
             layer.connect("clip-added", self._clipAddedCb)
             layer.connect("clip-removed", self._clipRemovedCb)
 
+        timeline.connect("layer-added", self._layerAddedCb)
+        timeline.connect("layer-removed", self._layerRemovedCb)
+
     def _disconnectFromTimeline(self, timeline):
-        timeline.disconnect_by_func(self._clipAddedCb)
-        timeline.disconnect_by_func(self._clipRemovedCb)
+        try:
+            timeline.disconnect_by_func(self._clipAddedCb)
+            timeline.disconnect_by_func(self._clipRemovedCb)
+        except TypeError:
+            # Was not connected to any layer yet
+            pass
 
     def _connectToClip(self, clip):
         tracker = ClipPropertyChangeTracker()
         tracker.connectToObject(clip)
         for property_name in tracker.property_names:
+            setattr(tracker, "last-%s" % property_name,
+                    clip.get_property(property_name))
             tracker.connect("notify::" + property_name,
                     self._clipPropertyChangedCb, property_name)
         self.clip_property_trackers[clip] = tracker
@@ -299,8 +290,9 @@ class TimelineLogObserver(object):
             self.effect_properties_tracker.addEffectElement(track_element.getElement())
 
     def _disconnectFromTrackElement(self, track_element):
-        for prop, interpolator in track_element.getInterpolators().values():
-            self._disconnectFromInterpolator(interpolator)
+        pass
+        #for prop, interpolator in track_element.getInterpolators().values():
+        #    self._disconnectFromInterpolator(interpolator)
 
     def _connectToInterpolator(self, interpolator):
         interpolator.connect("keyframe-added", self._interpolatorKeyframeAddedCb)
@@ -315,34 +307,29 @@ class TimelineLogObserver(object):
         tracker.disconnectFromObject(interpolator)
         tracker.disconnect_by_func(self._interpolatorKeyframeMovedCb)
 
-    def _clipAddedCb(self, timeline, clip):
+    def _clipAddedCb(self, layer, clip):
         self._connectToClip(clip)
-        action = self.ClipAddedAction(timeline, clip)
+        action = self.ClipAddedAction(layer, clip)
         self.log.push(action)
 
-    def _clipRemovedCb(self, timeline, clip):
+    def _clipRemovedCb(self, layer, clip):
         self._disconnectFromClip(clip)
-        action = self.ClipRemovedAction(timeline, clip)
+        action = self.ClipRemovedAction(layer, clip)
         self.log.push(action)
 
     def _clipPropertyChangedCb(self, tracker, clip,
             old_value, new_value, property_name):
-        action = self.timelinePropertyChangedAction(clip,
-                property_name, old_value, new_value)
+        new_value = clip.get_property(property_name)
+        action = self.timelinePropertyChangedAction(clip, property_name,
+                 getattr(tracker, "last-%s" % property_name), new_value)
+        setattr(tracker, "last-%s" % property_name, new_value)
         self.log.push(action)
 
     def _clipTrackElementAddedCb(self, clip, track_element):
         if isinstance(track_element, GES.BaseEffect):
             action = self.effectAddAction(clip, track_element,
                                           self.effect_properties_tracker)
-            # We use the action instead of the track element
-            # because the track_element changes when redoing
-            track_element.connect("active-changed",
-                                 self._trackElementActiveChangedCb, action)
             self.log.push(action)
-            element = track_element.getElement()
-            if element:
-                self.effect_properties_tracker.addEffectElement(element)
         else:
             self._connectToTrackElement(track_element)
 
@@ -375,3 +362,11 @@ class TimelineLogObserver(object):
         action = self.interpolatorKeyframeChangedAction(track_element,
                 keyframe, old_snapshot, new_snapshot)
         self.log.push(action)
+
+    def _layerAddedCb(self, timeline, layer):
+        layer.connect("clip-added", self._clipAddedCb)
+        layer.connect("clip-removed", self._clipRemovedCb)
+
+    def _layerRemovedCb(self, timeline, layer):
+        layer.disconnect_by_func(self._layerAddedCb)
+        layer.disconnect_by_func(self._layerRemovedCb)
diff --git a/pitivi/utils/timeline.py b/pitivi/utils/timeline.py
index 2f1bd33..3c7e1bb 100644
--- a/pitivi/utils/timeline.py
+++ b/pitivi/utils/timeline.py
@@ -44,23 +44,6 @@ class TimelineError(Exception):
     pass
 
 
-class ClipEdited(UndoableAction):
-    def __init__(self, focus, old_priority, new_priority, mode, edge, old_position, new_position):
-        self.focus = focus
-        self.old_priority = old_priority
-        self.old_position = old_position
-        self.new_priority = new_priority
-        self.new_position = new_position
-        self.mode = mode
-        self.edge = edge
-
-    def do(self):
-        self.focus.edit([], self.new_priority, self.mode, self.edge, int(self.new_position))
-
-    def undo(self):
-        self.focus.edit([], self.old_priority, self.mode, self.edge, int(self.old_position))
-
-
 class Selected(Signallable):
     """
     A simple class that let us emit a selected-changed signal
@@ -251,14 +234,8 @@ class EditingContext(Signallable):
         self.action_log.begin("move-clip")
 
     def finish(self):
-        """Clean up timeline for normal editing"""
-        if self.new_position is not None and self.new_priority is not None:
-            # The mouse cursor did move.
-            action = ClipEdited(self.focus, self.old_priority, self.new_priority, self.mode, self.edge,
-                                self.old_position, self.new_position)
-            self.action_log.push(action)
-            self.action_log.commit()
-            self.timeline.commit()
+        self.action_log.commit()
+        self.timeline.commit()
         self.emit("clip-trim-finished")
 
     def setMode(self, mode):
diff --git a/tests/test_project.py b/tests/test_project.py
index 6802941..8547e6f 100644
--- a/tests/test_project.py
+++ b/tests/test_project.py
@@ -27,10 +27,21 @@ from unittest import TestCase
 from gi.repository import GES
 from gi.repository import GLib
 
+from pitivi.application import Pitivi
 from pitivi.project import Project, ProjectManager
 from pitivi.utils.misc import uri_is_reachable
 
 
+def _createRealProject(name=None):
+    app = Pitivi()
+    app.emit("startup")
+    app.project_manager.newBlankProject()
+    if name:
+        app.project_manager.current_project.name = name
+
+    return app.project_manager.current_project
+
+
 class MockProject(object):
     settings = None
     format = None
@@ -311,7 +322,7 @@ class TestProjectLoading(TestCase):
             mainloop.quit()
 
         # Create a blank project and save it.
-        project = Project("noname")
+        project = _createRealProject(name="noname")
         result = [False]
         project.connect("loaded", loaded, self.mainloop, result)
 
@@ -326,7 +337,7 @@ class TestProjectLoading(TestCase):
         try:
             project.save(project.timeline, uri, None, overwrite=True)
 
-            project2 = Project(uri=uri)
+            project2 = _createRealProject()
             self.assertTrue(project2.createTimeline())
             result = [False]
             project2.connect("loaded", loaded, self.mainloop, result)
@@ -357,7 +368,7 @@ class TestProjectLoading(TestCase):
             mainloop.quit()
 
         # Create a blank project and save it.
-        project = Project("noname")
+        project = _createRealProject()
         result = [False, False, False]
         uris = ["file://%s/samples/tears_of_steel.webm" % os.path.dirname(os.path.abspath(__file__))]
         project.connect("loaded", loaded, self.mainloop, result, uris)
@@ -375,7 +386,7 @@ class TestExportSettings(TestCase):
     """Test the project.MultimediaSettings class."""
 
     def setUp(self):
-        self.project = Project()
+        self.project = _createRealProject()
 
     def testMasterAttributes(self):
         self._testMasterAttribute('muxer', dependant_attr='containersettings')


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