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