def clear_trace_cb(self, button): clear_trace_alert = ConfirmationAlert() clear_trace_alert.props.title = _('Are You Sure?') clear_trace_alert.props.msg = \ _('All trace points will be erased. This cannot be undone!') clear_trace_alert.connect('response', self.clear_trace_alert_cb) self.add_alert(clear_trace_alert)
def __show_duplicate_alert(self, menu_item): alert = ConfirmationAlert() alert.props.title = _('Do you want to duplicate %s Activity?') % \ self._activity_name alert.props.msg = _('This may take a few minutes') alert.connect('response', self.__duplicate_alert_response_cb) self.get_toplevel().add_alert(alert)
def __load_game(self, file_path, journal=False): confirmation_alert = ConfirmationAlert() confirmation_alert.props.title = _('Are You Sure?') confirmation_alert.props.msg = \ _('All your work will be discarded. This cannot be undone!') def action(alert, response): self.remove_alert(alert) if response is not Gtk.ResponseType.OK: return try: f = open(file_path, 'r') # Test if the file is valid project. json.loads(f.read()) f.close() self.read_file(file_path) except: title = _('Load project from journal') if not journal: title = _('Load example') msg = _('Error: Cannot open Physics project from this file.') alert = NotifyAlert(5) alert.props.title = title alert.props.msg = msg alert.connect('response', lambda alert, response: self.remove_alert(alert)) self.add_alert(alert) confirmation_alert.connect('response', action) self.add_alert(confirmation_alert)
def _downgrade_option_alert(bundle): alert = ConfirmationAlert() alert.props.title = _("Older Version Of %s Activity") % (bundle.get_name()) alert.props.msg = _("Do you want to downgrade to version %s") % bundle.get_activity_version() alert.connect("response", _downgrade_alert_response_cb, bundle) journalwindow.get_journal_window().add_alert(alert) alert.show()
def remove_extension(self, widget, event, path, cp_path, vbox, title): alert = ConfirmationAlert() alert.props.title = _('¿Remove extension?') alert.props.msg = _('Sure?') alert.connect('response', self.remove_confirmation, path, cp_path, vbox, title) self.activity.add_alert(alert)
def __load_game(self, file_path, journal=False): confirmation_alert = ConfirmationAlert() confirmation_alert.props.title = _("Are You Sure?") confirmation_alert.props.msg = _("All your work will be discarded. This cannot be undone!") def action(alert, response): self.remove_alert(alert) if response is not Gtk.ResponseType.OK: return try: f = open(file_path, "r") # Test if the file is valid project. json.loads(f.read()) f.close() self.read_file(file_path) self.game.run(True) except: title = _("Load project from journal") if not journal: title = _("Load example") msg = _("Error: Cannot open Physics project from this file.") alert = NotifyAlert(5) alert.props.title = title alert.props.msg = msg alert.connect("response", lambda alert, response: self.remove_alert(alert)) self.add_alert(alert) confirmation_alert.connect("response", action) self.add_alert(confirmation_alert)
def _tab_closed_cb(self, notebook, child): index = self.page_num(child) page = self.get_nth_page(index) text_buffer = page.get_children()[0].get_buffer() empty = text_buffer.get_char_count() == 0 if empty: self.__tab_close(index) self.emit('tab-closed', index) return tablabel = self.get_tab_label(page) path = tablabel.get_path() example = self.activity.is_example(path) pristine = not text_buffer.get_modified() if example and pristine: self.__tab_close(index) self.emit('tab-closed', index) return alert = ConfirmationAlert() alert.props.title = _('Erase') alert.props.msg = _('Do you want to permanently erase \"%s\"?') \ % tablabel.get_text() alert.connect('response', self._tab_close_alert_response_cb, index) self.activity.add_alert(alert)
def _downgrade_option_alert(bundle, metadata): alert = ConfirmationAlert() alert.props.title = _('Older Version Of %s Activity') % (bundle.get_name()) alert.props.msg = _('Do you want to downgrade to version %s') % \ bundle.get_activity_version() alert.connect('response', _downgrade_alert_response_cb, metadata) journalwindow.get_journal_window().add_alert(alert) alert.show()
def confirmation_alert(self, msg, title=None, confirmation_cb=None): alert = ConfirmationAlert() alert.props.title = title alert.props.msg = msg alert.pydebug_cb = confirmation_cb alert.connect('response', self._alert_response_cb) self._activity.add_alert(alert) return alert
def show_msg(self, text, title=""): """show_msg(text) shows text in a drop-down alert message. """ alert = ConfirmationAlert() alert.props.title = title alert.props.msg = text alert.connect('response', self.alert_cb) self.add_alert(alert) alert.show()
def _webservice_alert(self, message): alert = ConfirmationAlert() alert.props.title = message alert.props.msg = _('We are unable to install some software on your ' 'system.\nSugar must be upgraded before this ' 'activity can be run.') alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=message)
def _delete_poll_button_cb(self, button, event, sha, title): """ A DELETE button was clicked. """ alert = ConfirmationAlert() alert.props.title = _('Delete Poll?') alert.props.msg = _('Do you want delete the poll "%s"?') % title alert.connect('response', self._delete_alert_confirmation_cb, sha) self.add_alert(alert)
def clear_all_cb(self, button): def clear_all_alert_cb(alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action="clear_all")) if len(self.game.world.world.bodies) > 2: clear_all_alert = ConfirmationAlert() clear_all_alert.props.title = _("Are You Sure?") clear_all_alert.props.msg = _("All your work will be discarded. This cannot be undone!") clear_all_alert.connect("response", clear_all_alert_cb) self.add_alert(clear_all_alert)
def clear_all_cb(self, button): def clear_all_alert_cb(alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='clear_all')) if len(self.game.world.world.GetBodyList()) > 2: clear_all_alert = ConfirmationAlert() clear_all_alert.props.title = _('Are You Sure?') clear_all_alert.props.msg = \ _('All your work will be discarded. This cannot be undone!') clear_all_alert.connect('response', clear_all_alert_cb) self.add_alert(clear_all_alert)
def clear_all_cb(self, button): def clear_all_alert_cb(alert, response_id): self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: pygame.event.post(pygame.event.Event(pygame.USEREVENT, action='clear_all')) if len(self.game.world.world.bodies) > 2: clear_all_alert = ConfirmationAlert() clear_all_alert.props.title = _('Are You Sure?') clear_all_alert.props.msg = \ _('All your work will be discarded. This cannot be undone!') clear_all_alert.connect('response', clear_all_alert_cb) self.add_alert(clear_all_alert)
def publish(activity, force=False): if not [i for i in book.custom.index if i['ready']]: alert = NotifyAlert(5) alert.props.title = _('Nothing to publish') alert.props.msg = _('Mark arcticles from "Custom" ' 'panel and try again.') alert.connect('response', __alert_notify_response_cb, activity) activity.add_alert(alert) alert.show() return title = activity.metadata['title'] jobject = datastore.find({ 'activity_id': activity.get_id(), 'activity': book.custom.uid })[0] or None logger.debug('publish: title=%s jobject=%s force=%s' \ % (title, jobject and jobject[0].metadata['activity'], force)) if jobject: if force: jobject = jobject[0] else: alert = ConfirmationAlert() alert.props.title = _('Overwrite existed bundle?') alert.props.msg = _( 'A bundle for current object was already created. ' 'Click "OK" to overwrite it.') alert.connect('response', __alert_response_cb, activity, True) activity.add_alert(alert) alert.show() jobject[0].destroy() return else: jobject = datastore.create() jobject.metadata['activity_id'] = activity.get_id() jobject.metadata['activity'] = book.custom.uid jobject.metadata['mime_type'] = 'application/vnd.olpc-content' jobject.metadata['description'] = \ 'This is a bundle containing articles on %s.\n' \ 'To view these articles, open the \'Browse\' Activity.\n' \ 'Go to \'Books\', and select \'%s\'.' % (title, title) book.custom.sync_article() book.custom.revision += 1 jobject.metadata['title'] = title _publish(title, jobject) jobject.destroy() book.custom.sync_index() alert = NotifyAlert() alert.props.title = _('Book published to your Journal') alert.props.msg = _('You can read the book in Browse or ' 'access the .xol file from your Journal') alert.connect('response', __alert_notify_response_cb, activity) activity.add_alert(alert) alert.show()
def _save_colors_cb(self, button=None): ''' Save the new XO colors. ''' ''' We warn the user if they are going to save their selection ''' alert = ConfirmationAlert() alert.props.title = _('Saving colors') alert.props.msg = _('Do you want to save these colors?') def _change_colors_alert_response_cb(alert, response_id, self): if response_id is Gtk.ResponseType.OK: _logger.debug('saving colors') self.remove_alert(alert) self._confirm_save() elif response_id is Gtk.ResponseType.CANCEL: _logger.debug('cancel save') self.remove_alert(alert) alert.connect('response', _change_colors_alert_response_cb, self) self.add_alert(alert) alert.show()
def __permission_request_cb(self, webview, request): description = self._get_permission_name(request) site = webview.get_uri() match = _HOSTNAME_REGEX.match(site) if match: site = match.group(1) alert = ConfirmationAlert() alert.props.title = _('Allow %s to %s?') % \ (site, description) alert.props.msg = _( 'You can change your choice later by reloading the page') alert.connect('response', self.__permission_request_alert_cb, request) self._activity.add_alert(alert) # Allow async handeling return True
def _save_colors(self, widget): alert = ConfirmationAlert() alert.props.title = _("Saving colors") alert.props.msg = _("Do you want to save these colors?") alert.connect('response', self._alert_response_cb) self.add_alert(alert) alert.show_all()
def _alert_confirmation(self): alert = ConfirmationAlert() alert.remove_button(Gtk.ResponseType.CANCEL) alert.props.title = (_('Download Error')) alert.props.msg = (_('There was a problem with the download')) alert.connect('response', self._alert_response) self.add_alert(alert)
def __remove_clicked_cb(self, file_name): if self._image_canvas.is_image_active(): alert = ConfirmationAlert() alert.props.title = _('Do you want remove the selected image?') # alert.props.msg = _('') alert.connect('response', self.__confirm_remove_image_cb) self.add_alert(alert) else: if len(self._book_model.get_pages()) > 1: alert = ConfirmationAlert() alert.props.title = _('Do you want remove the page?') # alert.props.msg = _('') alert.connect('response', self.__confirm_remove_page_cb) self.add_alert(alert)
def _new_game_alert(self, button): ''' We warn the user if the game is in progress before loading a new game. ''' if self.collab.props.leader is not None and not self.collab.props.leader: # joiner cannot push buttons self._restoring = True self._no_action(button) self._restoring = False return if len(self._gnuchess.move_list) == 0: self._take_button_action(button) return self._restoring = True alert = ConfirmationAlert() alert.props.title = _('Game in progress.') alert.props.msg = _('Do you want to start a new game?') def _new_game_alert_response_cb(alert, response_id, self, button): if response_id is Gtk.ResponseType.OK: self._take_button_action(button) elif response_id is Gtk.ResponseType.CANCEL: self._no_action(button) self._restoring = False self.remove_alert(alert) alert.connect('response', _new_game_alert_response_cb, self, button) self.add_alert(alert) alert.show()
def _new_game_cb(self, button=None): ''' Start a new game. ''' if 'dirty' in self.metadata and self.metadata['dirty'] == 'True': if self._alert is not None: self.remove_alert(self._alert) self._alert = None self._alert = ConfirmationAlert() self._alert.props.title = \ _('Do you really want to load new images?') self._alert.props.msg = _('You have done work on this story.' ' Do you want to overwrite it?') self._alert.connect('response', self._confirmation_alert_cb) self.add_alert(self._alert) else: self.autoplay_button.set_sensitive(False) self._game.new_game()
def confirmation_alert(self, title, msg, cb, *cb_args): """Raise standard confirmation alert""" alert = ConfirmationAlert(title=title, msg=msg) def response(alert, response_id, self, cb, *cb_args): self.remove_alert(alert) if response_id is Gtk.ResponseType.OK: cb(*cb_args) alert.connect('response', response, self, cb, *cb_args) alert.show_all() self.add_alert(alert)
def __bookmarker_toggled_cb(self, button): page = self._view.get_current_page() if self._bookmarker.props.active: self._bookmark_view.add_bookmark(page) else: alert = ConfirmationAlert() alert.props.title = _('Delete bookmark') alert.props.msg = _('All the information related ' 'with this bookmark will be lost') self.add_alert(alert) alert.connect('response', self.__alert_response_cb, page) alert.show()
def _title_changed_event_cb(self, widget): old_title = self._metadata.get('title', None) new_title = self._title.get_text() if old_title != new_title: if new_title == '' or new_title.isspace(): alert = ConfirmationAlert() alert.props.title = _('Empty title') alert.props.msg = _('The title is usually not left empty') alert.connect('response', self._title_alert_response_cb, old_title, self._metadata.get('title_set_by_user', 0)) journalwindow.get_journal_window().add_alert(alert) alert.show() self._update_entry()
def __cell_title_edited_cb(self, cell, path, new_text): iterator = self._model.get_iter(path) old_text = self._model[iterator][ListModel.COLUMN_TITLE] if old_text != new_text and (new_text == '' or new_text.isspace()): alert = ConfirmationAlert() alert.props.title = _('Empty title') alert.props.msg = _('The title is usually not left empty') alert.connect('response', self._cell_title_alert_response_cb, path, new_text) journalwindow.get_journal_window().add_alert(alert) alert.show() return if old_text != new_text: self._model[iterator][ListModel.COLUMN_TITLE] = new_text self.emit('title-edit-finished', new_text, path)
def _load_extension(self): if not WEBSERVICES_AVAILABLE: _logger.error('Webservices not available on this version of Sugar') self._webservice_alert(_('Sugar upgrade required.')) return False extensions_path = os.path.join(os.path.expanduser('~'), '.sugar', 'default', 'extensions') webservice_path = os.path.join(extensions_path, 'webservice') sugarservices_path = os.path.join(self.bundle_path, 'sugarservices') init_path = os.path.join(self.bundle_path, 'sugarservices', '__init__.py') if not os.path.exists(extensions_path): try: subprocess.call(['mkdir', extensions_path]) except OSError as e: _logger.error('Could not mkdir %s, %s' % (extensions_path, e)) self._webservice_alert(_('System error.')) return False if not os.path.exists(webservice_path): try: subprocess.call(['mkdir', webservice_path]) except OSError as e: _logger.error('Could not mkdir %s, %s' % (webservice_path, e)) self._webservice_alert(_('System error.')) return False try: subprocess.call(['cp', init_path, webservice_path]) except OSError as e: _logger.error('Could not cp %s to %s, %s' % (init_path, webservice_path, e)) self._webservice_alert(_('System error.')) return False install = False if not os.path.exists(os.path.join(webservice_path, 'sugarservices')): _logger.error('SugarServices webservice not found. Installing...') install = True elif utils.get_sugarservices_version() < \ _REQUIRED_SUGARSERVICES_VERSION: _logger.error('Found old SugarServices version. Installing...') install = True if install: try: subprocess.call(['cp', '-r', sugarservices_path, webservice_path]) except OSError as e: _logger.error('Could not copy %s to %s, %s' % (sugarservices_path, webservice_path, e)) self._webservice_alert(_('System error.')) return False alert = ConfirmationAlert() alert.props.title = _('Restart required') alert.props.msg = _('We needed to install some software on your ' 'system.\nSugar must be restarted before ' 'sugarservices can commence.') alert.connect('response', self._reboot_alert_cb) self.add_alert(alert) self._load_intro_graphics(file_name='restart.html') return not install
def create_confirmation_alert(self, text, title=""): alert = ConfirmationAlert() alert.props.title = title alert.props.msg = text self.add_alert(alert) return alert
def check_volume_data(self): # Before we begin (and before each task), # we need to find any and all USB keys # and any and all training-data files on them. _logger.debug(utils.get_volume_paths()) self.volume_data = [] for path in utils.get_volume_paths(): os.path.basename(path) self.volume_data.append( {'basename': os.path.basename(path), 'files': utils.look_for_training_data(path), 'sugar_path': os.path.join(self.get_activity_root(), 'data'), 'usb_path': path}) _logger.debug(self.volume_data[-1]) # (1) We require a USB key if len(self.volume_data) == 0: _logger.error('NO USB KEY INSERTED') alert = ConfirmationAlert() alert.props.title = _('USB key required') alert.props.msg = _('You must insert a USB key before launching ' 'this activity.') alert.connect('response', self._remove_alert_cb) self.add_alert(alert) self._load_intro_graphics(file_name='insert-usb.html') return False # (2) Only one USB key if len(self.volume_data) > 1: _logger.error('MULTIPLE USB KEYS INSERTED') alert = ConfirmationAlert() alert.props.title = _('Multiple USB keys found') alert.props.msg = _('Only one USB key must be inserted while ' 'running this program.\nPlease remove any ' 'additional USB keys before launching ' 'this activity.') alert.connect('response', self._remove_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False volume = self.volume_data[0] # (3) At least 10MB of free space if utils.is_full(volume['usb_path'], required=_MINIMUM_SPACE): _logger.error('USB IS FULL') alert = ConfirmationAlert() alert.props.title = _('USB key is full') alert.props.msg = _('No room on USB') alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False # (4) File is read/write if not utils.is_writeable(volume['usb_path']): _logger.error('CANNOT WRITE TO USB') alert = ConfirmationAlert() alert.props.title = _('Cannot write to USB') alert.props.msg = _('USB key seems to be read-only.') alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False # (5) Only one set of training data per USB key # We expect UIDs to formated as XXXX-XXXX # We need to make sure we have proper UIDs associated with # the USBs and the files on them match the UID. # (a) If there are no files, we will assign the UID based on the # volume path; # (b) If there is one file with a valid UID, we use that UID; if len(volume['files']) == 0: volume['uid'] = 'training-data-%s' % \ utils.format_volume_name(volume['basename']) _logger.debug('No training data found. Using UID %s' % volume['uid']) return True elif len(volume['files']) == 1: volume['uid'] = 'training-data-%s' % volume['files'][0][-9:] _logger.debug('Training data found. Using UID %s' % volume['uid']) return True else: _logger.error('MULTIPLE TRAINING-DATA FILES FOUND') alert = ConfirmationAlert() alert.props.title = _('Multiple training-data files found.') alert.props.msg = _('There can only be one set of training ' 'data per USB key.') alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False
def _sync_data_from_USB(self, usb_data_path=None): # We need to sync up file on USB with file on disk, # but only if the email addresses match. Otherwise, # raise an error. if usb_data_path is not None: usb_data = {} if os.path.exists(usb_data_path): fd = open(usb_data_path, 'r') json_data = fd.read() fd.close() if len(json_data) > 0: try: usb_data = json.loads(json_data) except ValueError as e: _logger.error('Cannot load USB data: %s' % e) else: _logger.error('Cannot find USB data: %s' % usb_data_path) sugar_data_path = os.path.join( self.volume_data[0]['sugar_path'], self.volume_data[0]['uid']) sugar_data = {} if os.path.exists(sugar_data_path): fd = open(sugar_data_path, 'r') json_data = fd.read() fd.close() if len(json_data) > 0: try: sugar_data = json.loads(json_data) except ValueError as e: _logger.error('Cannot load Sugar data: %s' % e) else: _logger.error('Cannot find Sugar data: %s' % sugar_data_path) # First, check to make sure email_address matches if EMAIL_UID in usb_data: usb_email = usb_data[EMAIL_UID] else: usb_email = None if EMAIL_UID in sugar_data: sugar_email = sugar_data[EMAIL_UID] else: sugar_email = None if usb_email != sugar_email: if usb_email is None and sugar_email is not None: _logger.warning('Using email address from Sugar: %s' % sugar_email) usb_data[EMAIL_UID] = sugar_email elif usb_email is not None and sugar_email is None: _logger.warning('Using email address from USB: %s' % usb_email) sugar_data[EMAIL_UID] = usb_email elif usb_email is None and sugar_email is None: _logger.warning('No email address found') else: # FIX ME: We need to resolve this, but for right now, punt. alert = ConfirmationAlert() alert.props.title = _('Data mismatch') alert.props.msg = _('Are you %(usb)s or %(sugar)s?' % {'usb': usb_email, 'sugar': sugar_email}) alert.connect('response', self._close_alert_cb) self.add_alert(alert) self._load_intro_graphics(message=alert.props.msg) return False def count_completed(data): count = 0 for key in data: if isinstance(data[key], dict) and \ 'completed' in data[key] and \ data[key]['completed']: count += 1 return count # The database with the most completed tasks takes precedence. if count_completed(usb_data) >= count_completed(sugar_data): _logger.debug('data sync: USB data takes precedence') data_one = usb_data data_two = sugar_data else: _logger.debug('data sync: Sugar data takes precedence') data_one = sugar_data data_two = usb_data # Copy completed tasks from one to two for key in data_one: if isinstance(data_one[key], dict) and \ 'completed' in data_one[key] and \ data_one[key]['completed']: data_two[key] = data_one[key] # Copy completed tasks from two to one for key in data_two: if isinstance(data_two[key], dict) and \ 'completed' in data_two[key] and \ data_two[key]['completed']: data_one[key] = data_two[key] # Copy incompleted tasks from one to two for key in data_one: if isinstance(data_one[key], dict) and \ (not 'completed' in data_one[key] or not data_one[key]['completed']): data_two[key] = data_one[key] # Copy incompleted tasks from two to one for key in data_two: if isinstance(data_two[key], dict) and \ (not 'completed' in data_two[key] or not data_two[key]['completed']): data_one[key] = data_two[key] # Copy name, email_address, current_task... for key in data_one: if not isinstance(data_one[key], dict): data_two[key] = data_one[key] for key in data_two: if not isinstance(data_two[key], dict): data_one[key] = data_two[key] # Finally, write to the USB and ... json_data = json.dumps(data_one) fd = open(usb_data_path, 'w') fd.write(json_data) fd.close() # ...save a shadow copy in Sugar fd = open(sugar_data_path, 'w') fd.write(json_data) fd.close() return True else: _logger.error('No data to sync on USB') return False