##// END OF EJS Templates
HTML/XML export now single menu entry...
MinRK -
Show More
@@ -161,10 +161,34 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
161 self._reading_callback = None
161 self._reading_callback = None
162 self._tab_width = 8
162 self._tab_width = 8
163 self._text_completing_pos = 0
163 self._text_completing_pos = 0
164 self._filename = os.path.join(os.curdir, 'ipython.html')
164
165
165 # Set a monospaced font.
166 # Set a monospaced font.
166 self.reset_font()
167 self.reset_font()
167
168
169 # Configure actions.
170 action = QtGui.QAction('Print', None)
171 action.setEnabled(True)
172 action.setShortcut(QtGui.QKeySequence.Print)
173 action.triggered.connect(self.print_)
174 self.addAction(action)
175 self._print_action = action
176
177 action = QtGui.QAction('Save as HTML/XML', None)
178 action.setEnabled(self.can_export())
179 action.setShortcut(QtGui.QKeySequence.Save)
180 action.triggered.connect(self.export)
181 self.addAction(action)
182 self._export_action = action
183
184 action = QtGui.QAction('Select All', None)
185 action.setEnabled(True)
186 action.setShortcut(QtGui.QKeySequence.SelectAll)
187 action.triggered.connect(self.select_all)
188 self.addAction(action)
189 self._select_all_action = action
190
191
168 def eventFilter(self, obj, event):
192 def eventFilter(self, obj, event):
169 """ Reimplemented to ensure a console-like behavior in the underlying
193 """ Reimplemented to ensure a console-like behavior in the underlying
170 text widgets.
194 text widgets.
@@ -301,6 +325,12 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
301 return not QtGui.QApplication.clipboard().text().isEmpty()
325 return not QtGui.QApplication.clipboard().text().isEmpty()
302 return False
326 return False
303
327
328 def can_export(self):
329 """Returns whether we can export. Currently only rich widgets
330 can export html.
331 """
332 return self.kind == "rich"
333
304 def clear(self, keep_input=True):
334 def clear(self, keep_input=True):
305 """ Clear the console.
335 """ Clear the console.
306
336
@@ -502,50 +532,66 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
502 def print_(self, printer = None):
532 def print_(self, printer = None):
503 """ Print the contents of the ConsoleWidget to the specified QPrinter.
533 """ Print the contents of the ConsoleWidget to the specified QPrinter.
504 """
534 """
505 if(printer is None):
535 if (not printer):
506 printer = QtGui.QPrinter()
536 printer = QtGui.QPrinter()
507 if(QtGui.QPrintDialog(printer).exec_() != QtGui.QDialog.Accepted):
537 if(QtGui.QPrintDialog(printer).exec_() != QtGui.QDialog.Accepted):
508 return
538 return
509 self._control.print_(printer)
539 self._control.print_(printer)
510
540
511 def export_html_inline(self, parent = None):
541 def export(self, parent = None):
512 """ Export the contents of the ConsoleWidget as HTML with inline PNGs.
542 """Export HTML/XML in various modes from one Dialog."""
513 """
543 parent = parent or None # sometimes parent is False
514 self.export_html(parent, inline = True)
544 dialog = QtGui.QFileDialog(parent, 'Save Console as...')
545 dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
546 filters = [
547 'HTML with inline PNGs (*.html *.htm)',
548 'HTML with external PNGs (*.html *.htm)',
549 'XHTML with inline SVGs (*.xhtml *.xml)'
550 ]
551 dialog.setNameFilters(filters)
552 if self._filename:
553 dialog.selectFile(self._filename)
554 root,ext = os.path.splitext(self._filename)
555 if ext.lower() in ('.xml', '.xhtml'):
556 dialog.selectNameFilter(filters[-1])
557 if dialog.exec_():
558 filename = str(dialog.selectedFiles()[0])
559 self._filename = filename
560 choice = str(dialog.selectedNameFilter())
515
561
516 def export_html(self, parent = None, inline = False):
562 if choice.startswith('XHTML'):
563 exporter = self.export_xhtml
564 else:
565 exporter = lambda filename: self.export_html(filename, 'inline' in choice)
566
567 try:
568 return exporter(filename)
569 except Exception, e:
570 title = self.window().windowTitle()
571 msg = "Error while saving to: %s\n"%filename+str(e)
572 reply = QtGui.QMessageBox.warning(self, title, msg,
573 QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok)
574 return None
575
576 def export_html(self, filename, inline=False):
517 """ Export the contents of the ConsoleWidget as HTML.
577 """ Export the contents of the ConsoleWidget as HTML.
518
578
519 Parameters:
579 Parameters:
520 -----------
580 -----------
581 filename : str
582 The file to be saved.
521 inline : bool, optional [default True]
583 inline : bool, optional [default True]
522
523 If True, include images as inline PNGs. Otherwise,
584 If True, include images as inline PNGs. Otherwise,
524 include them as links to external PNG files, mimicking
585 include them as links to external PNG files, mimicking
525 Firefox's "Web Page, complete" behavior.
586 web browsers' "Web Page, Complete" behavior.
526 """
587 """
527 dialog = QtGui.QFileDialog(parent, 'Save HTML Document')
528 dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
529 dialog.setDefaultSuffix('html')
530 dialog.setNameFilter('HTML Document (*.htm *.html *)')
531 if dialog.exec_():
532 filename = str(dialog.selectedFiles()[0])
533 if(inline):
588 if(inline):
534 path = None
589 path = None
535 else:
590 else:
536 offset = filename.rfind(".")
591 root,ext = os.path.splitext(filename)
537 if(offset > 0):
592 path = root+"_files"
538 path = filename[:offset]+"_files"
539 else:
540 path = filename+"_files"
541 if os.path.isfile(path):
593 if os.path.isfile(path):
542 raise OSError("%s exists, but is not a dir"%path)
594 raise OSError("%s exists, but is not a directory."%path)
543 # don't mkdir unless there are images
544 # try:
545 # os.mkdir(path)
546 # except OSError:
547 # # TODO: check that this is an "already exists" error
548 # pass
549
595
550 f = open(filename, 'w')
596 f = open(filename, 'w')
551 try:
597 try:
@@ -557,20 +603,17 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
557 f.write(img_re.sub(
603 f.write(img_re.sub(
558 lambda x: self.image_tag(x, path = path, format = "png"),
604 lambda x: self.image_tag(x, path = path, format = "png"),
559 html))
605 html))
560 finally:
606 except Exception, e:
607 f.close()
608 raise e
609 else:
561 f.close()
610 f.close()
562 return filename
611 return filename
563 return None
564
612
565 def export_xhtml(self, parent = None):
613
614 def export_xhtml(self, filename):
566 """ Export the contents of the ConsoleWidget as XHTML with inline SVGs.
615 """ Export the contents of the ConsoleWidget as XHTML with inline SVGs.
567 """
616 """
568 dialog = QtGui.QFileDialog(parent, 'Save XHTML Document')
569 dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave)
570 dialog.setDefaultSuffix('xml')
571 dialog.setNameFilter('XHTML document (*.xml *.xhtml *)')
572 if dialog.exec_():
573 filename = str(dialog.selectedFiles()[0])
574 f = open(filename, 'w')
617 f = open(filename, 'w')
575 try:
618 try:
576 # N.B. this is overly restrictive, but Qt's output is
619 # N.B. this is overly restrictive, but Qt's output is
@@ -588,10 +631,12 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
588 f.write(img_re.sub(
631 f.write(img_re.sub(
589 lambda x: self.image_tag(x, path = None, format = "svg"),
632 lambda x: self.image_tag(x, path = None, format = "svg"),
590 html))
633 html))
591 finally:
634 except Exception, e:
635 f.close()
636 raise e
637 else:
592 f.close()
638 f.close()
593 return filename
639 return filename
594 return None
595
640
596 def fix_html_encoding(self, html):
641 def fix_html_encoding(self, html):
597 """ Return html string, with a UTF-8 declaration added to <HEAD>.
642 """ Return html string, with a UTF-8 declaration added to <HEAD>.
@@ -857,7 +902,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
857 def _context_menu_make(self, pos):
902 def _context_menu_make(self, pos):
858 """ Creates a context menu for the given QPoint (in widget coordinates).
903 """ Creates a context menu for the given QPoint (in widget coordinates).
859 """
904 """
860 menu = QtGui.QMenu()
905 menu = QtGui.QMenu(self)
861
906
862 cut_action = menu.addAction('Cut', self.cut)
907 cut_action = menu.addAction('Cut', self.cut)
863 cut_action.setEnabled(self.can_cut())
908 cut_action.setEnabled(self.can_cut())
@@ -872,22 +917,12 b' class ConsoleWidget(Configurable, QtGui.QWidget):'
872 paste_action.setShortcut(QtGui.QKeySequence.Paste)
917 paste_action.setShortcut(QtGui.QKeySequence.Paste)
873
918
874 menu.addSeparator()
919 menu.addSeparator()
875 menu.addAction('Select All', self.select_all)
920 menu.addAction(self._select_all_action)
876
921
877 if self.kind == 'rich':
878 # only the rich frontend can export html/xml
879 menu.addSeparator()
922 menu.addSeparator()
880 print_action = menu.addAction('Print', self.print_)
923 menu.addAction(self._export_action)
881 print_action.setEnabled(True)
924 menu.addAction(self._print_action)
882 html_action = menu.addAction('Export HTML (external PNGs)',
925
883 self.export_html)
884 html_action.setEnabled(True)
885 html_inline_action = menu.addAction('Export HTML (inline PNGs)',
886 self.export_html_inline)
887 html_inline_action.setEnabled(True)
888 xhtml_action = menu.addAction('Export XHTML (inline SVGs)',
889 self.export_xhtml)
890 xhtml_action.setEnabled(True)
891 return menu
926 return menu
892
927
893 def _control_key_down(self, modifiers, include_command=True):
928 def _control_key_down(self, modifiers, include_command=True):
General Comments 0
You need to be logged in to leave comments. Login now