[pitivi] Keep TimelineObjects sorted by start time in the Timeline.
- From: Edward Hervey <edwardrv src gnome org>
- To: svn-commits-list gnome org
- Subject: [pitivi] Keep TimelineObjects sorted by start time in the Timeline.
- Date: Fri, 24 Jul 2009 09:18:28 +0000 (UTC)
commit ca085490494b2927d4457bc2f277c181ac5483ed
Author: Alessandro Decina <alessandro d gmail com>
Date: Sun Jul 19 20:41:53 2009 +0200
Keep TimelineObjects sorted by start time in the Timeline.
Do the same as for Track, so that we can implement fast enough
Timeline.getPreviousTimelineObject and Timeline.getNextTimelineObject.
pitivi/timeline/timeline.py | 41 +++++++++++++++-
tests/test_timeline.py | 110 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 148 insertions(+), 3 deletions(-)
---
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 4724e39..dedbb70 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -27,6 +27,8 @@ from pitivi.log.loggable import Loggable
from pitivi.utils import UNKNOWN_DURATION, closest_item, PropertyChangeTracker
from pitivi.timeline.track import SourceTrackObject, TrackError
from pitivi.stream import match_stream_groups_map
+from pitivi.utils import start_insort_right, infinity, getPreviousObject, \
+ getNextObject
# Selection modes
SELECT = 0
@@ -414,7 +416,7 @@ class TimelineObject(Signallable, Loggable):
# FIXME: cycle
obj.timeline_object = self
- self.track_objects.append(obj)
+ start_insort_right(self.track_objects, obj)
self.emit("track-object-added", obj)
@@ -1279,7 +1281,9 @@ class Timeline(Signallable, Loggable):
if not obj.track_objects:
raise TimelineError()
- self.timeline_objects.append(obj)
+ self._connectToTimelineObject(obj)
+
+ start_insort_right(self.timeline_objects, obj)
obj.timeline = self
self.edges.addTimelineObject(obj)
@@ -1304,6 +1308,8 @@ class Timeline(Signallable, Loggable):
if obj.link is not None:
obj.link.removeTimelineObject(obj)
+ self._disconnectFromTimelineObject(obj)
+
obj.timeline = None
self.edges.removeTimelineObject(obj)
@@ -1324,6 +1330,23 @@ class Timeline(Signallable, Loggable):
for obj in objs:
self.removeTimelineObject(obj, deep=True)
+ def _timelineObjectStartChangedCb(self, timeline_object, start):
+ self.timeline_objects.remove(timeline_object)
+ start_insort_right(self.timeline_objects, timeline_object)
+
+ def _timelineObjectDurationChangedCb(self, timeline_object, duration):
+ pass
+
+ def _connectToTimelineObject(self, timeline_object):
+ timeline_object.connect('start-changed',
+ self._timelineObjectStartChangedCb)
+ timeline_object.connect('duration-changed',
+ self._timelineObjectDurationChangedCb)
+
+ def _disconnectFromTimelineObject(self, timeline_object):
+ timeline_object.disconnect_by_function(self._timelineObjectStartChangedCb)
+ timeline_object.disconnect_by_function(self._timelineObjectDurationChangedCb)
+
# FIXME : shouldn't this be made more generic (i.e. not specific to source factories) ?
# FIXME : Maybe it should be up to the ObjectFactory to create the TimelineObject since
# it would know the exact type of TimelineObject to create with what properties (essential
@@ -1386,6 +1409,20 @@ class Timeline(Signallable, Loggable):
return output_stream_to_track_map
+ def getPreviousTimelineObject(self, obj, priority=-1):
+ prev = getPreviousObject(obj, self.timeline_objects, priority)
+ if prev is None:
+ raise TimelineError("no previous timeline object", obj)
+
+ return prev
+
+ def getNextTimelineObject(self, obj, priority=-1):
+ next = getNextObject(obj, self.timeline_objects, priority)
+ if next is None:
+ raise TimelineError("no next timeline object", obj)
+
+ return next
+
def setSelectionToObj(self, obj, mode):
"""
Update the timeline's selection with the given object and mode.
diff --git a/tests/test_timeline.py b/tests/test_timeline.py
index facc27c..186f1d8 100644
--- a/tests/test_timeline.py
+++ b/tests/test_timeline.py
@@ -2,7 +2,7 @@
#
# tests/test_timeline.py
#
-# Copyright (c) 2008, Alessandro Decina <alessandro decina collabora co uk>
+# Copyright (c) 2008,2009, Alessandro Decina <alessandro decina collabora co uk>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -346,6 +346,114 @@ class TestTimelineAddRemoveTimelineObjects(TestCase):
timeline.removeFactory(factory)
self.failUnlessEqual(len(timeline.timeline_objects), 0)
+class TestTimeline(TestCase):
+ def setUp(self):
+ self.factory = StubFactory()
+ self.stream = AudioStream(gst.Caps('audio/x-raw-int'))
+ self.factory.addOutputStream(self.stream)
+ self.track1 = Track(self.stream)
+ self.timeline = Timeline()
+ TestCase.setUp(self)
+
+ def tearDown(self):
+ del self.factory
+ del self.stream
+ del self.track1
+ del self.timeline
+
+ def makeTimelineObject(self):
+ track_object = SourceTrackObject(self.factory, self.stream)
+ self.track1.addTrackObject(track_object)
+ timeline_object = TimelineObject(self.factory)
+ timeline_object.addTrackObject(track_object)
+ self.timeline.addTimelineObject(timeline_object)
+
+ return timeline_object
+
+ def testGetPreviousTimelineObject(self):
+ timeline_object1 = self.makeTimelineObject()
+ timeline_object2 = self.makeTimelineObject()
+ timeline_object3 = self.makeTimelineObject()
+ timeline_object4 = self.makeTimelineObject()
+
+ timeline_object1.start = 1 * gst.SECOND
+ timeline_object1.duration = 5 * gst.SECOND
+ timeline_object1.priority = 1
+
+ timeline_object2.start = 8 * gst.SECOND
+ timeline_object2.duration = 5 * gst.SECOND
+ timeline_object2.priority = 1
+
+ timeline_object3.start = 6 * gst.SECOND
+ timeline_object3.duration = 5 * gst.SECOND
+ timeline_object3.priority = 2
+
+ timeline_object4.start = 7 * gst.SECOND
+ timeline_object4.duration = 5 * gst.SECOND
+ timeline_object4.priority = 3
+
+ timeline = self.timeline
+
+ # no previous track_objectect
+ self.failUnlessRaises(TimelineError,
+ timeline.getPreviousTimelineObject, timeline_object4)
+
+ # same priority
+ prev = timeline.getPreviousTimelineObject(timeline_object2)
+ self.failUnlessEqual(prev, timeline_object1)
+
+ # given priority
+ prev = timeline.getPreviousTimelineObject(timeline_object2, priority=2)
+ self.failUnlessEqual(prev, timeline_object3)
+
+ # any priority
+ prev = timeline.getPreviousTimelineObject(timeline_object2, priority=None)
+ self.failUnlessEqual(prev, timeline_object4)
+
+ timeline_object3.start = 8 * gst.SECOND
+ # same start
+ prev = timeline.getPreviousTimelineObject(timeline_object2, priority=None)
+ self.failUnlessEqual(prev, timeline_object3)
+
+ def testGetNextTrackObject(self):
+ timeline_object1 = self.makeTimelineObject()
+ timeline_object2 = self.makeTimelineObject()
+ timeline_object3 = self.makeTimelineObject()
+ timeline_object4 = self.makeTimelineObject()
+
+ timeline_object1.start = 1 * gst.SECOND
+ timeline_object1.duration = 5 * gst.SECOND
+ timeline_object1.priority = 1
+
+ timeline_object2.start = 8 * gst.SECOND
+ timeline_object2.duration = 5 * gst.SECOND
+ timeline_object2.priority = 1
+
+ timeline_object3.start = 6 * gst.SECOND
+ timeline_object3.duration = 5 * gst.SECOND
+ timeline_object3.priority = 2
+
+ timeline_object4.start = 7 * gst.SECOND
+ timeline_object4.duration = 5 * gst.SECOND
+ timeline_object4.priority = 3
+
+ timeline = self.timeline
+
+ # no next timeline_objectect
+ self.failUnlessRaises(TimelineError, timeline.getNextTimelineObject, timeline_object2)
+
+ # same priority
+ prev = timeline.getNextTimelineObject(timeline_object1)
+ self.failUnlessEqual(prev, timeline_object2)
+
+ # given priority
+ prev = timeline.getNextTimelineObject(timeline_object1, priority=2)
+ self.failUnlessEqual(prev, timeline_object3)
+
+ # any priority
+ prev = timeline.getNextTimelineObject(timeline_object3, priority=None)
+ self.failUnlessEqual(prev, timeline_object4)
+
class TestLink(TestCase):
def test(self):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]