From da38a6b9061407df6ab9c4d557512a02953ddbdf 2010-08-13 16:00:06
From: epatters <epatters@enthought.com>
Date: 2010-08-13 16:00:06
Subject: [PATCH] * Fixed bug where ConsoleWidget accepted non-ASCII characters on paste (and also rich text in 'rich' mode)
* Minor cleanup to SVG payload handling.

---

diff --git a/IPython/frontend/qt/console/console_widget.py b/IPython/frontend/qt/console/console_widget.py
index 3218845..c5fe0d5 100644
--- a/IPython/frontend/qt/console/console_widget.py
+++ b/IPython/frontend/qt/console/console_widget.py
@@ -113,6 +113,20 @@ class ConsoleWidget(QtGui.QWidget):
     # 'ConsoleWidget' public interface
     #---------------------------------------------------------------------------
 
+    def can_paste(self):
+        """ Returns whether text can be pasted from the clipboard.
+        """
+        # Accept only text that can be ASCII encoded.
+        if self._control.textInteractionFlags() & QtCore.Qt.TextEditable:
+            text = QtGui.QApplication.clipboard().text()
+            if not text.isEmpty():
+                try:
+                    str(text)
+                    return True
+                except UnicodeEncodeError:
+                    pass
+        return False
+
     def clear(self, keep_input=False):
         """ Clear the console, then write a new prompt. If 'keep_input' is set,
             restores the old input buffer when the new prompt is written.
@@ -262,8 +276,9 @@ class ConsoleWidget(QtGui.QWidget):
     def paste(self):
         """ Paste the contents of the clipboard into the input region.
         """
-        self._keep_cursor_in_buffer()
-        self._control.paste()
+        if self.can_paste():
+            self._keep_cursor_in_buffer()
+            self._control.paste()
 
     def print_(self, printer):
         """ Print the contents of the ConsoleWidget to the specified QPrinter.
@@ -446,6 +461,7 @@ class ConsoleWidget(QtGui.QWidget):
             control = QtGui.QPlainTextEdit()
         elif kind == 'rich':
             control = QtGui.QTextEdit()
+            control.setAcceptRichText(False)
         else:
             raise ValueError("Kind %s unknown." % repr(kind))
         layout.addWidget(control)
@@ -895,7 +911,7 @@ class ConsoleWidget(QtGui.QWidget):
 
         paste_action = QtGui.QAction('Paste', menu)
         paste_action.triggered.connect(self.paste)
-        paste_action.setEnabled(self._control.canPaste())
+        paste_action.setEnabled(self.can_paste())
         paste_action.setShortcut(QtGui.QKeySequence.Paste)
         menu.addAction(paste_action)
         menu.addSeparator()
diff --git a/IPython/frontend/qt/console/rich_ipython_widget.py b/IPython/frontend/qt/console/rich_ipython_widget.py
index f87e3ec..1867e9e 100644
--- a/IPython/frontend/qt/console/rich_ipython_widget.py
+++ b/IPython/frontend/qt/console/rich_ipython_widget.py
@@ -22,14 +22,12 @@ class RichIPythonWidget(IPythonWidget):
         super(RichIPythonWidget, self).__init__(kind='rich', parent=parent)
     
     #---------------------------------------------------------------------------
-    # 'FrontendWidget' interface
+    # 'FrontendWidget' protected interface
     #---------------------------------------------------------------------------
 
     def _handle_execute_payload(self, payload):
         """ Reimplemented to handle pylab plot payloads.
         """
-        super(RichIPythonWidget, self)._handle_execute_payload(payload)
-
         plot_payload = payload.get('plot', None)
         if plot_payload and plot_payload['format'] == 'svg':
             try:
@@ -41,3 +39,5 @@ class RichIPythonWidget(IPythonWidget):
                 cursor.insertBlock()
                 cursor.insertImage(image)
                 cursor.insertBlock()
+        else:
+            super(RichIPythonWidget, self)._handle_execute_payload(payload)
diff --git a/IPython/frontend/qt/util.py b/IPython/frontend/qt/util.py
index b43788f..ec76f25 100644
--- a/IPython/frontend/qt/util.py
+++ b/IPython/frontend/qt/util.py
@@ -29,16 +29,16 @@ class MetaQObjectHasTraits(MetaQObject, MetaHasTraits):
 #-----------------------------------------------------------------------------
         
 def image_from_svg(string, size=None):
-    """ Convert a string containing SVG data into a QImage.
+    """ Convert a SVG document to a QImage.
 
     Parameters:
     -----------
     string : str
-        A Python string containing the SVG data.
+        A Python string containing a SVG document.
 
-    size : QSize or None [default None]
-        The size of the image that is produced. If not specified, the SVG data's
-        default size is used.
+    size : QSize, optional
+        The size of the image that is produced. If not specified, the SVG
+        document's default size is used.
     
     Raises:
     -------
@@ -47,18 +47,18 @@ def image_from_svg(string, size=None):
 
     Returns:
     --------
-    A QImage with format QImage.Format_ARGB32_Premultiplied.
+    A QImage of format QImage.Format_ARGB32.
     """
     from PyQt4 import QtSvg
 
-    bytes = QtCore.QByteArray(string)
+    bytes = QtCore.QByteArray.fromRawData(string) # shallow copy
     renderer = QtSvg.QSvgRenderer(bytes)
     if not renderer.isValid():
         raise ValueError('Invalid SVG data.')
 
     if size is None:
         size = renderer.defaultSize()
-    image = QtGui.QImage(size, QtGui.QImage.Format_ARGB32_Premultiplied)
+    image = QtGui.QImage(size, QtGui.QImage.Format_ARGB32)
     painter = QtGui.QPainter(image)
     renderer.render(painter)
     return image