[pitivi] timeline: Allow disabling seek when left-clicking



commit 10b4b91cb23d43f18f1ce9078fdba423a5f16527
Author: Alexandru Băluț <alexandru balut gmail com>
Date:   Wed Oct 21 08:23:10 2015 +0200

    timeline: Allow disabling seek when left-clicking
    
    Currently the user can select, edit and seek with the left mouse button.
    The behavior of the right mouse button has not been not defined yet.
    It does some stuff similarly with the LMB and other times it does nothing.
    
    With this change, the RMB can be used only for seeking. Now it's also possible
    to scrub with the RMB directly on the timeline. Previously this was possible
    only on the ruler (with LMB or RMB).
    
    Now it's possible to disable seeking when the LMB is clicked. There is a new
    "Left click also seeks" preference which is enabled by default because
    this is the old behavior.
    
    Fixes https://phabricator.freedesktop.org/T3158
    
    Differential Revision: https://phabricator.freedesktop.org/D513
    Reviewed-by: Thibault Saunier <tsaunier gnome org>

 pitivi/timeline/elements.py |   27 +++++++++++-----
 pitivi/timeline/timeline.py |   71 +++++++++++++++++++++++++++----------------
 2 files changed, 64 insertions(+), 34 deletions(-)
---
diff --git a/pitivi/timeline/elements.py b/pitivi/timeline/elements.py
index e6aa4c0..235cdee 100644
--- a/pitivi/timeline/elements.py
+++ b/pitivi/timeline/elements.py
@@ -592,11 +592,6 @@ class TrimHandle(Gtk.EventBox, Loggable):
         else:
             self.props.halign = Gtk.Align.START
 
-        self.connect("notify::window", self._windowSetCb)
-
-    def _windowSetCb(self, window, pspec):
-        self.props.window.set_cursor(CURSORS[self.edge])
-
     def do_draw(self, cr):
         Gtk.EventBox.do_draw(self, cr)
         if TrimHandle.PIXBUF is None:
@@ -606,9 +601,13 @@ class TrimHandle(Gtk.EventBox, Loggable):
 
     def enlarge(self):
         self.props.width_request = TrimHandle.SELECTED_WIDTH
+        if self.props.window:
+            self.props.window.set_cursor(CURSORS[self.edge])
 
     def shrink(self):
         self.props.width_request = TrimHandle.DEFAULT_WIDTH
+        if self.props.window:
+            self.props.window.set_cursor(NORMAL_CURSOR)
 
 
 class Clip(Gtk.EventBox, timelineUtils.Zoomable, Loggable):
@@ -754,6 +753,10 @@ class Clip(Gtk.EventBox, timelineUtils.Zoomable, Loggable):
         self.handles.append(self.leftHandle)
         self.handles.append(self.rightHandle)
 
+    def shrinkTrimHandles(self):
+        for handle in self.handles:
+            handle.shrink()
+
     def sendFakeEvent(self, event, event_widget):
         if event.type == Gdk.EventType.BUTTON_RELEASE:
             self.__buttonReleaseEventCb(event_widget, event)
@@ -764,13 +767,18 @@ class Clip(Gtk.EventBox, timelineUtils.Zoomable, Loggable):
         self.updatePosition()
         Gtk.EventBox.do_draw(self, cr)
 
-    def __buttonReleaseEventCb(self, unused_action, unused_actor):
+    def __buttonReleaseEventCb(self, unused_widget, event):
         if self.timeline.got_dragged:
             # This means a drag & drop operation just finished and
             # this button-release-event should be ignored.
             self.timeline.got_dragged = False
             return False
 
+        res, button = event.get_button()
+        if res and button == 3:
+            # We are supposed to only seek.
+            return False
+
         # TODO : Let's be more specific, masks etc ..
         mode = timelineUtils.SELECT
         if self.timeline.parent._controlMask:
@@ -820,11 +828,14 @@ class Clip(Gtk.EventBox, timelineUtils.Zoomable, Loggable):
             handle.hide()
 
     def _eventCb(self, element, event):
-        if event.type == Gdk.EventType.ENTER_NOTIFY and event.mode == Gdk.CrossingMode.NORMAL:
+        if (event.type == Gdk.EventType.ENTER_NOTIFY and
+                event.mode == Gdk.CrossingMode.NORMAL and
+                not self.timeline._scrubbing):
             ui.set_children_state_recurse(self, Gtk.StateFlags.PRELIGHT)
             for handle in self.handles:
                 handle.enlarge()
-        elif event.type == Gdk.EventType.LEAVE_NOTIFY and event.mode == Gdk.CrossingMode.NORMAL:
+        elif (event.type == Gdk.EventType.LEAVE_NOTIFY and
+                event.mode == Gdk.CrossingMode.NORMAL):
             ui.unset_children_state_recurse(self, Gtk.StateFlags.PRELIGHT)
             for handle in self.handles:
                 handle.shrink()
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 9cdcb57..02c2c64 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -76,6 +76,18 @@ PreferencesDialog.addNumericPreference('imageClipLength',
                                            "Default clip length (in milliseconds) of images when inserting 
on the timeline."),
                                        lower=1)
 
+GlobalSettings.addConfigOption('leftClickAlsoSeeks',
+                               section="user-interface",
+                               key="left-click-to-select",
+                               default=True,
+                               notify=True)
+
+PreferencesDialog.addTogglePreference('leftClickAlsoSeeks',
+                                      section=_("Behavior"),
+                                      label=_("Left click also seeks"),
+                                      description=_(
+                                          "Whether left-clicking also seeks besides selecting and editing 
clips."))
+
 """
 Convention throughout this file:
 Every GES element which name could be mistaken with a UI element
@@ -220,6 +232,17 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
         hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
         self.add(hbox)
 
+        # Stuff the layers representation in a Layout so we can have other
+        # widgets there, see below.
+        self.layout = Gtk.Layout()
+        self.__layers_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+        self.__layers_vbox.props.width_request = self.get_allocated_width()
+        self.__layers_vbox.props.height_request = self.get_allocated_height()
+        self.layout.put(self.__layers_vbox, 0, 0)
+        self.hadj = self.layout.get_hadjustment()
+        self.vadj = self.layout.get_vadjustment()
+        hbox.pack_end(self.layout, False, True, 0)
+
         # Stuff the layers controls in a Viewport so it can be scrolled.
         self.__layers_controls_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
         self.__layers_controls_vbox.props.hexpand = False
@@ -234,17 +257,6 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
             viewport_style.remove_class(css_class)
         hbox.pack_start(viewport, False, False, 0)
 
-        # Stuff the layers representation in a Layout so we can have other
-        # widgets there, see below.
-        self.layout = Gtk.Layout()
-        self.__layers_vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
-        self.__layers_vbox.props.width_request = self.get_allocated_width()
-        self.__layers_vbox.props.height_request = self.get_allocated_height()
-        self.layout.put(self.__layers_vbox, 0, 0)
-        self.hadj = self.layout.get_hadjustment()
-        self.vadj = self.layout.get_vadjustment()
-        hbox.pack_start(self.layout, False, True, 0)
-
         self.get_style_context().add_class("Timeline")
         self.props.expand = True
         self.get_accessible().set_name("timeline canvas")
@@ -266,6 +278,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
         self.__playhead = VerticalBar("PlayHead")
         self.layout.put(self.__playhead, self.nsToPixel(self.__last_position), 0)
         self.__disableCenterPlayhead = False
+        self._scrubbing = False
 
         self.__snap_position = 0
         self.__snap_bar = VerticalBar("SnapBar")
@@ -586,6 +599,13 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
                 else:
                     self.__marquee.setStartPosition(event)
 
+        self._scrubbing = res and button == 3
+        if self._scrubbing:
+            self._seek(event)
+            clip = self._getParentOfType(event_widget, Clip)
+            if clip:
+                clip.shrinkTrimHandles()
+
         return False
 
     def __buttonReleaseEventCb(self, unused_widget, event):
@@ -596,25 +616,14 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
             self.dragEnd()
         elif self.__moving_layer:
             self.__endMovingLayer()
-
             return False
-        elif button == 1:
+        elif res and button == 1:
             self._selectUnderMarquee()
 
-        event_widget = self.get_event_widget(event)
-        if event_widget and self._getParentOfType(event_widget, LayerControls):
-            # Never seek when the LayerControls box has been clicked
-
-            return False
+        self._scrubbing = False
 
-        if allow_seek:
-            event_widget = self.get_event_widget(event)
-            x, unusedy = event_widget.translate_coordinates(self, event.x, event.y)
-            x -= CONTROL_WIDTH
-            x += self.hadj.get_value()
-
-            position = self.pixelToNs(x)
-            self._project.seeker.seek(position)
+        if allow_seek and res and (button == 1 and self.app.settings.leftClickAlsoSeeks):
+            self._seek(event)
 
         self._snapEndedCb()
 
@@ -647,9 +656,19 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
                 self.moveLayer(self.__moving_layer, priority)
         elif self.__marquee.start_x:
             self.__marquee.move(event)
+        elif self._scrubbing:
+            self._seek(event)
 
         return False
 
+    def _seek(self, event):
+        event_widget = self.get_event_widget(event)
+        x, unused_y = event_widget.translate_coordinates(self, event.x, event.y)
+        x -= CONTROL_WIDTH
+        x += self.hadj.get_value()
+        position = max(0, self.pixelToNs(x))
+        self._project.seeker.seek(position)
+
     def _selectUnderMarquee(self):
         self.resetSelectionGroup()
         if self.__marquee.props.width_request > 0:


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