Exemple #1
0
    def __quit_timeout_cb(self):
        self.unbusy()
        alert = TimeoutAlert(30)
        alert.props.title = _('An activity is not responding.')
        alert.props.msg = _('You may lose unsaved work if you continue.')
        alert.connect('response', self.__quit_accept_cb)

        self.add_alert(alert)
        alert.show()
Exemple #2
0
    def __quit_timeout_cb(self):
        jarabe.desktop.homewindow.get_instance().unbusy()
        alert = TimeoutAlert(30)
        alert.props.title = _("An activity is not responding.")
        alert.props.msg = _("You may lose unsaved work if you continue.")
        alert.connect("response", self.__quit_accept_cb)

        jarabe.desktop.homewindow.get_instance().add_alert(alert)
        alert.show()
    def print_file(self, widget):
        def _alert_response(alert, response):
            self.vbox.remove(alert)

        view = self.get_view()
        buffer = view.get_buffer()
        path = view.get_file()

        if not path:
            alert = TimeoutAlert(10)
            alert.props.title = _('This file has not saved.')
            alert.props.msg = _('You must save this file to print.')
            hbox = alert.get_children()[0]
            buttonbox = hbox.get_children()[1]
            button = buttonbox.get_children()[0]
            buttonbox.remove(button)

            alert.connect('response', _alert_response)

            self.vbox.pack_start(alert, False, False, 0)
            self.vbox.reorder_child(alert, 0)

            return

        compositor = GtkSource.PrintCompositor.new_from_view(view)
        compositor.set_wrap_mode(view.get_wrap_mode())
        compositor.set_highlight_syntax(buffer.get_highlight_syntax())
        compositor.set_print_line_numbers(self.conf['show-line-numbers'])

        if view.buffer.language:
            compositor.set_header_format(
                False,
                '%s - %s' % (view.buffer.get_language_str(), view.get_file()),
                None, None)

        compositor.set_footer_format(True, '%T', path, 'Page %N/%Q')
        compositor.set_print_header(True)
        compositor.set_print_footer(True)

        operation = Gtk.PrintOperation()
        operation.set_job_name(path)

        operation.connect('begin-print', self.begin_print, compositor)
        operation.connect('draw-page', self.draw_page, compositor)

        res = operation.run(Gtk.PrintOperationAction.PRINT_DIALOG, None)
        if res == Gtk.PrintOperationResult.ERROR:
            dialog = Gtk.MessageDialog(self,
                                       Gtk.DialogFlags.DESTROY_WITH_PARENT,
                                       Gtk.MessageType.ERROR,
                                       Gtk.ButtonsType.OK,
                                       'Error to print the file: %s' % path)

            dialog.run()
            dialog.destroy()
Exemple #4
0
    def print_file(self, widget):
        def _alert_response(alert, response):
            self.vbox.remove(alert)

        view = self.get_view()
        buffer = view.get_buffer()
        path = view.get_file()

        if not path:
            alert = TimeoutAlert(10)
            alert.props.title = G.TEXT_FILE_NOT_SAVED
            alert.props.msg = G.TEXT_MUST_SAVE
            hbox = alert.get_children()[0]
            buttonbox = hbox.get_children()[1]
            button = buttonbox.get_children()[0]
            buttonbox.remove(button)

            alert.connect("response", _alert_response)

            self.vbox.pack_start(alert, False, False, 0)
            self.vbox.reorder_child(alert, 0)

            return

        compositor = GtkSource.PrintCompositor.new_from_view(view)
        compositor.set_highlight_syntax(buffer.get_highlight_syntax())
        compositor.set_print_line_numbers(self.conf["show-line-numbers"])

        if view.buffer.language:
            compositor.set_header_format(
                False,
                "%s - %s" % (view.buffer.get_language_str(), view.get_file()),
                None, None)

        compositor.set_footer_format(True, "%T", path, "Page %N/%Q")
        compositor.set_print_header(True)
        compositor.set_print_footer(True)

        operation = Gtk.PrintOperation()
        operation.set_job_name(path)

        operation.connect("begin-print", self.begin_print, compositor)
        operation.connect("draw-page", self.draw_page, compositor)

        res = operation.run(Gtk.PrintOperationAction.PRINT_DIALOG, None)
        if res == Gtk.PrintOperationResult.ERROR:
            dialog = Gtk.MessageDialog(self,
                                       Gtk.DialogFlags.DESTROY_WITH_PARENT,
                                       Gtk.MessageType.ERROR,
                                       Gtk.ButtonsType.OK,
                                       "Error to print the file: %s" % path)

            dialog.run()
            dialog.destroy()
    def create_alert(self, path):
        alert = TimeoutAlert(10)
        alert.props.title = G.TEXT_FILE_NOT_EXISTS1
        alert.props.msg = G.TEXT_FILE_NOT_EXISTS2

        hbox = alert.get_children()[0]
        buttonbox = hbox.get_children()[1]
        button = buttonbox.get_children()[0]
        buttonbox.remove(button)

        alert.connect("response", self.__alert_response)

        self.vbox.pack_start(alert, False, False, 0)
        self.vbox.reorder_child(alert, 2)
    def __decide_destination_cb(self, download, suggested_filename):
        logging.debug('__decide_desintation_cb suggests %s',
                      suggested_filename)
        alert = TimeoutAlert(9)
        alert.props.title = _('Download started')
        alert.props.msg = suggested_filename
        self._activity.add_alert(alert)
        alert.connect('response', self.__start_response_cb)
        alert.show()

        self._suggested_filename = suggested_filename
        # figure out download URI
        self._dest_path = tempfile.mktemp(
            dir=self.temp_path, suffix=suggested_filename,
            prefix='tmp')
        logging.debug('Download destination path: %s' % self._dest_path)
        self._download.set_destination('file://' + self._dest_path)
        logging.error(self._download.get_destination)
        return True
Exemple #7
0
    def __decide_destination_cb(self, download, suggested_filename):
        logging.debug('__decide_desintation_cb suggests %s',
                      suggested_filename)
        self._start_alert = TimeoutAlert(9)
        self._start_alert.props.title = _('Downloading')
        self._start_alert.props.msg = suggested_filename
        self._activity.add_alert(self._start_alert)
        self._start_alert.connect('response', self.__start_response_cb)
        self._start_alert.show()

        self._suggested_filename = suggested_filename
        # figure out download URI
        self._dest_path = tempfile.mktemp(dir=self.temp_path,
                                          suffix=suggested_filename,
                                          prefix='tmp')
        logging.debug('Download destination path: %s' % self._dest_path)
        self._download.set_destination('file://' + self._dest_path)
        logging.error(self._download.get_destination)
        return True
Exemple #8
0
    def __quit_timeout_cb(self):
        self.unbusy()
        alert = TimeoutAlert(30)
        alert.props.title = _('An activity is not responding.')
        alert.props.msg = _('You may lose unsaved work if you continue.')
        alert.connect('response', self.__quit_accept_cb)

        self.add_alert(alert)
        alert.show()
Exemple #9
0
    def __quit_timeout_cb(self):
        jarabe.desktop.homewindow.get_instance().unbusy()
        alert = TimeoutAlert(30)
        alert.props.title = _('An activity is not responding.')
        alert.props.msg = _('You may lose unsaved work if you continue.')
        alert.connect('response', self.__quit_accept_cb)

        jarabe.desktop.homewindow.get_instance().add_alert(alert)
        alert.show()
Exemple #10
0
    def create_alert(self, path):
        alert = TimeoutAlert(10)
        alert.props.title = _('This file not exists.')
        alert.props.msg = _(
            "Apparently you've selected a file that does not exist.")
        image = Gtk.Image.new_from_stock(Gtk.STOCK_OK, Gtk.IconSize.MENU)
        alert.add_button(Gtk.ResponseType.NO, _('Ok'), icon=image)

        alert.connect('response', self.__alert_response)

        self.vbox.pack_start(alert, False, False, 0)
        self.vbox.reorder_child(alert, 1)
    def __state_change_cb(self, download, gparamspec):
        state = self._download.get_status()
        if state == WebKit.DownloadStatus.STARTED:
            self._create_journal_object()
            self._object_id = self.dl_jobject.object_id

            alert = TimeoutAlert(9)
            alert.props.title = _('Download started')
            alert.props.msg = _('%s' % self._download.get_suggested_filename())
            self._activity.add_alert(alert)
            alert.connect('response', self.__start_response_cb)
            alert.show()
            global _active_downloads
            _active_downloads.append(self)

        elif state == WebKit.DownloadStatus.FINISHED:
            self._stop_alert = Alert()
            self._stop_alert.props.title = _('Download completed')
            self._stop_alert.props.msg = \
                _('%s' % self._download.get_suggested_filename())
            open_icon = Icon(icon_name='zoom-activity')
            self._stop_alert.add_button(Gtk.ResponseType.APPLY,
                                        _('Show in Journal'), open_icon)
            open_icon.show()
            ok_icon = Icon(icon_name='dialog-ok')
            self._stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
            ok_icon.show()
            self._activity.add_alert(self._stop_alert)
            self._stop_alert.connect('response', self.__stop_response_cb)
            self._stop_alert.show()

            self.dl_jobject.metadata['title'] = \
                self._download.get_suggested_filename()
            self.dl_jobject.metadata['description'] = _('From: %s') \
                % self._source
            self.dl_jobject.metadata['progress'] = '100'
            self.dl_jobject.file_path = self._dest_path

            # sniff for a mime type, no way to get headers from WebKit
            sniffed_mime_type = mime.get_for_file(self._dest_path)
            self.dl_jobject.metadata['mime_type'] = sniffed_mime_type

            datastore.write(self.dl_jobject,
                            transfer_ownership=True,
                            reply_handler=self.__internal_save_cb,
                            error_handler=self.__internal_error_cb,
                            timeout=360)

        elif state == WebKit.DownloadStatus.CANCELLED:
            self.cleanup()
Exemple #12
0
from gi.repository import Gtk
from sugar3.graphics.alert import TimeoutAlert
from common import set_theme
set_theme()


def __start_response_cb(widget, data=None):
    print 'Response: start download'


w = Gtk.Window()
w.connect("delete-event", Gtk.main_quit)

box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
w.add(box)

alert = TimeoutAlert(9)
alert.props.title = 'Download started'
alert.props.msg = 'Sugar'
box.pack_start(alert, False, False, 0)
alert.connect('response', __start_response_cb)

w.show_all()

Gtk.main()
from gi.repository import Gtk

from sugar3.graphics.alert import Alert, TimeoutAlert

def _destroy_cb(widget, data=None):
    Gtk.main_quit()

def __start_response_cb(widget, data=None):
    print 'Response: start download'

w = Gtk.Window()
w.connect("destroy", _destroy_cb)

box = Gtk.VBox()
w.add(box)

alert = TimeoutAlert(9)
alert.props.title = 'Download started'
alert.props.msg = 'Sugar'
box.pack_start(alert, False, False, 0)
alert.connect('response', __start_response_cb)

w.show_all()

Gtk.main()
Exemple #14
0
class Download(object):
    def __init__(self, webkit_download, activity):
        self._download = webkit_download
        self._activity = activity

        self._source = self._download.get_request().get_uri()
        logging.debug('START Download %s', self._source)

        self.datastore_deleted_handler = None

        self.dl_jobject = None
        self._object_id = None
        self._start_alert = None
        self._stop_alert = None

        self._dest_path = ''
        self._progress = 0
        self._last_update_progress = 0
        self._progress_sid = None

        self.temp_path = os.path.join(self._activity.get_activity_root(),
                                      'instance')
        if not os.path.exists(self.temp_path):
            os.makedirs(self.temp_path)

        self._download.connect('failed', self.__download_failed_cb)
        self._download.connect('finished', self.__download_finished_cb)
        self._download.connect('received-data',
                               self.__download_received_data_cb)

        # Notify response is called before decide destination
        self._download.connect('notify::response', self.__notify_response_cb)
        self._download.connect('decide-destination',
                               self.__decide_destination_cb)
        self._download.connect('created-destination',
                               self.__created_destination_cb)

    def __notify_response_cb(self, download, pspec):
        logging.debug('__notify_response_cb')
        response = download.get_response()

        # Check free space and cancel the download if there is not enough.
        total_size = response.get_content_length()
        logging.debug('Total size of the file: %s', total_size)
        enough_space = self.enough_space(total_size, path=self.temp_path)
        if not enough_space:
            logging.debug('Download canceled because of Disk Space')
            self.cancel()

            self._canceled_alert = Alert()
            self._canceled_alert.props.title = _('Not enough space '
                                                 'to download')

            total_size_mb = total_size / 1024.0**2
            free_space_mb = (self._free_available_space(
                path=self.temp_path) - SPACE_THRESHOLD) \
                / 1024.0 ** 2
            filename = response.get_suggested_filename()
            self._canceled_alert.props.msg = \
                _('Download "%{filename}" requires %{total_size_in_mb}'
                  ' MB of free space, only %{free_space_in_mb} MB'
                  ' is available' %
                  {'filename': filename,
                   'total_size_in_mb': format_float(total_size_mb),
                   'free_space_in_mb': format_float(free_space_mb)})
            ok_icon = Icon(icon_name='dialog-ok')
            self._canceled_alert.add_button(Gtk.ResponseType.OK, _('Ok'),
                                            ok_icon)
            ok_icon.show()
            self._canceled_alert.connect('response',
                                         self.__canceled_response_cb)
            self._activity.add_alert(self._canceled_alert)

    def __canceled_response_cb(self, alert, response_id):
        self._activity.remove_alert(alert)

    def __decide_destination_cb(self, download, suggested_filename):
        logging.debug('__decide_desintation_cb suggests %s',
                      suggested_filename)
        self._start_alert = TimeoutAlert(9)
        self._start_alert.props.title = _('Downloading')
        self._start_alert.props.msg = suggested_filename
        self._activity.add_alert(self._start_alert)
        self._start_alert.connect('response', self.__start_response_cb)
        self._start_alert.show()

        self._suggested_filename = suggested_filename
        # figure out download URI
        self._dest_path = tempfile.mktemp(dir=self.temp_path,
                                          suffix=suggested_filename,
                                          prefix='tmp')
        logging.debug('Download destination path: %s' % self._dest_path)
        self._download.set_destination('file://' + self._dest_path)
        logging.error(self._download.get_destination)
        return True

    def __created_destination_cb(self, download, dest):
        logging.debug('__created_destination_cb at %s', dest)
        self._create_journal_object()
        self._object_id = self.dl_jobject.object_id

    def _update_progress(self):
        if self._progress > self._last_update_progress:
            self._last_update_progress = self._progress
            self.dl_jobject.metadata['progress'] = str(self._progress)
            datastore.write(self.dl_jobject)

        self._progress_sid = None
        return False

    def __download_received_data_cb(self, download, data_size):
        self._progress = int(self._download.get_estimated_progress() * 100)

        if self._progress_sid is None:
            self._progress_sid = GObject.timeout_add(PROGRESS_TIMEOUT,
                                                     self._update_progress)

    def __download_finished_cb(self, download):
        if hasattr(self._activity, 'busy'):
            self._activity.unbusy()

        if self._progress_sid is not None:
            GObject.source_remove(self._progress_sid)

        if self.dl_jobject is None:
            return  # the "failed" signal was observed

        self.dl_jobject.metadata['title'] = self._suggested_filename
        self.dl_jobject.metadata['description'] = _('From: %s') \
            % self._source
        self.dl_jobject.metadata['progress'] = '100'
        self.dl_jobject.file_path = self._dest_path

        mime_type = Gio.content_type_guess(self._dest_path)[0]
        if mime_type != 'application/vnd.olpc-sugar':
            mime_type = download.get_response().get_mime_type()

        self.dl_jobject.metadata['mime_type'] = mime_type

        if mime_type in ('image/bmp', 'image/gif', 'image/jpeg', 'image/png',
                         'image/tiff'):
            preview = self._get_preview()
            if preview is not None:
                self.dl_jobject.metadata['preview'] = \
                    dbus.ByteArray(preview)

        datastore.write(self.dl_jobject,
                        transfer_ownership=True,
                        reply_handler=self.__internal_save_cb,
                        error_handler=self.__internal_error_cb,
                        timeout=360)

        if self._start_alert is not None:
            self._activity.remove_alert(self._start_alert)
        self._stop_alert = Alert()
        self._stop_alert.props.title = _('Downloaded')
        self._stop_alert.props.msg = self._suggested_filename

        bundle = None
        if _HAS_BUNDLE_LAUNCHER:
            bundle = get_bundle(object_id=self._object_id)

        if bundle is not None:
            icon = Icon(file=bundle.get_icon())
            label = _('Open with %s') % bundle.get_name()
            response_id = Gtk.ResponseType.APPLY
        else:
            icon = Icon(icon_name='zoom-activity')
            label = _('Show in Journal')
            response_id = Gtk.ResponseType.ACCEPT

        self._stop_alert.add_button(response_id, label, icon)
        icon.show()

        ok_icon = Icon(icon_name='dialog-ok')
        self._stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
        ok_icon.show()

        self._activity.add_alert(self._stop_alert)
        self._stop_alert.connect('response', self.__stop_response_cb)
        self._stop_alert.show()

    def __download_failed_cb(self, download, error):
        logging.error('Error downloading URI due to %s' % error)
        self.cleanup()

    def __internal_save_cb(self):
        logging.debug('Object saved succesfully to the datastore.')
        self.cleanup()

    def __internal_error_cb(self, err):
        logging.debug('Error saving activity object to datastore: %s' % err)
        self.cleanup()

    def __start_response_cb(self, alert, response_id):
        if response_id is Gtk.ResponseType.CANCEL:
            logging.debug('Download Canceled')
            self.cancel()
            try:
                datastore.delete(self._object_id)
            except Exception as e:
                logging.warning('Object has been deleted already %s' % e)

            self.cleanup()
            if self._stop_alert is not None:
                self._activity.remove_alert(self._stop_alert)

        self._activity.remove_alert(alert)
        self._start_alert = None

    def __stop_response_cb(self, alert, response_id):
        if response_id == Gtk.ResponseType.APPLY:
            launch_bundle(object_id=self._object_id)
        if response_id == Gtk.ResponseType.ACCEPT:
            activity.show_object_in_journal(self._object_id)
        self._activity.remove_alert(alert)

    def cleanup(self):
        global _active_downloads
        if self in _active_downloads:
            _active_downloads.remove(self)

        if self.datastore_deleted_handler is not None:
            self.datastore_deleted_handler.remove()
            self.datastore_deleted_handler = None

        if os.path.isfile(self._dest_path):
            os.remove(self._dest_path)

        if self.dl_jobject is not None:
            self.dl_jobject.destroy()
            self.dl_jobject = None

    def cancel(self):
        self._download.cancel()

    def enough_space(self, size, path='/'):
        """Check if there is enough (size) free space on path

        size -- free space requested in Bytes

        path -- device where the check will be done. For example: '/tmp'

        This method is useful to check the free space, for example,
        before starting a download from internet, creating a big map
        in some game or whatever action that needs some space in the
        Hard Disk.
        """

        free_space = self._free_available_space(path=path)
        return free_space - size > SPACE_THRESHOLD

    def _free_available_space(self, path='/'):
        """Return available space in Bytes

        This method returns the available free space in the 'path' and
        returns this amount in Bytes.
        """

        s = os.statvfs(path)
        return s.f_bavail * s.f_frsize

    def _create_journal_object(self):
        logging.debug('_create_journal_object')
        self.dl_jobject = datastore.create()
        filename = self._download.get_response().get_suggested_filename()
        self.dl_jobject.metadata['title'] = \
            _('Downloading %(filename)s from \n%(source)s.') % \
            {'filename': filename, 'source': self._source}

        self.dl_jobject.metadata['progress'] = '0'
        self.dl_jobject.metadata['keep'] = '0'
        self.dl_jobject.metadata['buddies'] = ''
        self.dl_jobject.metadata['preview'] = ''
        self.dl_jobject.metadata['icon-color'] = \
            profile.get_color().to_string()
        self.dl_jobject.metadata['mime_type'] = ''
        self.dl_jobject.file_path = self._dest_path
        datastore.write(self.dl_jobject)

        bus = dbus.SessionBus()
        obj = bus.get_object(DS_DBUS_SERVICE, DS_DBUS_PATH)
        datastore_dbus = dbus.Interface(obj, DS_DBUS_INTERFACE)
        self.datastore_deleted_handler = datastore_dbus.connect_to_signal(
            'Deleted',
            self.__datastore_deleted_cb,
            arg0=self.dl_jobject.object_id)

    def _get_preview(self):
        # This code borrows from sugar3.activity.Activity.get_preview
        # to make the preview with cairo, and also uses GdkPixbuf to
        # load any GdkPixbuf supported format.
        pixbuf = GdkPixbuf.Pixbuf.new_from_file(self._dest_path)
        image_width = pixbuf.get_width()
        image_height = pixbuf.get_height()

        preview_width, preview_height = activity.PREVIEW_SIZE
        preview_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
                                             preview_width, preview_height)
        cr = cairo.Context(preview_surface)

        scale_w = preview_width * 1.0 / image_width
        scale_h = preview_height * 1.0 / image_height
        scale = min(scale_w, scale_h)

        translate_x = int((preview_width - (image_width * scale)) / 2)
        translate_y = int((preview_height - (image_height * scale)) / 2)

        cr.translate(translate_x, translate_y)
        cr.scale(scale, scale)

        cr.set_source_rgba(1, 1, 1, 0)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()
        Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0)
        cr.paint()

        preview_str = io.BytesIO()
        preview_surface.write_to_png(preview_str)
        return preview_str.getvalue()

    def __datastore_deleted_cb(self, uid):
        logging.debug(
            'Downloaded entry has been deleted'
            ' from the datastore: %r', uid)
        global _active_downloads
        if self in _active_downloads:
            self.cancel()
            self.cleanup()
Exemple #15
0
from gi.repository import Gtk
from sugar3.graphics.alert import TimeoutAlert
from common import set_theme

set_theme()
w = Gtk.Window()
w.connect("delete-event", Gtk.main_quit)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
w.add(box)

# Create a TimeoutAlert Object
alert = TimeoutAlert(5)
alert.props.title = '<Alert Title>'
alert.props.msg = '<Alert Message>'

# Add Timeout Object to the box
box.pack_start(alert, False, False, 0)


# Called when an alert object throws a response event.
def __alert_response_cb(alert, response_id):
    if response_id is Gtk.ResponseType.OK:
        print('Continue Button was clicked.')
    elif response_id is Gtk.ResponseType.CANCEL:
        print('Cancel Button was clicked.')
    elif response_id == -1:
        print('Timeout occurred')


alert.connect('response', __alert_response_cb)
w.show_all()
    def __state_change_cb(self, download, gparamspec):
        state = self._download.get_status()
        if state == WebKit.DownloadStatus.STARTED:
            # Check free space and cancel the download if there is not enough.
            total_size = self._download.get_total_size()
            logging.debug('Total size of the file: %s', total_size)
            enough_space = self.enough_space(total_size, path=self.temp_path)
            if not enough_space:
                logging.debug('Download canceled because of Disk Space')
                self.cancel()

                self._canceled_alert = Alert()
                self._canceled_alert.props.title = _('Not enough space '
                                                     'to download')

                total_size_mb = total_size / 1024.0**2
                free_space_mb = (self._free_available_space(
                    path=self.temp_path) - SPACE_THRESHOLD) \
                    / 1024.0 ** 2
                filename = self._download.get_suggested_filename()
                self._canceled_alert.props.msg = \
                    _('Download "%{filename}" requires %{total_size_in_mb}'
                      ' MB of free space, only %{free_space_in_mb} MB'
                      ' is available' %
                      {'filename': filename,
                       'total_size_in_mb': format_float(total_size_mb),
                       'free_space_in_mb': format_float(free_space_mb)})
                ok_icon = Icon(icon_name='dialog-ok')
                self._canceled_alert.add_button(Gtk.ResponseType.OK, _('Ok'),
                                                ok_icon)
                ok_icon.show()
                self._canceled_alert.connect('response',
                                             self.__stop_response_cb)
                self._activity.add_alert(self._canceled_alert)
            else:
                # FIXME: workaround for SL #4385
                # self._download.connect('notify::progress',
                #                        self.__progress_change_cb)
                self._download.connect('notify::current-size',
                                       self.__current_size_changed_cb)

                self._create_journal_object()
                self._object_id = self.dl_jobject.object_id

                alert = TimeoutAlert(9)
                alert.props.title = _('Download started')
                alert.props.msg = _('%s' %
                                    self._download.get_suggested_filename())
                self._activity.add_alert(alert)
                alert.connect('response', self.__start_response_cb)
                alert.show()
                global _active_downloads
                _active_downloads.append(self)

        elif state == WebKit.DownloadStatus.FINISHED:
            self._stop_alert = Alert()
            self._stop_alert.props.title = _('Download completed')
            self._stop_alert.props.msg = \
                _('%s' % self._download.get_suggested_filename())

            if self._progress_sid is not None:
                GObject.source_remove(self._progress_sid)

            self.dl_jobject.metadata['title'] = \
                self._download.get_suggested_filename()
            self.dl_jobject.metadata['description'] = _('From: %s') \
                % self._source
            self.dl_jobject.metadata['progress'] = '100'
            self.dl_jobject.file_path = self._dest_path

            # sniff for a mime type, no way to get headers from WebKit
            sniffed_mime_type = mime.get_for_file(self._dest_path)
            self.dl_jobject.metadata['mime_type'] = sniffed_mime_type

            if sniffed_mime_type in ('image/bmp', 'image/gif', 'image/jpeg',
                                     'image/png', 'image/tiff'):
                preview = self._get_preview()
                if preview is not None:
                    self.dl_jobject.metadata['preview'] = \
                        dbus.ByteArray(preview)

            datastore.write(self.dl_jobject,
                            transfer_ownership=True,
                            reply_handler=self.__internal_save_cb,
                            error_handler=self.__internal_error_cb,
                            timeout=360)

            bundle = None
            if _HAS_BUNDLE_LAUNCHER:
                bundle = get_bundle(object_id=self._object_id)

            if bundle is not None:
                icon = Icon(file=bundle.get_icon())
                label = _('Open with %s') % bundle.get_name()
                response_type = Gtk.ResponseType.APPLY
            else:
                icon = Icon(icon_name='zoom-activity')
                label = _('Show in Journal')
                response_type = Gtk.ResponseType.ACCEPT

            self._stop_alert.add_button(response_type, label, icon)
            icon.show()

            ok_icon = Icon(icon_name='dialog-ok')
            self._stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
            ok_icon.show()

            self._activity.add_alert(self._stop_alert)
            self._stop_alert.connect('response', self.__stop_response_cb)
            self._stop_alert.show()

        elif state == WebKit.DownloadStatus.CANCELLED:
            self.cleanup()
class Download(object):

    def __init__(self, webkit_download, activity):
        self._download = webkit_download
        self._activity = activity

        self._source = self._download.get_request().get_uri()
        logging.debug('START Download %s', self._source)

        self.datastore_deleted_handler = None

        self.dl_jobject = None
        self._object_id = None
        self._start_alert = None
        self._stop_alert = None

        self._dest_path = ''
        self._progress = 0
        self._last_update_progress = 0
        self._progress_sid = None

        self.temp_path = os.path.join(
            self._activity.get_activity_root(), 'instance')
        if not os.path.exists(self.temp_path):
            os.makedirs(self.temp_path)

        self._download.connect('failed', self.__download_failed_cb)
        self._download.connect('finished', self.__download_finished_cb)
        self._download.connect('received-data',
                               self.__download_received_data_cb)

        # Notify response is called before decide destination
        self._download.connect('notify::response', self.__notify_response_cb)
        self._download.connect('decide-destination',
                               self.__decide_destination_cb)
        self._download.connect('created-destination',
                               self.__created_destination_cb)

    def __notify_response_cb(self, download, pspec):
        logging.debug('__notify_response_cb')
        response = download.get_response()

        # Check free space and cancel the download if there is not enough.
        total_size = response.get_content_length()
        logging.debug('Total size of the file: %s', total_size)
        enough_space = self.enough_space(
            total_size, path=self.temp_path)
        if not enough_space:
            logging.debug('Download canceled because of Disk Space')
            self.cancel()

            self._canceled_alert = Alert()
            self._canceled_alert.props.title = _('Not enough space '
                                                 'to download')

            total_size_mb = total_size / 1024.0 ** 2
            free_space_mb = (self._free_available_space(
                path=self.temp_path) - SPACE_THRESHOLD) \
                / 1024.0 ** 2
            filename = response.get_suggested_filename()
            self._canceled_alert.props.msg = \
                _('Download "%{filename}" requires %{total_size_in_mb}'
                  ' MB of free space, only %{free_space_in_mb} MB'
                  ' is available' %
                  {'filename': filename,
                   'total_size_in_mb': format_float(total_size_mb),
                   'free_space_in_mb': format_float(free_space_mb)})
            ok_icon = Icon(icon_name='dialog-ok')
            self._canceled_alert.add_button(Gtk.ResponseType.OK,
                                            _('Ok'), ok_icon)
            ok_icon.show()
            self._canceled_alert.connect('response',
                                         self.__canceled_response_cb)
            self._activity.add_alert(self._canceled_alert)

    def __canceled_response_cb(self, alert, response_id):
        self._activity.remove_alert(alert)

    def __decide_destination_cb(self, download, suggested_filename):
        logging.debug('__decide_desintation_cb suggests %s',
                      suggested_filename)
        self._start_alert = TimeoutAlert(9)
        self._start_alert.props.title = _('Downloading')
        self._start_alert.props.msg = suggested_filename
        self._activity.add_alert(self._start_alert)
        self._start_alert.connect('response', self.__start_response_cb)
        self._start_alert.show()

        self._suggested_filename = suggested_filename
        # figure out download URI
        self._dest_path = tempfile.mktemp(
            dir=self.temp_path, suffix=suggested_filename,
            prefix='tmp')
        logging.debug('Download destination path: %s' % self._dest_path)
        self._download.set_destination('file://' + self._dest_path)
        logging.error(self._download.get_destination)
        return True

    def __created_destination_cb(self, download, dest):
        logging.debug('__created_destination_cb at %s', dest)
        self._create_journal_object()
        self._object_id = self.dl_jobject.object_id

    def _update_progress(self):
        if self._progress > self._last_update_progress:
            self._last_update_progress = self._progress
            self.dl_jobject.metadata['progress'] = str(self._progress)
            datastore.write(self.dl_jobject)

        self._progress_sid = None
        return False

    def __download_received_data_cb(self, download, data_size):
        self._progress = int(self._download.get_estimated_progress() * 100)

        if self._progress_sid is None:
            self._progress_sid = GObject.timeout_add(
                PROGRESS_TIMEOUT, self._update_progress)

    def __download_finished_cb(self, download):
        if hasattr(self._activity, 'busy'):
            self._activity.unbusy()

        if self._progress_sid is not None:
            GObject.source_remove(self._progress_sid)

        if self.dl_jobject is None:
            return  # the "failed" signal was observed

        self.dl_jobject.metadata['title'] = self._suggested_filename
        self.dl_jobject.metadata['description'] = _('From: %s') \
            % self._source
        self.dl_jobject.metadata['progress'] = '100'
        self.dl_jobject.file_path = self._dest_path

        mime_type = Gio.content_type_guess(self._dest_path)[0]
        if mime_type != 'application/vnd.olpc-sugar':
            mime_type = download.get_response().get_mime_type()

        self.dl_jobject.metadata['mime_type'] = mime_type

        if mime_type in ('image/bmp', 'image/gif', 'image/jpeg',
                         'image/png', 'image/tiff'):
            preview = self._get_preview()
            if preview is not None:
                self.dl_jobject.metadata['preview'] = \
                    dbus.ByteArray(preview)

        datastore.write(self.dl_jobject,
                        transfer_ownership=True,
                        reply_handler=self.__internal_save_cb,
                        error_handler=self.__internal_error_cb,
                        timeout=360)

        if self._start_alert is not None:
            self._activity.remove_alert(self._start_alert)
        self._stop_alert = Alert()
        self._stop_alert.props.title = _('Downloaded')
        self._stop_alert.props.msg = self._suggested_filename

        bundle = None
        if _HAS_BUNDLE_LAUNCHER:
            bundle = get_bundle(object_id=self._object_id)

        if bundle is not None:
            icon = Icon(file=bundle.get_icon())
            label = _('Open with %s') % bundle.get_name()
            response_id = Gtk.ResponseType.APPLY
        else:
            icon = Icon(icon_name='zoom-activity')
            label = _('Show in Journal')
            response_id = Gtk.ResponseType.ACCEPT

        self._stop_alert.add_button(response_id, label, icon)
        icon.show()

        ok_icon = Icon(icon_name='dialog-ok')
        self._stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
        ok_icon.show()

        self._activity.add_alert(self._stop_alert)
        self._stop_alert.connect('response', self.__stop_response_cb)
        self._stop_alert.show()

    def __download_failed_cb(self, download, error):
        logging.error('Error downloading URI due to %s'
                      % error)
        self.cleanup()

    def __internal_save_cb(self):
        logging.debug('Object saved succesfully to the datastore.')
        self.cleanup()

    def __internal_error_cb(self, err):
        logging.debug('Error saving activity object to datastore: %s' % err)
        self.cleanup()

    def __start_response_cb(self, alert, response_id):
        if response_id is Gtk.ResponseType.CANCEL:
            logging.debug('Download Canceled')
            self.cancel()
            try:
                datastore.delete(self._object_id)
            except Exception, e:
                logging.warning('Object has been deleted already %s' % e)

            self.cleanup()
            if self._stop_alert is not None:
                self._activity.remove_alert(self._stop_alert)

        self._activity.remove_alert(alert)
        self._start_alert = None
    def __state_change_cb(self, download, gparamspec):
        state = self._download.get_status()
        if state == WebKit.DownloadStatus.STARTED:
            # Check free space and cancel the download if there is not enough.
            total_size = self._download.get_total_size()
            logging.debug('Total size of the file: %s', total_size)
            enough_space = self.enough_space(total_size, path=self.temp_path)
            if not enough_space:
                logging.debug('Download canceled because of Disk Space')
                self.cancel()

                self._canceled_alert = Alert()
                self._canceled_alert.props.title = _('Not enough space '
                                                     'to download')

                total_size_mb = total_size / 1024.0**2
                free_space_mb = self._free_available_space(
                    path=self.temp_path) - SPACE_THRESHOLD / 1024.0**2
                filename = self._download.get_suggested_filename()
                self._canceled_alert.props.msg = \
                    _('Download "%{filename}" requires %{total_size_in_mb}'
                      ' MB of free space, only %{free_space_in_mb} MB'
                      ' is available' %
                      {'filename': filename,
                       'total_size_in_mb': format_float(total_size_mb),
                       'free_space_in_mb': format_float(free_space_mb)})
                ok_icon = Icon(icon_name='dialog-ok')
                self._canceled_alert.add_button(Gtk.ResponseType.OK, _('Ok'),
                                                ok_icon)
                ok_icon.show()
                self._canceled_alert.connect('response',
                                             self.__stop_response_cb)
                self._activity.add_alert(self._canceled_alert)
            else:
                self._download.connect('notify::progress',
                                       self.__progress_change_cb)
                self._create_journal_object()
                self._object_id = self.dl_jobject.object_id

                alert = TimeoutAlert(9)
                alert.props.title = _('Download started')
                alert.props.msg = _('%s' %
                                    self._download.get_suggested_filename())
                self._activity.add_alert(alert)
                alert.connect('response', self.__start_response_cb)
                alert.show()
                global _active_downloads
                _active_downloads.append(self)

        elif state == WebKit.DownloadStatus.FINISHED:
            self._stop_alert = Alert()
            self._stop_alert.props.title = _('Download completed')
            self._stop_alert.props.msg = \
                _('%s' % self._download.get_suggested_filename())
            open_icon = Icon(icon_name='zoom-activity')
            self._stop_alert.add_button(Gtk.ResponseType.APPLY,
                                        _('Show in Journal'), open_icon)
            open_icon.show()
            ok_icon = Icon(icon_name='dialog-ok')
            self._stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
            ok_icon.show()
            self._activity.add_alert(self._stop_alert)
            self._stop_alert.connect('response', self.__stop_response_cb)
            self._stop_alert.show()

            if self._dest_path.endswith('.journal'):

                metadata, preview_data, file_path = \
                    utils.unpackage_ds_object(self._dest_path)
                original_object_id = metadata['original_object_id']
                for key in metadata.keys():
                    self.dl_jobject.metadata[key] = metadata[key]

                self.dl_jobject.metadata['preview'] = dbus.ByteArray(
                    preview_data)

                self.dl_jobject.file_path = file_path

                datastore.write(self.dl_jobject,
                                transfer_ownership=True,
                                reply_handler=self.__internal_save_cb,
                                error_handler=self.__internal_error_cb,
                                timeout=360)

                # notify to the server, the object was successfully downloaded
                url = 'ws://%s:%d/websocket' % (self._activity.ip,
                                                self._activity.port)
                messanger = utils.Messanger(url)
                data = utils.get_user_data()
                data['object_id'] = original_object_id
                messanger.send_message('DOWNLOADED', data)

            else:
                self.dl_jobject.metadata['title'] = \
                    self._download.get_suggested_filename()
                self.dl_jobject.metadata['description'] = _('From: %s') \
                    % self._source
                self.dl_jobject.metadata['progress'] = '100'
                self.dl_jobject.file_path = self._dest_path

                # sniff for a mime type, no way to get headers from WebKit
                sniffed_mime_type = mime.get_for_file(self._dest_path)
                self.dl_jobject.metadata['mime_type'] = sniffed_mime_type

                datastore.write(self.dl_jobject,
                                transfer_ownership=True,
                                reply_handler=self.__internal_save_cb,
                                error_handler=self.__internal_error_cb,
                                timeout=360)

        elif state == WebKit.DownloadStatus.CANCELLED:
            self.cleanup()
    def __state_change_cb(self, download, gparamspec):
        state = self._download.get_status()
        if state == WebKit.DownloadStatus.STARTED:
            # Check free space and cancel the download if there is not enough.
            total_size = self._download.get_total_size()
            logging.debug('Total size of the file: %s', total_size)
            enough_space = self.enough_space(
                total_size, path=self.temp_path)
            if not enough_space:
                logging.debug('Download canceled because of Disk Space')
                self.cancel()

                self._canceled_alert = Alert()
                self._canceled_alert.props.title = _('Not enough space '
                                                     'to download')

                total_size_mb = total_size / 1024.0 ** 2
                free_space_mb = (self._free_available_space(
                    path=self.temp_path) - SPACE_THRESHOLD) \
                    / 1024.0 ** 2
                filename = self._download.get_suggested_filename()
                self._canceled_alert.props.msg = \
                    _('Download "%{filename}" requires %{total_size_in_mb}'
                      ' MB of free space, only %{free_space_in_mb} MB'
                      ' is available' %
                      {'filename': filename,
                       'total_size_in_mb': format_float(total_size_mb),
                       'free_space_in_mb': format_float(free_space_mb)})
                ok_icon = Icon(icon_name='dialog-ok')
                self._canceled_alert.add_button(Gtk.ResponseType.OK,
                                                _('Ok'), ok_icon)
                ok_icon.show()
                self._canceled_alert.connect('response',
                                             self.__stop_response_cb)
                self._activity.add_alert(self._canceled_alert)
            else:
                # FIXME: workaround for SL #4385
                # self._download.connect('notify::progress',
                #                        self.__progress_change_cb)
                self._download.connect('notify::current-size',
                                       self.__current_size_changed_cb)

                self._create_journal_object()
                self._object_id = self.dl_jobject.object_id

                alert = TimeoutAlert(9)
                alert.props.title = _('Download started')
                alert.props.msg = _('%s' %
                                    self._download.get_suggested_filename())
                self._activity.add_alert(alert)
                alert.connect('response', self.__start_response_cb)
                alert.show()
                global _active_downloads
                _active_downloads.append(self)

        elif state == WebKit.DownloadStatus.FINISHED:
            self._stop_alert = Alert()
            self._stop_alert.props.title = _('Download completed')
            self._stop_alert.props.msg = \
                _('%s' % self._download.get_suggested_filename())
            open_icon = Icon(icon_name='zoom-activity')
            self._stop_alert.add_button(Gtk.ResponseType.APPLY,
                                        _('Show in Journal'), open_icon)
            open_icon.show()
            ok_icon = Icon(icon_name='dialog-ok')
            self._stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
            ok_icon.show()
            self._activity.add_alert(self._stop_alert)
            self._stop_alert.connect('response', self.__stop_response_cb)
            self._stop_alert.show()

            if self._progress_sid is not None:
                GObject.source_remove(self._progress_sid)

            self.dl_jobject.metadata['title'] = \
                self._download.get_suggested_filename()
            self.dl_jobject.metadata['description'] = _('From: %s') \
                % self._source
            self.dl_jobject.metadata['progress'] = '100'
            self.dl_jobject.file_path = self._dest_path

            # sniff for a mime type, no way to get headers from WebKit
            sniffed_mime_type = mime.get_for_file(self._dest_path)
            self.dl_jobject.metadata['mime_type'] = sniffed_mime_type

            if sniffed_mime_type in ('image/bmp', 'image/gif', 'image/jpeg',
                                     'image/png', 'image/tiff'):
                preview = self._get_preview()
                if preview is not None:
                    self.dl_jobject.metadata['preview'] = \
                        dbus.ByteArray(preview)

            datastore.write(self.dl_jobject,
                            transfer_ownership=True,
                            reply_handler=self.__internal_save_cb,
                            error_handler=self.__internal_error_cb,
                            timeout=360)

        elif state == WebKit.DownloadStatus.CANCELLED:
            self.cleanup()
Exemple #20
0
class Download(object):
    def __init__(self, webkit_download, activity):
        self._download = webkit_download
        self._activity = activity

        self._source = self._download.get_request().get_uri()
        logging.debug('START Download %s', self._source)

        self.datastore_deleted_handler = None

        self.dl_jobject = None
        self._object_id = None
        self._start_alert = None
        self._stop_alert = None

        self._dest_path = ''
        self._progress = 0
        self._last_update_progress = 0
        self._progress_sid = None

        self.temp_path = os.path.join(self._activity.get_activity_root(),
                                      'instance')
        if not os.path.exists(self.temp_path):
            os.makedirs(self.temp_path)

        self._download.connect('failed', self.__download_failed_cb)
        self._download.connect('finished', self.__download_finished_cb)
        self._download.connect('received-data',
                               self.__download_received_data_cb)

        # Notify response is called before decide destination
        self._download.connect('notify::response', self.__notify_response_cb)
        self._download.connect('decide-destination',
                               self.__decide_destination_cb)
        self._download.connect('created-destination',
                               self.__created_destination_cb)

    def __notify_response_cb(self, download, pspec):
        logging.debug('__notify_response_cb')
        response = download.get_response()

        # Check free space and cancel the download if there is not enough.
        total_size = response.get_content_length()
        logging.debug('Total size of the file: %s', total_size)
        enough_space = self.enough_space(total_size, path=self.temp_path)
        if not enough_space:
            logging.debug('Download canceled because of Disk Space')
            self.cancel()

            self._canceled_alert = Alert()
            self._canceled_alert.props.title = _('Not enough space '
                                                 'to download')

            total_size_mb = total_size / 1024.0**2
            free_space_mb = (self._free_available_space(
                path=self.temp_path) - SPACE_THRESHOLD) \
                / 1024.0 ** 2
            filename = response.get_suggested_filename()
            self._canceled_alert.props.msg = \
                _('Download "%{filename}" requires %{total_size_in_mb}'
                  ' MB of free space, only %{free_space_in_mb} MB'
                  ' is available' %
                  {'filename': filename,
                   'total_size_in_mb': format_float(total_size_mb),
                   'free_space_in_mb': format_float(free_space_mb)})
            ok_icon = Icon(icon_name='dialog-ok')
            self._canceled_alert.add_button(Gtk.ResponseType.OK, _('Ok'),
                                            ok_icon)
            ok_icon.show()
            self._canceled_alert.connect('response',
                                         self.__canceled_response_cb)
            self._activity.add_alert(self._canceled_alert)

    def __canceled_response_cb(self, alert, response_id):
        self._activity.remove_alert(alert)

    def __decide_destination_cb(self, download, suggested_filename):
        logging.debug('__decide_desintation_cb suggests %s',
                      suggested_filename)
        self._start_alert = TimeoutAlert(9)
        self._start_alert.props.title = _('Downloading')
        self._start_alert.props.msg = suggested_filename
        self._activity.add_alert(self._start_alert)
        self._start_alert.connect('response', self.__start_response_cb)
        self._start_alert.show()

        self._suggested_filename = suggested_filename
        # figure out download URI
        self._dest_path = tempfile.mktemp(dir=self.temp_path,
                                          suffix=suggested_filename,
                                          prefix='tmp')
        logging.debug('Download destination path: %s' % self._dest_path)
        self._download.set_destination('file://' + self._dest_path)
        logging.error(self._download.get_destination)
        return True

    def __created_destination_cb(self, download, dest):
        logging.debug('__created_destination_cb at %s', dest)
        self._create_journal_object()
        self._object_id = self.dl_jobject.object_id

    def _update_progress(self):
        if self._progress > self._last_update_progress:
            self._last_update_progress = self._progress
            self.dl_jobject.metadata['progress'] = str(self._progress)
            datastore.write(self.dl_jobject)

        self._progress_sid = None
        return False

    def __download_received_data_cb(self, download, data_size):
        self._progress = int(self._download.get_estimated_progress() * 100)

        if self._progress_sid is None:
            self._progress_sid = GObject.timeout_add(PROGRESS_TIMEOUT,
                                                     self._update_progress)

    def __download_finished_cb(self, download):
        if hasattr(self._activity, 'busy'):
            self._activity.unbusy()

        if self._progress_sid is not None:
            GObject.source_remove(self._progress_sid)

        if self.dl_jobject is None:
            return  # the "failed" signal was observed

        self.dl_jobject.metadata['title'] = self._suggested_filename
        self.dl_jobject.metadata['description'] = _('From: %s') \
            % self._source
        self.dl_jobject.metadata['progress'] = '100'
        self.dl_jobject.file_path = self._dest_path

        mime_type = Gio.content_type_guess(self._dest_path)[0]
        if mime_type != 'application/vnd.olpc-sugar':
            mime_type = download.get_response().get_mime_type()

        self.dl_jobject.metadata['mime_type'] = mime_type

        if mime_type in ('image/bmp', 'image/gif', 'image/jpeg', 'image/png',
                         'image/tiff'):
            preview = self._get_preview()
            if preview is not None:
                self.dl_jobject.metadata['preview'] = \
                    dbus.ByteArray(preview)

        datastore.write(self.dl_jobject,
                        transfer_ownership=True,
                        reply_handler=self.__internal_save_cb,
                        error_handler=self.__internal_error_cb,
                        timeout=360)

        if self._start_alert is not None:
            self._activity.remove_alert(self._start_alert)
        self._stop_alert = Alert()
        self._stop_alert.props.title = _('Downloaded')
        self._stop_alert.props.msg = self._suggested_filename

        bundle = None
        if _HAS_BUNDLE_LAUNCHER:
            bundle = get_bundle(object_id=self._object_id)

        if bundle is not None:
            icon = Icon(file=bundle.get_icon())
            label = _('Open with %s') % bundle.get_name()
            response_id = Gtk.ResponseType.APPLY
        else:
            icon = Icon(icon_name='zoom-activity')
            label = _('Show in Journal')
            response_id = Gtk.ResponseType.ACCEPT

        self._stop_alert.add_button(response_id, label, icon)
        icon.show()

        ok_icon = Icon(icon_name='dialog-ok')
        self._stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
        ok_icon.show()

        self._activity.add_alert(self._stop_alert)
        self._stop_alert.connect('response', self.__stop_response_cb)
        self._stop_alert.show()

    def __download_failed_cb(self, download, error):
        logging.error('Error downloading URI due to %s' % error)
        self.cleanup()

    def __internal_save_cb(self):
        logging.debug('Object saved succesfully to the datastore.')
        self.cleanup()

    def __internal_error_cb(self, err):
        logging.debug('Error saving activity object to datastore: %s' % err)
        self.cleanup()

    def __start_response_cb(self, alert, response_id):
        if response_id is Gtk.ResponseType.CANCEL:
            logging.debug('Download Canceled')
            self.cancel()
            try:
                datastore.delete(self._object_id)
            except Exception, e:
                logging.warning('Object has been deleted already %s' % e)

            self.cleanup()
            if self._stop_alert is not None:
                self._activity.remove_alert(self._stop_alert)

        self._activity.remove_alert(alert)
        self._start_alert = None
    def __state_change_cb(self, download, gparamspec):
        state = self._download.get_status()
        if state == WebKit.DownloadStatus.STARTED:
            # Check free space and cancel the download if there is not enough.
            total_size = self._download.get_total_size()
            logging.debug('Total size of the file: %s', total_size)
            enough_space = self.enough_space(
                total_size, path=self.temp_path)
            if not enough_space:
                logging.debug('Download canceled because of Disk Space')
                self.cancel()

                self._canceled_alert = Alert()
                self._canceled_alert.props.title = _('Not enough space '
                                                     'to download')

                total_size_mb = total_size / 1024.0 ** 2
                free_space_mb = self._free_available_space(
                    path=self.temp_path) - SPACE_THRESHOLD / 1024.0 ** 2
                filename = self._download.get_suggested_filename()
                self._canceled_alert.props.msg = \
                    _('Download "%{filename}" requires %{total_size_in_mb}'
                      ' MB of free space, only %{free_space_in_mb} MB'
                      ' is available' %
                      {'filename': filename,
                       'total_size_in_mb': format_float(total_size_mb),
                       'free_space_in_mb': format_float(free_space_mb)})
                ok_icon = Icon(icon_name='dialog-ok')
                self._canceled_alert.add_button(Gtk.ResponseType.OK,
                                                _('Ok'), ok_icon)
                ok_icon.show()
                self._canceled_alert.connect('response',
                                             self.__stop_response_cb)
                self._activity.add_alert(self._canceled_alert)
            else:
                self._download.connect('notify::progress',
                                       self.__progress_change_cb)
                self._create_journal_object()
                self._object_id = self.dl_jobject.object_id

                alert = TimeoutAlert(9)
                alert.props.title = _('Download started')
                alert.props.msg = _('%s' %
                                    self._download.get_suggested_filename())
                self._activity.add_alert(alert)
                alert.connect('response', self.__start_response_cb)
                alert.show()
                global _active_downloads
                _active_downloads.append(self)

        elif state == WebKit.DownloadStatus.FINISHED:
            self._stop_alert = Alert()
            self._stop_alert.props.title = _('Download completed')
            self._stop_alert.props.msg = \
                _('%s' % self._download.get_suggested_filename())
            open_icon = Icon(icon_name='zoom-activity')
            self._stop_alert.add_button(Gtk.ResponseType.APPLY,
                                        _('Show in Journal'), open_icon)
            open_icon.show()
            ok_icon = Icon(icon_name='dialog-ok')
            self._stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon)
            ok_icon.show()
            self._activity.add_alert(self._stop_alert)
            self._stop_alert.connect('response', self.__stop_response_cb)
            self._stop_alert.show()

            if self._dest_path.endswith('.journal'):

                metadata, preview_data, file_path = \
                    utils.unpackage_ds_object(self._dest_path)
                original_object_id = metadata['original_object_id']
                for key in metadata.keys():
                    self.dl_jobject.metadata[key] = metadata[key]

                self.dl_jobject.metadata['preview'] = dbus.ByteArray(
                    preview_data)

                self.dl_jobject.file_path = file_path

                datastore.write(self.dl_jobject,
                                transfer_ownership=True,
                                reply_handler=self.__internal_save_cb,
                                error_handler=self.__internal_error_cb,
                                timeout=360)

                # notify to the server, the object was successfully downloaded
                url = 'ws://%s:%d/websocket' % (self._activity.ip,
                                                self._activity.port)
                messanger = utils.Messanger(url)
                data = utils.get_user_data()
                data['object_id'] = original_object_id
                messanger.send_message('DOWNLOADED', data)

            else:
                self.dl_jobject.metadata['title'] = \
                    self._download.get_suggested_filename()
                self.dl_jobject.metadata['description'] = _('From: %s') \
                    % self._source
                self.dl_jobject.metadata['progress'] = '100'
                self.dl_jobject.file_path = self._dest_path

                # sniff for a mime type, no way to get headers from WebKit
                sniffed_mime_type = mime.get_for_file(self._dest_path)
                self.dl_jobject.metadata['mime_type'] = sniffed_mime_type

                datastore.write(self.dl_jobject,
                                transfer_ownership=True,
                                reply_handler=self.__internal_save_cb,
                                error_handler=self.__internal_error_cb,
                                timeout=360)

        elif state == WebKit.DownloadStatus.CANCELLED:
            self.cleanup()