[pitivi] elements: Fix keyframe curve clickable when not visible



commit d216ac76e7eca51acd306370f17daecf7d753033
Author: Alexandru Băluț <alexandru balut gmail com>
Date:   Tue Aug 9 15:38:52 2016 +0200

    elements: Fix keyframe curve clickable when not visible
    
    The keyframe curve widgets are now removed from the clip container
    instead of just hiding them.
    
    An alternative would have been to check in each matplotlib signal
    handler (connected with mpl_connect) whether the keyframe curve widget
    is visible, due to the fact that these signals are triggered even when
    the widget is not visible. The implemented fix seems more
    straightforward though.
    
    Fixes https://phabricator.freedesktop.org/T7514
    
    Reviewed-by: Thibault Saunier <tsaunier gnome org>
    Differential Revision: https://phabricator.freedesktop.org/D1269

 pitivi/timeline/elements.py |   48 +++++++++++++-----------------------------
 pitivi/utils/timeline.py    |   38 ++++++++++++++++++++-------------
 tests/common.py             |    3 +-
 3 files changed, 39 insertions(+), 50 deletions(-)
---
diff --git a/pitivi/timeline/elements.py b/pitivi/timeline/elements.py
index 5a87683..d23d664 100644
--- a/pitivi/timeline/elements.py
+++ b/pitivi/timeline/elements.py
@@ -288,9 +288,6 @@ class KeyframeCurve(FigureCanvas, Loggable):
             self.handling_motion = True
 
     def __mplMotionEventCb(self, event):
-        if not self.props.visible:
-            return
-
         if event.ydata is not None and event.xdata is not None:
             # The mouse event is in the figure boundaries.
             if self.__offset is not None:
@@ -515,9 +512,9 @@ class TimelineElement(Gtk.Layout, Zoomable, Loggable):
                                     self.__keyframePlotChangedCb)
         self.keyframe_curve.connect("enter", self.__curveEnterCb)
         self.keyframe_curve.connect("leave", self.__curveLeaveCb)
-        self.add(self.keyframe_curve)
         self.keyframe_curve.set_size_request(self.__width, self.__height)
-        self.keyframe_curve.props.visible = bool(self._ges_elem.selected)
+        self.keyframe_curve.show()
+        self.__update_keyframe_curve_visibility()
         self.queue_draw()
 
     def __createControlBinding(self, element):
@@ -541,47 +538,32 @@ class TimelineElement(Gtk.Layout, Zoomable, Loggable):
         if binding.props.name == self.__controlledProperty.name:
             self.__createKeyframeCurve(binding)
 
-    def __showKeyframes(self):
-        if self.timeline.app.project_manager.current_project.pipeline.getState() == Gst.State.PLAYING:
-            return False
-
-        if not self.keyframe_curve:
-            return False
-
-        # We do not show keyframes while a clip is being moved on the timeline
-        if self.timeline.draggingElement and not self.keyframe_curve.handling_motion:
-            return False
-
-        # We do not show keyframes when there are several clips selected
-        if len(self.timeline.selection) > 1:
-            return False
-
-        return self._ges_elem.selected
-
     def do_draw(self, cr):
         self.propagate_draw(self.__background, cr)
 
         if self.__previewer:
             self.propagate_draw(self.__previewer, cr)
 
-        if self.__showKeyframes():
-            self.propagate_draw(self.keyframe_curve, cr)
-
-    def do_show_all(self):
-        for child in self.get_children():
-            if bool(self._ges_elem.selected) or child != self.keyframe_curve:
-                child.show_all()
-
-        self.show()
+        if self.keyframe_curve and self.keyframe_curve.is_drawable():
+            project = self.timeline.app.project_manager.current_project
+            if project.pipeline.getState() != Gst.State.PLAYING:
+                self.propagate_draw(self.keyframe_curve, cr)
 
     # Callbacks
-    def __selectedChangedCb(self, unused_ges_elem, selected):
+    def __selectedChangedCb(self, unused_selected, selected):
         if self.keyframe_curve:
-            self.keyframe_curve.props.visible = selected
+            self.__update_keyframe_curve_visibility()
 
         if self.__previewer:
             self.__previewer.setSelected(selected)
 
+    def __update_keyframe_curve_visibility(self):
+        """Updates the keyframes widget visibility by adding or removing it."""
+        if self._ges_elem.selected and len(self.timeline.selection) == 1:
+            self.add(self.keyframe_curve)
+        else:
+            self.remove(self.keyframe_curve)
+
     def __keyframePlotChangedCb(self, unused_curve):
         self.queue_draw()
 
diff --git a/pitivi/utils/timeline.py b/pitivi/utils/timeline.py
index 9ab7c78..e400ec9 100644
--- a/pitivi/utils/timeline.py
+++ b/pitivi/utils/timeline.py
@@ -22,8 +22,9 @@ from gi.repository import GObject
 from gi.repository import Gst
 from gi.repository import Gtk
 
-from pitivi.utils import ui
 from pitivi.utils.loggable import Loggable
+from pitivi.utils.ui import set_children_state_recurse
+from pitivi.utils.ui import unset_children_state_recurse
 
 
 # Selection modes
@@ -120,24 +121,31 @@ class Selection(GObject.Object, Loggable):
             return
         self.selected = selection
 
-        for obj in old_selection - self.selected:
-            obj.selected.selected = False
+        for obj, selected in self.__get_selection_changes(old_selection):
+            obj.selected.selected = selected
             if obj.ui:
-                ui.unset_children_state_recurse(obj.ui, Gtk.StateFlags.SELECTED)
-            for element in obj.get_children(False):
-                if not isinstance(element, GES.BaseEffect) and not isinstance(element, GES.TextOverlay):
-                    element.selected.selected = False
-
-        for obj in self.selected - old_selection:
-            obj.selected.selected = True
-            if not hasattr(obj, "ui") or not obj.ui:
-                continue
-            ui.set_children_state_recurse(obj.ui, Gtk.StateFlags.SELECTED)
+                if selected:
+                    set_children_state_recurse(obj.ui, Gtk.StateFlags.SELECTED)
+                else:
+                    unset_children_state_recurse(obj.ui, Gtk.StateFlags.SELECTED)
             for element in obj.get_children(False):
-                if not isinstance(element, GES.BaseEffect) and not isinstance(element, GES.TextOverlay):
-                    element.selected.selected = True
+                if isinstance(obj, GES.BaseEffect) or\
+                        isinstance(obj, GES.TextOverlay):
+                    continue
+                element.selected.selected = selected
+
         self.emit("selection-changed")
 
+    def __get_selection_changes(self, old_selection):
+        for obj in old_selection - self.selected:
+            yield obj, False
+
+        # Announce all selected objects that they are selected, even if
+        # they were already selected. This allows them to update based on
+        # the current selection.
+        for obj in self.selected:
+            yield obj, True
+
     def select(self, objs):
         self.setSelection(objs, SELECT)
 
diff --git a/tests/common.py b/tests/common.py
index 167b36a..d2b6b02 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -62,7 +62,6 @@ def __create_settings(proxyingStrategy=ProxyingStrategy.NOTHING,
 
 
 def create_pitivi_mock(**settings):
-
     app = mock.MagicMock()
 
     app.write_action = mock.MagicMock(spec=Pitivi.write_action)
@@ -248,5 +247,5 @@ def clean_proxy_samples():
 def create_test_clip(clip_type):
     clip = clip_type()
     clip.selected = Selected()
-
+    clip.ui = None
     return clip


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