##// END OF EJS Templates
Clean up styling information.
epatters -
Show More
@@ -1,275 +1,275 b''
1 # Standard library imports
1 # Standard library imports
2 from subprocess import Popen
2 from subprocess import Popen
3
3
4 # System library imports
4 # System library imports
5 from PyQt4 import QtCore, QtGui
5 from PyQt4 import QtCore, QtGui
6
6
7 # Local imports
7 # Local imports
8 from IPython.core.inputsplitter import IPythonInputSplitter
8 from IPython.core.inputsplitter import IPythonInputSplitter
9 from IPython.core.usage import default_banner
9 from IPython.core.usage import default_banner
10 from frontend_widget import FrontendWidget
10 from frontend_widget import FrontendWidget
11
11
12
12
13 class IPythonPromptBlock(object):
13 class IPythonPromptBlock(object):
14 """ An internal storage object for IPythonWidget.
14 """ An internal storage object for IPythonWidget.
15 """
15 """
16 def __init__(self, block, length, number):
16 def __init__(self, block, length, number):
17 self.block = block
17 self.block = block
18 self.length = length
18 self.length = length
19 self.number = number
19 self.number = number
20
20
21
21
22 class IPythonWidget(FrontendWidget):
22 class IPythonWidget(FrontendWidget):
23 """ A FrontendWidget for an IPython kernel.
23 """ A FrontendWidget for an IPython kernel.
24 """
24 """
25
25
26 # Signal emitted when an editor is needed for a file and the editor has been
26 # Signal emitted when an editor is needed for a file and the editor has been
27 # specified as 'custom'.
27 # specified as 'custom'.
28 custom_edit_requested = QtCore.pyqtSignal(object)
28 custom_edit_requested = QtCore.pyqtSignal(object)
29
29
30 # The default stylesheet: black text on a white background.
30 # The default stylesheet: black text on a white background.
31 default_stylesheet = """
31 default_stylesheet = """
32 .error { color: red; }
32 .error { color: red; }
33 .in-prompt { color: navy; }
33 .in-prompt { color: navy; }
34 .in-prompt-number { font-weight: bold; }
34 .in-prompt-number { font-weight: bold; }
35 .out-prompt { color: darkred; }
35 .out-prompt { color: darkred; }
36 .out-prompt-number { font-weight: bold; }
36 .out-prompt-number { font-weight: bold; }
37 """
37 """
38
38
39 # A dark stylesheet: white text on a black background.
39 # A dark stylesheet: white text on a black background.
40 dark_stylesheet = """
40 dark_stylesheet = """
41 QPlainTextEdit { background-color: black; color: white }
41 QPlainTextEdit, QTextEdit { background-color: black; color: white }
42 QFrame { border: 1px solid grey; }
42 QFrame { border: 1px solid grey; }
43 .error { color: red; }
43 .error { color: red; }
44 .in-prompt { color: lime; }
44 .in-prompt { color: lime; }
45 .in-prompt-number { color: lime; font-weight: bold; }
45 .in-prompt-number { color: lime; font-weight: bold; }
46 .out-prompt { color: red; }
46 .out-prompt { color: red; }
47 .out-prompt-number { color: red; font-weight: bold; }
47 .out-prompt-number { color: red; font-weight: bold; }
48 """
48 """
49
49
50 # Default prompts.
50 # Default prompts.
51 in_prompt = 'In [<span class="in-prompt-number">%i</span>]: '
51 in_prompt = 'In [<span class="in-prompt-number">%i</span>]: '
52 out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
52 out_prompt = 'Out[<span class="out-prompt-number">%i</span>]: '
53
53
54 # FrontendWidget protected class attributes.
54 # FrontendWidget protected class attributes.
55 #_input_splitter_class = IPythonInputSplitter
55 #_input_splitter_class = IPythonInputSplitter
56
56
57 #---------------------------------------------------------------------------
57 #---------------------------------------------------------------------------
58 # 'object' interface
58 # 'object' interface
59 #---------------------------------------------------------------------------
59 #---------------------------------------------------------------------------
60
60
61 def __init__(self, *args, **kw):
61 def __init__(self, *args, **kw):
62 super(IPythonWidget, self).__init__(*args, **kw)
62 super(IPythonWidget, self).__init__(*args, **kw)
63
63
64 # IPythonWidget protected variables.
64 # IPythonWidget protected variables.
65 self._previous_prompt_obj = None
65 self._previous_prompt_obj = None
66
66
67 # Set a default editor and stylesheet.
67 # Set a default editor and stylesheet.
68 self.set_editor('default')
68 self.set_editor('default')
69 self.reset_styling()
69 self.reset_styling()
70
70
71 #---------------------------------------------------------------------------
71 #---------------------------------------------------------------------------
72 # 'BaseFrontendMixin' abstract interface
72 # 'BaseFrontendMixin' abstract interface
73 #---------------------------------------------------------------------------
73 #---------------------------------------------------------------------------
74
74
75 def _handle_pyout(self, msg):
75 def _handle_pyout(self, msg):
76 """ Reimplemented for IPython-style "display hook".
76 """ Reimplemented for IPython-style "display hook".
77 """
77 """
78 content = msg['content']
78 content = msg['content']
79 prompt_number = content['prompt_number']
79 prompt_number = content['prompt_number']
80 self._append_plain_text(content['output_sep'])
80 self._append_plain_text(content['output_sep'])
81 self._append_html(self._make_out_prompt(prompt_number))
81 self._append_html(self._make_out_prompt(prompt_number))
82 self._append_plain_text(content['data'] + '\n' + content['output_sep2'])
82 self._append_plain_text(content['data'] + '\n' + content['output_sep2'])
83
83
84 #---------------------------------------------------------------------------
84 #---------------------------------------------------------------------------
85 # 'FrontendWidget' interface
85 # 'FrontendWidget' interface
86 #---------------------------------------------------------------------------
86 #---------------------------------------------------------------------------
87
87
88 def execute_file(self, path, hidden=False):
88 def execute_file(self, path, hidden=False):
89 """ Reimplemented to use the 'run' magic.
89 """ Reimplemented to use the 'run' magic.
90 """
90 """
91 self.execute('run %s' % path, hidden=hidden)
91 self.execute('run %s' % path, hidden=hidden)
92
92
93 #---------------------------------------------------------------------------
93 #---------------------------------------------------------------------------
94 # 'FrontendWidget' protected interface
94 # 'FrontendWidget' protected interface
95 #---------------------------------------------------------------------------
95 #---------------------------------------------------------------------------
96
96
97 def _get_banner(self):
97 def _get_banner(self):
98 """ Reimplemented to return IPython's default banner.
98 """ Reimplemented to return IPython's default banner.
99 """
99 """
100 return default_banner + '\n'
100 return default_banner + '\n'
101
101
102 def _process_execute_error(self, msg):
102 def _process_execute_error(self, msg):
103 """ Reimplemented for IPython-style traceback formatting.
103 """ Reimplemented for IPython-style traceback formatting.
104 """
104 """
105 content = msg['content']
105 content = msg['content']
106 traceback_lines = content['traceback'][:]
106 traceback_lines = content['traceback'][:]
107 traceback = ''.join(traceback_lines)
107 traceback = ''.join(traceback_lines)
108 traceback = traceback.replace(' ', '&nbsp;')
108 traceback = traceback.replace(' ', '&nbsp;')
109 traceback = traceback.replace('\n', '<br/>')
109 traceback = traceback.replace('\n', '<br/>')
110
110
111 ename = content['ename']
111 ename = content['ename']
112 ename_styled = '<span class="error">%s</span>' % ename
112 ename_styled = '<span class="error">%s</span>' % ename
113 traceback = traceback.replace(ename, ename_styled)
113 traceback = traceback.replace(ename, ename_styled)
114
114
115 self._append_html(traceback)
115 self._append_html(traceback)
116
116
117 def _show_interpreter_prompt(self, number=None, input_sep='\n'):
117 def _show_interpreter_prompt(self, number=None, input_sep='\n'):
118 """ Reimplemented for IPython-style prompts.
118 """ Reimplemented for IPython-style prompts.
119 """
119 """
120 # TODO: If a number was not specified, make a prompt number request.
120 # TODO: If a number was not specified, make a prompt number request.
121 if number is None:
121 if number is None:
122 number = 0
122 number = 0
123
123
124 # Show a new prompt and save information about it so that it can be
124 # Show a new prompt and save information about it so that it can be
125 # updated later if the prompt number turns out to be wrong.
125 # updated later if the prompt number turns out to be wrong.
126 self._append_plain_text(input_sep)
126 self._append_plain_text(input_sep)
127 self._show_prompt(self._make_in_prompt(number), html=True)
127 self._show_prompt(self._make_in_prompt(number), html=True)
128 block = self._control.document().lastBlock()
128 block = self._control.document().lastBlock()
129 length = len(self._prompt)
129 length = len(self._prompt)
130 self._previous_prompt_obj = IPythonPromptBlock(block, length, number)
130 self._previous_prompt_obj = IPythonPromptBlock(block, length, number)
131
131
132 # Update continuation prompt to reflect (possibly) new prompt length.
132 # Update continuation prompt to reflect (possibly) new prompt length.
133 self._set_continuation_prompt(
133 self._set_continuation_prompt(
134 self._make_continuation_prompt(self._prompt), html=True)
134 self._make_continuation_prompt(self._prompt), html=True)
135
135
136 def _show_interpreter_prompt_for_reply(self, msg):
136 def _show_interpreter_prompt_for_reply(self, msg):
137 """ Reimplemented for IPython-style prompts.
137 """ Reimplemented for IPython-style prompts.
138 """
138 """
139 # Update the old prompt number if necessary.
139 # Update the old prompt number if necessary.
140 content = msg['content']
140 content = msg['content']
141 previous_prompt_number = content['prompt_number']
141 previous_prompt_number = content['prompt_number']
142 if self._previous_prompt_obj and \
142 if self._previous_prompt_obj and \
143 self._previous_prompt_obj.number != previous_prompt_number:
143 self._previous_prompt_obj.number != previous_prompt_number:
144 block = self._previous_prompt_obj.block
144 block = self._previous_prompt_obj.block
145 if block.isValid():
145 if block.isValid():
146
146
147 # Remove the old prompt and insert a new prompt.
147 # Remove the old prompt and insert a new prompt.
148 cursor = QtGui.QTextCursor(block)
148 cursor = QtGui.QTextCursor(block)
149 cursor.movePosition(QtGui.QTextCursor.Right,
149 cursor.movePosition(QtGui.QTextCursor.Right,
150 QtGui.QTextCursor.KeepAnchor,
150 QtGui.QTextCursor.KeepAnchor,
151 self._previous_prompt_obj.length)
151 self._previous_prompt_obj.length)
152 prompt = self._make_in_prompt(previous_prompt_number)
152 prompt = self._make_in_prompt(previous_prompt_number)
153 self._prompt = self._insert_html_fetching_plain_text(
153 self._prompt = self._insert_html_fetching_plain_text(
154 cursor, prompt)
154 cursor, prompt)
155
155
156 # XXX: When the HTML is inserted, Qt blows away the syntax
156 # XXX: When the HTML is inserted, Qt blows away the syntax
157 # highlighting for the line. I cannot for the life of me
157 # highlighting for the line. I cannot for the life of me
158 # determine how to preserve the existing formatting.
158 # determine how to preserve the existing formatting.
159 self._highlighter.highlighting_on = True
159 self._highlighter.highlighting_on = True
160 self._highlighter.rehighlightBlock(cursor.block())
160 self._highlighter.rehighlightBlock(cursor.block())
161 self._highlighter.highlighting_on = False
161 self._highlighter.highlighting_on = False
162
162
163 self._previous_prompt_obj = None
163 self._previous_prompt_obj = None
164
164
165 # Show a new prompt with the kernel's estimated prompt number.
165 # Show a new prompt with the kernel's estimated prompt number.
166 next_prompt = content['next_prompt']
166 next_prompt = content['next_prompt']
167 self._show_interpreter_prompt(next_prompt['prompt_number'],
167 self._show_interpreter_prompt(next_prompt['prompt_number'],
168 next_prompt['input_sep'])
168 next_prompt['input_sep'])
169
169
170 #---------------------------------------------------------------------------
170 #---------------------------------------------------------------------------
171 # 'IPythonWidget' interface
171 # 'IPythonWidget' interface
172 #---------------------------------------------------------------------------
172 #---------------------------------------------------------------------------
173
173
174 def edit(self, filename):
174 def edit(self, filename):
175 """ Opens a Python script for editing.
175 """ Opens a Python script for editing.
176
176
177 Parameters:
177 Parameters:
178 -----------
178 -----------
179 filename : str
179 filename : str
180 A path to a local system file.
180 A path to a local system file.
181
181
182 Raises:
182 Raises:
183 -------
183 -------
184 OSError
184 OSError
185 If the editor command cannot be executed.
185 If the editor command cannot be executed.
186 """
186 """
187 if self._editor == 'default':
187 if self._editor == 'default':
188 url = QtCore.QUrl.fromLocalFile(filename)
188 url = QtCore.QUrl.fromLocalFile(filename)
189 if not QtGui.QDesktopServices.openUrl(url):
189 if not QtGui.QDesktopServices.openUrl(url):
190 message = 'Failed to open %s with the default application'
190 message = 'Failed to open %s with the default application'
191 raise OSError(message % repr(filename))
191 raise OSError(message % repr(filename))
192 elif self._editor is None:
192 elif self._editor is None:
193 self.custom_edit_requested.emit(filename)
193 self.custom_edit_requested.emit(filename)
194 else:
194 else:
195 Popen(self._editor + [filename])
195 Popen(self._editor + [filename])
196
196
197 def reset_styling(self):
197 def reset_styling(self):
198 """ Restores the default IPythonWidget styling.
198 """ Restores the default IPythonWidget styling.
199 """
199 """
200 self.set_styling(self.default_stylesheet, syntax_style='default')
200 self.set_styling(self.default_stylesheet, syntax_style='default')
201 # self.set_styling(self.dark_stylesheet, syntax_style='monokai')
201 #self.set_styling(self.dark_stylesheet, syntax_style='monokai')
202
202
203 def set_editor(self, editor):
203 def set_editor(self, editor):
204 """ Sets the editor to use with the %edit magic.
204 """ Sets the editor to use with the %edit magic.
205
205
206 Parameters:
206 Parameters:
207 -----------
207 -----------
208 editor : str or sequence of str
208 editor : str or sequence of str
209 A command suitable for use with Popen. This command will be executed
209 A command suitable for use with Popen. This command will be executed
210 with a single argument--a filename--when editing is requested.
210 with a single argument--a filename--when editing is requested.
211
211
212 This parameter also takes two special values:
212 This parameter also takes two special values:
213 'default' : Files will be edited with the system default
213 'default' : Files will be edited with the system default
214 application for Python files.
214 application for Python files.
215 'custom' : Emit a 'custom_edit_requested(str)' signal instead
215 'custom' : Emit a 'custom_edit_requested(str)' signal instead
216 of opening an editor.
216 of opening an editor.
217 """
217 """
218 if editor == 'default':
218 if editor == 'default':
219 self._editor = 'default'
219 self._editor = 'default'
220 elif editor == 'custom':
220 elif editor == 'custom':
221 self._editor = None
221 self._editor = None
222 elif isinstance(editor, basestring):
222 elif isinstance(editor, basestring):
223 self._editor = [ editor ]
223 self._editor = [ editor ]
224 else:
224 else:
225 self._editor = list(editor)
225 self._editor = list(editor)
226
226
227 def set_styling(self, stylesheet, syntax_style=None):
227 def set_styling(self, stylesheet, syntax_style=None):
228 """ Sets the IPythonWidget styling.
228 """ Sets the IPythonWidget styling.
229
229
230 Parameters:
230 Parameters:
231 -----------
231 -----------
232 stylesheet : str
232 stylesheet : str
233 A CSS stylesheet. The stylesheet can contain classes for:
233 A CSS stylesheet. The stylesheet can contain classes for:
234 1. Qt: QPlainTextEdit, QFrame, QWidget, etc
234 1. Qt: QPlainTextEdit, QFrame, QWidget, etc
235 2. Pygments: .c, .k, .o, etc (see PygmentsHighlighter)
235 2. Pygments: .c, .k, .o, etc (see PygmentsHighlighter)
236 3. IPython: .error, .in-prompt, .out-prompt, etc.
236 3. IPython: .error, .in-prompt, .out-prompt, etc.
237
237
238 syntax_style : str or None [default None]
238 syntax_style : str or None [default None]
239 If specified, use the Pygments style with given name. Otherwise,
239 If specified, use the Pygments style with given name. Otherwise,
240 the stylesheet is queried for Pygments style information.
240 the stylesheet is queried for Pygments style information.
241 """
241 """
242 self.setStyleSheet(stylesheet)
242 self.setStyleSheet(stylesheet)
243 self._control.document().setDefaultStyleSheet(stylesheet)
243 self._control.document().setDefaultStyleSheet(stylesheet)
244 if self._page_control:
244 if self._page_control:
245 self._page_control.document().setDefaultStyleSheet(stylesheet)
245 self._page_control.document().setDefaultStyleSheet(stylesheet)
246
246
247 if syntax_style is None:
247 if syntax_style is None:
248 self._highlighter.set_style_sheet(stylesheet)
248 self._highlighter.set_style_sheet(stylesheet)
249 else:
249 else:
250 self._highlighter.set_style(syntax_style)
250 self._highlighter.set_style(syntax_style)
251
251
252 #---------------------------------------------------------------------------
252 #---------------------------------------------------------------------------
253 # 'IPythonWidget' protected interface
253 # 'IPythonWidget' protected interface
254 #---------------------------------------------------------------------------
254 #---------------------------------------------------------------------------
255
255
256 def _make_in_prompt(self, number):
256 def _make_in_prompt(self, number):
257 """ Given a prompt number, returns an HTML In prompt.
257 """ Given a prompt number, returns an HTML In prompt.
258 """
258 """
259 body = self.in_prompt % number
259 body = self.in_prompt % number
260 return '<span class="in-prompt">%s</span>' % body
260 return '<span class="in-prompt">%s</span>' % body
261
261
262 def _make_continuation_prompt(self, prompt):
262 def _make_continuation_prompt(self, prompt):
263 """ Given a plain text version of an In prompt, returns an HTML
263 """ Given a plain text version of an In prompt, returns an HTML
264 continuation prompt.
264 continuation prompt.
265 """
265 """
266 end_chars = '...: '
266 end_chars = '...: '
267 space_count = len(prompt.lstrip('\n')) - len(end_chars)
267 space_count = len(prompt.lstrip('\n')) - len(end_chars)
268 body = '&nbsp;' * space_count + end_chars
268 body = '&nbsp;' * space_count + end_chars
269 return '<span class="in-prompt">%s</span>' % body
269 return '<span class="in-prompt">%s</span>' % body
270
270
271 def _make_out_prompt(self, number):
271 def _make_out_prompt(self, number):
272 """ Given a prompt number, returns an HTML Out prompt.
272 """ Given a prompt number, returns an HTML Out prompt.
273 """
273 """
274 body = self.out_prompt % number
274 body = self.out_prompt % number
275 return '<span class="out-prompt">%s</span>' % body
275 return '<span class="out-prompt">%s</span>' % body
@@ -1,138 +1,127 b''
1 # System library imports
1 # System library imports
2 from PyQt4 import QtCore, QtGui
2 from PyQt4 import QtCore, QtGui
3
3
4 # Local imports
4 # Local imports
5 from IPython.frontend.qt.svg import save_svg, svg_to_clipboard, svg_to_image
5 from IPython.frontend.qt.svg import save_svg, svg_to_clipboard, svg_to_image
6 from ipython_widget import IPythonWidget
6 from ipython_widget import IPythonWidget
7
7
8
8
9 class RichIPythonWidget(IPythonWidget):
9 class RichIPythonWidget(IPythonWidget):
10 """ An IPythonWidget that supports rich text, including lists, images, and
10 """ An IPythonWidget that supports rich text, including lists, images, and
11 tables. Note that raw performance will be reduced compared to the plain
11 tables. Note that raw performance will be reduced compared to the plain
12 text version.
12 text version.
13 """
13 """
14
14
15 # Protected class variables.
15 # Protected class variables.
16 _svg_text_format_property = 1
16 _svg_text_format_property = 1
17
17
18 # We need to override this because this class uses QTextEdit.
19 dark_stylesheet = """
20 QTextEdit { background-color: black; color: white }
21 QFrame { border: 1px solid grey; }
22 .error { color: red; }
23 .in-prompt { color: lime; }
24 .in-prompt-number { color: lime; font-weight: bold; }
25 .out-prompt { color: red; }
26 .out-prompt-number { color: red; font-weight: bold; }
27 """
28
29 #---------------------------------------------------------------------------
18 #---------------------------------------------------------------------------
30 # 'object' interface
19 # 'object' interface
31 #---------------------------------------------------------------------------
20 #---------------------------------------------------------------------------
32
21
33 def __init__(self, *args, **kw):
22 def __init__(self, *args, **kw):
34 """ Create a RichIPythonWidget.
23 """ Create a RichIPythonWidget.
35 """
24 """
36 kw['kind'] = 'rich'
25 kw['kind'] = 'rich'
37 super(RichIPythonWidget, self).__init__(*args, **kw)
26 super(RichIPythonWidget, self).__init__(*args, **kw)
38
27
39 #---------------------------------------------------------------------------
28 #---------------------------------------------------------------------------
40 # 'ConsoleWidget' protected interface
29 # 'ConsoleWidget' protected interface
41 #---------------------------------------------------------------------------
30 #---------------------------------------------------------------------------
42
31
43 def _show_context_menu(self, pos):
32 def _show_context_menu(self, pos):
44 """ Reimplemented to show a custom context menu for images.
33 """ Reimplemented to show a custom context menu for images.
45 """
34 """
46 format = self._control.cursorForPosition(pos).charFormat()
35 format = self._control.cursorForPosition(pos).charFormat()
47 name = format.stringProperty(QtGui.QTextFormat.ImageName)
36 name = format.stringProperty(QtGui.QTextFormat.ImageName)
48 if name.isEmpty():
37 if name.isEmpty():
49 super(RichIPythonWidget, self)._show_context_menu(pos)
38 super(RichIPythonWidget, self)._show_context_menu(pos)
50 else:
39 else:
51 menu = QtGui.QMenu()
40 menu = QtGui.QMenu()
52
41
53 menu.addAction('Copy Image', lambda: self._copy_image(name))
42 menu.addAction('Copy Image', lambda: self._copy_image(name))
54 menu.addAction('Save Image As...', lambda: self._save_image(name))
43 menu.addAction('Save Image As...', lambda: self._save_image(name))
55 menu.addSeparator()
44 menu.addSeparator()
56
45
57 svg = format.stringProperty(self._svg_text_format_property)
46 svg = format.stringProperty(self._svg_text_format_property)
58 if not svg.isEmpty():
47 if not svg.isEmpty():
59 menu.addSeparator()
48 menu.addSeparator()
60 menu.addAction('Copy SVG', lambda: svg_to_clipboard(svg))
49 menu.addAction('Copy SVG', lambda: svg_to_clipboard(svg))
61 menu.addAction('Save SVG As...',
50 menu.addAction('Save SVG As...',
62 lambda: save_svg(svg, self._control))
51 lambda: save_svg(svg, self._control))
63
52
64 menu.exec_(self._control.mapToGlobal(pos))
53 menu.exec_(self._control.mapToGlobal(pos))
65
54
66 #---------------------------------------------------------------------------
55 #---------------------------------------------------------------------------
67 # 'FrontendWidget' protected interface
56 # 'FrontendWidget' protected interface
68 #---------------------------------------------------------------------------
57 #---------------------------------------------------------------------------
69
58
70 def _process_execute_ok(self, msg):
59 def _process_execute_ok(self, msg):
71 """ Reimplemented to handle matplotlib plot payloads.
60 """ Reimplemented to handle matplotlib plot payloads.
72 """
61 """
73 payload = msg['content']['payload']
62 payload = msg['content']['payload']
74 for item in payload:
63 for item in payload:
75 if item['type'] == 'plot':
64 if item['type'] == 'plot':
76 if item['format'] == 'svg':
65 if item['format'] == 'svg':
77 svg = item['data']
66 svg = item['data']
78 try:
67 try:
79 image = svg_to_image(svg)
68 image = svg_to_image(svg)
80 except ValueError:
69 except ValueError:
81 self._append_plain_text('Received invalid plot data.')
70 self._append_plain_text('Received invalid plot data.')
82 else:
71 else:
83 format = self._add_image(image)
72 format = self._add_image(image)
84 format.setProperty(self._svg_text_format_property, svg)
73 format.setProperty(self._svg_text_format_property, svg)
85 cursor = self._get_end_cursor()
74 cursor = self._get_end_cursor()
86 cursor.insertBlock()
75 cursor.insertBlock()
87 cursor.insertImage(format)
76 cursor.insertImage(format)
88 cursor.insertBlock()
77 cursor.insertBlock()
89 else:
78 else:
90 # Add other plot formats here!
79 # Add other plot formats here!
91 pass
80 pass
92 else:
81 else:
93 # Add other payload types here!
82 # Add other payload types here!
94 pass
83 pass
95 else:
84 else:
96 super(RichIPythonWidget, self)._process_execute_ok(msg)
85 super(RichIPythonWidget, self)._process_execute_ok(msg)
97
86
98 #---------------------------------------------------------------------------
87 #---------------------------------------------------------------------------
99 # 'RichIPythonWidget' protected interface
88 # 'RichIPythonWidget' protected interface
100 #---------------------------------------------------------------------------
89 #---------------------------------------------------------------------------
101
90
102 def _add_image(self, image):
91 def _add_image(self, image):
103 """ Adds the specified QImage to the document and returns a
92 """ Adds the specified QImage to the document and returns a
104 QTextImageFormat that references it.
93 QTextImageFormat that references it.
105 """
94 """
106 document = self._control.document()
95 document = self._control.document()
107 name = QtCore.QString.number(image.cacheKey())
96 name = QtCore.QString.number(image.cacheKey())
108 document.addResource(QtGui.QTextDocument.ImageResource,
97 document.addResource(QtGui.QTextDocument.ImageResource,
109 QtCore.QUrl(name), image)
98 QtCore.QUrl(name), image)
110 format = QtGui.QTextImageFormat()
99 format = QtGui.QTextImageFormat()
111 format.setName(name)
100 format.setName(name)
112 return format
101 return format
113
102
114 def _copy_image(self, name):
103 def _copy_image(self, name):
115 """ Copies the ImageResource with 'name' to the clipboard.
104 """ Copies the ImageResource with 'name' to the clipboard.
116 """
105 """
117 image = self._get_image(name)
106 image = self._get_image(name)
118 QtGui.QApplication.clipboard().setImage(image)
107 QtGui.QApplication.clipboard().setImage(image)
119
108
120 def _get_image(self, name):
109 def _get_image(self, name):
121 """ Returns the QImage stored as the ImageResource with 'name'.
110 """ Returns the QImage stored as the ImageResource with 'name'.
122 """
111 """
123 document = self._control.document()
112 document = self._control.document()
124 variant = document.resource(QtGui.QTextDocument.ImageResource,
113 variant = document.resource(QtGui.QTextDocument.ImageResource,
125 QtCore.QUrl(name))
114 QtCore.QUrl(name))
126 return variant.toPyObject()
115 return variant.toPyObject()
127
116
128 def _save_image(self, name, format='PNG'):
117 def _save_image(self, name, format='PNG'):
129 """ Shows a save dialog for the ImageResource with 'name'.
118 """ Shows a save dialog for the ImageResource with 'name'.
130 """
119 """
131 dialog = QtGui.QFileDialog(self._control, 'Save Image')
120 dialog = QtGui.QFileDialog(self._control, 'Save Image')
132 dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
121 dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
133 dialog.setDefaultSuffix(format.lower())
122 dialog.setDefaultSuffix(format.lower())
134 dialog.setNameFilter('%s file (*.%s)' % (format, format.lower()))
123 dialog.setNameFilter('%s file (*.%s)' % (format, format.lower()))
135 if dialog.exec_():
124 if dialog.exec_():
136 filename = dialog.selectedFiles()[0]
125 filename = dialog.selectedFiles()[0]
137 image = self._get_image(name)
126 image = self._get_image(name)
138 image.save(filename, format)
127 image.save(filename, format)
General Comments 0
You need to be logged in to leave comments. Login now