Skip to content

Commit

Permalink
* Added "smart copy" support to FrontendWidget and ConsoleWidget. Tab…
Browse files Browse the repository at this point in the history
…s are expanded and prompts are stripped.

* ConsoleWidget now overrides drag events in a cleaner way.
  • Loading branch information
epatters committed Sep 6, 2010
1 parent b00fa28 commit e6a1247
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 32 deletions.
43 changes: 15 additions & 28 deletions IPython/frontend/qt/console/console_widget.py
Expand Up @@ -15,27 +15,6 @@
from completion_widget import CompletionWidget


class ConsolePlainTextEdit(QtGui.QPlainTextEdit):
""" A QPlainTextEdit suitable for use with ConsoleWidget.
"""
# Prevents text from being moved by drag and drop. Note that is not, for
# some reason, sufficient to catch drag events in the ConsoleWidget's
# event filter.
def dragEnterEvent(self, event): pass
def dragLeaveEvent(self, event): pass
def dragMoveEvent(self, event): pass
def dropEvent(self, event): pass

class ConsoleTextEdit(QtGui.QTextEdit):
""" A QTextEdit suitable for use with ConsoleWidget.
"""
# See above.
def dragEnterEvent(self, event): pass
def dragLeaveEvent(self, event): pass
def dragMoveEvent(self, event): pass
def dropEvent(self, event): pass


class ConsoleWidget(Configurable, QtGui.QWidget):
""" An abstract base class for console-type widgets. This class has
functionality for:
Expand Down Expand Up @@ -205,6 +184,11 @@ def eventFilter(self, obj, event):
event.accept()
return False

# Prevent text from being moved by drag and drop.
elif etype in (QtCore.QEvent.DragEnter, QtCore.QEvent.DragLeave,
QtCore.QEvent.DragMove, QtCore.QEvent.Drop):
return True

return super(ConsoleWidget, self).eventFilter(obj, event)

#---------------------------------------------------------------------------
Expand Down Expand Up @@ -267,7 +251,7 @@ def clear(self, keep_input=True):
self.input_buffer = input_buffer

def copy(self):
""" Copy the current selected text to the clipboard.
""" Copy the currently selected text to the clipboard.
"""
self._control.copy()

Expand Down Expand Up @@ -667,13 +651,13 @@ def _create_control(self):
"""
# Create the underlying control.
if self.kind == 'plain':
control = ConsolePlainTextEdit()
control = QtGui.QPlainTextEdit()
elif self.kind == 'rich':
control = ConsoleTextEdit()
control = QtGui.QTextEdit()
control.setAcceptRichText(False)

# Install event filters. The filter on the viewport is needed for
# mouse events.
# mouse events and drag events.
control.installEventFilter(self)
control.viewport().installEventFilter(self)

Expand All @@ -694,7 +678,7 @@ def _create_control(self):
def _create_page_control(self):
""" Creates and connects the underlying paging widget.
"""
control = ConsolePlainTextEdit()
control = QtGui.QPlainTextEdit()
control.installEventFilter(self)
control.setReadOnly(True)
control.setUndoRedoEnabled(False)
Expand All @@ -713,8 +697,11 @@ def _event_filter_console_keypress(self, event):
alt_down = event.modifiers() & QtCore.Qt.AltModifier
shift_down = event.modifiers() & QtCore.Qt.ShiftModifier

if event.matches(QtGui.QKeySequence.Paste):
# Call our paste instead of the underlying text widget's.
if event.matches(QtGui.QKeySequence.Copy):
self.copy()
intercepted = True

elif event.matches(QtGui.QKeySequence.Paste):
self.paste()
intercepted = True

Expand Down
19 changes: 17 additions & 2 deletions IPython/frontend/qt/console/frontend_widget.py
Expand Up @@ -8,7 +8,7 @@
from PyQt4 import QtCore, QtGui

# Local imports
from IPython.core.inputsplitter import InputSplitter
from IPython.core.inputsplitter import InputSplitter, transform_classic_prompt
from IPython.frontend.qt.base_frontend_mixin import BaseFrontendMixin
from IPython.utils.io import raw_print
from IPython.utils.traitlets import Bool
Expand Down Expand Up @@ -126,6 +126,21 @@ def __init__(self, *args, **kw):
document = self._control.document()
document.contentsChange.connect(self._document_contents_change)

#---------------------------------------------------------------------------
# 'ConsoleWidget' public interface
#---------------------------------------------------------------------------

def copy(self):
""" Copy the currently selected text to the clipboard, removing prompts.
"""
text = str(self._control.textCursor().selection().toPlainText())
if text:
# Remove prompts.
lines = map(transform_classic_prompt, text.splitlines())
text = '\n'.join(lines)
# Expand tabs so that we respect PEP-8.
QtGui.QApplication.clipboard().setText(text.expandtabs(4))

#---------------------------------------------------------------------------
# 'ConsoleWidget' abstract interface
#---------------------------------------------------------------------------
Expand Down Expand Up @@ -306,7 +321,7 @@ def _stopped_channels(self):
self._highlighter.highlighting_on = False

#---------------------------------------------------------------------------
# 'FrontendWidget' interface
# 'FrontendWidget' public interface
#---------------------------------------------------------------------------

def execute_file(self, path, hidden=False):
Expand Down
21 changes: 19 additions & 2 deletions IPython/frontend/qt/console/ipython_widget.py
Expand Up @@ -19,7 +19,8 @@
from PyQt4 import QtCore, QtGui

# Local imports
from IPython.core.inputsplitter import IPythonInputSplitter
from IPython.core.inputsplitter import IPythonInputSplitter, \
transform_ipy_prompt
from IPython.core.usage import default_banner
from IPython.utils.traitlets import Bool, Str
from frontend_widget import FrontendWidget
Expand Down Expand Up @@ -198,7 +199,23 @@ def _started_channels(self):
#self.kernel_manager.xreq_channel.history(raw=True, output=False)

#---------------------------------------------------------------------------
# 'FrontendWidget' interface
# 'ConsoleWidget' public interface
#---------------------------------------------------------------------------

def copy(self):
""" Copy the currently selected text to the clipboard, removing prompts
if possible.
"""
text = str(self._control.textCursor().selection().toPlainText())
if text:
# Remove prompts.
lines = map(transform_ipy_prompt, text.splitlines())
text = '\n'.join(lines)
# Expand tabs so that we respect PEP-8.
QtGui.QApplication.clipboard().setText(text.expandtabs(4))

#---------------------------------------------------------------------------
# 'FrontendWidget' public interface
#---------------------------------------------------------------------------

def execute_file(self, path, hidden=False):
Expand Down

0 comments on commit e6a1247

Please sign in to comment.