[pitivi] timeline: Disable ungroup/group when necessary



commit 0420e89108e91908a7ffe1b6c16bcc4101860b55
Author: Suhas Nayak <suhas2go gmail com>
Date:   Sun Feb 12 00:48:38 2017 +0530

    timeline: Disable ungroup/group when necessary
    
    ungroup button is now disabled when the current selection
    contains only one GES_TRACK_ELEMENT or when the elements are
    not in a group.
    
    group button is disabled if the current selection elements
    have the same toplevel parent.
    
    updateActions is now called in the beginning as well, which
    disables ungroup and group actions.
    
    Closes #1699

 pitivi/timeline/timeline.py     | 14 +++++++++++---
 pitivi/utils/timeline.py        | 18 +++++++++++++++++-
 tests/test_timeline_timeline.py | 31 +++++++++++++++++++++++++++++++
 tests/test_undo_timeline.py     |  4 +---
 tests/test_utils_timeline.py    | 18 ++++++++++++++++++
 5 files changed, 78 insertions(+), 7 deletions(-)
---
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 9b0d98d1..b953645f 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -1416,11 +1416,12 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
         self.timeline.setProject(self._project)
 
     def updateActions(self):
-        selection_non_empty = bool(self.timeline.selection)
+        selection = self.timeline.selection
+        selection_non_empty = bool(selection)
         self.delete_action.set_enabled(selection_non_empty)
         self.delete_and_shift_action.set_enabled(selection_non_empty)
-        self.group_action.set_enabled(selection_non_empty)
-        self.ungroup_action.set_enabled(selection_non_empty)
+        self.group_action.set_enabled(selection.can_group)
+        self.ungroup_action.set_enabled(selection.can_ungroup and not selection.can_group)
         self.copy_action.set_enabled(selection_non_empty)
         can_paste = bool(self.__copied_group)
         self.paste_action.set_enabled(can_paste)
@@ -1613,6 +1614,8 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
                                ["<Shift>Right"],
                                _("Seek forward one second"))
 
+        self.updateActions()
+
     def _scrollToPixel(self, x):
         hadj = self.timeline.hadj
         self.log("Scroll to: %s %s %s", x, hadj.props.lower, hadj.props.upper)
@@ -1731,6 +1734,11 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
             if new_group:
                 self.timeline.current_group.add(new_group)
 
+            # timeline.selection doesn't change during grouping,
+            # we need to manually update group actions.
+            self.timeline.selection.set_can_group_ungroup()
+            self.updateActions()
+
     def __copyClipsCb(self, unused_action, unused_parameter):
         if self.timeline.current_group:
             self.__copied_group = self.timeline.current_group.copy(True)
diff --git a/pitivi/utils/timeline.py b/pitivi/utils/timeline.py
index b5730bb8..91aedbfe 100644
--- a/pitivi/utils/timeline.py
+++ b/pitivi/utils/timeline.py
@@ -88,6 +88,8 @@ class Selection(GObject.Object, Loggable):
         GObject.Object.__init__(self)
         Loggable.__init__(self)
         self.selected = set()
+        self.can_group = False
+        self.can_ungroup = False
 
     def setSelection(self, objs, mode):
         """Updates the current selection.
@@ -133,9 +135,23 @@ class Selection(GObject.Object, Loggable):
                         isinstance(obj, GES.TextOverlay):
                     continue
                 element.selected.selected = selected
-
+        self.set_can_group_ungroup()
         self.emit("selection-changed")
 
+    def set_can_group_ungroup(self):
+        containers = set()
+        for obj in self.selected:
+            toplevel = obj.get_toplevel_parent()
+            if not toplevel.props.serialize:
+                for child in toplevel.get_children(False):
+                    containers.add(child)
+            else:
+                containers.add(toplevel)
+            if len(containers) > 1:
+                break
+        self.can_group = len(containers) > 1
+        self.can_ungroup = len(self.getSelectedTrackElements()) > 1
+
     def __get_selection_changes(self, old_selection):
         for obj in old_selection - self.selected:
             yield obj, False
diff --git a/tests/test_timeline_timeline.py b/tests/test_timeline_timeline.py
index f49eaeda..c262cc47 100644
--- a/tests/test_timeline_timeline.py
+++ b/tests/test_timeline_timeline.py
@@ -252,6 +252,37 @@ class TestLayers(BaseTestTimeline):
 
 class TestGrouping(BaseTestTimeline):
 
+    def __check_can_group_ungroup(self, timeline_container, can_group, can_ungroup):
+        self.assertEqual(can_group, timeline_container.group_action.props.enabled)
+        self.assertEqual(can_ungroup, timeline_container.ungroup_action.props.enabled)
+
+    def test_can_group_ungroup(self):
+        timeline_container = create_timeline_container()
+        timeline = timeline_container.timeline
+        self.__check_can_group_ungroup(timeline_container, False, False)
+        ges_clip, = self.addClipsSimple(timeline, 1)
+        self.toggle_clip_selection(ges_clip, expect_selected=True)
+        self.__check_can_group_ungroup(timeline_container, False, True)
+
+        timeline_container.ungroup_action.emit("activate", None)
+        self.__check_can_group_ungroup(timeline_container, False, False)
+
+        layer, = timeline.ges_timeline.get_layers()
+        ges_clip0, ges_clip1 = layer.get_clips()
+        self.toggle_clip_selection(ges_clip0, expect_selected=True)
+        self.__check_can_group_ungroup(timeline_container, False, False)
+
+        # Press <ctrl> so selecting in ADD mode
+        event = mock.Mock()
+        event.keyval = Gdk.KEY_Control_L
+        timeline_container.do_key_press_event(event)
+
+        self.toggle_clip_selection(ges_clip1, expect_selected=True)
+        self.__check_can_group_ungroup(timeline_container, True, False)
+
+        timeline_container.group_action.emit("activate", None)
+        self.__check_can_group_ungroup(timeline_container, False, True)
+
     def group_clips(self, timeline_container, clips):
         timeline = timeline_container.timeline
         timeline.app.settings.leftClickAlsoSeeks = False
diff --git a/tests/test_undo_timeline.py b/tests/test_undo_timeline.py
index 23e07eb8..4995fd60 100644
--- a/tests/test_undo_timeline.py
+++ b/tests/test_undo_timeline.py
@@ -189,9 +189,7 @@ class TestTimelineObserver(BaseTestUndoTimeline):
         self.assertEqual(len(clips), 1, clips)
         self.assertEqual(len(clips[0].get_children(False)), 2)
 
-        timeline.selection.select([clip])
-        timeline.resetSelectionGroup()
-        timeline.current_group.add(clip)
+        common.TestCase.toggle_clip_selection(self, clips[0], True)
         self.timeline_container.ungroup_action.activate(None)
         clips = list(self.getTimelineClips())
         self.assertEqual(len(clips), 2, clips)
diff --git a/tests/test_utils_timeline.py b/tests/test_utils_timeline.py
index bbc38a8b..88897d58 100644
--- a/tests/test_utils_timeline.py
+++ b/tests/test_utils_timeline.py
@@ -78,3 +78,21 @@ class TestSelection(common.TestCase):
         self.assertIsNone(selection.getSingleClip())
         self.assertIsNone(selection.getSingleClip(GES.UriClip))
         self.assertIsNone(selection.getSingleClip(GES.TitleClip))
+
+    def test_can_group_ungroup(self):
+        clip1 = common.create_test_clip(GES.UriClip)
+        clip2 = common.create_test_clip(GES.UriClip)
+        selection = Selection()
+        self.assertFalse(selection)
+
+        selection.setSelection([clip1], SELECT)
+        self.assertFalse(selection.can_ungroup)
+        self.assertFalse(selection.can_group)
+
+        selection.setSelection([clip2], SELECT_ADD)
+        self.assertTrue(selection.can_group)
+        self.assertFalse(selection.can_ungroup)
+
+        selection.setSelection([], SELECT)
+        self.assertFalse(selection.can_group)
+        self.assertFalse(selection.can_ungroup)


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