[pitivi] timeline: Avoid creating new layer by mistake
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] timeline: Avoid creating new layer by mistake
- Date: Mon, 11 Feb 2019 04:18:23 +0000 (UTC)
commit 5f0898735095bc349a6b54460f16829ceb612b3d
Author: Yash Agrawal <yagrawal900 gmail com>
Date: Sun Jan 20 15:29:37 2019 +0530
timeline: Avoid creating new layer by mistake
Whenever the mouse cursor moves during a clip drag operation, we start a
one second timer which highlights the separator and enables
dropping-to-create-a-new-layer.
Fixes #2268
pitivi/timeline/timeline.py | 24 +++++++++++++--
tests/test_undo_timeline.py | 74 +++++++++++++++++++++++++++++----------------
2 files changed, 69 insertions(+), 29 deletions(-)
---
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 04f2ca20..5271d21f 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -65,6 +65,10 @@ from pitivi.utils.ui import URI_TARGET_ENTRY
from pitivi.utils.widgets import ZoomBox
+# Creates new layer if a clip is held at layers separator after this time interval
+SEPARATOR_ACCEPTING_DROP_INTERVAL_MS = 1000
+
+
GlobalSettings.addConfigOption('edgeSnapDeadband',
section="user-interface",
key="edge-snap-deadband",
@@ -340,6 +344,8 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
# Whether the user is dragging a layer.
self.__moving_layer = None
+ self._separator_accepting_drop = False
+ self._separator_accepting_drop_id = 0
self.__last_position = 0
self._scrubbing = False
self._scrolling = False
@@ -593,7 +599,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
event_widget = Gtk.get_event_widget(event)
if event.get_state() & (Gdk.ModifierType.CONTROL_MASK |
- Gdk.ModifierType.MOD1_MASK):
+ Gdk.ModifierType.MOD1_MASK):
# Zoom.
x, unused_y = event_widget.translate_coordinates(self.layout.layers_vbox, event.x, event.y)
# Figure out first where to scroll at the end.
@@ -1284,10 +1290,22 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
# When dragging clips from more than one layer, do not allow
# them to be dragged between layers to create a new layer.
self.__on_separators = []
- self._setSeparatorsPrelight(True)
+
+ self._separator_accepting_drop = False
+ if self._separator_accepting_drop_id:
+ GLib.source_remove(self._separator_accepting_drop_id)
+ self._separator_accepting_drop_id = 0
+ if self.__on_separators:
+ self._separator_accepting_drop_id = GLib.timeout_add(SEPARATOR_ACCEPTING_DROP_INTERVAL_MS,
+ self._separator_accepting_drop_timeout_cb)
self.editing_context.edit_to(position, self._on_layer)
+ def _separator_accepting_drop_timeout_cb(self):
+ self._separator_accepting_drop_id = 0
+ self._setSeparatorsPrelight(True)
+ self._separator_accepting_drop = True
+
def create_layer(self, priority):
"""Adds a new layer to the GES timeline."""
self.debug("Creating layer: priority = %s", priority)
@@ -1308,7 +1326,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
if self.editing_context:
self.__end_snap()
- if self.__on_separators and self.__got_dragged and not self.__clickedHandle:
+ if self._separator_accepting_drop and self.__on_separators and self.__got_dragged and not
self.__clickedHandle:
priority = self.separator_priority(self.__on_separators[1])
ges_layer = self.create_layer(priority)
position = self.editing_context.new_position
diff --git a/tests/test_undo_timeline.py b/tests/test_undo_timeline.py
index 7bca226e..99cdff38 100644
--- a/tests/test_undo_timeline.py
+++ b/tests/test_undo_timeline.py
@@ -21,6 +21,7 @@ from unittest import mock
from gi.repository import Gdk
from gi.repository import GES
+from gi.repository import GLib
from gi.repository import Gst
from gi.repository import GstController
from gi.repository import Gtk
@@ -985,7 +986,8 @@ class TestGObjectObserver(BaseTestUndoTimeline):
class TestDragDropUndo(BaseTestUndoTimeline):
- def test_clip_dragged_to_create_layer_below(self):
+ def clip_dragged_to_create_layer(self, below):
+ """Simulates dragging a clip on a separator, without dropping it."""
self.setup_timeline_container()
timeline_ui = self.timeline_container.timeline
layers = self.timeline.get_layers()
@@ -995,7 +997,7 @@ class TestDragDropUndo(BaseTestUndoTimeline):
self.layer.add_clip(clip)
# Drag a clip on a separator to create a layer.
- with mock.patch.object(Gtk, 'get_event_widget') as get_event_widget:
+ with mock.patch.object(Gtk, "get_event_widget") as get_event_widget:
get_event_widget.return_value = clip.ui
event = mock.Mock()
@@ -1009,10 +1011,36 @@ class TestDragDropUndo(BaseTestUndoTimeline):
event = mock.Mock()
event.get_state.return_value = Gdk.ModifierType.BUTTON1_MASK
event.x = 1
- event.y = LAYER_HEIGHT * 2
+ if below:
+ event.y = LAYER_HEIGHT * 2
+ else:
+ event.y = -1
event.get_button.return_value = True, 1
timeline_ui._motion_notify_event_cb(None, event)
+ return clip, event, timeline_ui
+
+ def test_clip_dragged_to_create_layer_below_denied(self):
+ """Checks clip dropped onto the separator below without hovering."""
+ clip, event, timeline_ui = self.clip_dragged_to_create_layer(True)
+
+ timeline_ui._button_release_event_cb(None, event)
+
+ layers = self.timeline.get_layers()
+ self.assertEqual(len(layers), 1)
+ self.assertEqual(layers[0], self.layer)
+ self.check_layers(layers)
+ self.assertEqual(layers[0].get_clips(), [clip])
+
+ stack, = self.action_log.undo_stacks
+ # Only the clip creation action should be on the stack.
+ self.assertEqual(len(stack.done_actions), 1, stack.done_actions)
+
+ def test_clip_dragged_to_create_layer_below(self):
+ """Checks clip dropped onto the separator below after hovering."""
+ clip, event, timeline_ui = self.clip_dragged_to_create_layer(True)
+
+ timeline_ui._separator_accepting_drop_timeout_cb()
timeline_ui._button_release_event_cb(None, event)
layers = self.timeline.get_layers()
@@ -1037,34 +1065,28 @@ class TestDragDropUndo(BaseTestUndoTimeline):
self.assertEqual(layers[0].get_clips(), [])
self.assertEqual(layers[1].get_clips(), [clip])
- def test_clip_dragged_to_create_layer_above(self):
- self.setup_timeline_container()
- timeline_ui = self.timeline_container.timeline
- layers = self.timeline.get_layers()
- self.assertEqual(len(layers), 1)
+ return clip, event, timeline_ui
- clip = GES.TitleClip()
- self.layer.add_clip(clip)
+ def test_clip_dragged_to_create_layer_above_denied(self):
+ """Checks clip dropped onto the separator above without hovering."""
+ clip, event, timeline_ui = self.clip_dragged_to_create_layer(False)
- # Drag a clip on a separator to create a layer.
- with mock.patch.object(Gtk, 'get_event_widget') as get_event_widget:
- get_event_widget.return_value = clip.ui
+ timeline_ui._button_release_event_cb(None, event)
- event = mock.Mock()
- event.x = 0
- event.get_button.return_value = True, 1
- timeline_ui._button_press_event_cb(None, event)
+ layers = self.timeline.get_layers()
+ self.assertEqual(len(layers), 1)
+ self.check_layers(layers)
+ self.assertEqual(layers[0].get_clips(), [clip])
- def translate_coordinates(widget, x, y):
- return x, y
- clip.ui.translate_coordinates = translate_coordinates
- event = mock.Mock()
- event.get_state.return_value = Gdk.ModifierType.BUTTON1_MASK
- event.x = 1
- event.y = -1
- event.get_button.return_value = True, 1
- timeline_ui._motion_notify_event_cb(None, event)
+ stack, = self.action_log.undo_stacks
+ # Only the clip creation action should be on the stack.
+ self.assertEqual(len(stack.done_actions), 1, stack.done_actions)
+
+ def test_clip_dragged_to_create_layer_above(self):
+ """Checks clip dropped onto the separator above after hovering."""
+ clip, event, timeline_ui = self.clip_dragged_to_create_layer(False)
+ timeline_ui._separator_accepting_drop_timeout_cb()
timeline_ui._button_release_event_cb(None, event)
layers = self.timeline.get_layers()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]