##// END OF EJS Templates
Paging using payloads now works.
Paging using payloads now works.

File last commit:

r2830:51713815
r2830:51713815
Show More
rich_ipython_widget.py
151 lines | 6.4 KiB | text/x-python | PythonLexer
/ IPython / frontend / qt / console / rich_ipython_widget.py
Brian Granger
%edit is now working....
r2827 import os
epatters
* The SVG payload matplotlib backend now works....
r2758 # System library imports
from PyQt4 import QtCore, QtGui
# Local imports
epatters
* Added a custom context menu to the RichIPythonWidget which allows saving plot as an images or SVG documents....
r2765 from IPython.frontend.qt.svg import save_svg, svg_to_clipboard, svg_to_image
epatters
* The SVG payload matplotlib backend now works....
r2758 from ipython_widget import IPythonWidget
class RichIPythonWidget(IPythonWidget):
""" An IPythonWidget that supports rich text, including lists, images, and
tables. Note that raw performance will be reduced compared to the plain
text version.
"""
epatters
* Added a custom context menu to the RichIPythonWidget which allows saving plot as an images or SVG documents....
r2765 # Protected class variables.
_svg_text_format_property = 1
epatters
* The SVG payload matplotlib backend now works....
r2758 #---------------------------------------------------------------------------
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 # 'object' interface
epatters
* The SVG payload matplotlib backend now works....
r2758 #---------------------------------------------------------------------------
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 def __init__(self, *args, **kw):
epatters
* The SVG payload matplotlib backend now works....
r2758 """ Create a RichIPythonWidget.
"""
epatters
* Added a pager with several different options to ConsoleWidget....
r2776 kw['kind'] = 'rich'
super(RichIPythonWidget, self).__init__(*args, **kw)
epatters
* Added a custom context menu to the RichIPythonWidget which allows saving plot as an images or SVG documents....
r2765
#---------------------------------------------------------------------------
# 'ConsoleWidget' protected interface
#---------------------------------------------------------------------------
def _show_context_menu(self, pos):
""" Reimplemented to show a custom context menu for images.
"""
format = self._control.cursorForPosition(pos).charFormat()
name = format.stringProperty(QtGui.QTextFormat.ImageName)
if name.isEmpty():
super(RichIPythonWidget, self)._show_context_menu(pos)
else:
menu = QtGui.QMenu()
menu.addAction('Copy Image', lambda: self._copy_image(name))
menu.addAction('Save Image As...', lambda: self._save_image(name))
menu.addSeparator()
svg = format.stringProperty(self._svg_text_format_property)
if not svg.isEmpty():
menu.addSeparator()
menu.addAction('Copy SVG', lambda: svg_to_clipboard(svg))
menu.addAction('Save SVG As...',
lambda: save_svg(svg, self._control))
menu.exec_(self._control.mapToGlobal(pos))
epatters
* The SVG payload matplotlib backend now works....
r2758
#---------------------------------------------------------------------------
epatters
* Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)...
r2762 # 'FrontendWidget' protected interface
epatters
* The SVG payload matplotlib backend now works....
r2758 #---------------------------------------------------------------------------
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 def _process_execute_ok(self, msg):
""" Reimplemented to handle matplotlib plot payloads.
epatters
* The SVG payload matplotlib backend now works....
r2758 """
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 payload = msg['content']['payload']
epatters
Minor cleanup to RichIPythonWidget.
r2818 for item in payload:
Brian Granger
%edit is now working....
r2827 if item['source'] == 'IPython.zmq.pylab.backend_payload.add_plot_payload':
epatters
Minor cleanup to RichIPythonWidget.
r2818 if item['format'] == 'svg':
svg = item['data']
try:
image = svg_to_image(svg)
except ValueError:
self._append_plain_text('Received invalid plot data.')
Brian Granger
First working draft of new payload system.
r2814 else:
epatters
Minor cleanup to RichIPythonWidget.
r2818 format = self._add_image(image)
format.setProperty(self._svg_text_format_property, svg)
cursor = self._get_end_cursor()
cursor.insertBlock()
cursor.insertImage(format)
cursor.insertBlock()
Brian Granger
First working draft of new payload system.
r2814 else:
epatters
Minor cleanup to RichIPythonWidget.
r2818 # Add other plot formats here!
Brian Granger
First working draft of new payload system.
r2814 pass
Brian Granger
%edit is now working....
r2827 elif item['source'] == 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic':
# TODO: I have implmented the logic for TextMate on the Mac.
# But, we need to allow payload handlers on the non-rich
# text IPython widget as well. Furthermore, we should probably
# move these handlers to separate methods. But, we need to
# be very careful to process the payload list in order. Thus,
# we will probably need a _handle_payload method of the
# base class that dispatches to the separate handler methods
# for each payload source. If a particular subclass doesn't
# have a handler for a payload source, it should at least
# print a nice message.
filename = item['filename']
line_number = item['line_number']
if line_number is None:
cmd = 'mate %s' % filename
else:
cmd = 'mate -l %s %s' % (line_number, filename)
os.system(cmd)
Brian Granger
Paging using payloads now works.
r2830 elif item['source'] == 'IPython.zmq.page.page':
# TODO: This is probably a good place to start, but Evan can
# add better paging capabilities.
self._append_plain_text(item['data'])
epatters
Minor cleanup to RichIPythonWidget.
r2818 else:
# Add other payload types here!
pass
epatters
* Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)...
r2762 else:
epatters
* Moved KernelManager attribute management code in FrontendWidget into a mixin class usable in any Qt frontend. Registering handlers for message types is now trivial....
r2770 super(RichIPythonWidget, self)._process_execute_ok(msg)
epatters
* Added a custom context menu to the RichIPythonWidget which allows saving plot as an images or SVG documents....
r2765
#---------------------------------------------------------------------------
# 'RichIPythonWidget' protected interface
#---------------------------------------------------------------------------
def _add_image(self, image):
""" Adds the specified QImage to the document and returns a
QTextImageFormat that references it.
"""
document = self._control.document()
name = QtCore.QString.number(image.cacheKey())
document.addResource(QtGui.QTextDocument.ImageResource,
QtCore.QUrl(name), image)
format = QtGui.QTextImageFormat()
format.setName(name)
return format
def _copy_image(self, name):
""" Copies the ImageResource with 'name' to the clipboard.
"""
image = self._get_image(name)
QtGui.QApplication.clipboard().setImage(image)
def _get_image(self, name):
""" Returns the QImage stored as the ImageResource with 'name'.
"""
document = self._control.document()
variant = document.resource(QtGui.QTextDocument.ImageResource,
QtCore.QUrl(name))
return variant.toPyObject()
def _save_image(self, name, format='PNG'):
""" Shows a save dialog for the ImageResource with 'name'.
"""
dialog = QtGui.QFileDialog(self._control, 'Save Image')
dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
dialog.setDefaultSuffix(format.lower())
dialog.setNameFilter('%s file (*.%s)' % (format, format.lower()))
if dialog.exec_():
filename = dialog.selectedFiles()[0]
image = self._get_image(name)
image.save(filename, format)