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>