[pitivi] timeline: Allow seeking to previous/next cut



commit 8d1f76445f0851b4562c3d3833dd806f8e2e7fb8
Author: Ayush <ayush mittal9398 gmail com>
Date:   Thu Aug 1 00:11:58 2019 +0530

    timeline: Allow seeking to previous/next cut
    
    Fixes #2281

 pitivi/timeline/timeline.py     | 58 +++++++++++++++++++++++++++++++++++++++++
 tests/test_timeline_timeline.py | 24 +++++++++++++++++
 2 files changed, 82 insertions(+)
---
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 64b1f2b6..1c5d321d 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -1698,6 +1698,18 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
         self.app.shortcuts.add("timeline.add-layer", ["<Primary>n"],
                                _("Add layer"))
 
+        self.seek_forward_clip_action = Gio.SimpleAction.new("seek-forward-clip", None)
+        self.seek_forward_clip_action.connect("activate", self._seek_forward_clip_cb)
+        group.add_action(self.seek_forward_clip_action)
+        self.app.shortcuts.add("timeline.seek-forward-clip", ["<Primary>Right"],
+                               _("Seeks to the first clip edge after the playhead."))
+
+        self.seek_backward_clip_action = Gio.SimpleAction.new("seek-backward-clip", None)
+        self.seek_backward_clip_action.connect("activate", self._seek_backward_clip_cb)
+        group.add_action(self.seek_backward_clip_action)
+        self.app.shortcuts.add("timeline.seek-backward-clip", ["<Primary>Left"],
+                               _("Seeks to the first clip edge before the playhead."))
+
         if in_devel():
             self.gapless_action = Gio.SimpleAction.new("toggle-gapless-mode", None)
             self.gapless_action.connect("activate", self._gaplessmode_toggled_cb)
@@ -1915,6 +1927,52 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
             priority = len(self.ges_timeline.get_layers())
             self.timeline.create_layer(priority)
 
+    def first_clip_edge(self, before=None, after=None):
+        assert (after is not None) != (before is not None)
+
+        if after is not None:
+            start = after
+            end = self.ges_timeline.props.duration
+            edges = [end]
+        else:
+            start = 0
+            end = before
+            edges = [start]
+
+        if start >= end:
+            return None
+
+        for layer in self.ges_timeline.layers:
+            clips = layer.get_clips_in_interval(start, end)
+            for clip in clips:
+                if clip.start > start:
+                    edges.append(clip.start)
+                if clip.start + clip.duration < end:
+                    edges.append(clip.start + clip.duration)
+
+        if after is not None:
+            return min(edges)
+        else:
+            return max(edges)
+
+    def _seek_forward_clip_cb(self, unused_action, unused_parameter):
+        """Seeks to the first clip edge at the right of the playhead."""
+        position = self.first_clip_edge(after=self._project.pipeline.getPosition())
+        if position is None:
+            return
+
+        self._project.pipeline.simple_seek(position)
+        self.timeline.scrollToPlayhead(align=Gtk.Align.CENTER, when_not_in_view=True)
+
+    def _seek_backward_clip_cb(self, unused_action, unused_parameter):
+        """Seeks to the first clip edge at the left of the playhead."""
+        position = self.first_clip_edge(before=self._project.pipeline.getPosition())
+        if position is None:
+            return
+
+        self._project.pipeline.simple_seek(position)
+        self.timeline.scrollToPlayhead(align=Gtk.Align.CENTER, when_not_in_view=True)
+
     def _alignSelectedCb(self, unused_action, unused_parameter):
         if not self.ges_timeline:
             return
diff --git a/tests/test_timeline_timeline.py b/tests/test_timeline_timeline.py
index 3877c398..167d2c0b 100644
--- a/tests/test_timeline_timeline.py
+++ b/tests/test_timeline_timeline.py
@@ -798,3 +798,27 @@ class TestTimelineContainer(BaseTestTimeline):
 
         # Check the title clips are ignored.
         timeline_container.update_clips_asset(mock.Mock(), mock.Mock())
+
+
+class TestClipsEdges(BaseTestTimeline):
+
+    def test_clips_edges(self):
+        """Test function for function clips_edges."""
+        timeline_container = common.create_timeline_container()
+        timeline = timeline_container.timeline
+        clips = self.addClipsSimple(timeline, 5)
+        timeline.ges_timeline.layers[0].remove_clip(clips[0])
+        self.add_clip(timeline.ges_timeline.layers[0], 5, 0, 10)
+
+        self.assertEqual(timeline_container.first_clip_edge(after=0), 5)
+        self.assertEqual(timeline_container.first_clip_edge(after=9), 10)
+        self.assertEqual(timeline_container.first_clip_edge(after=10), 15)
+        self.assertEqual(timeline_container.first_clip_edge(after=48), 50)
+        self.assertEqual(timeline_container.first_clip_edge(after=49), 50)
+
+        self.assertEqual(timeline_container.first_clip_edge(before=0), None)
+        self.assertEqual(timeline_container.first_clip_edge(before=1), 0)
+        self.assertEqual(timeline_container.first_clip_edge(before=9), 5)
+        self.assertEqual(timeline_container.first_clip_edge(before=10), 5)
+        self.assertEqual(timeline_container.first_clip_edge(before=11), 10)
+        self.assertEqual(timeline_container.first_clip_edge(before=20), 15)


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