Show More
@@ -1,3 +1,11 | |||
|
1 | #----------------------------------------------------------------------------- | |
|
2 | # Copyright (c) 2010-2012, IPython Development Team. | |
|
3 | # | |
|
4 | # Distributed under the terms of the Modified BSD License. | |
|
5 | # | |
|
6 | # The full license is in the file COPYING.txt, distributed with this software. | |
|
7 | #----------------------------------------------------------------------------- | |
|
8 | ||
|
1 | 9 | # Standard libary imports. |
|
2 | 10 | from base64 import decodestring |
|
3 | 11 | import os |
@@ -36,6 +44,12 class RichIPythonWidget(IPythonWidget): | |||
|
36 | 44 | # Dictionary for resolving document resource names to SVG data. |
|
37 | 45 | self._name_to_svg_map = {} |
|
38 | 46 | |
|
47 | # Do we support jpg ? | |
|
48 | # it seems that sometime jpg support is a plugin of QT, so try to assume | |
|
49 | # it is not always supported. | |
|
50 | self._supported_format = map(str,QtGui.QImageReader.supportedImageFormats()) | |
|
51 | self._jpg_supported = 'jpeg' in self._supported_format | |
|
52 | ||
|
39 | 53 | #--------------------------------------------------------------------------- |
|
40 | 54 | # 'ConsoleWidget' protected interface |
|
41 | 55 | #--------------------------------------------------------------------------- |
@@ -69,24 +83,35 class RichIPythonWidget(IPythonWidget): | |||
|
69 | 83 | def _handle_pyout(self, msg): |
|
70 | 84 | """ Overridden to handle rich data types, like SVG. |
|
71 | 85 | """ |
|
86 | def pre_image_append(): | |
|
87 | self.log.debug("pyout: %s", msg.get('content', '')) | |
|
88 | self._append_plain_text(self.output_sep, True) | |
|
89 | self._append_html(self._make_out_prompt(prompt_number), True) | |
|
90 | # This helps the output to look nice. | |
|
91 | self._append_plain_text('\n', True) | |
|
92 | ||
|
72 | 93 | if not self._hidden and self._is_from_this_session(msg): |
|
73 | 94 | content = msg['content'] |
|
74 | 95 | prompt_number = content['execution_count'] |
|
75 | 96 | data = content['data'] |
|
76 | 97 | if data.has_key('image/svg+xml'): |
|
77 | self.log.debug("pyout: %s", msg.get('content', '')) | |
|
78 | self._append_plain_text(self.output_sep, True) | |
|
79 | self._append_html(self._make_out_prompt(prompt_number), True) | |
|
98 | pre_image_append() | |
|
80 | 99 | self._append_svg(data['image/svg+xml'], True) |
|
81 | 100 | self._append_html(self.output_sep2, True) |
|
82 | 101 | elif data.has_key('image/png'): |
|
83 | self.log.debug("pyout: %s", msg.get('content', '')) | |
|
84 | self._append_plain_text(self.output_sep, True) | |
|
85 | self._append_html(self._make_out_prompt(prompt_number), True) | |
|
86 | # This helps the output to look nice. | |
|
87 | self._append_plain_text('\n', True) | |
|
102 | pre_image_append() | |
|
88 | 103 | self._append_png(decodestring(data['image/png'].encode('ascii')), True) |
|
89 | 104 | self._append_html(self.output_sep2, True) |
|
105 | elif data.has_key('image/jpeg') and self._jpg_supported: | |
|
106 | pre_image_append() | |
|
107 | self._append_jpg(decodestring(data['image/jpeg'].encode('ascii')), True) | |
|
108 | self._append_html(self.output_sep2, True) | |
|
109 | # image/jpg should be an invalid mimetype, but python mimetype package | |
|
110 | # handel it. | |
|
111 | elif data.has_key('image/jpg') and self._jpg_supported: | |
|
112 | pre_image_append() | |
|
113 | self._append_jpg(decodestring(data['image/jpg'].encode('ascii')), True) | |
|
114 | self._append_html(self.output_sep2, True) | |
|
90 | 115 | else: |
|
91 | 116 | # Default back to the plain text representation. |
|
92 | 117 | return super(RichIPythonWidget, self)._handle_pyout(msg) |
@@ -110,6 +135,14 class RichIPythonWidget(IPythonWidget): | |||
|
110 | 135 | # in a JSON structure so we decode it. |
|
111 | 136 | png = decodestring(data['image/png'].encode('ascii')) |
|
112 | 137 | self._append_png(png, True) |
|
138 | elif data.has_key('image/jpeg') and self._jpg_supported: | |
|
139 | self.log.debug("display: %s", msg.get('content', '')) | |
|
140 | jpg = decodestring(data['image/jpeg'].encode('ascii')) | |
|
141 | self._append_jpg(jpg, True) | |
|
142 | elif data.has_key('image/jpg') and self._jpg_supported: | |
|
143 | self.log.debug("display: %s", msg.get('content', '')) | |
|
144 | jpg = decodestring(data['image/jpg'].encode('ascii')) | |
|
145 | self._append_jpg(jpg, True) | |
|
113 | 146 | else: |
|
114 | 147 | # Default back to the plain text representation. |
|
115 | 148 | return super(RichIPythonWidget, self)._handle_display_data(msg) |
@@ -118,6 +151,10 class RichIPythonWidget(IPythonWidget): | |||
|
118 | 151 | # 'RichIPythonWidget' protected interface |
|
119 | 152 | #--------------------------------------------------------------------------- |
|
120 | 153 | |
|
154 | def _append_jpg(self, jpg, before_prompt=False): | |
|
155 | """ Append raw JPG data to the widget.""" | |
|
156 | self._append_custom(self._insert_jpg, jpg, before_prompt) | |
|
157 | ||
|
121 | 158 | def _append_png(self, png, before_prompt=False): |
|
122 | 159 | """ Append raw PNG data to the widget. |
|
123 | 160 | """ |
@@ -168,10 +205,10 class RichIPythonWidget(IPythonWidget): | |||
|
168 | 205 | written (e.g., for linked images). If None, all images are to be |
|
169 | 206 | included inline. |
|
170 | 207 | |
|
171 | format : "png"|"svg", optional [default "png"] | |
|
208 | format : "png"|"svg"|"jpg", optional [default "png"] | |
|
172 | 209 | Format for returned or referenced images. |
|
173 | 210 | """ |
|
174 |
if format |
|
|
211 | if format in ("png","jpg"): | |
|
175 | 212 | try: |
|
176 | 213 | image = self._get_image(match.group("name")) |
|
177 | 214 | except KeyError: |
@@ -181,20 +218,20 class RichIPythonWidget(IPythonWidget): | |||
|
181 | 218 | if not os.path.exists(path): |
|
182 | 219 | os.mkdir(path) |
|
183 | 220 | relpath = os.path.basename(path) |
|
184 |
if image.save("%s/qt_img%s. |
|
|
221 | if image.save("%s/qt_img%s.%s" % (path,match.group("name"),format), | |
|
185 | 222 | "PNG"): |
|
186 |
return '<img src="%s/qt_img%s. |
|
|
187 | match.group("name")) | |
|
223 | return '<img src="%s/qt_img%s.%s">' % (relpath, | |
|
224 | match.group("name"),format) | |
|
188 | 225 | else: |
|
189 | 226 | return "<b>Couldn't save image!</b>" |
|
190 | 227 | else: |
|
191 | 228 | ba = QtCore.QByteArray() |
|
192 | 229 | buffer_ = QtCore.QBuffer(ba) |
|
193 | 230 | buffer_.open(QtCore.QIODevice.WriteOnly) |
|
194 |
image.save(buffer_, |
|
|
231 | image.save(buffer_, format.upper()) | |
|
195 | 232 | buffer_.close() |
|
196 |
return '<img src="data:image/ |
|
|
197 | re.sub(r'(.{60})',r'\1\n',str(ba.toBase64()))) | |
|
233 | return '<img src="data:image/%s;base64,\n%s\n" />' % ( | |
|
234 | format,re.sub(r'(.{60})',r'\1\n',str(ba.toBase64()))) | |
|
198 | 235 | |
|
199 | 236 | elif format == "svg": |
|
200 | 237 | try: |
@@ -215,14 +252,22 class RichIPythonWidget(IPythonWidget): | |||
|
215 | 252 | else: |
|
216 | 253 | return '<b>Unrecognized image format</b>' |
|
217 | 254 | |
|
255 | def _insert_jpg(self, cursor, jpg): | |
|
256 | """ Insert raw PNG data into the widget.""" | |
|
257 | self._insert_img(cursor, jpg, 'jpg') | |
|
258 | ||
|
218 | 259 | def _insert_png(self, cursor, png): |
|
219 | 260 | """ Insert raw PNG data into the widget. |
|
220 | 261 | """ |
|
262 | self._insert_img(cursor, png, 'png') | |
|
263 | ||
|
264 | def _insert_img(self, cursor, img, fmt): | |
|
265 | """ insert a raw image, jpg or png """ | |
|
221 | 266 | try: |
|
222 | 267 | image = QtGui.QImage() |
|
223 |
image.loadFromData( |
|
|
268 | image.loadFromData(img, fmt.upper()) | |
|
224 | 269 | except ValueError: |
|
225 |
self._insert_plain_text(cursor, 'Received invalid |
|
|
270 | self._insert_plain_text(cursor, 'Received invalid %s data.'%fmt) | |
|
226 | 271 | else: |
|
227 | 272 | format = self._add_image(image) |
|
228 | 273 | cursor.insertBlock() |
General Comments 0
You need to be logged in to leave comments.
Login now