[Sugar-devel] [PATCH Browse 2/2] Add support for exporting ("printing") to PDF

Gonzalo Odiard gonzalo at laptop.org
Sun May 29 19:18:31 EDT 2011


Thanks for working in this!
It's a great addition to Browse.

Gonzalo

On Sun, May 29, 2011 at 11:04 AM, Sascha Silbe <silbe at activitycentral.com>wrote:

> 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
>
> _______________________________________________
> Sugar-devel mailing list
> Sugar-devel at lists.sugarlabs.org
> http://lists.sugarlabs.org/listinfo/sugar-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sugarlabs.org/archive/sugar-devel/attachments/20110529/316d039c/attachment.html>


More information about the Sugar-devel mailing list