[Sugar-devel] [PATCH Browse 2/2] Add support for exporting ("printing") to PDF
Sascha Silbe
silbe at activitycentral.com
Sun May 29 10:04:22 EDT 2011
The content of the current tab gets exported as a new data store entry
(independent from the current Browse session), including some of the
metadata (title, original_url).
Similar to the way it works for Turtle Art, we expose the functionality as a
button in the Activity toolbar, with 'document-save' as icon. There is no way
for the user to influence the result (i.e. to set print options).
To work around a python-xpcom bug [1], we "patch" python-xpcom at runtime.
Given the current state of affairs regarding python-xpcom, this is probably
the best we can do.
[1] http://bugs.debian.org/628484
Signed-off-by: Sascha Silbe <silbe at activitycentral.com>
---
browser.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
webtoolbar.py | 10 ++++++++
2 files changed, 78 insertions(+), 0 deletions(-)
diff --git a/browser.py b/browser.py
index 649a71e..bd57e79 100644
--- a/browser.py
+++ b/browser.py
@@ -20,6 +20,7 @@ import os
import time
import logging
from gettext import gettext as _
+import tempfile
import gobject
import gtk
@@ -304,6 +305,73 @@ class Browser(WebView):
self.emit('is-setup')
+ def export_pdf(self):
+ temp_dir = os.path.join(activity.get_activity_root(), 'instance')
+ pdf_file = tempfile.NamedTemporaryFile(suffix='.pdf', dir=temp_dir,
+ delete=False)
+
+ logging.debug('pdf_file.name = %r', pdf_file.name)
+ try:
+ self._generate_pdf(pdf_file.name)
+ except:
+ os.remove(pdf_file.name)
+ raise
+
+ def _generate_pdf(self, file_name):
+ cls = components.classes['@mozilla.org/gfx/printsettings-service;1']
+ setting_service = cls.getService(interfaces.nsIPrintSettingsService)
+ req = self.get_dom_window().QueryInterface(interfaces.nsIInterfaceRequestor)
+ print_iface = req.getInterface(interfaces.nsIWebBrowserPrint)
+
+ settings = setting_service.newPrintSettings
+ settings.printSilent = True
+ settings.printToFile = True
+ settings.toFileName = file_name
+ settings.outputFormat = interfaces.nsIPrintSettings.kOutputFormatPDF
+
+ try:
+ print_method = getattr(print_iface, 'print')
+ except SyntaxError:
+ # HACK: Run-time patch python-xpcom to work around a bug.
+ # 'print' is a reserved keyword, so it must not occur in generated
+ # code.
+ iid = interfaces.nsIWebBrowserPrint
+ internal_interface = print_iface.__dict__['_interfaces_'][iid]
+ info = internal_interface.__dict__['_method_infos_']['print']
+ info.name = 'print_'
+ print_method = getattr(print_iface, 'print')
+
+ save_info = {'file_name': file_name, 'title': self.props.title,
+ 'uri': self.get_url_from_nsiuri(self.progress.location)}
+
+ def save_callback(info):
+ # Even after the progress listener reports completion, the file
+ # is still empty. We need to wait for everything to calm down
+ # before triggering the save.
+ gobject.idle_add(self._save_pdf, info)
+
+ listener = xpcom.server.WrapObject(SaveListener(save_info,
+ save_callback),
+ interfaces.nsIWebProgressListener)
+ print_method(settings, listener)
+
+ def _save_pdf(self, info):
+ logging.debug('_save_pdf(%r)', info)
+ try:
+ if os.stat(info['file_name']).st_size == 0:
+ raise ValueError('Generated PDF file is empty')
+
+ ds_object = datastore.create()
+ ds_object.file_path = info['file_name']
+ ds_object.metadata['mime_type'] = 'application/pdf'
+ ds_object.metadata['title'] = info['title']
+ ds_object.metadata['original_uri'] = info['uri']
+ datastore.write(ds_object, transfer_ownership=True)
+ except:
+ if os.path.exists(info['file_name']):
+ os.remove(info['file_name'])
+ raise
+
def get_url_from_nsiuri(self, uri):
"""
get a nsIURI object and return a string with the url
diff --git a/webtoolbar.py b/webtoolbar.py
index 8b0e108..3ce4011 100644
--- a/webtoolbar.py
+++ b/webtoolbar.py
@@ -255,6 +255,12 @@ class PrimaryToolbar(ToolbarBase):
else:
toolbar = self
+ export_pdf_button = ToolButton('document-save')
+ export_pdf_button.set_tooltip(_('Export as PDF'))
+ export_pdf_button.connect('clicked', self._export_pdf_cb)
+ activity_button.page.insert(export_pdf_button, -1)
+ export_pdf_button.show()
+
self._go_home = ToolButton('go-home')
self._go_home.set_tooltip(_('Home page'))
self._go_home.connect('clicked', self._go_home_cb)
@@ -494,3 +500,7 @@ class PrimaryToolbar(ToolbarBase):
def _link_add_clicked_cb(self, button):
self.emit('add-link')
+
+ def _export_pdf_cb(self, button):
+ browser = self._tabbed_view.props.current_browser
+ browser.export_pdf()
--
1.7.2.5
More information about the Sugar-devel
mailing list