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()
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()
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
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 __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 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()
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()
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()
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()
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()