From f5cbf8be19d76590cd7d6bb98b8ed5d600eb4642 Mon Sep 17 00:00:00 2001 From: "Bradley M. Froehle" Date: Fri, 10 Aug 2012 09:34:55 -0700 Subject: [PATCH] Refactor drag and drop support to explicitly use drag and drop events. Removes event filter code which was previously used to ensure that text outside of the current cell could not be removed via drag and drop. --- IPython/frontend/qt/console/console_widget.py | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/IPython/frontend/qt/console/console_widget.py b/IPython/frontend/qt/console/console_widget.py index 1cfa695b8a8..b6b85c4260b 100644 --- a/IPython/frontend/qt/console/console_widget.py +++ b/IPython/frontend/qt/console/console_widget.py @@ -268,7 +268,6 @@ def __init__(self, parent=None, **kw): self._continuation_prompt = '> ' self._continuation_prompt_html = None self._executing = False - self._filter_drag = False self._filter_resize = False self._html_exporter = HtmlExporter(self._control) self._input_buffer_executing = '' @@ -343,7 +342,37 @@ def __init__(self, parent=None, **kw): triggered=self.reset_font) self.addAction(self.reset_font_size) + # Accept drag and drop events here. Drops were already turned off + # in self._control when that widget was created. + self.setAcceptDrops(True) + #--------------------------------------------------------------------------- + # Drag and drop support + #--------------------------------------------------------------------------- + + def dragEnterEvent(self, e): + if e.mimeData().hasText(): + # By changing the action to copy we don't need to worry about + # the user accidentally moving text around in the widget. + e.setDropAction(QtCore.Qt.CopyAction) + e.accept() + + def dragMoveEvent(self, e): + if e.mimeData().hasText(): + cursor = self._control.cursorForPosition(e.pos()) + if self._in_buffer(cursor.position()): + e.setDropAction(QtCore.Qt.CopyAction) + self._control.setTextCursor(cursor) + else: + e.setDropAction(QtCore.Qt.IgnoreAction) + e.accept() + + def dropEvent(self, e): + if e.mimeData().hasText(): + cursor = self._control.cursorForPosition(e.pos()) + if self._in_buffer(cursor.position()): + text = e.mimeData().text() + self._insert_plain_text_into_buffer(cursor, text) def eventFilter(self, obj, event): """ Reimplemented to ensure a console-like behavior in the underlying @@ -392,39 +421,6 @@ def eventFilter(self, obj, event): event.key() in self._shortcuts: event.accept() - # Ensure that drags are safe. The problem is that the drag starting - # logic, which determines whether the drag is a Copy or Move, is locked - # down in QTextControl. If the widget is editable, which it must be if - # we're not executing, the drag will be a Move. The following hack - # prevents QTextControl from deleting the text by clearing the selection - # when a drag leave event originating from this widget is dispatched. - # The fact that we have to clear the user's selection is unfortunate, - # but the alternative--trying to prevent Qt from using its hardwired - # drag logic and writing our own--is worse. - elif etype == QtCore.QEvent.DragEnter and \ - obj == self._control.viewport() and \ - event.source() == self._control.viewport(): - self._filter_drag = True - elif etype == QtCore.QEvent.DragLeave and \ - obj == self._control.viewport() and \ - self._filter_drag: - cursor = self._control.textCursor() - cursor.clearSelection() - self._control.setTextCursor(cursor) - self._filter_drag = False - - # Ensure that drops are safe. - elif etype == QtCore.QEvent.Drop and obj == self._control.viewport(): - cursor = self._control.cursorForPosition(event.pos()) - if self._in_buffer(cursor.position()): - text = event.mimeData().text() - self._insert_plain_text_into_buffer(cursor, text) - - # Qt is expecting to get something here--drag and drop occurs in its - # own event loop. Send a DragLeave event to end it. - QtGui.qApp.sendEvent(obj, QtGui.QDragLeaveEvent()) - return True - # Handle scrolling of the vsplit pager. This hack attempts to solve # problems with tearing of the help text inside the pager window. This # happens only on Mac OS X with both PySide and PyQt. This fix isn't @@ -1035,8 +1031,12 @@ def _create_control(self): control.setAcceptRichText(False) control.setMouseTracking(True) + # Prevent the widget from handling drops, as we already provide + # the logic in this class. + control.setAcceptDrops(False) + # Install event filters. The filter on the viewport is needed for - # mouse events and drag events. + # mouse events. control.installEventFilter(self) control.viewport().installEventFilter(self)