Ticket #971: keep_offline.patch

File keep_offline.patch, 7.8 KB (added by lucian, 15 years ago)

'Keep offline' button next to 'Bookmark' button, the resulting Journal objects can be opened with browse. Not tested enough.

  • downloadmanager.py

    diff --git a/downloadmanager.py b/downloadmanager.py
    index a3fe6d8..a2d8c82 100644
    a b import logging 
    2020from gettext import gettext as _
    2121import time
    2222import tempfile
     23import zipfile
     24import shutil
    2325import urlparse
    2426import urllib
    2527
    class _SaveLinkProgressListener(object): 
    382384
    383385    def onDataAvailable(self, request, context, inputStream, offset, count):
    384386        self._external_listener.onDataAvailable(request, context, inputStream,
    385                                                 offset, count);
    386 
     387                                                offset, count)
     388                                               
     389def save_document(browser, activity):
     390    cls = components.classes[ \
     391                    '@mozilla.org/embedding/browser/nsWebBrowserPersist;1']
     392    persist = cls.createInstance(interfaces.nsIWebBrowserPersist)
     393                                     
     394    local = components.classes["@mozilla.org/file/local;1"]
     395    local_file = local.createInstance(interfaces.nsILocalFile)
     396    local_data = local.createInstance(interfaces.nsILocalFile)
     397
     398    temp_dir = tempfile.mkdtemp()
     399
     400    local_file.initWithPath(os.path.join(temp_dir, 'index.html'))
     401    local_data.initWithPath(os.path.join(temp_dir, 'data'))
     402   
     403    persist.persistFlags = interfaces.nsIWebBrowserPersist \
     404                                     .PERSIST_FLAGS_REPLACE_EXISTING_FILES
     405    persist.progressListener = _SaveDocumentProgressListener(activity,
     406                                    temp_dir, browser.props.title)._wrapped
     407    persist.saveDocument(browser.dom_window.document, local_file, local_data,
     408                         None, 0, 0)
     409                                 
     410class _SaveDocumentProgressListener(object):
     411    _com_interfaces_ = interfaces.nsIWebProgressListener
     412   
     413    def __init__(self, activity, temp_dir, title):
     414        self._activity = activity
     415        self._temp_dir = temp_dir
     416        self._title = title
     417        self._zip_path = os.path.join(activity.get_activity_root(),
     418                                      'instance', self._title+'.zip')
     419        self._jobject = None
     420       
     421        self._wrapped = xpcom.server.WrapObject(self,
     422                                interfaces.nsIWebProgressListener)
     423                               
     424    def onStateChange(self, web_progress, request, state_flags, status):
     425        if state_flags & interfaces.nsIWebProgressListener.STATE_STOP:
     426            if NS_FAILED(status):
     427                alert = TimeoutAlert(9)
     428                alert.props.title = _('Keep offline')
     429                alert.props.msg = _('Saving "%s" for offline use failed') % \
     430                                  self._title
     431                self._activity.add_alert(alert)
     432                alert.connect('response', self.__fail_response_cb)
     433                alert.show()
     434            else:
     435                try: # HACK because NS_FAILED(status) is wrong
     436                    self._create_zip()
     437                    self._create_journal_object()
     438                except OSError:
     439                    return
     440               
     441                alert = Alert()
     442                alert.props.title = _('Keep offline')
     443               
     444                cancel_icon = Icon(icon_name='dialog-cancel')
     445                alert.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), cancel_icon)
     446                cancel_icon.show()
     447
     448                open_icon = Icon(icon_name='filesave')
     449                alert.add_button(gtk.RESPONSE_OK, _('Show in Journal'),
     450                                 open_icon)
     451                open_icon.show()
     452               
     453                self._activity.add_alert(alert)
     454                alert.connect('response', self.__success_response_cb)
     455               
     456    def onStatusChange(self, web_progress, request, status, message):
     457        pass
     458                   
     459    def onProgressChange(self, web_progress, request, cur_self_progress,
     460                           max_self_progress, cur_total_progress,
     461                           max_total_progress):
     462        pass
     463       
     464    def onLocationChange(self, web_progress, request, location):
     465        pass
     466   
     467    def onSecurityChange(self, web_progress, request, state):
     468        pass
     469                               
     470    def __fail_response_cb(self, alert, response_id):
     471        self._activity.remove_alert(alert)
     472       
     473    def __success_response_cb(self, alert, response_id):
     474        self._activity.remove_alert(alert)
     475       
     476        if response_id is gtk.RESPONSE_OK:
     477            activity.show_object_in_journal(self._jobject.object_id)
     478           
     479               
     480    def _create_zip(self):
     481        bundle = zipfile.ZipFile(self._zip_path, 'w', zipfile.ZIP_DEFLATED)
     482
     483        bundle.write(os.path.join(self._temp_dir, 'index.html'), 'index.html')
     484        data_path = os.path.join(self._temp_dir, 'data')
     485        for i in os.listdir(data_path):
     486            bundle.write(os.path.join(data_path, i),
     487                         os.path.join('data', i))
     488        bundle.close()
     489               
     490    def _create_journal_object(self):
     491        self._jobject = datastore.create()
     492        self._jobject.metadata['title'] = self._title
     493        self._jobject.metadata['icon-color'] = \
     494                profile.get_color().to_string()
     495        self._jobject.metadata['mime_type'] = 'application/zip'
     496        self._jobject.metadata['activity'] = 'org.laptop.WebActivity'
     497        self._jobject.file_path = self._zip_path
     498        datastore.write(self._jobject)
  • webactivity.py

    diff --git a/webactivity.py b/webactivity.py
    index f5657c7..64472ad 100644
    a b import shutil 
    3030import sqlite3
    3131import cjson
    3232import gconf
     33import zipfile
     34import tempfile
    3335
    3436# HACK: Needed by http://dev.sugarlabs.org/ticket/456
    3537import gnome
    class WebActivity(activity.Activity): 
    395397            else:
    396398                _logger.error('Open uri-list: Does not support'
    397399                              'list of multiple uris by now.')
     400        elif self.metadata['mime_type'] == 'application/zip':
     401            temp_dir = tempfile.mkdtemp()
     402           
     403            z = zipfile.ZipFile(file_path, 'r')
     404            os.mkdir(os.path.join(temp_dir, 'data'))
     405            for i in z.namelist():
     406                open(os.path.join(temp_dir, i), 'wb').write(z.read(i))
     407               
     408            html_path = 'file://' + os.path.join(temp_dir, 'index.html')
     409            self._tabbed_view.props.current_browser.load_uri(html_path)
    398410        else:
    399411            self._tabbed_view.props.current_browser.load_uri(file_path)
    400412       
    class WebActivity(activity.Activity): 
    559571        browser = self._tabbed_view.props.current_browser
    560572        browser.get_source(async_cb, async_err_cb)
    561573
     574    def save_current_document(self):
     575        downloadmanager.save_document(self._tabbed_view.props.current_browser,
     576                                      self)
     577 No newline at end of file
  • webtoolbar.py

    diff --git a/webtoolbar.py b/webtoolbar.py
    index f784f34..4c5ff75 100644
    a b class PrimaryToolbar(ToolbarBox): 
    272272        self._link_add.connect('clicked', self._link_add_clicked_cb)
    273273        self.toolbar.insert(self._link_add, -1)
    274274        self._link_add.show()
     275       
     276        self._save_document = ToolButton('filesave')
     277        self._save_document.set_tooltip(_('Keep offline'))
     278        self._save_document.connect('clicked', self._save_document_clicked_cb)
     279        self.toolbar.insert(self._save_document, -1)
     280        self._save_document.show()
    275281
    276282        stop_button = StopButton(self._activity)
    277283        self.toolbar.insert(stop_button, -1)
    class PrimaryToolbar(ToolbarBox): 
    458464    def _link_add_clicked_cb(self, button):
    459465        self.emit('add-link')
    460466
     467    def _save_document_clicked_cb(self, button):
     468        self._activity.save_current_document()
     469 No newline at end of file