From f5cbf8be19d76590cd7d6bb98b8ed5d600eb4642 2012-10-25 00:19:53 From: Bradley M. Froehle Date: 2012-10-25 00:19:53 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. --- diff --git a/IPython/frontend/qt/console/console_widget.py b/IPython/frontend/qt/console/console_widget.py index 1cfa695..b6b85c4 100644 --- a/IPython/frontend/qt/console/console_widget.py +++ b/IPython/frontend/qt/console/console_widget.py @@ -268,7 +268,6 @@ class ConsoleWidget(LoggingConfigurable, QtGui.QWidget): 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 @@ class ConsoleWidget(LoggingConfigurable, QtGui.QWidget): 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 @@ class ConsoleWidget(LoggingConfigurable, QtGui.QWidget): 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 @@ class ConsoleWidget(LoggingConfigurable, QtGui.QWidget): 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)