def _incompatible(self): ''' Display abbreviated activity user interface with alert ''' toolbox = ToolbarBox() stop = StopButton(self) toolbox.toolbar.add(stop) self.set_toolbar_box(toolbox) title = _('Activity not compatible with this system.') msg = _('Please downgrade activity and try again.') alert = Alert(title=title, msg=msg) alert.add_button(0, 'Stop', Icon(icon_name='activity-stop')) self.add_alert(alert) label = Gtk.Label(_('Uh oh, WebKit2 is too old. ' 'Browse-200 and later require WebKit2 API 4.0, ' 'sorry!')) self.set_canvas(label) ''' Workaround: start Terminal activity, then type sugar-erase-bundle org.laptop.WebActivity then in My Settings, choose Software Update, which will offer older Browse. ''' alert.connect('response', self.__incompatible_response_cb) stop.connect('clicked', self.__incompatible_stop_clicked_cb, alert) self.show_all()
def __init__(self, timeout=5, **kwargs): Alert.__init__(self, **kwargs) self._pb = Gtk.ProgressBar() self._msg_box.pack_start(self._pb, False, False, 0) self._pb.set_size_request(int(Gdk.Screen.width() * 9. / 10.), -1) self._pb.set_fraction(0.0) self._pb.show()
def _show_alert(self, message, title=None): alert = Alert() if title is None: title = _('Atention') alert.props.title = title alert.props.msg = message alert.add_button(Gtk.ResponseType.OK, _('Ok')) self.add_alert(alert) alert.connect('response', self._alert_response_cb)
def __init__(self, **kwargs): Alert.__init__(self, **kwargs) icon = Icon(icon_name='dialog-cancel') self.add_button(Gtk.ResponseType.CANCEL, _('Save As'), icon) icon.show() icon = Icon(icon_name='dialog-ok') self.add_button(Gtk.ResponseType.OK, _('Overwrite'), icon) icon.show()
def can_close(self): if self._force_close: return True elif downloadmanager.can_quit(): return True else: alert = Alert() alert.props.title = ngettext('Download in progress', 'Downloads in progress', downloadmanager.num_downloads()) message = ngettext('Stopping now will erase your download', 'Stopping now will erase your downloads', downloadmanager.num_downloads()) alert.props.msg = message cancel_icon = Icon(icon_name='dialog-cancel') cancel_label = ngettext('Continue download', 'Continue downloads', downloadmanager.num_downloads()) alert.add_button(Gtk.ResponseType.CANCEL, cancel_label, cancel_icon) stop_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Stop'), stop_icon) stop_icon.show() self.add_alert(alert) alert.connect('response', self.__inprogress_response_cb) alert.show() self.present() return False
def _create_alert(self, title, msg): """Create and display an alert that cannot be dismissed by the user.""" alert = Alert() alert.props.title = title alert.props.msg = msg alert.connect('response', self._alert_cancel_cb) self.add_alert(alert) return alert
def _search_clicked_cb(self, widget): title = self.searchentry.get_text() wiki = self.wikimenu.combo.props.value if not title: return if book.wiki.find('%s (from %s)' % (title, wiki))[0]: alert = Alert() alert.props.title = _('Exists') alert.props.msg = _('"%s" article already exists' % title) alert.show() else: Timer(0, self._download, [title, wiki]).start()
def _new_game_alert(self): alert = Alert() alert.props.title = _('New game') alert.props.msg = _('Do you want to play a new game?') icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel'), icon) icon.show() ok_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('New game'), ok_icon) ok_icon.show() alert.connect('response', self.__game_alert_response_cb) self._parent.add_alert(alert) alert.show()
def __register_activate_cb(self, icon): alert = Alert() try: schoolserver.register_laptop() except RegisterError as e: alert.props.title = _('Registration Failed') alert.props.msg = '%s' % e else: alert.props.title = _('Registration Successful') alert.props.msg = _('You are now registered ' 'with your school server.') ok_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) self._box.add_alert(alert) alert.connect('response', self.__register_alert_response_cb)
def _show_error_alert(self, title, msg=None): self._alert = ErrorAlert() self._alert.props.title = title if msg is not None: self._alert.props.msg = msg self.add_alert(self._alert) self._alert.connect('response', self._alert_cancel_cb) self._alert.show()
def _object_chooser(self, mime_type, type_name): chooser = ObjectChooser() matches_mime_type = False response = chooser.run() if response == Gtk.ResponseType.ACCEPT: jobject = chooser.get_selected_object() metadata = jobject.metadata file_path = jobject.file_path if metadata['mime_type'] == mime_type: matches_mime_type = True else: alert = Alert() alert.props.title = _('Invalid object') alert.props.msg = \ _('The selected object must be a %s file' % (type_name)) ok_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) ok_icon.show() alert.connect('response', lambda a, r: self.remove_alert(a)) self.add_alert(alert) alert.show() return matches_mime_type, file_path, metadata['title']
def _value_changed(self, cell, path, new_text, model, activity): _logger.info("Change '%s' to '%s'" % (model[path][1], new_text)) is_number = True number = new_text.replace(",", ".") try: float(number) except ValueError: is_number = False if is_number: decimals = utils.get_decimals(str(float(number))) new_text = locale.format('%.' + decimals + 'f', float(number)) model[path][1] = str(new_text) self.emit("value-changed", str(path), number) elif not is_number: alert = Alert() alert.props.title = _('Invalid Value') alert.props.msg = \ _('The value must be a number (integer or decimal)') ok_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) ok_icon.show() alert.connect('response', lambda a, r: activity.remove_alert(a)) activity.add_alert(alert) alert.show()
def __erase_activate_cb(self, menu_item): alert = Alert() erase_string = _("Erase") alert.props.title = erase_string alert.props.msg = _('Do you want to permanently erase "%s"?') % self._metadata["title"] icon = Icon(icon_name="dialog-cancel") alert.add_button(Gtk.ResponseType.CANCEL, _("Cancel"), icon) icon.show() ok_icon = Icon(icon_name="dialog-ok") alert.add_button(Gtk.ResponseType.OK, erase_string, ok_icon) ok_icon.show() alert.connect("response", self.__erase_alert_response_cb) journalwindow.get_journal_window().add_alert(alert) alert.show()
def _erase_button_clicked_cb(self, button): alert = Alert() erase_string = _('Erase') alert.props.title = erase_string alert.props.msg = _('Do you want to permanently erase \"%s\"?') \ % self._metadata['title'] icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel'), icon) icon.show() ok_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, erase_string, ok_icon) ok_icon.show() alert.connect('response', self.__erase_alert_response_cb) journalwindow.get_journal_window().add_alert(alert) alert.show()
def __pdf_alert(self, object_id): alert = Alert() alert.props.title = _("Page saved") alert.props.msg = _("The page has been saved as PDF to journal") alert.add_button(Gtk.ResponseType.APPLY, _("Show in Journal"), Icon(icon_name="zoom-activity")) alert.add_button(Gtk.ResponseType.OK, _("Ok"), Icon(icon_name="dialog-ok")) # Remove other alerts for alert in self._activity._alerts: self._activity.remove_alert(alert) self._activity.add_alert(alert) alert.connect("response", self.__pdf_response_alert, object_id) alert.show_all()
def _show_journal_alert(self, title, msg): _stop_alert = Alert() _stop_alert.props.title = title _stop_alert.props.msg = msg _stop_alert.add_button(Gtk.ResponseType.APPLY, _('Show in Journal'), Icon(icon_name='zoom-activity')) _stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), Icon(icon_name='dialog-ok')) # Remove other alerts for alert in self._alerts: self.remove_alert(alert) self.add_alert(_stop_alert) _stop_alert.connect('response', self.__stop_response_cb) _stop_alert.show_all()
def _alert(self, title, text=None): try: self.remove_alert(self.alert) finally: self.alert = Alert() self.alert.props.title = title self.alert.props.msg = text self.add_alert(self.alert) self.alert.connect('response', self._alert_cancel_cb) self.alert.show()
def _save_epub(self): epub_file_name = create_ebub_from_book_model( self.metadata['title'], self._book_model) # create a new journal item fileObject = datastore.create() fileObject.metadata['title'] = \ _('"%s" as book') % self.metadata['title'] fileObject.metadata['mime_type'] = 'application/epub+zip' full_text = '' for page in self._book_model.get_pages(): full_text += page.text + '\n' fileObject.metadata['fulltext'] = full_text fileObject.metadata['icon-color'] = self.metadata['icon-color'] fileObject.metadata['keep'] = self.metadata.get('keep', '0') fileObject.metadata['preview'] = self.metadata['preview'] fileObject.file_path = epub_file_name # store the journal item datastore.write(fileObject, transfer_ownership=True) book_object_id = fileObject.object_id fileObject.destroy() del fileObject shutil.rmtree(os.path.dirname(epub_file_name)) finish_alert = Alert() finish_alert.props.title = _('Book created') finish_alert.props.msg = _('You can read the book in your Journal') open_icon = Icon(icon_name='zoom-activity') finish_alert.add_button(Gtk.ResponseType.APPLY, _('Show in Journal'), open_icon) open_icon.show() ok_icon = Icon(icon_name='dialog-ok') finish_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) ok_icon.show() # Remove other alerts for alert in self._alerts: self.remove_alert(alert) self.add_alert(finish_alert) finish_alert.connect('response', self.__book_saved_alert_response_cb, book_object_id) finish_alert.show()
def _shared_cb(self, activity): self._logger.debug('My activity was shared') self.alert = Alert() self.alert.props.title = 'Shared Activity' self.alert.props.msg = 'Shared messages to be displayed here' self.add_alert(self.alert) self.initiating = True self._sharing_setup() self._logger.debug('This is my activity: making a tube...') id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {})
def _incompatible(self): ''' Display abbreviated activity user interface with alert ''' toolbox = ToolbarBox() stop = StopButton(self) toolbox.toolbar.add(stop) self.set_toolbar_box(toolbox) title = _('Activity not compatible with this system.') msg = _('Please downgrade activity and try again.') alert = Alert(title=title, msg=msg) alert.add_button(0, 'Stop', Icon(icon_name='activity-stop')) self.add_alert(alert) label = Gtk.Label(_('Uh oh, GStreamer is too old.')) self.set_canvas(label) alert.connect('response', self.__incompatible_response_cb) stop.connect('clicked', self.__incompatible_stop_clicked_cb, alert) self.show_all()
def _show_journal_alert(self, title, msg, object_id): open_alert = Alert() open_alert.props.title = title open_alert.props.msg = msg open_icon = Icon(icon_name='zoom-activity') open_alert.add_button(Gtk.ResponseType.APPLY, _('Show in Journal'), open_icon) open_icon.show() ok_icon = Icon(icon_name='dialog-ok') open_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) ok_icon.show() # Remove other alerts for alert in self._alerts: self.remove_alert(alert) self.add_alert(open_alert) open_alert.connect('response', self.__open_response_cb, object_id) open_alert.show()
def __pdf_alert(self, object_id): alert = Alert() alert.props.title = _('Page saved') alert.props.msg = _('The page has been saved as PDF to journal') alert.add_button(Gtk.ResponseType.APPLY, _('Show in Journal'), Icon(icon_name='zoom-activity')) alert.add_button(Gtk.ResponseType.OK, _('Ok'), Icon(icon_name='dialog-ok')) # Remove other alerts for alert in self._activity._alerts: self._activity.remove_alert(alert) self._activity.add_alert(alert) alert.connect('response', self.__pdf_response_alert, object_id) alert.show_all()
def __crashed_cb(self, browser): self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.LEFT_PTR)) uri = browser.cached_uri logging.error('WebKit2 WebView at uri %r has crashed', uri) self.close_tab(browser.get_parent()) alert = Alert(title=_('This tab has crashed Browse: %s') % uri, msg=_('If you reopen the tab, it may just crash again')) alert.add_button(Gtk.ResponseType.OK, _('Reopen')) alert.add_button(Gtk.ResponseType.CANCEL, _('Disregard')) alert.connect('response', self.__crashed_alert_cb, uri) self._activity.add_alert(alert)
def _show_missing_tracks_alert(self, tracks): self._alert = Alert() title = _('%s tracks not found.') % len(tracks) self._alert.props.title = title icon = Icon(icon_name='dialog-cancel') self._alert.add_button(Gtk.ResponseType.CANCEL, _('Dismiss'), icon) icon.show() icon = Icon(icon_name='dialog-ok') self._alert.add_button(Gtk.ResponseType.APPLY, _('Details'), icon) icon.show() self.add_alert(self._alert) self._alert.connect( 'response', self.__missing_tracks_alert_response_cb, tracks)
def _clear_game_bt(self, button): if self.activity.game.model.is_demo or \ len(self.activity.cardlist.pairs) == 0: self.clear_game() else: alert = Alert() alert.props.title = _('Clear all the tiles from the game?') icon = Icon(icon_name='dialog-ok') alert.add_button(1, _('Clear'), icon) icon = Icon(icon_name='dialog-cancel') alert.add_button(0, _('Do not clear'), icon) alert.connect('response', self._clear_game_alert_cb) self.activity.add_alert(alert)
def __activate_game_cb(self, menu, i): self._game_selected_index = i if self.activity.game.model.is_demo: self._change_game() else: alert = Alert() alert.props.title = _('Discard your modified game?') icon = Icon(icon_name='dialog-ok') alert.add_button(1, _('Discard'), icon) icon = Icon(icon_name='dialog-cancel') alert.add_button(0, _('Do not discard'), icon) alert.connect('response', self._change_game_alert_cb) self.activity.add_alert(alert)
def __activate_art4apps_game_cb(self, menu, category, language): self._art4apps_data = (category, language) if self.activity.game.model.is_demo: self._change_art4apps_game(category, language) else: alert = Alert() alert.props.title = _('Discard your modified game?') icon = Icon(icon_name='dialog-ok') alert.add_button(1, _('Discard'), icon) icon = Icon(icon_name='dialog-cancel') alert.add_button(0, _('Do not discard'), icon) alert.connect('response', self._change_art4apps_game_alert_cb) self.activity.add_alert(alert)
def __save_ebook_clicked_cb(self, button): alert = Alert() alert.props.title = _('Book creation') alert.props.msg = _('Do you want to add an image for the cover?') icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.YES, _('Yes'), icon) icon.show() icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.NO, _('No'), icon) icon.show() alert.connect('response', self.__add_cover_response_cb, self._set_cover_and_create_book) self.add_alert(alert)
def __init__(self, **kwargs): Alert.__init__(self, **kwargs) # Name entry box self._name_view = Gtk.EventBox() self._name_view.show() # Entry box self._name_entry = Gtk.Entry() halign = Gtk.Alignment.new(0, 0, 0, 0) self._hbox.pack_start(halign, False, False, 0) halign.add(self._name_view) halign.show() self._name_view.add(self._name_entry) self._name_entry.show() halign = Gtk.Alignment.new(0, 0, 0, 0) self._buttons_box = Gtk.HButtonBox() self._buttons_box.set_layout(Gtk.ButtonBoxStyle.END) self._buttons_box.set_spacing(style.DEFAULT_SPACING) halign.add(self._buttons_box) self._hbox.pack_start(halign, False, False, 0) halign.show() self.show_all()
def _erase_comment_cb(self, widget, event): alert = Alert() entry = self.get_selection().get_selected()[1] erase_string = _('Erase') alert.props.title = erase_string alert.props.msg = _('Do you want to permanently erase \"%s\"?') \ % self._store[entry][self.COMMENT_MESSAGE] icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel'), icon) icon.show() ok_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, erase_string, ok_icon) ok_icon.show() alert.connect('response', self._erase_alert_response_cb, entry) journalwindow.get_journal_window().add_alert(alert) alert.show()
def __erase_activated_cb(self, tree_view, bundle_id): registry = bundleregistry.get_registry() activity_info = registry.get_bundle(bundle_id) alert = Alert() alert.props.title = _('Confirm erase') alert.props.msg = \ _('Confirm erase: Do you want to permanently erase %s?') \ % activity_info.get_name() cancel_icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Keep'), cancel_icon) erase_icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Erase'), erase_icon) alert.connect('response', self.__erase_confirmation_dialog_response_cb, bundle_id) self.add_alert(alert)
def __init__(self, handle): ''' Initialize the Sugar activity ''' super(Dimensions, self).__init__(handle) self.ready_to_play = False self._prompt = '' self._read_journal_data() self._sep = [] self._setup_toolbars() self._setup_canvas() if self.shared_activity: # We're joining if not self.get_shared(): xocolors = XoColor(profile.get_color().to_string()) share_icon = Icon(icon_name='zoom-neighborhood', xo_color=xocolors) self._joined_alert = Alert() self._joined_alert.props.icon = share_icon self._joined_alert.props.title = _('Please wait') self._joined_alert.props.msg = _('Starting connection...') self.add_alert(self._joined_alert) # Wait for joined signal self.connect("joined", self._joined_cb) self._setup_presence_service() if not hasattr(self, '_saved_state'): self._saved_state = None self.vmw.new_game(show_selector=True) else: self.vmw.new_game(saved_state=self._saved_state, deck_index=self._deck_index) self.ready_to_play = True if self._editing_word_list: self.vmw.editing_word_list = True self.vmw.edit_word_list() elif self._editing_custom_cards: self.vmw.editing_custom_cards = True self.vmw.edit_custom_card() Gdk.Screen.get_default().connect('size-changed', self._configure_cb) self._configure_cb(None)
def _new_tube_cb(self, id, initiator, type, service, params, state): ''' Create a new tube. ''' _logger.debug( 'New tube: ID=%d initator=%d type=%d service=%s ' 'params=%r state=%d', id, initiator, type, service, params, state) if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE): if state == telepathy.TUBE_STATE_LOCAL_PENDING: self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube( id) self.collab = CollabWrapper(self) self.collab.message.connect(self.event_received_cb) self.collab.setup() if self._waiting_for_reflections: self.send_event(JOIN_CMD, {}) self._joined_alert = Alert() self._joined_alert.props.title = _('Please wait') self._joined_alert.props.msg = _('Requesting reflections...') self.add_alert(self._joined_alert)
def _incompatible(self): ''' Display abbreviated activity user interface with alert ''' toolbox = ToolbarBox() stop = StopButton(self) toolbox.toolbar.add(stop) self.set_toolbar_box(toolbox) title = _('Activity not compatible with this system.') msg = _('Please erase the activity.') alert = Alert(title=title, msg=msg) alert.add_button(0, 'Stop', Icon(icon_name='activity-stop')) self.add_alert(alert) label = Gtk.Label(_('You do not have an accelerometer.')) self.set_canvas(label) alert.connect('response', self.__incompatible_response_cb) stop.connect('clicked', self.__incompatible_stop_clicked_cb, alert) self.show_all()
def _create_alert(name, scrolled): title = G.TEXT_SAVE_CHANGES_QUESTION.replace("****", name) msg = G.TEXT_IF_NOT_SAVE no = Gtk.Image.new_from_icon_name("activity-stop", Gtk.IconSize.MENU) save = Gtk.Image.new_from_icon_name("filesave", Gtk.IconSize.MENU) alert = Alert() alert.props.title = title alert.props.msg = msg alert.add_button(Gtk.ResponseType.NO, _("No save"), icon=no) alert.add_button(Gtk.ResponseType.YES, _("Save"), icon=save) alert.connect("response", _alert_response, scrolled) self.vbox.pack_start(alert, False, False, 0) self.vbox.reorder_child(alert, 0) self.vbox.show_all()
def __create_new_folder(self, entry): if entry.get_text(): try: path = os.path.join(self.folder, entry.get_text()) os.mkdir(path) self.folder = path except OSError as msg: alert = Alert() alert.props.title = _('Error creating the folder.') alert.props.msg = msg 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) item = entry.get_parent() self.toolbar.remove(item) self.button_new_folder.set_sensitive(True)
def _create_alert(name, scrolled): title = _('Save changes to document "%s" before closing?' % name) msg = _('If you do not save, changes will be lost forever.') no = Gtk.Image.new_from_icon_name('activity-stop', Gtk.IconSize.MENU) save = Gtk.Image.new_from_icon_name('filesave', Gtk.IconSize.MENU) alert = Alert() alert.props.title = title alert.props.msg = msg button1 = alert.add_button(Gtk.ResponseType.NO, _('No save'), icon=no) button2 = alert.add_button(Gtk.ResponseType.YES, _('Save'), icon=save) alert.connect('response', _alert_response, scrolled) self.vbox.pack_start(alert, False, False, 0) self.vbox.reorder_child(alert, 0) self.vbox.show_all()
class FileChooserSave(FileChooser): __gsignals__ = { "save-file": (GObject.SIGNAL_RUN_FIRST, None, [str]) } def __init__(self, folder=None): FileChooser.__init__(self, folder) self.alert = None self.view.set_selection_mode(Gtk.SelectionMode.SINGLE) self.view.connect("selection-changed", self.__selection_changed) self.view.connect("button-press-event", self.__button_press_event_cb) self.entry.connect("activate", self._save_path_from_entry) self.connect("key-release-event", self.__key_release_event_cb) self.__make_toolbar() self.show_folder() self.show_all() def __make_toolbar(self): self.toolbar = Gtk.Toolbar() self.toolbar.modify_bg( Gtk.StateType.NORMAL, style.COLOR_TOOLBAR_GREY.get_gdk_color()) self.toolbar.insert(self.go_up_button, -1) self.toolbar.insert(Gtk.SeparatorToolItem(), -1) self.button_new_folder = ToolButton(icon_name="new-folder") self.button_new_folder.set_tooltip(_("Create a folder")) self.button_new_folder.connect("clicked", self.create_folder) self.toolbar.insert(self.button_new_folder, -1) item = Gtk.ToolItem() item.add(self.entry) self.toolbar.insert(item, -1) separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) self.toolbar.insert(separator, -1) item = Gtk.ToolItem() self.entry_name = Gtk.Entry() self.entry_name.set_size_request(200, -1) self.entry_name.set_placeholder_text("Select a name for this file.") self.entry_name.connect("activate", self.__name_selected) item.add(self.entry_name) self.toolbar.insert(item, -1) self.entries.append(self.entry_name) self.button_save = ToolButton(icon_name="save-as") self.button_save.connect("clicked", self.__save_path_from_button) self.toolbar.insert(self.button_save, -1) self.close_button = ToolButton(icon_name="dialog-cancel") self.close_button.connect("clicked", self.close) self.toolbar.insert(self.close_button, -1) self.vbox.pack_start(self.toolbar, False, False, 0) def __key_release_event_cb(self, widget, event): if event.keyval == Gdk.KEY_Return: if self.area.get_selected_items(): self.__name_selected() elif event.keyval == Gdk.KEY_BackSpace: if not self.entry.has_focus() and not self.entry_name.has_focus(): self.go_up() elif event.keyval == Gdk.KEY_Escape: self.close() def create_folder(self, widget): self.button_new_folder.set_sensitive(False) entry = Gtk.Entry() entry.set_placeholder_text("Select a name") entry.connect("activate", self.__create_new_folder) item = Gtk.ToolItem() item.add(entry) self.toolbar.insert(item, 4) self.toolbar.show_all() def __create_new_folder(self, entry): if entry.get_text(): try: path = os.path.join(self.folder, entry.get_text()) os.mkdir(path) self.folder = path except OSError as msg: if self.alert: self.vbox.remove(self.alert) self.alert = None self.alert = Alert() self.alert.props.title = G.TEXT_ERROR_CREATING_FOLDER self.alert.props.msg = msg image = Gtk.Image.new_from_stock( Gtk.STOCK_OK, Gtk.IconSize.MENU) self.alert.add_button(Gtk.ResponseType.NO, _("Ok"), icon=image) self.alert.connect("response", self.__alert_response) self.vbox.pack_start(self.alert, False, False, 0) self.vbox.reorder_child(self.alert, 1) item = entry.get_parent() self.toolbar.remove(item) self.button_new_folder.set_sensitive(True) def __save_path_from_button(self, button): self.__name_selected() def __name_selected(self, entry=None): path = os.path.join(self.folder, self.entry_name.get_text()) self._save_path_from_entry(path=path) def _save_path_from_entry(self, entry=None, path=None): if not path: path = self.entry.get_text() if os.path.exists(path): if os.path.isdir(path): self.folder = path elif os.path.isfile(path): self.create_alert(path) elif not os.path.exists(path): if os.path.isdir(self.go_up(path, _return=True)): self.emit("save-file", path) self.destroy() def create_alert(self, path): if self.alert: self.vbox.remove(self.alert) self.alert = None self.alert = Alert() self.alert.props.title = G.TEXT_FILE_ALREADY_EXISTS self.alert.props.msg = G.TEXT_OVERWRITE_QUESTION.replace("****", path) cancel = Gtk.Image.new_from_icon_name( "dialog-cancel", Gtk.IconSize.MENU) save = Gtk.Image.new_from_icon_name("filesave", Gtk.IconSize.MENU) self.alert.add_button(Gtk.ResponseType.NO, _("Cancel"), icon=cancel) self.alert.add_button(Gtk.ResponseType.YES, _("Save"), icon=save) self.alert.connect("response", self.__alert_response, path) self.vbox.pack_start(self.alert, False, False, 0) self.vbox.reorder_child(self.alert, 2) def __alert_response(self, alert, response, path): if response == Gtk.ResponseType.NO: self.vbox.remove(alert) elif response == Gtk.ResponseType.YES: self.emit("save-file", path) self.destroy() self.alert_status = 0 self.alert = None def __selection_changed(self, view): if self.view.get_selected_items(): path = self.view.get_selected_items()[0] iter = self.model.get_iter(path) name = self.model.get_value(iter, 0) if os.path.isfile(os.path.join(self.folder, name)): self.entry_name.set_text(name) else: self.entry_name.set_text("") else: self.entry_name.set_text("") def __button_press_event_cb(self, view, event): if event.button != 1: return try: path = view.get_path_at_pos(int(event.x), int(event.y)) iter = self.model.get_iter(path) directory = os.path.join( self.folder, self.model.get_value(iter, 0)) if event.type.value_name == "GDK_2BUTTON_PRESS": if os.path.isdir(directory): self.folder = directory self.selected_path = None elif os.path.isfile(directory): self.selected_path = directory self.create_alert(directory) elif event.type.value_name == "GDK_1BUTTON_PRESS": self.selected_path = directory except TypeError: self.selected_path = None
class JukeboxActivity(activity.Activity): __gsignals__ = { 'playlist-finished': (GObject.SignalFlags.RUN_FIRST, None, []), } def __init__(self, handle): activity.Activity.__init__(self, handle) self.player = None self._alert = None self._playlist_jobject = None self.set_title(_('Jukebox Activity')) self.max_participants = 1 toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) activity_toolbar = activity_button.page toolbar_box.toolbar.insert(activity_button, 0) self.title_entry = activity_toolbar.title self._view_toolbar = ViewToolbar() self._view_toolbar.connect('go-fullscreen', self.__go_fullscreen_cb) self._view_toolbar.connect('toggle-playlist', self.__toggle_playlist_cb) view_toolbar_button = ToolbarButton(page=self._view_toolbar, icon_name='toolbar-view') self._view_toolbar.show() toolbar_box.toolbar.insert(view_toolbar_button, -1) view_toolbar_button.show() self._control_toolbar = Gtk.Toolbar() self._control_toolbar_button = ToolbarButton( page=self._control_toolbar, icon_name='media-playback-start') self._control_toolbar.show() toolbar_box.toolbar.insert(self._control_toolbar_button, -1) self._control_toolbar_button.hide() self.set_toolbar_box(toolbar_box) toolbar_box.show_all() self.connect('key_press_event', self.__key_press_event_cb) self.connect('playlist-finished', self.__playlist_finished_cb) # We want to be notified when the activity gets the focus or # loses it. When it is not active, we don't need to keep # reproducing the video self.connect('notify::active', self.__notify_active_cb) self._video_canvas = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self._playlist_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) self.playlist_widget = PlayList() self.playlist_widget.connect('play-index', self.__play_index_cb) self.playlist_widget.connect('missing-tracks', self.__missing_tracks_cb) self.playlist_widget.set_size_request( Gdk.Screen.width() * PLAYLIST_WIDTH_PROP, 0) self.playlist_widget.show() self._playlist_box.pack_start(self.playlist_widget, expand=True, fill=True, padding=0) self._playlist_toolbar = Gtk.Toolbar() move_up = ToolButton("go-up") move_up.set_tooltip(_("Move up")) move_up.connect("clicked", self._move_up_cb) self._playlist_toolbar.insert(move_up, 0) move_down = ToolButton("go-down") move_down.set_tooltip(_("Move down")) move_down.connect("clicked", self._move_down_cb) self._playlist_toolbar.insert(move_down, 1) self._playlist_box.pack_end(self._playlist_toolbar, False, False, 0) self._video_canvas.pack_start(self._playlist_box, False, False, 0) # Create the player just once logging.debug('Instantiating GstPlayer') self.player = GstPlayer() self.player.connect('eos', self.__player_eos_cb) self.player.connect('error', self.__player_error_cb) self.player.connect('play', self.__player_play_cb) self.control = Controls(self, toolbar_box.toolbar, self._control_toolbar) self._separator = Gtk.SeparatorToolItem() self._separator.props.draw = False self._separator.set_expand(True) self._separator.show() toolbar_box.toolbar.insert(self._separator, -1) self._stop = StopButton(self) toolbar_box.toolbar.insert(self._stop, -1) self._empty_widget = Gtk.Label(label="") self._empty_widget.show() self.videowidget = VideoWidget() self.set_canvas(self._video_canvas) self._init_view_area() self.show_all() # need hide the playlist by default self._playlist_box.hide() self._configure_cb() self.player.init_view_area(self.videowidget) self._volume_monitor = Gio.VolumeMonitor.get() self._volume_monitor.connect('mount-added', self.__mount_added_cb) self._volume_monitor.connect('mount-removed', self.__mount_removed_cb) if handle.object_id is None: # The activity was launched from scratch. We need to show # the Empty Widget self.playlist_widget.hide() emptypanel.show(self, 'activity-jukebox', _('No media'), _('Choose media files'), self.control.show_picker_cb) self.control.check_if_next_prev() Gdk.Screen.get_default().connect('size-changed', self._configure_cb) def _move_up_cb(self, button): self.playlist_widget.move_up() def _move_down_cb(self, button): self.playlist_widget.move_down() def _configure_cb(self, event=None): toolbar = self.get_toolbar_box().toolbar toolbar.remove(self._stop) toolbar.remove(self._separator) if Gdk.Screen.width() < Gdk.Screen.height(): self._control_toolbar_button.show() self._control_toolbar_button.set_expanded(True) self.control.update_layout(landscape=False) toolbar.insert(self._separator, -1) else: self._control_toolbar_button.set_expanded(False) self._control_toolbar_button.hide() self.control.update_layout(landscape=True) toolbar.insert(self._stop, -1) def __notify_active_cb(self, widget, event): """Sugar notify us that the activity is becoming active or inactive. When we are inactive, we stop the player if it is reproducing a video. """ logging.debug('JukeboxActivity notify::active signal received') if self.player.player.props.current_uri is not None and \ self.player.playing_video(): if not self.player.is_playing() and self.props.active: self.player.play() if self.player.is_playing() and not self.props.active: self.player.pause() def _init_view_area(self): """ Use a notebook with two pages, one empty an another with the videowidget """ self.view_area = Gtk.Notebook() self.view_area.set_show_tabs(False) self.view_area.append_page(self._empty_widget, None) self.view_area.append_page(self.videowidget, None) self._video_canvas.pack_end(self.view_area, expand=True, fill=True, padding=0) def _switch_canvas(self, show_video): """Show or hide the video visualization in the canvas. When hidden, the canvas is filled with an empty widget to ensure redrawing. """ if show_video: self.view_area.set_current_page(1) else: self.view_area.set_current_page(0) self._video_canvas.queue_draw() def __key_press_event_cb(self, widget, event): keyname = Gdk.keyval_name(event.keyval) logging.info("Keyname Press: %s, time: %s", keyname, event.time) if self.title_entry.has_focus(): return False if keyname == "space": self.control._button_clicked_cb(None) return True def __playlist_finished_cb(self, widget): self._switch_canvas(show_video=False) self._view_toolbar._show_playlist.set_active(True) self.unfullscreen() # Select the first stream to be played when Play button will # be pressed self.playlist_widget.set_current_playing(0) self.control.check_if_next_prev() def songchange(self, direction): current_playing = self.playlist_widget.get_current_playing() if direction == 'prev' and current_playing > 0: self.play_index(current_playing - 1) elif direction == 'next' and \ current_playing < len(self.playlist_widget._items) - 1: self.play_index(current_playing + 1) else: self.emit('playlist-finished') def play_index(self, index): # README: this line is no more necessary because of the # .playing_video() method # self._switch_canvas(show_video=True) self.playlist_widget.set_current_playing(index) path = self.playlist_widget._items[index]['path'] if self.playlist_widget.check_available_media(path): if self.playlist_widget.is_from_journal(path): path = self.playlist_widget.get_path_from_journal(path) self.control.check_if_next_prev() self.player.set_uri(path) self.player.play() else: self.songchange('next') def __play_index_cb(self, widget, index, path): # README: this line is no more necessary because of the # .playing_video() method # self._switch_canvas(show_video=True) self.playlist_widget.set_current_playing(index) if self.playlist_widget.is_from_journal(path): path = self.playlist_widget.get_path_from_journal(path) self.control.check_if_next_prev() self.player.set_uri(path) self.player.play() def __player_eos_cb(self, widget): self.songchange('next') def _show_error_alert(self, title, msg=None): self._alert = ErrorAlert() self._alert.props.title = title if msg is not None: self._alert.props.msg = msg self.add_alert(self._alert) self._alert.connect('response', self._alert_cancel_cb) self._alert.show() def __mount_added_cb(self, volume_monitor, device): logging.debug('Mountpoint added. Checking...') self.remove_alert(self._alert) self.playlist_widget.update() def __mount_removed_cb(self, volume_monitor, device): logging.debug('Mountpoint removed. Checking...') self.remove_alert(self._alert) self.playlist_widget.update() def __missing_tracks_cb(self, widget, tracks): self._show_missing_tracks_alert(tracks) def _show_missing_tracks_alert(self, tracks): self._alert = Alert() title = _('%s tracks not found.') % len(tracks) self._alert.props.title = title icon = Icon(icon_name='dialog-cancel') self._alert.add_button(Gtk.ResponseType.CANCEL, _('Dismiss'), icon) icon.show() icon = Icon(icon_name='dialog-ok') self._alert.add_button(Gtk.ResponseType.APPLY, _('Details'), icon) icon.show() self.add_alert(self._alert) self._alert.connect('response', self.__missing_tracks_alert_response_cb, tracks) def __missing_tracks_alert_response_cb(self, alert, response_id, tracks): if response_id == Gtk.ResponseType.APPLY: vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) vbox.props.valign = Gtk.Align.CENTER label = Gtk.Label(label='') label.set_markup(_('<b>Missing tracks</b>')) vbox.pack_start(label, False, False, 15) for track in tracks: label = Gtk.Label(label=track['path']) vbox.add(label) _missing_tracks = Gtk.ScrolledWindow() _missing_tracks.add_with_viewport(vbox) _missing_tracks.show_all() self.view_area.append_page(_missing_tracks, None) self.view_area.set_current_page(2) self.remove_alert(alert) def _alert_cancel_cb(self, alert, response_id): self.remove_alert(alert) def __player_play_cb(self, widget): # Do not show the visualization widget if we are playing just # an audio stream def callback(): if self.player.playing_video(): self._switch_canvas(True) else: self._switch_canvas(False) return False # HACK: we need a timeout here because gstreamer returns # n-video = 0 if we call it immediately GObject.timeout_add(1000, callback) def __player_error_cb(self, widget, message, detail): self.player.stop() self.control.set_disabled() logging.error('ERROR MESSAGE: %s', message) logging.error('ERROR DETAIL: %s', detail) file_path = self.playlist_widget._items[ self.playlist_widget.get_current_playing()]['path'] mimetype = mime.get_for_file(file_path) title = _('Error') msg = _('This "%s" file can\'t be played') % mimetype self._switch_canvas(False) self._show_error_alert(title, msg) def can_close(self): # We need to put the Gst.State in NULL so gstreamer can # cleanup the pipeline self.player.stop() return True def read_file(self, file_path): """Load a file from the datastore on activity start.""" logging.debug('JukeBoxAtivity.read_file: %s', file_path) title = self.metadata['title'] self.playlist_widget.load_file(file_path, title) self._view_toolbar._show_playlist.set_active(True) def write_file(self, file_path): def write_playlist_to_file(file_path): """Open the file at file_path and write the playlist. It is saved in audio/x-mpegurl format. """ list_file = open(file_path, 'w') for uri in self.playlist_widget._items: list_file.write('#EXTINF:%s\n' % uri['title']) list_file.write('%s\n' % uri['path']) list_file.close() if not self.metadata['mime_type']: self.metadata['mime_type'] = 'audio/x-mpegurl' if self.metadata['mime_type'] == 'audio/x-mpegurl': write_playlist_to_file(file_path) else: if self._playlist_jobject is None: self._playlist_jobject = \ self.playlist_widget.create_playlist_jobject() # Add the playlist to the playlist jobject description. # This is only done if the activity was not started from a # playlist or from scratch: description = '' for uri in self.playlist_widget._items: description += '%s\n' % uri['title'] self._playlist_jobject.metadata['description'] = description write_playlist_to_file(self._playlist_jobject.file_path) datastore.write(self._playlist_jobject) def __go_fullscreen_cb(self, toolbar): self.fullscreen() def __toggle_playlist_cb(self, toolbar): if self._view_toolbar._show_playlist.get_active(): self._playlist_box.show_all() else: self._playlist_box.hide() self._video_canvas.queue_draw()
class CEdit(activity.Activity): def __init__(self, handle): activity.Activity.__init__(self, handle) self.get_conf() self.reopen = True self.vbox = Gtk.VBox() self.infobar = InfoBar() self.make_toolbar() self.make_notebook() self.infobar.connect('language-changed', self.set_language) self.vbox.pack_end(self.infobar, False, False, 0) self.set_canvas(self.vbox) self.show_all() def get_conf(self): if 'saved' in self.metadata: self.conf = {} self.conf['font'] = str(self.metadata['font']) self.conf['font-size'] = int(self.metadata['font-size']) self.conf['show-line-numbers'] = bool( int(self.metadata['show-line-numbers'])) self.conf['tab-width'] = int(self.metadata['tab-width']) self.conf['use-spaces'] = bool(int(self.metadata['use-spaces'])) self.conf['theme'] = str(self.metadata['theme']) self.conf['right-line-pos'] = int(self.metadata['right-line-pos']) self.conf['show-right-line'] = bool( int(self.metadata['show-right-line'])) self.conf['wrap-mode'] = str(self.metadata['wrap-mode']) else: self.conf = { 'font': 'Monospace', 'font-size': 14, 'show-line-numbers': True, 'tab-width': 4, 'use-spaces': True, 'theme': 'classic', 'right-line-pos': 80, 'show-right-line': False, 'wrap-mode': 'none' } def make_toolbar(self): def make_separator(toolbar, expand=True): separator = Gtk.SeparatorToolItem() separator.props.draw = not expand separator.set_expand(expand) toolbar.insert(separator, -1) toolbar_box = ToolbarBox() toolbar = toolbar_box.toolbar activity_button = ToolButton() activity_button.set_icon_widget(ActivityIcon(None)) toolbar.insert(activity_button, -1) toolbar.insert(Gtk.SeparatorToolItem(), -1) toolbar_file = Gtk.Toolbar() boton_toolbar_file = ToolbarButton(page=toolbar_file, icon_name='txt') toolbar.add(boton_toolbar_file) toolbar_edit = EditToolbar() button_toolbar_edit = ToolbarButton(page=toolbar_edit, icon_name='toolbar-edit') toolbar.insert(button_toolbar_edit, -1) toolbar_view = Gtk.Toolbar() boton_toolbar_view = ToolbarButton(page=toolbar_view, icon_name='toolbar-view') toolbar.insert(boton_toolbar_view, -1) self.button_undo = toolbar_edit.undo self.button_undo.props.accelerator = '<Ctrl>Z' self.button_undo.set_sensitive(False) toolbar_edit.undo.connect('clicked', self.undo) self.button_redo = toolbar_edit.redo self.button_redo.props.accelerator = '<Ctrl><Mayus>Z' self.button_redo.set_sensitive(False) self.button_redo.connect('clicked', self.redo) self.entry_search = IconEntry() item_entry = Gtk.ToolItem() self.entry_search.set_size_request(250, -1) self.entry_search.set_placeholder_text('Search...') self.entry_search.set_icon_from_name(Gtk.EntryIconPosition.SECONDARY, 'search') self.entry_search.connect('changed', self.search_text) self.entry_search.connect('activate', self.search_text, True) item_entry.add(self.entry_search) toolbar_edit.insert(item_entry, -1) self.entry_replace = IconEntry() item_entry = Gtk.ToolItem() self.entry_replace.set_size_request(250, -1) self.entry_replace.set_placeholder_text('Replace...') self.entry_replace.connect('activate', self.replace_text) item_entry.add(self.entry_replace) toolbar_edit.insert(item_entry, -1) button_new = ToolButton('new-file') button_new.props.accelerator = '<Ctrl>N' button_new.connect('clicked', lambda w: self.new_page()) button_new.set_tooltip(_('New file')) toolbar_file.insert(button_new, -1) button_open = ToolButton('fileopen') button_open.props.accelerator = '<Ctrl>O' button_open.set_tooltip(_('Open file from file system')) button_open.connect('clicked', self.file_chooser_open) toolbar_file.insert(button_open, -1) self.button_save = ToolButton('filesave') self.button_save.props.accelerator = '<Ctrl>S' self.button_save.set_tooltip(_('Save file to the file system')) self.button_save.connect('clicked', self.file_chooser_save) toolbar_file.insert(self.button_save, -1) button_save_as = ToolButton('save-as') button_save_as.props.accelerator = '<Ctrl><Mayus>S' button_save_as.set_tooltip(_('Save as file to the file system')) button_save_as.connect('clicked', self.file_chooser_save, True) toolbar_file.insert(button_save_as, -1) make_separator(toolbar_file, False) button_print = ToolButton('printer') button_print.props.accelerator = '<Ctrl>I' button_print.set_tooltip(_('Print file')) button_print.connect('clicked', self.print_file) toolbar_file.insert(button_print, -1) make_separator(toolbar_edit, False) button_clock = ToolButton('clock') button_clock.props.accelerator = '<Ctrl>T' button_clock.set_tooltip(_('Insert date and time')) button_clock.connect('clicked', self.insert_date_and_time) toolbar_edit.insert(button_clock, -1) button_wrap_none = Gtk.RadioToolButton() button_wrap_none.set_icon_name('wrap-none') button_wrap_none.connect("toggled", self.wrap_mode_changed, 'none') toolbar_view.insert(button_wrap_none, -1) button_wrap_char = Gtk.RadioToolButton.new_from_widget( button_wrap_none) button_wrap_char.set_icon_name('format-justify-fill') button_wrap_char.connect("toggled", self.wrap_mode_changed, 'char') toolbar_view.insert(button_wrap_char, -1) button_wrap_word = Gtk.RadioToolButton.new_from_widget( button_wrap_none) button_wrap_word.set_icon_name('format-justify-left') button_wrap_word.connect("toggled", self.wrap_mode_changed, 'word') toolbar_view.insert(button_wrap_word, -1) if self.conf['wrap-mode'] == 'none': button_wrap_none.set_active(True) elif self.conf['wrap-mode'] == 'char': button_wrap_none.set_active(True) elif self.conf['wrap-mode'] == 'word': button_wrap_none.set_active(True) make_separator(toolbar_view, False) item_font_size = FontSize() item_font_size.set_font_size(self.conf['font-size']) item_font_size.connect('changed', self.font_size_changed) toolbar_view.insert(item_font_size, -1) combo_font = FontComboBox(self.conf['font']) combo_font.connect('changed', self.font_changed) toolbar_view.insert(combo_font, -1) make_separator(toolbar_view, False) button_numbers = ToggleToolButton('show-numbers') button_numbers.props.accelerator = '<Ctrl><Mayus>N' button_numbers.set_tooltip(_('Show line numbers')) button_numbers.set_active(self.conf['show-line-numbers']) button_numbers.connect('toggled', self.show_numbers_changed) toolbar_view.insert(button_numbers, -1) button_right_line = ToggleToolButton('show-right-line') button_right_line.props.accelerator = '<Ctrl>L' button_right_line.set_tooltip(_('Show a line in a specific position')) button_right_line.set_active(self.conf['show-right-line']) button_right_line.connect('toggled', self.show_right_line_changed) toolbar_view.insert(button_right_line, -1) self.spinner_right_line = Spinner(self.conf['right-line-pos'], 1, 150) self.spinner_right_line.set_sensitive(self.conf['show-right-line']) self.spinner_right_line.connect('value-changed', self.right_line_pos_changed) toolbar_view.insert(self.spinner_right_line, -1) make_separator(toolbar_view, False) combo_styles = ComboStyles(self.conf['theme']) combo_styles.connect('theme-changed', self.theme_changed) toolbar_view.insert(combo_styles, -1) make_separator(toolbar, True) button_stop = ToolButton('activity-stop') button_stop.props.accelerator = '<Ctrl>Q' button_stop.connect('clicked', self._exit) toolbar.insert(button_stop, -1) toolbar_file.show_all() toolbar_edit.show_all() toolbar_view.show_all() toolbar_edit.copy.hide() toolbar_edit.paste.hide() self.set_toolbar_box(toolbar_box) def make_notebook(self): self.notebook = Gtk.Notebook() button_add = Gtk.ToolButton.new_from_stock(Gtk.STOCK_ADD) button_add.connect('clicked', lambda w: self.new_page()) self.notebook.set_scrollable(True) self.notebook.set_show_tabs(True) self.notebook.set_action_widget(button_add, Gtk.PackType.END) self.notebook.add_events(Gdk.EventMask.SCROLL_MASK | Gdk.EventMask.SMOOTH_SCROLL_MASK) self.notebook.connect('switch-page', self.update_buttons) self.notebook.connect('scroll-event', self.notebook_scrolled) self.notebook.connect('page-removed', self.page_removed) self.vbox.pack_start(self.notebook, True, True, 2) self.new_page() button_add.show() self.show_all() def page_removed(self, notebook, scroll, page): if not self.reopen: return if len(self.notebook.get_children()) == 0: self.new_page() def set_language(self, infobar, language): buffer = self.get_view().buffer buffer.set_language_from_string(language) def set_language_from_buffer(self, buffer, language): self.infobar.set_language(language) def notebook_scrolled(self, widget, event): if event.get_scroll_direction()[1] == Gdk.ScrollDirection.UP: self.notebook.prev_page() elif event.get_scroll_direction()[1] == Gdk.ScrollDirection.DOWN: self.notebook.next_page() def update_buttons(self, notebook=None, scrolled=None, *args): if not isinstance(scrolled, Gtk.ScrolledWindow): view = self.get_view() else: view = scrolled.get_children()[0] buffer = view.get_buffer() self.button_undo.set_sensitive(buffer.can_undo()) self.button_redo.set_sensitive(buffer.can_redo()) self.button_save.set_sensitive(buffer.get_modified()) self.entry_search.set_sensitive(bool(buffer.get_all_text())) self.entry_replace.set_sensitive(bool(buffer.get_all_text())) self.spinner_right_line.set_sensitive(self.conf['show-right-line']) self.infobar.set_language(buffer.get_language_str()) self.update_cursor_position(buffer) def new_page(self, view=None, label=None): if not view: view = View(self.conf) view.buffer.connect('changed', self.update_buttons) view.buffer.connect('mark-set', self.update_cursor_position) view.buffer.connect('language-changed', self.set_language_from_buffer) if not label: label = view.get_file_name() if type(label) == str: label = Gtk.Label(label) label.modify_font(Pango.FontDescription('15 bold')) view.connect('title-changed', self.change_title_from_view) scrolled = Gtk.ScrolledWindow() scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) scrolled.set_shadow_type(Gtk.ShadowType.ETCHED_IN) scrolled.add(view) hbox = Gtk.HBox() hbox.set_size_request(-1, 20) hbox.pack_start(label, False, False, 0) button = Gtk.Button() button.set_relief(Gtk.ReliefStyle.NONE) button.set_size_request(12, 12) button.set_image( Gtk.Image.new_from_stock(Gtk.STOCK_CLOSE, Gtk.IconSize.MENU)) button.connect('clicked', self.remove_page_from_widget, scrolled) hbox.pack_start(button, False, False, 0) self.notebook.append_page(scrolled, hbox) self.notebook.set_tab_reorderable(scrolled, True) view.grab_focus() hbox.show_all() self.show_all() self.notebook.set_current_page(self.notebook.get_n_pages() - 1) return view def update_cursor_position(self, buffer, *args): iter = buffer.get_iter_at_mark(buffer.get_insert()) line = iter.get_line() + 1 column = iter.get_line_offset() + 1 self.infobar.set_pos(line, column) def file_chooser_open(self, widget): path = self.get_view().get_file() file_chooser = FileChooserOpen(self, path) file_chooser.connect('open-file', self._open_file_from_chooser) file_chooser.show_all() def file_chooser_save(self, widget, force=False, close=False): # Force is for "save as" idx = self.notebook.get_current_page() view = self.get_view() if view.get_file() and not force: self.save_file(idx=idx, path=view.get_file()) return file_chooser = FileChooserSave() file_chooser.connect('save-file', self._save_file_from_chooser, close) file_chooser.show_all() def begin_print(self, operation, context, compositor): while not compositor.paginate(context): pass n_pages = compositor.get_n_pages() operation.set_n_pages(n_pages) def draw_page(self, operation, context, page_nr, compositor): compositor.draw_page(context, page_nr) 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 _open_file_from_chooser(self, widget, path): children = self.notebook.get_children() for scrolled in children: view = scrolled.get_children()[0] if view.get_file() == path: idx = children.index(scrolled) self.notebook.set_current_page(idx) return view = self.get_view() if view.get_file(): self.new_page(label=view.get_file_name()) view = self.get_view(idx=-1) view.set_file(path) def _save_file_from_chooser(self, widget, path, close=False): view = self.get_view() view.save_file(path) if close: view = self.get_view() scrolled = view.get_parent() idx = self.notebook.get_children().index(scrolled) self.notebook.remove_page(idx) def save_file(self, widget=None, idx=None, path=None): if idx is not None: idx = self.notebook.get_current_page() scrolled = self.notebook.get_children()[idx] view = scrolled.get_children()[0] view.save_file(view.get_file()) def remove_page_from_widget(self, widget, scrolled, force=False): view = scrolled.get_children()[0] buffer = view.get_buffer() idx = self.notebook.get_children().index(scrolled) if not buffer.get_modified() or force: self.notebook.remove_page(idx) else: name = view.get_file_name() title = _('Save changes to document "%s" before closing?' % name) msg = _('If you do not save, changes will be lost forever.') cancel = Gtk.Image.new_from_icon_name('dialog-cancel', Gtk.IconSize.MENU) no = Gtk.Image.new_from_icon_name('activity-stop', Gtk.IconSize.MENU) save = Gtk.Image.new_from_icon_name('filesave', Gtk.IconSize.MENU) self.alert = Alert() self.alert.props.title = title self.alert.props.msg = msg button1 = self.alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel'), icon=cancel) button2 = self.alert.add_button(Gtk.ResponseType.NO, _('No save'), icon=no) button3 = self.alert.add_button(Gtk.ResponseType.YES, _('Save'), icon=save) self.alert.connect('response', self._alert_response, scrolled) self.vbox.pack_start(self.alert, False, False, 0) self.vbox.reorder_child(self.alert, 0) self.vbox.show_all() def change_title_from_view(self, view=None, label=None): if not view: view = self.get_view() if not label: label = view.get_file_name() scrolled = view.get_parent() hbox = self.notebook.get_tab_label(scrolled) widget = hbox.get_children()[0] changed = view.get_buffer().get_modified() widget.set_label(label) color = '#FF0000' if changed else '#FFFFFF' widget.modify_fg(Gtk.StateType.NORMAL, Gdk.color_parse(color)) self.update_buttons() def get_view(self, idx=None): if idx is None: idx = self.notebook.get_current_page() scrolled = self.notebook.get_children()[idx] return scrolled.get_children()[0] def undo(self, widget): self.get_view().undo() self.change_title_from_view() def redo(self, widget): self.get_view().redo() self.change_title_from_view() def search_text(self, entry, enter=False): text = entry.get_text() self.get_view().search(text, enter) def replace_text(self, entry): text_search = self.entry_search.get_text() text_replace = entry.get_text() self.get_view().replace(text_search, text_replace) def wrap_mode_changed(self, widget, mode): self.conf['wrap-mode'] = mode self.set_conf_to_views() def font_size_changed(self, widget, font_size): self.conf['font-size'] = font_size self.set_conf_to_views() def font_changed(self, widget, font): self.conf['font'] = font self.set_conf_to_views() def show_numbers_changed(self, widget): self.conf['show-line-numbers'] = widget.get_active() self.set_conf_to_views() def show_right_line_changed(self, widget): self.conf['show-right-line'] = widget.get_active() self.update_buttons() self.set_conf_to_views() def right_line_pos_changed(self, widget, value): self.conf['right-line-pos'] = value self.set_conf_to_views() def theme_changed(self, widget, theme): self.conf['theme'] = theme self.set_conf_to_views() def tab_width_changed(self, widget, tab_width): self.conf['tab-width'] = tab_width self.set_conf_to_views() def set_conf_to_views(self): for scrolled in self.notebook.get_children(): view = scrolled.get_children()[0] view.set_conf(self.conf) def insert_date_and_time(self, widget): view = self.get_view() day = datetime.date.today() date = day.strftime('%d/%m/%y') hour = time.strftime('%H:%M:%S') text = date + ' ' + hour view.buffer.insert_interactive_at_cursor(text, -1, True) def _alert_response(self, widget, response, scrolled): if response == Gtk.ResponseType.NO: self.remove_page_from_widget(None, scrolled, force=True) elif response == Gtk.ResponseType.YES: self.file_chooser_save(None, False, True) self.vbox.remove(self.alert) def write_file(self, file_path): files = [] for scrolled in self.notebook.get_children(): view = scrolled.get_children()[0] if view.get_file(): files.append(view.get_file) self.metadata['saved'] = True self.metadata['font'] = self.conf['font'] self.metadata['font-size'] = self.conf['font-size'] self.metadata['show-line-numbers'] = self.conf['show-line-numbers'] self.metadata['tab-width'] = self.conf['tab-width'] self.metadata['use-spaces'] = self.conf['use-spaces'] self.metadata['theme'] = self.conf['theme'] self.metadata['right-line-pos'] = self.conf['right-line-pos'] self.metadata['show-right-line'] = self.conf['show-right-line'] self.metadata['wrap-mode'] = self.conf['wrap-mode'] def _exit(self, *args): def _remove_page(widget, scrolled): if scrolled in self.notebook.get_children(): idx = self.notebook.get_children().index(scrolled) self.notebook.remove_page(idx) check_modified() def _alert_response(alert, response, scrolled): self.vbox.remove(alert) if response == Gtk.ResponseType.YES: view = scrolled.get_children()[0] if view.get_file(): idx = self.notebook.get_children() self.save_file(idx=idx, path=view.get_file()) self.remove_page_from_widget(None, scrolled, force=True) return file_chooser = FileChooserSave() file_chooser.connect('save-file', self._save_file_from_chooser, True) file_chooser.connect('destroy', _remove_page, scrolled) file_chooser.show_all() else: self.remove_page_from_widget(None, scrolled, force=True) check_modified() def _create_alert(name, scrolled): title = _('Save changes to document "%s" before closing?' % name) msg = _('If you do not save, changes will be lost forever.') no = Gtk.Image.new_from_icon_name('activity-stop', Gtk.IconSize.MENU) save = Gtk.Image.new_from_icon_name('filesave', Gtk.IconSize.MENU) alert = Alert() alert.props.title = title alert.props.msg = msg button1 = alert.add_button(Gtk.ResponseType.NO, _('No save'), icon=no) button2 = alert.add_button(Gtk.ResponseType.YES, _('Save'), icon=save) alert.connect('response', _alert_response, scrolled) self.vbox.pack_start(alert, False, False, 0) self.vbox.reorder_child(alert, 0) self.vbox.show_all() def check_modified(): if not self.notebook.get_children(): _close() return self.notebook.set_current_page(self.notebook.get_n_pages() - 1) scrolled = self.notebook.get_children()[-1] view = scrolled.get_children()[0] buffer = view.get_buffer() if buffer.get_modified(): name = view.get_file_name() _create_alert(name, scrolled) else: self.remove_page_from_widget(None, scrolled, force=True) check_modified() def _close(): self.close() self.reopen = False check_modified()
def __init__(self, handle): ''' Initialize the toolbar ''' try: super(ReflectActivity, self).__init__(handle) except dbus.exceptions.DBusException as e: _logger.error(str(e)) logging.error('setting reflection data to []') self.reflection_data = [] self.connect('realize', self.__realize_cb) self.font_size = 8 self.max_participants = 4 self._setup_toolbars() color = profile.get_color() color_stroke = color.get_stroke_color() color_fill = color.get_fill_color() lighter = utils.lighter_color([color_stroke, color_fill]) darker = 1 - lighter if lighter == 0: self.bg_color = style.Color(color_stroke) self.fg_color = style.Color(color_fill) else: self.bg_color = style.Color(color_fill) self.fg_color = style.Color(color_stroke) self.modify_bg(Gtk.StateType.NORMAL, self.bg_color.get_gdk_color()) self.bundle_path = activity.get_bundle_path() self.tmp_path = os.path.join(activity.get_activity_root(), 'instance') self.sharing = False self._copy_entry = None self._paste_entry = None self._webkit = None self._clipboard_text = '' self._fixed = None self.initiating = True if self.shared_activity: # We're joining if not self.get_shared(): self.initiating = False self.busy_cursor() share_icon = Icon(icon_name='zoom-neighborhood') self._joined_alert = Alert() self._joined_alert.props.icon = share_icon self._joined_alert.props.title = _('Please wait') self._joined_alert.props.msg = _('Starting connection...') self.add_alert(self._joined_alert) # Wait for joined signal self.connect("joined", self._joined_cb) self._open_reflect_windows() self._setup_presence_service() # Joiners wait to receive data from sharer # Otherwise, load reflections from local store if not self.shared_activity: self.busy_cursor() GObject.idle_add(self._load_reflections)
def __accept_clicked_cb(self, widget): if hasattr(self._section_view, "apply"): self._section_view.apply() if self._section_view.needs_restart: self._section_toolbar.accept_button.set_sensitive(False) self._section_toolbar.cancel_button.set_sensitive(False) alert = Alert() alert.props.title = _('Warning') alert.props.msg = _('Changes require restart') if self._section_view.props.is_cancellable: icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel changes'), icon) icon.show() if self._current_option not in ('aboutme', 'backup'): icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.ACCEPT, _('Later'), icon) icon.show() icon = Icon(icon_name='system-restart') alert.add_button(Gtk.ResponseType.APPLY, _('Restart now'), icon) icon.show() self._vbox.pack_start(alert, False, False, 0) self._vbox.reorder_child(alert, 2) alert.connect('response', self.__response_cb) alert.show() else: self._show_main_view()
class Network(SectionView): def __init__(self, model, alerts): SectionView.__init__(self) self._model = model self.restart_alerts = alerts self._jabber_sid = 0 self._radio_valid = True self._jabber_change_handler = None self._radio_change_handler = None self._wireless_configuration_reset_handler = None self._start_jabber = self._model.get_jabber() self._proxy_settings = {} self._proxy_inline_alerts = {} self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) group = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL) self._radio_alert_box = Gtk.HBox(spacing=style.DEFAULT_SPACING) scrolled = Gtk.ScrolledWindow() scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.add(scrolled) scrolled.show() workspace = Gtk.VBox() scrolled.add_with_viewport(workspace) workspace.show() separator_wireless = Gtk.HSeparator() workspace.pack_start(separator_wireless, False, True, 0) separator_wireless.show() label_wireless = Gtk.Label(label=_('Wireless')) label_wireless.set_alignment(0, 0) workspace.pack_start(label_wireless, False, True, 0) label_wireless.show() box_wireless = Gtk.VBox() box_wireless.set_border_width(style.DEFAULT_SPACING * 2) box_wireless.set_spacing(style.DEFAULT_SPACING) radio_info = Gtk.Label(label=_('The wireless radio may be turned' ' off to save battery life.')) radio_info.set_alignment(0, 0) radio_info.set_line_wrap(True) radio_info.show() box_wireless.pack_start(radio_info, False, True, 0) box_radio = Gtk.HBox(spacing=style.DEFAULT_SPACING) self._button = Gtk.CheckButton() self._button.set_alignment(0, 0) box_radio.pack_start(self._button, False, True, 0) self._button.show() label_radio = Gtk.Label(label=_('Radio')) label_radio.set_alignment(0, 0.5) box_radio.pack_start(label_radio, False, True, 0) label_radio.show() box_wireless.pack_start(box_radio, False, True, 0) box_radio.show() self._radio_alert = InlineAlert() self._radio_alert_box.pack_start(self._radio_alert, False, True, 0) box_radio.pack_end(self._radio_alert_box, False, True, 0) self._radio_alert_box.show() if 'radio' in self.restart_alerts: self._radio_alert.props.msg = self.restart_msg self._radio_alert.show() wireless_info = Gtk.Label( label=_('Discard wireless connections if' ' you have trouble connecting to the network')) wireless_info.set_alignment(0, 0) wireless_info.set_line_wrap(True) wireless_info.show() box_wireless.pack_start(wireless_info, False, True, 0) box_clear_wireless = Gtk.HBox(spacing=style.DEFAULT_SPACING) self._clear_wireless_button = Gtk.Button() self._clear_wireless_button.set_label( _('Discard wireless connections')) box_clear_wireless.pack_start(self._clear_wireless_button, False, True, 0) if not self._model.have_wireless_networks(): self._clear_wireless_button.set_sensitive(False) self._clear_wireless_button.show() box_wireless.pack_start(box_clear_wireless, False, True, 0) box_clear_wireless.show() workspace.pack_start(box_wireless, False, True, 0) box_wireless.show() separator_mesh = Gtk.HSeparator() workspace.pack_start(separator_mesh, False, False, 0) separator_mesh.show() label_mesh = Gtk.Label(label=_('Collaboration')) label_mesh.set_alignment(0, 0) workspace.pack_start(label_mesh, False, True, 0) label_mesh.show() box_mesh = Gtk.VBox() box_mesh.set_border_width(style.DEFAULT_SPACING * 2) box_mesh.set_spacing(style.DEFAULT_SPACING) server_info = Gtk.Label( _("The server is the equivalent of what" " room you are in; people on the same server" " will be able to see each other, even when" " they aren't on the same network.")) server_info.set_alignment(0, 0) server_info.set_line_wrap(True) box_mesh.pack_start(server_info, False, True, 0) server_info.show() box_server = Gtk.HBox(spacing=style.DEFAULT_SPACING) label_server = Gtk.Label(label=_('Server:')) label_server.set_alignment(1, 0.5) label_server.modify_fg(Gtk.StateType.NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) box_server.pack_start(label_server, False, True, 0) group.add_widget(label_server) label_server.show() self._entry = Gtk.Entry() self._entry.set_alignment(0) self._entry.set_size_request(int(Gdk.Screen.width() / 3), -1) box_server.pack_start(self._entry, False, True, 0) self._entry.show() box_mesh.pack_start(box_server, False, True, 0) box_server.show() social_help_info = Gtk.Label( _('Social Help is a forum that lets you connect with developers' ' and discuss Sugar Activities. Changing servers means' ' discussions will happen in a different place with' ' different people.')) social_help_info.set_alignment(0, 0) social_help_info.set_line_wrap(True) box_mesh.pack_start(social_help_info, False, True, 0) social_help_info.show() social_help_box = Gtk.HBox(spacing=style.DEFAULT_SPACING) social_help_label = Gtk.Label(label=_('Social Help Server:')) social_help_label.set_alignment(1, 0.5) social_help_label.modify_fg(Gtk.StateType.NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) social_help_box.pack_start(social_help_label, False, True, 0) group.add_widget(social_help_label) social_help_label.show() self._social_help_entry = Gtk.Entry() self._social_help_entry.set_alignment(0) self._social_help_entry.set_size_request(int(Gdk.Screen.width() / 3), -1) social_help_box.pack_start(self._social_help_entry, False, True, 0) self._social_help_entry.show() box_mesh.pack_start(social_help_box, False, True, 0) social_help_box.show() workspace.pack_start(box_mesh, False, True, 0) box_mesh.show() separator_proxy = Gtk.HSeparator() workspace.pack_start(separator_proxy, False, False, 0) separator_proxy.show() self._add_proxy_section(workspace) self.setup() def _add_proxy_section(self, workspace): label_proxy = Gtk.Label(_('Proxy')) label_proxy.set_alignment(0, 0) workspace.pack_start(label_proxy, False, True, 0) label_proxy.show() box_proxy = Gtk.VBox() box_proxy.set_border_width(style.DEFAULT_SPACING * 2) box_proxy.set_spacing(style.DEFAULT_SPACING) workspace.pack_start(box_proxy, False, True, 0) box_proxy.show() self._proxy_alert = Alert() self._proxy_alert.props.title = _('Error') self._proxy_alert.props.msg = _('Proxy settings cannot be verified') box_proxy.pack_start(self._proxy_alert, False, False, 0) self._proxy_alert.connect('response', self._response_cb) self._proxy_alert.hide() # GSettings schemas for proxy: schemas = [ 'org.sugarlabs.system.proxy', 'org.sugarlabs.system.proxy.http', 'org.sugarlabs.system.proxy.https', 'org.sugarlabs.system.proxy.ftp', 'org.sugarlabs.system.proxy.socks' ] for schema in schemas: proxy_setting = Gio.Settings.new(schema) # We are not going to apply the settings immediatly. # We'll apply them if the user presses the "accept" # button, or we'll revert them if the user presses the # "cancel" button. proxy_setting.delay() alert = InlineAlert() self._proxy_settings[schema] = proxy_setting self._proxy_inline_alerts[schema] = alert size_group = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL) automatic_proxy_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) manual_proxy_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) option_sets = [('None', 'none', Gtk.VBox()), ('Use system proxy', 'system', Gtk.VBox()), ('Manual', 'manual', manual_proxy_box), ('Automatic', 'auto', automatic_proxy_box)] box_mode = ComboSettingBox( _('Method:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'mode', option_sets, size_group) box_proxy.pack_start(box_mode, False, False, 0) box_mode.show() url_box = StringSettingBox( _('Configuration URL:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'autoconfig-url', size_group) automatic_proxy_box.pack_start(url_box, True, True, 0) url_box.show() wpad_help_text = _('Web Proxy Autodiscovery is used when a' ' Configuration URL is not provided. This is not' ' recommended for untrusted public networks.') automatic_proxy_help = Gtk.Label(wpad_help_text) automatic_proxy_help.set_alignment(0, 0) automatic_proxy_help.set_line_wrap(True) automatic_proxy_help.show() automatic_proxy_box.pack_start(automatic_proxy_help, True, True, 0) # HTTP Section schema = 'org.sugarlabs.system.proxy.http' box_http = HostPortSettingBox(_('HTTP Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_http, False, False, 0) box_http.show() auth_contents_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) auth_box = OptionalSettingsBox(_('Use authentication'), self._proxy_settings[schema], 'use-authentication', auth_contents_box) manual_proxy_box.pack_start(auth_box, False, False, 0) auth_box.show() proxy_http_setting = Gio.Settings.new(schema) proxy_http_setting.delay() box_username = StringSettingBox(_('Username:'******'authentication-user', size_group) auth_contents_box.pack_start(box_username, False, False, 0) box_username.show() box_password = StringSettingBox(_('Password:'******'authentication-password', size_group, password_field=True) auth_contents_box.pack_start(box_password, False, False, 0) box_password.show() # HTTPS Section schema = 'org.sugarlabs.system.proxy.https' box_https = HostPortSettingBox(_('HTTPS Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_https, False, False, 0) box_https.show() # FTP Section schema = 'org.sugarlabs.system.proxy.ftp' box_ftp = HostPortSettingBox(_('FTP Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_ftp, False, False, 0) box_ftp.show() # SOCKS Section schema = 'org.sugarlabs.system.proxy.socks' box_socks = HostPortSettingBox(_('SOCKS Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_socks, False, False, 0) box_socks.show() box_ignore = StringSettingBox_with_convert( _('Ignore Hosts:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'ignore-hosts', type_as_to_string, string_to_type_as, size_group) manual_proxy_box.pack_start(box_ignore, False, False, 0) box_ignore.show() def setup(self): self._entry.set_text(self._start_jabber) self._social_help_entry.set_text(self._model.get_social_help()) try: radio_state = self._model.get_radio() except self._model.ReadError as detail: self._radio_alert.props.msg = detail self._radio_alert.show() else: self._button.set_active(radio_state) self._radio_valid = True self.needs_restart = False self._radio_change_handler = self._button.connect( 'toggled', self.__radio_toggled_cb) self._wireless_configuration_reset_handler = \ self._clear_wireless_button.connect( 'clicked', self.__wireless_configuration_reset_cb) def _response_cb(self, alert, response_id): if response_id is Gtk.ResponseType.APPLY: self._proxy_alert.hide() self._apply_proxy_settings() self.show_restart_alert = True self.emit('add-alert') elif response_id is Gtk.ResponseType.CANCEL: self.undo() self._proxy_alert.remove_button(Gtk.ResponseType.APPLY) self._proxy_alert.remove_button(Gtk.ResponseType.CANCEL) self._proxy_alert.hide() self.emit('set-toolbar-sensitivity', True) def _ping_servers(self): response_to_return = True non_blank_host_name_counter = 0 # To check accidental blank hostnames for schema in list(self._proxy_settings.keys()): if (schema != 'org.sugarlabs.system.proxy'): hostname = Gio.Settings.get_string( self._proxy_settings[schema], 'host') if hostname != '': non_blank_host_name_counter += 1 response = os.system("ping -c 1 -W 1 " + hostname) if (response): self._proxy_inline_alerts[schema].show() response_to_return = False if non_blank_host_name_counter == 0: response_to_return = False return response_to_return def _verify_settings(self): self._proxy_alert.props.title = _('Please Wait!') self._proxy_alert.props.msg = _('Proxy settings are being verified.') self._proxy_alert.show() flag_all_true = True g_proxy_schema = self._proxy_settings['org.sugarlabs.system.proxy'] g_mode = Gio.Settings.get_string(g_proxy_schema, 'mode') self.show_restart_alert = False if g_mode == 'auto': flag_all_true = os.path.isfile( Gio.Settings.get_string(g_proxy_schema, 'autoconfig-url')) elif g_mode == 'manual': flag_all_true = self._ping_servers() if flag_all_true: self.show_restart_alert = True self._proxy_alert.hide() self._apply_proxy_settings() else: self._proxy_alert.props.title = _('Error!') self._proxy_alert.props.msg = _('The following setting(s) seems ' 'to be incorrect and may break ' 'your internet connection') icon = Icon(icon_name='dialog-cancel') self._proxy_alert.add_button(Gtk.ResponseType.APPLY, _('Break my internet'), icon) icon.show() icon = Icon(icon_name='dialog-ok') self._proxy_alert.add_button(Gtk.ResponseType.CANCEL, _('Reset'), icon) icon.show() def _apply_proxy_settings(self): for setting in list(self._proxy_settings.values()): if (Gio.Settings.get_has_unapplied(setting)): setting.apply() def apply(self): self._apply_jabber(self._entry.get_text()) self._model.set_social_help(self._social_help_entry.get_text()) settings_changed = False for setting in list(self._proxy_settings.values()): if (Gio.Settings.get_has_unapplied(setting)): settings_changed = True if settings_changed: self.needs_restart = True self._is_cancellable = False self.restart_msg = _('Proxy changes require restart') self._verify_settings() else: self.show_restart_alert = True def undo(self): self._button.disconnect(self._radio_change_handler) self._radio_alert.hide() for setting in list(self._proxy_settings.values()): setting.revert() for alert in list(self._proxy_inline_alerts.values()): alert.hide() def _validate(self): if self._radio_valid: self.props.is_valid = True else: self.props.is_valid = False def __radio_toggled_cb(self, widget, data=None): radio_state = widget.get_active() try: self._model.set_radio(radio_state) except self._model.ReadError as detail: self._radio_alert.props.msg = detail self._radio_valid = False else: self._radio_valid = True if self._model.have_wireless_networks(): self._clear_wireless_button.set_sensitive(True) self._validate() return False def _apply_jabber(self, jabber): if jabber == self._model.get_jabber(): return self._model.set_jabber(jabber) def __wireless_configuration_reset_cb(self, widget): # FIXME: takes effect immediately, not after CP is closed with # confirmation button self._model.clear_wireless_networks() self._clear_wireless_button.set_sensitive(False)
class Download(object): def __init__(self, download, browser): self._download = download self._activity = browser.get_toplevel() self._source = download.get_uri() self._download.connect('notify::status', self.__state_change_cb) self._download.connect('error', self.__error_cb) self.datastore_deleted_handler = None self.dl_jobject = None self._object_id = None self._last_update_time = 0 self._last_update_percent = 0 self._stop_alert = None # figure out download URI self.temp_path = os.path.join(activity.get_activity_root(), 'instance') if not os.path.exists(self.temp_path): os.makedirs(self.temp_path) fd, self._dest_path = tempfile.mkstemp( dir=self.temp_path, suffix=download.get_suggested_filename(), prefix='tmp') os.close(fd) logging.debug('Download destination path: %s' % self._dest_path) # We have to start the download to get 'total-size' # property. It not, 0 is returned self._download.set_destination_uri('file://' + self._dest_path) self._download.start() def __progress_change_cb(self, download, something): progress = self._download.get_progress() self.dl_jobject.metadata['progress'] = str(int(progress * 100)) datastore.write(self.dl_jobject) 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 __error_cb(self, download, err_code, err_detail, reason): logging.debug('Error downloading URI code %s, detail %s: %s' % (err_code, err_detail, reason)) 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): global _active_downloads 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)
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()
class Network(SectionView): def __init__(self, model, alerts): SectionView.__init__(self) self._model = model self.restart_alerts = alerts self._jabber_sid = 0 self._radio_valid = True self._jabber_change_handler = None self._radio_change_handler = None self._wireless_configuration_reset_handler = None self._start_jabber = self._model.get_jabber() self._proxy_settings = {} self._proxy_inline_alerts = {} self.set_border_width(style.DEFAULT_SPACING * 2) self.set_spacing(style.DEFAULT_SPACING) group = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL) self._radio_alert_box = Gtk.HBox(spacing=style.DEFAULT_SPACING) scrolled = Gtk.ScrolledWindow() scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) self.add(scrolled) scrolled.show() workspace = Gtk.VBox() scrolled.add_with_viewport(workspace) workspace.show() separator_wireless = Gtk.HSeparator() workspace.pack_start(separator_wireless, False, True, 0) separator_wireless.show() label_wireless = Gtk.Label(label=_('Wireless')) label_wireless.set_alignment(0, 0) workspace.pack_start(label_wireless, False, True, 0) label_wireless.show() box_wireless = Gtk.VBox() box_wireless.set_border_width(style.DEFAULT_SPACING * 2) box_wireless.set_spacing(style.DEFAULT_SPACING) radio_info = Gtk.Label(label=_('The wireless radio may be turned' ' off to save battery life.')) radio_info.set_alignment(0, 0) radio_info.set_line_wrap(True) radio_info.show() box_wireless.pack_start(radio_info, False, True, 0) box_radio = Gtk.HBox(spacing=style.DEFAULT_SPACING) self._button = Gtk.CheckButton() self._button.set_alignment(0, 0) box_radio.pack_start(self._button, False, True, 0) self._button.show() label_radio = Gtk.Label(label=_('Radio')) label_radio.set_alignment(0, 0.5) box_radio.pack_start(label_radio, False, True, 0) label_radio.show() box_wireless.pack_start(box_radio, False, True, 0) box_radio.show() self._radio_alert = InlineAlert() self._radio_alert_box.pack_start(self._radio_alert, False, True, 0) box_radio.pack_end(self._radio_alert_box, False, True, 0) self._radio_alert_box.show() if 'radio' in self.restart_alerts: self._radio_alert.props.msg = self.restart_msg self._radio_alert.show() wireless_info = Gtk.Label( label=_('Discard wireless connections if' ' you have trouble connecting to the network')) wireless_info.set_alignment(0, 0) wireless_info.set_line_wrap(True) wireless_info.show() box_wireless.pack_start(wireless_info, False, True, 0) box_clear_wireless = Gtk.HBox(spacing=style.DEFAULT_SPACING) self._clear_wireless_button = Gtk.Button() self._clear_wireless_button.set_label( _('Discard wireless connections')) box_clear_wireless.pack_start( self._clear_wireless_button, False, True, 0) if not self._model.have_wireless_networks(): self._clear_wireless_button.set_sensitive(False) self._clear_wireless_button.show() box_wireless.pack_start(box_clear_wireless, False, True, 0) box_clear_wireless.show() workspace.pack_start(box_wireless, False, True, 0) box_wireless.show() separator_mesh = Gtk.HSeparator() workspace.pack_start(separator_mesh, False, False, 0) separator_mesh.show() label_mesh = Gtk.Label(label=_('Collaboration')) label_mesh.set_alignment(0, 0) workspace.pack_start(label_mesh, False, True, 0) label_mesh.show() box_mesh = Gtk.VBox() box_mesh.set_border_width(style.DEFAULT_SPACING * 2) box_mesh.set_spacing(style.DEFAULT_SPACING) server_info = Gtk.Label(_("The server is the equivalent of what" " room you are in; people on the same server" " will be able to see each other, even when" " they aren't on the same network.")) server_info.set_alignment(0, 0) server_info.set_line_wrap(True) box_mesh.pack_start(server_info, False, True, 0) server_info.show() box_server = Gtk.HBox(spacing=style.DEFAULT_SPACING) label_server = Gtk.Label(label=_('Server:')) label_server.set_alignment(1, 0.5) label_server.modify_fg(Gtk.StateType.NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) box_server.pack_start(label_server, False, True, 0) group.add_widget(label_server) label_server.show() self._entry = Gtk.Entry() self._entry.set_alignment(0) self._entry.set_size_request(int(Gdk.Screen.width() / 3), -1) box_server.pack_start(self._entry, False, True, 0) self._entry.show() box_mesh.pack_start(box_server, False, True, 0) box_server.show() social_help_info = Gtk.Label( _('Social Help is a forum that lets you connect with developers' ' and discuss Sugar Activities. Changing servers means' ' discussions will happen in a different place with' ' different people.')) social_help_info.set_alignment(0, 0) social_help_info.set_line_wrap(True) box_mesh.pack_start(social_help_info, False, True, 0) social_help_info.show() social_help_box = Gtk.HBox(spacing=style.DEFAULT_SPACING) social_help_label = Gtk.Label(label=_('Social Help Server:')) social_help_label.set_alignment(1, 0.5) social_help_label.modify_fg(Gtk.StateType.NORMAL, style.COLOR_SELECTION_GREY.get_gdk_color()) social_help_box.pack_start(social_help_label, False, True, 0) group.add_widget(social_help_label) social_help_label.show() self._social_help_entry = Gtk.Entry() self._social_help_entry.set_alignment(0) self._social_help_entry.set_size_request( int(Gdk.Screen.width() / 3), -1) social_help_box.pack_start(self._social_help_entry, False, True, 0) self._social_help_entry.show() box_mesh.pack_start(social_help_box, False, True, 0) social_help_box.show() workspace.pack_start(box_mesh, False, True, 0) box_mesh.show() separator_proxy = Gtk.HSeparator() workspace.pack_start(separator_proxy, False, False, 0) separator_proxy.show() self._add_proxy_section(workspace) self.setup() def _add_proxy_section(self, workspace): label_proxy = Gtk.Label(_('Proxy')) label_proxy.set_alignment(0, 0) workspace.pack_start(label_proxy, False, True, 0) label_proxy.show() box_proxy = Gtk.VBox() box_proxy.set_border_width(style.DEFAULT_SPACING * 2) box_proxy.set_spacing(style.DEFAULT_SPACING) workspace.pack_start(box_proxy, False, True, 0) box_proxy.show() self._proxy_alert = Alert() self._proxy_alert.props.title = _('Error') self._proxy_alert.props.msg = _('Proxy settings cannot be verified') box_proxy.pack_start(self._proxy_alert, False, False, 0) self._proxy_alert.connect('response', self._response_cb) self._proxy_alert.hide() # GSettings schemas for proxy: schemas = ['org.sugarlabs.system.proxy', 'org.sugarlabs.system.proxy.http', 'org.sugarlabs.system.proxy.https', 'org.sugarlabs.system.proxy.ftp', 'org.sugarlabs.system.proxy.socks'] for schema in schemas: proxy_setting = Gio.Settings.new(schema) # We are not going to apply the settings immediatly. # We'll apply them if the user presses the "accept" # button, or we'll revert them if the user presses the # "cancel" button. proxy_setting.delay() alert = InlineAlert() self._proxy_settings[schema] = proxy_setting self._proxy_inline_alerts[schema] = alert size_group = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL) automatic_proxy_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) manual_proxy_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) option_sets = [('None', 'none', Gtk.VBox()), ('Use system proxy', 'system', Gtk.VBox()), ('Manual', 'manual', manual_proxy_box), ('Automatic', 'auto', automatic_proxy_box)] box_mode = ComboSettingBox( _('Method:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'mode', option_sets, size_group) box_proxy.pack_start(box_mode, False, False, 0) box_mode.show() url_box = StringSettingBox( _('Configuration URL:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'autoconfig-url', size_group) automatic_proxy_box.pack_start(url_box, True, True, 0) url_box.show() wpad_help_text = _('Web Proxy Autodiscovery is used when a' ' Configuration URL is not provided. This is not' ' recommended for untrusted public networks.') automatic_proxy_help = Gtk.Label(wpad_help_text) automatic_proxy_help.set_alignment(0, 0) automatic_proxy_help.set_line_wrap(True) automatic_proxy_help.show() automatic_proxy_box.pack_start(automatic_proxy_help, True, True, 0) # HTTP Section schema = 'org.sugarlabs.system.proxy.http' box_http = HostPortSettingBox( _('HTTP Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_http, False, False, 0) box_http.show() auth_contents_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) auth_box = OptionalSettingsBox( _('Use authentication'), self._proxy_settings[schema], 'use-authentication', auth_contents_box) manual_proxy_box.pack_start(auth_box, False, False, 0) auth_box.show() proxy_http_setting = Gio.Settings.new(schema) proxy_http_setting.delay() box_username = StringSettingBox( _('Username:'******'authentication-user', size_group) auth_contents_box.pack_start(box_username, False, False, 0) box_username.show() box_password = StringSettingBox( _('Password:'******'authentication-password', size_group, password_field=True) auth_contents_box.pack_start(box_password, False, False, 0) box_password.show() # HTTPS Section schema = 'org.sugarlabs.system.proxy.https' box_https = HostPortSettingBox( _('HTTPS Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_https, False, False, 0) box_https.show() # FTP Section schema = 'org.sugarlabs.system.proxy.ftp' box_ftp = HostPortSettingBox( _('FTP Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_ftp, False, False, 0) box_ftp.show() # SOCKS Section schema = 'org.sugarlabs.system.proxy.socks' box_socks = HostPortSettingBox( _('SOCKS Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_socks, False, False, 0) box_socks.show() box_ignore = StringSettingBox_with_convert( _('Ignore Hosts:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'ignore-hosts', type_as_to_string, string_to_type_as, size_group) manual_proxy_box.pack_start(box_ignore, False, False, 0) box_ignore.show() def setup(self): self._entry.set_text(self._start_jabber) self._social_help_entry.set_text(self._model.get_social_help()) try: radio_state = self._model.get_radio() except self._model.ReadError, detail: self._radio_alert.props.msg = detail self._radio_alert.show() else:
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 __create_restart_alert_cb(self, widget=None, event=None): alert = Alert() alert.props.title = _('Warning') alert.props.msg = self._section_view.restart_msg if self._section_view.props.is_cancellable: icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel changes'), icon) icon.show() if self._section_view.props.is_deferrable: icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.ACCEPT, _('Later'), icon) icon.show() icon = Icon(icon_name='system-restart') alert.add_button(Gtk.ResponseType.APPLY, _('Restart now'), icon) icon.show() self.add_alert(alert) alert.connect('response', self.__response_cb) alert.show()
def __create_empty_file_cb(self, button): alert = Alert() alert.props.title = _('Create new file') alert.props.msg = _('Select the name of the file') # HACK alert._hbox.remove(alert._buttons_box) alert.entry = Gtk.Entry() alert._hbox.pack_start(alert.entry, True, True, 0) alert._buttons_box = Gtk.HButtonBox() alert._buttons_box.set_layout(Gtk.ButtonBoxStyle.END) alert._buttons_box.set_spacing(style.DEFAULT_SPACING) alert._hbox.pack_start(alert._buttons_box, True, True, 0) icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel'), icon) icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.OK, _('Ok'), icon) alert.show_all() # self.add_alert(alert) alert.connect('response', self.__create_file_alert_cb)
def __register_activate_cb(self, icon): alert = Alert() alert.props.title = _('Registration') alert.props.msg = _('Please wait, searching for your school server.') self._box.add_alert(alert) GObject.idle_add(self.__register)
def _restart_alert(self): alert = Alert() alert.props.title = _('Warning') alert.props.msg = _('Changes require restart') icon = Icon(icon_name='dialog-cancel') alert.add_button(Gtk.ResponseType.CANCEL, _('Cancel changes'), icon) icon.show() icon = Icon(icon_name='dialog-ok') alert.add_button(Gtk.ResponseType.ACCEPT, _('Later'), icon) icon.show() icon = Icon(icon_name='system-restart') alert.add_button(Gtk.ResponseType.APPLY, _('Restart now'), icon) icon.show() alert.connect('response', self.__response_cb) self.add_alert(alert) alert.show()
def _show_journal_alert(self, title, msg): _stop_alert = Alert() _stop_alert.props.title = title _stop_alert.props.msg = msg 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() _stop_alert.add_button(Gtk.ResponseType.ACCEPT, label, icon) else: icon = Icon(icon_name='zoom-activity') label = _('Show in Journal') _stop_alert.add_button(Gtk.ResponseType.APPLY, label, icon) icon.show() ok_icon = Icon(icon_name='dialog-ok') _stop_alert.add_button(Gtk.ResponseType.OK, _('Ok'), ok_icon) ok_icon.show() # Remove other alerts for alert in self._alerts: self.remove_alert(alert) self.add_alert(_stop_alert) _stop_alert.connect('response', self.__stop_response_cb) _stop_alert.show()
class Download(object): def __init__(self, download, browser): self._download = download self._activity = browser.get_toplevel() self._source = download.get_uri() self._download.connect('notify::status', self.__state_change_cb) self._download.connect('error', self.__error_cb) self.datastore_deleted_handler = None self.dl_jobject = None self._object_id = None self._stop_alert = None self._progress = 0 self._last_update_progress = 0 self._progress_sid = None # figure out download URI self.temp_path = os.path.join(activity.get_activity_root(), 'instance') if not os.path.exists(self.temp_path): os.makedirs(self.temp_path) fd, self._dest_path = tempfile.mkstemp( dir=self.temp_path, suffix=download.get_suggested_filename(), prefix='tmp') os.close(fd) logging.debug('Download destination path: %s' % self._dest_path) # We have to start the download to get 'total-size' # property. It not, 0 is returned self._download.set_destination_uri('file://' + self._dest_path) self._download.start() 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 __progress_change_cb(self, download, something): self._progress = int(self._download.get_progress() * 100) if self._progress_sid is None: self._progress_sid = GObject.timeout_add(PROGRESS_TIMEOUT, self._update_progress) def __current_size_changed_cb(self, download, something): current_size = self._download.get_current_size() total_size = self._download.get_total_size() self._progress = int(current_size * 100 / total_size) if self._progress_sid is None: self._progress_sid = GObject.timeout_add(PROGRESS_TIMEOUT, self._update_progress) 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() def __error_cb(self, download, err_code, err_detail, reason): logging.debug('Error downloading URI code %s, detail %s: %s' % (err_code, err_detail, reason)) 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): global _active_downloads 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)
class DevTutorActivity(activity.Activity): """DevTutorActivity class as specified in activity.info""" def __init__(self, handle): activity.Activity.__init__(self, handle) self.max_participants = 10 # toolbar with the new toolbar redesign toolbar_box = ToolbarBox() activity_button = ActivityToolbarButton(self) toolbar_box.toolbar.insert(activity_button, 0) activity_button.show() self.back_button = BackButton() self.back_button.connect('clicked', self.show_options1) toolbar_box.toolbar.insert(self.back_button, -1) self.back_button.show() separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) separator.show() stop_button = StopButton(self) toolbar_box.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbar_box) toolbar_box.show() self.show_options() self._logger = logging.getLogger('hellomesh-activity') self.hellotube = None # Shared session self.initiating = False # get the Presence Service self.pservice = presenceservice.get_instance() # Buddy object for you owner = self.pservice.get_owner() self.owner = owner self.connect('shared', self._shared_cb) self.connect('joined', self._joined_cb) def show_options1(self, data=None): self.show_options() def show_options(self): self.main_container = Gtk.VBox() self.add_padding() self.line1 = Gtk.HBox() button1 = Gtk.Button("Show modules") #button1.set_size_request(200,80) #self.line1.pack_start(button1, False, False, 0) self.line1.add(button1) button1.connect('clicked', self.show_modules, None) button1.get_child().modify_font(Pango.FontDescription("Sans 14")) button1.show() self.main_container.add(self.line1) self.line1.show() self.add_padding() self.line2 = Gtk.HBox() button2 = Gtk.Button("Show activities") #button2.set_size_request(200,80) #self.line2.pack_start(button2, False, False, 0) self.line2.add(button2) button2.connect('clicked', self.show_activity_list, None) button2.get_child().modify_font(Pango.FontDescription("Sans 14")) button2.show() self.main_container.add(self.line2) self.line2.show() self.add_padding() self.line3 = Gtk.HBox() text = Gtk.TextView() self.entry = Gtk.Entry() self.entry.set_sensitive(True) self.entry.connect('activate', self.entry_activate_cb) self.entry.show() self.line3.add(self.entry) self.main_container.add(self.line3) self.line3.show() self.set_canvas(self.main_container) self.main_container.show() def add_padding(self): self.line_space1 = Gtk.HBox() self.main_container.add(self.line_space1) self.line_space1.show() self.line_space2 = Gtk.HBox() self.main_container.add(self.line_space2) self.line_space2.show() def show_modules(self, sender, data=None): self.mod = ShowModules(self.set_canvas) self.mod.show_modules() def show_activity_list(self, sender, data=None): self.back_button.connect('clicked', self.show_options1) self.main_container = Gtk.VBox() self.add_padding() self.line1 = Gtk.HBox() button1 = Gtk.Button("Hello World activity") #button1.set_size_request(200,80) #self.line1.pack_start(button1, False, False, 0) self.line1.add(button1) button1.connect('clicked', self.show_labels_hello, None) button1.get_child().modify_font(Pango.FontDescription("Sans 14")) button1.show() self.main_container.add(self.line1) self.line1.show() self.add_padding() self.line2 = Gtk.HBox() button2 = Gtk.Button("Write activity") #button2.set_size_request(200,80) #self.line2.pack_start(button2, False, False, 0) self.line2.add(button2) button2.connect('clicked', self.show_labels_write, None) button2.get_child().modify_font(Pango.FontDescription("Sans 14")) button2.show() self.main_container.add(self.line2) self.line2.show() self.add_padding() self.set_canvas(self.main_container) self.main_container.show() def show_labels_hello(self, sender, data=None): self.back_button.connect('clicked', self.show_activity_list) self.main_container = Gtk.VBox() self.add_padding() self.line1 = Gtk.HBox() self.label1 = Gtk.Label( _("Hello World activity step 1 - call activity.__init__")) self.label1.set_line_wrap(True) self.label1.modify_font(Pango.FontDescription("Sans 12")) self.line1.add(self.label1) self.label1.show() button1 = Gtk.Button("Show result") button1.set_size_request(200, 80) self.line1.pack_start(button1, False, False, 0) button1.connect('clicked', self.hello_launch1, None) button1.get_child().modify_font(Pango.FontDescription("Sans 14")) button1.show() self.main_container.add(self.line1) self.line1.show() self.add_padding() self.line2 = Gtk.HBox() self.label2 = Gtk.Label(_("Hello Word activity step 2 - add toolbox")) self.label2.set_line_wrap(True) self.label2.modify_font(Pango.FontDescription("Sans 12")) self.line2.add(self.label2) self.label2.show() button2 = Gtk.Button("Show result") button2.set_size_request(200, 80) self.line2.pack_start(button2, False, False, 0) button2.connect('clicked', self.hello_launch2, None) button2.get_child().modify_font(Pango.FontDescription("Sans 14")) button2.show() self.main_container.add(self.line2) self.line2.show() self.add_padding() self.line3 = Gtk.HBox() self.label3 = Gtk.Label( _("Hello World activity step 3 - add hello world label")) self.label3.set_line_wrap(True) self.label3.modify_font(Pango.FontDescription("Sans 12")) self.line3.add(self.label3) self.label3.show() button3 = Gtk.Button("Show result") button3.set_size_request(200, 80) self.line3.pack_start(button3, False, False, 0) button3.connect('clicked', self.hello_launch3, None) button3.get_child().modify_font(Pango.FontDescription("Sans 14")) button3.show() self.main_container.add(self.line3) self.line3.show() self.add_padding() self.line4 = Gtk.HBox() self.label4 = Gtk.Label( _("Hello World activity step 4 - add rotate button")) self.label4.set_line_wrap(True) self.label4.modify_font(Pango.FontDescription("Sans 12")) self.line4.add(self.label4) self.label4.show() button4 = Gtk.Button("Show result") button4.set_size_request(200, 80) self.line4.pack_start(button4, False, False, 0) button4.connect('clicked', self.hello_launch4, None) button4.get_child().modify_font(Pango.FontDescription("Sans 14")) button4.show() self.main_container.add(self.line4) self.line4.show() self.add_padding() self.set_canvas(self.main_container) self.main_container.show() def show_labels_write(self, sender, data=None): self.back_button.connect('clicked', self.show_activity_list) self.main_container = Gtk.VBox() self.add_padding() self.line1 = Gtk.HBox() self.label1 = Gtk.Label(_("Write activity step 1 ")) self.label1.set_line_wrap(True) self.label1.modify_font(Pango.FontDescription("Sans 12")) self.line1.add(self.label1) self.label1.show() button1 = Gtk.Button("Show result") button1.set_size_request(200, 80) self.line1.pack_start(button1, False, False, 0) button1.connect('clicked', self.write_launch1, None) button1.get_child().modify_font(Pango.FontDescription("Sans 14")) button1.show() self.main_container.add(self.line1) self.line1.show() self.add_padding() self.line2 = Gtk.HBox() self.label2 = Gtk.Label(_("Write activity step 2")) self.label2.set_line_wrap(True) self.label2.modify_font(Pango.FontDescription("Sans 12")) self.line2.add(self.label2) self.label2.show() button2 = Gtk.Button("Show result") button2.set_size_request(200, 80) self.line2.pack_start(button2, False, False, 0) button2.connect('clicked', self.write_launch2, None) button2.get_child().modify_font(Pango.FontDescription("Sans 14")) button2.show() self.main_container.add(self.line2) self.line2.show() self.set_canvas(self.main_container) self.add_padding() self.line3 = Gtk.HBox() self.label3 = Gtk.Label(_("Write activity step 3")) self.label3.set_line_wrap(True) self.label3.modify_font(Pango.FontDescription("Sans 12")) self.line3.add(self.label3) self.label3.show() button3 = Gtk.Button("Show result") button3.set_size_request(200, 80) self.line3.pack_start(button3, False, False, 0) button3.connect('clicked', self.write_launch3, None) button3.get_child().modify_font(Pango.FontDescription("Sans 14")) button3.show() self.main_container.add(self.line3) self.line3.show() self.add_padding() self.set_canvas(self.main_container) self.main_container.show() def hello_launch1(self, sender, data=None): f = open('/tmp/1', 'w') os.putenv('TUTOR_CLASS', 'HelloWorldActivity') self.launch() def hello_launch2(self, sender, data=None): f = open('/tmp/2', 'w') self.hello_launch1(sender, data) def hello_launch3(self, sender, data=None): f = open('/tmp/3', 'w') self.hello_launch2(sender, data) def hello_launch4(self, sender, data=None): f = open('/tmp/4', 'w') self.hello_launch3(sender, data) def write_launch1(self, sender, data=None): f = open('/tmp/1', 'w') os.putenv('TUTOR_CLASS', 'AbiWordActivity') self.launch() def write_launch2(self, sender, data=None): f = open('/tmp/2', 'w') self.write_launch1(sender, data) def write_launch3(self, sender, data=None): f = open('/tmp/3', 'w') self.write_launch2(sender, data) def launch(self): subprocess.Popen(['sugar-launch', 'org.sugarlabs.DevTutor']) def entry_activate_cb(self, entry): """Handle the event when Enter is pressed in the Entry.""" text = entry.props.text if self.hellotube is not None: self.hellotube.SendText(text) def entry_text_update_cb(self, text): """Update Entry text when text received from others.""" self.entry.props.text = text def _alert(self, title, text=None): try: self.remove_alert(self.alert) finally: self.alert = Alert() self.alert.props.title = title self.alert.props.msg = text self.add_alert(self.alert) self.alert.connect('response', self._alert_cancel_cb) self.alert.show() def _alert_cancel_cb(self, alert, response_id): #self.remove_alert(alert) pass def _shared_cb(self, activity): self._logger.debug('My activity was shared') self.alert = Alert() self.alert.props.title = 'Shared Activity' self.alert.props.msg = 'Shared messages to be displayed here' self.add_alert(self.alert) self.initiating = True self._sharing_setup() self._logger.debug('This is my activity: making a tube...') id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( SERVICE, {}) def _sharing_setup(self): if self.shared_activity is None: self._logger.error('Failed to share or join activity') return self.conn = self.shared_activity.telepathy_conn self.tubes_chan = self.shared_activity.telepathy_tubes_chan self.text_chan = self.shared_activity.telepathy_text_chan self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( 'NewTube', self._new_tube_cb) self.shared_activity.connect('buddy-joined', self._buddy_joined_cb) self.shared_activity.connect('buddy-left', self._buddy_left_cb) self.entry.set_sensitive(True) self.entry.grab_focus() # Optional - included for example: # Find out who's already in the shared activity: for buddy in self.shared_activity.get_joined_buddies(): self._logger.debug('Buddy %s is already in the activity', buddy.props.nick) def _list_tubes_reply_cb(self, tubes): for tube_info in tubes: self._new_tube_cb(*tube_info) def _list_tubes_error_cb(self, e): self._logger.error('ListTubes() failed: %s', e) def _joined_cb(self, activity): if not self.shared_activity: return self._logger.debug('Joined an existing shared activity') self._alert('Joined', 'Joined a shared activity') self.initiating = False self._sharing_setup() self._logger.debug('This is not my activity: waiting for a tube...') self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( reply_handler=self._list_tubes_reply_cb, error_handler=self._list_tubes_error_cb) def _new_tube_cb(self, id, initiator, type, service, params, state): self._logger.debug( 'New tube: ID=%d initator=%d type=%d service=%s ' 'params=%r state=%d', id, initiator, type, service, params, state) if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE): if state == telepathy.TUBE_STATE_LOCAL_PENDING: self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube( id) tube_conn = TubeConnection( self.conn, self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) self.hellotube = TextSync(tube_conn, self.initiating, self.entry_text_update_cb, self._alert, self._get_buddy) def _buddy_joined_cb(self, activity, buddy): """Called when a buddy joins the shared activity. This doesn't do much here as HelloMesh doesn't have much functionality. It's up to you do do interesting things with the Buddy... """ self._logger.debug('Buddy %s joined', buddy.props.nick) self._alert('Buddy joined', '%s joined' % buddy.props.nick) def _buddy_left_cb(self, activity, buddy): """Called when a buddy leaves the shared activity. This doesn't do much here as HelloMesh doesn't have much functionality. It's up to you do do interesting things with the Buddy... """ self._logger.debug('Buddy %s left', buddy.props.nick) self._alert('Buddy left', '%s left' % buddy.props.nick) def _get_buddy(self, cs_handle): """Get a Buddy from a channel specific handle.""" self._logger.debug('Trying to find owner of handle %u...', cs_handle) group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP] my_csh = group.GetSelfHandle() self._logger.debug('My handle in that group is %u', my_csh) if my_csh == cs_handle: handle = self.conn.GetSelfHandle() self._logger.debug('CS handle %u belongs to me, %u', cs_handle, handle) elif group.GetGroupFlags( ) & telepathy.CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES: handle = group.GetHandleOwners([cs_handle])[0] self._logger.debug('CS handle %u belongs to %u', cs_handle, handle) else: handle = cs_handle self._logger.debug('non-CS handle %u belongs to itself', handle) # XXX: deal with failure to get the handle owner assert handle != 0 return self.pservice.get_buddy_by_telepathy_handle( self.conn.service_name, self.conn.object_path, handle)
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
class BatchOperator(GObject.GObject): """ This class implements the course of actions that happens when clicking upon an BatchOperation (eg. Batch-Copy-Toolbar-button; Batch-Copy-To-Journal-button; Batch-Copy-To-Documents-button; Batch-Copy-To-Mounted-Drive-button; Batch-Copy-To-Clipboard-button; Batch-Erase-Button; """ def __init__(self, journalactivity, uid_list, alert_title, alert_message, operation_cb): GObject.GObject.__init__(self) self._journalactivity = journalactivity self._uid_list = uid_list[:] self._alert_title = alert_title self._alert_message = alert_message self._operation_cb = operation_cb self._show_confirmation_alert() def _show_confirmation_alert(self): self._journalactivity.freeze_ui() GObject.idle_add(self.__show_confirmation_alert_internal) def __show_confirmation_alert_internal(self): # Show a alert requesting confirmation before run the batch operation self._confirmation_alert = Alert() self._confirmation_alert.props.title = self._alert_title self._confirmation_alert.props.msg = self._alert_message stop_icon = Icon(icon_name='dialog-cancel') self._confirmation_alert.add_button(Gtk.ResponseType.CANCEL, _('Stop'), stop_icon) stop_icon.show() ok_icon = Icon(icon_name='dialog-ok') self._confirmation_alert.add_button(Gtk.ResponseType.OK, _('Continue'), ok_icon) ok_icon.show() self._journalactivity.add_alert(self._confirmation_alert) self._confirmation_alert.connect('response', self.__confirmation_response_cb) self._confirmation_alert.show() def __confirmation_response_cb(self, alert, response): if response == Gtk.ResponseType.CANCEL: self._journalactivity.unfreeze_ui() self._journalactivity.remove_alert(alert) # this is only in the case the operation already started # and the user want stop it. self._stop_batch_operation() else: GObject.idle_add(self._prepare_batch_execution) def _prepare_batch_execution(self): self._object_index = 0 # Next, proceed with the objects self._operate_by_uid() def _operate_by_uid(self): GObject.idle_add(self._operate_by_uid_internal) def _operate_by_uid_internal(self): # If there is still some uid left, proceed with the operation. # Else, proceed to post-operations. if self._object_index < len(self._uid_list): uid = self._uid_list[self._object_index] metadata = model.get(uid) title = None if 'title' in metadata: title = metadata['title'] if title is None or title == '': title = _('Untitled') alert_message = _('%(index)d of %(total)d : %(object_title)s') % { 'index': self._object_index, 'total': len(self._uid_list), 'object_title': title } self._confirmation_alert.props.msg = alert_message GObject.idle_add(self._operate_per_metadata, metadata) else: self._finish_batch_execution() def _operate_per_metadata(self, metadata): self._operation_cb(metadata) # process the next self._object_index = self._object_index + 1 GObject.idle_add(self._operate_by_uid_internal) def _stop_batch_execution(self): self._object_index = len(self._uid_list) def _finish_batch_execution(self): self._journalactivity.unfreeze_ui() self._journalactivity.remove_alert(self._confirmation_alert) self._journalactivity.update_selected_items_ui()
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()
def _journal_alert(self, object_id, title, msg): alert = Alert() alert.props.title = title alert.props.msg = msg bundle = get_bundle(object_id=object_id) if bundle is not None: alert.add_button(Gtk.ResponseType.ACCEPT, _('Open with {}').format(bundle.get_name()), Icon(file=bundle.get_icon())) else: alert.add_button(Gtk.ResponseType.APPLY, _('Show in Journal'), Icon(icon_name='zoom-activity')) alert.add_button(Gtk.ResponseType.OK, _('Ok'), Icon(icon_name='dialog-ok')) # Remove other alerts for alert in self._alerts: self.remove_alert(alert) self.add_alert(alert) alert.connect('response', self.__alert_response_cb, object_id) alert.show_all()
def _add_proxy_section(self, workspace): label_proxy = Gtk.Label(_('Proxy')) label_proxy.set_alignment(0, 0) workspace.pack_start(label_proxy, False, True, 0) label_proxy.show() box_proxy = Gtk.VBox() box_proxy.set_border_width(style.DEFAULT_SPACING * 2) box_proxy.set_spacing(style.DEFAULT_SPACING) workspace.pack_start(box_proxy, False, True, 0) box_proxy.show() self._proxy_alert = Alert() self._proxy_alert.props.title = _('Error') self._proxy_alert.props.msg = _('Proxy settings cannot be verified') box_proxy.pack_start(self._proxy_alert, False, False, 0) self._proxy_alert.connect('response', self._response_cb) self._proxy_alert.hide() # GSettings schemas for proxy: schemas = [ 'org.sugarlabs.system.proxy', 'org.sugarlabs.system.proxy.http', 'org.sugarlabs.system.proxy.https', 'org.sugarlabs.system.proxy.ftp', 'org.sugarlabs.system.proxy.socks' ] for schema in schemas: proxy_setting = Gio.Settings.new(schema) # We are not going to apply the settings immediatly. # We'll apply them if the user presses the "accept" # button, or we'll revert them if the user presses the # "cancel" button. proxy_setting.delay() alert = InlineAlert() self._proxy_settings[schema] = proxy_setting self._proxy_inline_alerts[schema] = alert size_group = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL) automatic_proxy_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) manual_proxy_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) option_sets = [('None', 'none', Gtk.VBox()), ('Use system proxy', 'system', Gtk.VBox()), ('Manual', 'manual', manual_proxy_box), ('Automatic', 'auto', automatic_proxy_box)] box_mode = ComboSettingBox( _('Method:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'mode', option_sets, size_group) box_proxy.pack_start(box_mode, False, False, 0) box_mode.show() url_box = StringSettingBox( _('Configuration URL:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'autoconfig-url', size_group) automatic_proxy_box.pack_start(url_box, True, True, 0) url_box.show() wpad_help_text = _('Web Proxy Autodiscovery is used when a' ' Configuration URL is not provided. This is not' ' recommended for untrusted public networks.') automatic_proxy_help = Gtk.Label(wpad_help_text) automatic_proxy_help.set_alignment(0, 0) automatic_proxy_help.set_line_wrap(True) automatic_proxy_help.show() automatic_proxy_box.pack_start(automatic_proxy_help, True, True, 0) # HTTP Section schema = 'org.sugarlabs.system.proxy.http' box_http = HostPortSettingBox(_('HTTP Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_http, False, False, 0) box_http.show() auth_contents_box = Gtk.VBox(spacing=style.DEFAULT_SPACING) auth_box = OptionalSettingsBox(_('Use authentication'), self._proxy_settings[schema], 'use-authentication', auth_contents_box) manual_proxy_box.pack_start(auth_box, False, False, 0) auth_box.show() proxy_http_setting = Gio.Settings.new(schema) proxy_http_setting.delay() box_username = StringSettingBox(_('Username:'******'authentication-user', size_group) auth_contents_box.pack_start(box_username, False, False, 0) box_username.show() box_password = StringSettingBox(_('Password:'******'authentication-password', size_group, password_field=True) auth_contents_box.pack_start(box_password, False, False, 0) box_password.show() # HTTPS Section schema = 'org.sugarlabs.system.proxy.https' box_https = HostPortSettingBox(_('HTTPS Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_https, False, False, 0) box_https.show() # FTP Section schema = 'org.sugarlabs.system.proxy.ftp' box_ftp = HostPortSettingBox(_('FTP Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_ftp, False, False, 0) box_ftp.show() # SOCKS Section schema = 'org.sugarlabs.system.proxy.socks' box_socks = HostPortSettingBox(_('SOCKS Proxy:'), self._proxy_inline_alerts[schema], self._proxy_settings[schema], size_group) manual_proxy_box.pack_start(box_socks, False, False, 0) box_socks.show() box_ignore = StringSettingBox_with_convert( _('Ignore Hosts:'), self._proxy_settings['org.sugarlabs.system.proxy'], 'ignore-hosts', type_as_to_string, string_to_type_as, size_group) manual_proxy_box.pack_start(box_ignore, False, False, 0) box_ignore.show()
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()