Ticket #394: 0001-Cancel-a-download-if-space-is-very-tight-SL-394.4.patch

File 0001-Cancel-a-download-if-space-is-very-tight-SL-394.4.patch, 6.3 KB (added by humitos, 11 years ago)

This patch puts the "enough_space" in the Download class inside the Browse Activity, so we don't have to modify sugar3.activity.Activity class in this cycle

  • downloadmanager.py

    From f075a18ce5d3a9ad30420c569b4eb5e84db442b5 Mon Sep 17 00:00:00 2001
    From: Manuel Kaufmann <humitos@gmail.com>
    Date: Mon, 17 Sep 2012 11:19:02 -0300
    Subject: [PATCH Browse] Cancel a download if space is very tight SL #394
    
    It checks for enough space[1] before downloading the file. If there is no
    enough space, Browse will cancel the download process before starting
    it and an Alert will be shown to the user to inform this situation.
    
    [1] this check is: free_space - file_to_download > 50Mb
    
    Signed-off-by: Manuel Kaufmann <humitos@gmail.com>
    ---
     downloadmanager.py | 88 ++++++++++++++++++++++++++++++++++++++++++++----------
     1 file changed, 72 insertions(+), 16 deletions(-)
    
    diff --git a/downloadmanager.py b/downloadmanager.py
    index 9950c16..155864a 100644
    a b DS_DBUS_PATH = '/org/laptop/sugar/DataStore' 
    3838_active_downloads = []
    3939_dest_to_window = {}
    4040
     41SPACE_THRESHOLD = 52428800
     42
    4143
    4244def can_quit():
    4345    return len(_active_downloads) == 0
    class Download(object): 
    6163        self._activity = browser.get_toplevel()
    6264        self._source = download.get_uri()
    6365
    64         self._download.connect('notify::progress', self.__progress_change_cb)
    6566        self._download.connect('notify::status', self.__state_change_cb)
    6667        self._download.connect('error', self.__error_cb)
    6768
    class Download(object): 
    7475        self._stop_alert = None
    7576
    7677        # figure out download URI
    77         temp_path = os.path.join(activity.get_activity_root(), 'instance')
    78         if not os.path.exists(temp_path):
    79             os.makedirs(temp_path)
     78        self.temp_path = os.path.join(activity.get_activity_root(), 'instance')
     79        if not os.path.exists(self.temp_path):
     80            os.makedirs(self.temp_path)
    8081
    81         fd, self._dest_path = tempfile.mkstemp(dir=temp_path,
     82        fd, self._dest_path = tempfile.mkstemp(dir=self.temp_path,
    8283                                    suffix=download.get_suggested_filename(),
    8384                                    prefix='tmp')
    8485        os.close(fd)
    8586        logging.debug('Download destination path: %s' % self._dest_path)
    8687
     88        # We have to start the download to get 'total-size'
     89        # property. It not, 0 is returned
    8790        self._download.set_destination_uri('file://' + self._dest_path)
    8891        self._download.start()
    8992
    class Download(object): 
    9598    def __state_change_cb(self, download, gparamspec):
    9699        state = self._download.get_status()
    97100        if state == WebKit.DownloadStatus.STARTED:
    98             self._create_journal_object()
    99             self._object_id = self.dl_jobject.object_id
    100 
    101             alert = TimeoutAlert(9)
    102             alert.props.title = _('Download started')
    103             alert.props.msg = _('%s' % self._download.get_suggested_filename())
    104             self._activity.add_alert(alert)
    105             alert.connect('response', self.__start_response_cb)
    106             alert.show()
    107             global _active_downloads
    108             _active_downloads.append(self)
     101            # Check free space and cancel the download if there is not enough.
     102            total_size = self._download.get_total_size()
     103            logging.debug('Total size of the file: %s', total_size)
     104            enough_space = self.enough_space(
     105                total_size, path=self.temp_path)
     106            if not enough_space:
     107                logging.debug('Download canceled because of Disk Space')
     108                self.cancel()
     109
     110                self._canceled_alert = Alert()
     111                self._canceled_alert.props.title = _('Not enough space '
     112                                                     'to download')
     113
     114                total_size_mb = total_size / 1024.0 ** 2
     115                free_space_mb = self._free_available_space(
     116                    path=self.temp_path) - SPACE_THRESHOLD \
     117                    / 1024.0 ** 2
     118                filename = self._download.get_suggested_filename()
     119                self._canceled_alert.props.msg = \
     120                    _('Download "%s" requires %.2f MB of free space, only '
     121                      '%.2f MB is available' % (filename, total_size_mb,
     122                                              free_space_mb))
     123                ok_icon = Icon(icon_name='dialog-ok')
     124                self._canceled_alert.add_button(Gtk.ResponseType.OK,
     125                                                _('Ok'), ok_icon)
     126                ok_icon.show()
     127                self._canceled_alert.connect('response',
     128                                             self.__stop_response_cb)
     129                self._activity.add_alert(self._canceled_alert)
     130            else:
     131                self._download.connect('notify::progress',
     132                                       self.__progress_change_cb)
     133                self._create_journal_object()
     134                self._object_id = self.dl_jobject.object_id
     135
     136                alert = TimeoutAlert(9)
     137                alert.props.title = _('Download started')
     138                alert.props.msg = _('%s' %
     139                                    self._download.get_suggested_filename())
     140                self._activity.add_alert(alert)
     141                alert.connect('response', self.__start_response_cb)
     142                alert.show()
     143                global _active_downloads
     144                _active_downloads.append(self)
    109145
    110146        elif state == WebKit.DownloadStatus.FINISHED:
    111147            self._stop_alert = Alert()
    class Download(object): 
    197233    def cancel(self):
    198234        self._download.cancel()
    199235
     236    def enough_space(self, size, path='/'):
     237        """Check if there is enough (size) free space on path
     238
     239        size -- free space requested in Kb
     240
     241        path -- device where the check will be done. For example: '/tmp'
     242
     243        This method is useful to check the free space, for example,
     244        before starting a download from internet, creating a big map
     245        in some game or whatever action that needs some space in the
     246        Hard Disk.
     247        """
     248
     249        free_space = self._free_available_space(path=path)
     250        return free_space - size > SPACE_THRESHOLD
     251
     252    def _free_available_space(self, path='/'):
     253        s = os.statvfs(path)
     254        return s.f_bavail * s.f_frsize
     255
    200256    def _create_journal_object(self):
    201257        self.dl_jobject = datastore.create()
    202258        self.dl_jobject.metadata['title'] = \