def __init__(self, params, prev_page="location_grp", next_page="timezone", **kwargs): super().__init__(self, params, name="location", prev_page=prev_page, next_page=next_page, **kwargs) self.listbox = self.ui.get_object("listbox") self.listbox.connect("row-selected", self.on_listbox_row_selected) self.listbox.set_selection_mode(Gtk.SelectionMode.BROWSE) self.listbox.get_style_context().add_class('list_box') self.label_choose_country = self.ui.get_object("label_choose_country") self.label_help = self.ui.get_object("label_help") self.locales = {} self.load_locales() self.title = _('Location') self.selected_country = "" self.show_all_locations = False self.in_group = True self.context_filter = ContextFilter() button = self.ui.get_object("show_all_locations_checkbutton") button.connect("toggled", self.on_show_all_locations_checkbox_toggled, "") self.scrolledwindow = self.ui.get_object("scrolledwindow1")
def __init__(self, params, prev_page="location_grp", next_page="timezone", **kwargs): super().__init__(self, params, name="location", prev_page=prev_page, next_page=next_page, **kwargs) self.listbox = self.ui.get_object("listbox") self.listbox.connect("row-selected", self.on_listbox_row_selected) self.listbox.set_selection_mode(Gtk.SelectionMode.BROWSE) self.listbox.get_style_context().add_class('list_box') self.label_choose_country = self.ui.get_object("label_choose_country") self.label_help = self.ui.get_object("label_help") self.locales = {} self.load_locales() self.title = _('Location') self.selected_country = "" self.show_all_locations = False self.in_group = True self.context_filter = ContextFilter() button = self.ui.get_object("show_all_locations_checkbutton") button.connect( "toggled", self.on_show_all_locations_checkbox_toggled, "") self.scrolledwindow = self.ui.get_object("scrolledwindow1")
def setup_logging(): """ Configure our logger """ logger = logging.getLogger() logger.handlers = [] if cmd_line.debug: log_level = logging.DEBUG else: log_level = logging.INFO logger.setLevel(log_level) context_filter = ContextFilter() logger.addFilter(context_filter.filter) # Log format formatter = logging.Formatter( fmt= "%(asctime)s [%(levelname)s] %(filename)s(%(lineno)d) %(funcName)s(): %(message)s", datefmt="%Y-%m-%d %H:%M:%S") # File logger try: file_handler = logging.FileHandler('/tmp/cnchi.log', mode='w') file_handler.setLevel(log_level) file_handler.setFormatter(formatter) logger.addHandler(file_handler) except PermissionError as permission_error: print("Can't open /tmp/cnchi.log : ", permission_error) # Stdout logger if cmd_line.verbose: # Show log messages to stdout stream_handler = logging.StreamHandler() stream_handler.setLevel(log_level) stream_handler.setFormatter(formatter) logger.addHandler(stream_handler) if cmd_line.log_server: log_server = cmd_line.log_server if log_server == 'bugsnag': if not BUGSNAG_ERROR: # Bugsnag logger bugsnag_api = context_filter.api_key if bugsnag_api is not None: bugsnag.configure(api_key=bugsnag_api, app_version=info.CNCHI_VERSION, project_root='/usr/share/cnchi/cnchi', release_stage=info.CNCHI_RELEASE_STAGE) bugsnag_handler = BugsnagHandler(api_key=bugsnag_api) bugsnag_handler.setLevel(logging.WARNING) bugsnag_handler.setFormatter(formatter) bugsnag_handler.addFilter(context_filter.filter) bugsnag.before_notify( context_filter.bugsnag_before_notify_callback) logger.addHandler(bugsnag_handler) logging.info( "Sending Cnchi log messages to bugsnag server (using python-bugsnag)." ) else: logging.warning( "Cannot read the bugsnag api key, logging to bugsnag is not possible." ) else: logging.warning(BUGSNAG_ERROR) else: # Socket logger socket_handler = logging.handlers.SocketHandler( log_server, logging.handlers.DEFAULT_TCP_LOGGING_PORT) socket_formatter = logging.Formatter(formatter) socket_handler.setFormatter(socket_formatter) logger.addHandler(socket_handler) # Also add uuid filter to requests logs logger_requests = logging.getLogger( "requests.packages.urllib3.connectionpool") logger_requests.addFilter(context_filter.filter) uid = str(uuid.uuid1()).split("-") myuid = uid[3] + "-" + uid[1] + "-" + uid[2] + "-" + uid[4] logging.info("Sending Cnchi logs to {0} with id '{1}'".format( log_server, myuid))
def manage_events_from_cb_queue(self): """ We should be quick here and do as less as possible """ if self.fatal_error: return False if self.callback_queue is None: return True while not self.callback_queue.empty(): try: event = self.callback_queue.get_nowait() except ValueError as queue_error: # Calling get_nowait so many times can issue a ValueError # exception with this error: semaphore or lock released too # many times. Log it anyways to keep an eye on this error logging.error(queue_error) return True except queue.Empty: # Queue is empty, just quit. return True if event[0] == 'percent': self.progress_bar.set_fraction(float(event[1])) elif event[0] == 'downloads_percent': self.downloads_progress_bar.set_fraction(float(event[1])) elif event[0] == 'progress_bar_show_text': if len(event[1]) > 0: # self.progress_bar.set_show_text(True) self.progress_bar.set_text(event[1]) else: # self.progress_bar.set_show_text(False) self.progress_bar.set_text("") elif event[0] == 'progress_bar': if event[1] == 'hide': self.progress_bar.hide() elif event[1] == 'show': self.progress_bar.show() elif event[0] == 'downloads_progress_bar': if event[1] == 'hide': self.downloads_progress_bar.hide() elif event[1] == 'show': self.downloads_progress_bar.show() elif event[0] == 'pulse': if event[1] == 'stop': self.stop_pulse() elif event[1] == 'start': self.start_pulse() elif event[0] == 'finished': logging.info(event[1]) log_util = ContextFilter() log_util.send_install_result("True") if (self.settings.get('bootloader_install')): install_ok = _("Installation Complete!\n" "Do you want to restart your system now?") response = show.question(self.get_main_window(), install_ok) misc.remove_temp_files() logging.shutdown() if response == Gtk.ResponseType.YES: self.reboot() else: sys.exit(0) return False elif event[0] == 'error': log_util = ContextFilter() log_util.send_install_result("False") self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() # Add install id to error message (we can lookup logs on bugsnag by the install id) tpl = _( 'Please reference the following number when reporting this error: ' ) error_message = '{0}\n{1}{2}'.format(event[1], tpl, log_util.install_id) # Show the error show.fatal_error(self.get_main_window(), error_message) elif event[0] == 'info': logging.info(event[1]) if self.should_pulse: self.progress_bar.set_text(event[1]) else: self.set_message(event[1]) elif event[0] == 'cache_pkgs_md5_check_failed': logging.debug('Adding %s to cache_pkgs_md5_check_failed list', event[1]) self.settings.set('cache_pkgs_md5_check_failed', event[1]) self.callback_queue.task_done() return True
def get_and_save_install_id(): context_filter = ContextFilter() context_filter.get_and_save_install_id(is_location_screen=True)
def manage_events_from_cb_queue(self): """ We should be quick here and do as less as possible """ if self.fatal_error: return False if self.callback_queue is None: return True while not self.callback_queue.empty(): try: event = self.callback_queue.get_nowait() except ValueError as queue_error: # Calling get_nowait so many times can issue a ValueError # exception with this error: semaphore or lock released too # many times. Log it anyways to keep an eye on this error logging.error(queue_error) return True except queue.Empty: # Queue is empty, just quit. return True if event[0] == 'percent': self.progress_bar.set_fraction(float(event[1])) elif event[0] == 'downloads_percent': self.downloads_progress_bar.set_fraction(float(event[1])) elif event[0] == 'progress_bar_show_text': if len(event[1]) > 0: # self.progress_bar.set_show_text(True) self.progress_bar.set_text(event[1]) else: # self.progress_bar.set_show_text(False) self.progress_bar.set_text("") elif event[0] == 'progress_bar': if event[1] == 'hide': self.progress_bar.hide() elif event[1] == 'show': self.progress_bar.show() elif event[0] == 'downloads_progress_bar': if event[1] == 'hide': self.downloads_progress_bar.hide() elif event[1] == 'show': self.downloads_progress_bar.show() elif event[0] == 'pulse': if event[1] == 'stop': self.stop_pulse() elif event[1] == 'start': self.start_pulse() elif event[0] == 'finished': logging.info(event[1]) log_util = ContextFilter() log_util.send_install_result("True") if (self.settings.get('bootloader_install') and not self.settings.get( 'bootloader_installation_successful')): # Warn user about GRUB and ask if we should open wiki page. boot_warn = _( "IMPORTANT: There may have been a problem " "with the bootloader installation which " "could prevent your system from booting " "properly. Before rebooting, you may want " "to verify whether or not the bootloader is " "installed and configured.\n\n" "The Arch Linux Wiki contains " "troubleshooting information:\n" "\thttps://wiki.archlinux.org/index.php/GRUB\n\n" "Would you like to view the wiki page now?") response = show.question(self.get_main_window(), boot_warn) if response == Gtk.ResponseType.YES: import webbrowser misc.drop_privileges() wiki_url = 'https://wiki.archlinux.org/index.php/GRUB' webbrowser.open(wiki_url) install_ok = _("Installation Complete!\n" "Do you want to restart your system now?") response = show.question(self.get_main_window(), install_ok) misc.remove_temp_files() logging.shutdown() if response == Gtk.ResponseType.YES: self.reboot() else: sys.exit(0) return False elif event[0] == 'error': log_util = ContextFilter() log_util.send_install_result("False") self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() # Add install id to error message (we can lookup logs on bugsnag by the install id) tpl = _( 'Please reference the following number when reporting this error: ' ) error_message = '{0}\n{1}{2}'.format(event[1], tpl, log_util.install_id) # Show the error show.fatal_error(self.get_main_window(), error_message) elif event[0] == 'info': logging.info(event[1]) if self.should_pulse: self.progress_bar.set_text(event[1]) else: self.set_message(event[1]) elif event[0] == 'cache_pkgs_md5_check_failed': logging.debug('Adding %s to cache_pkgs_md5_check_failed list', event[1]) self.settings.set('cache_pkgs_md5_check_failed', event[1]) self.callback_queue.task_done() return True
def manage_events_from_cb_queue(self): """ We should be quick here and do as less as possible """ if self.fatal_error: return False if self.callback_queue is None: return True while not self.callback_queue.empty(): try: event = self.callback_queue.get_nowait() except ValueError as queue_error: # Calling get_nowait so many times can issue a ValueError # exception with this error: semaphore or lock released too # many times. Log it anyways to keep an eye on this error logging.error(queue_error) return True except queue.Empty: # Queue is empty, just quit. return True if event[0] == 'percent': self.progress_bar.set_fraction(float(event[1])) elif event[0] == 'downloads_percent': self.downloads_progress_bar.set_fraction(float(event[1])) elif event[0] == 'progress_bar_show_text': if len(event[1]) > 0: # self.progress_bar.set_show_text(True) self.progress_bar.set_text(event[1]) else: # self.progress_bar.set_show_text(False) self.progress_bar.set_text("") elif event[0] == 'progress_bar': if event[1] == 'hide': self.progress_bar.hide() elif event[1] == 'show': self.progress_bar.show() elif event[0] == 'downloads_progress_bar': if event[1] == 'hide': self.downloads_progress_bar.hide() elif event[1] == 'show': self.downloads_progress_bar.show() elif event[0] == 'pulse': if event[1] == 'stop': self.stop_pulse() elif event[1] == 'start': self.start_pulse() elif event[0] == 'finished': logging.info(event[1]) log_util = ContextFilter() log_util.send_install_result("True") if (self.settings.get('bootloader_install') and not self.settings.get('bootloader_installation_successful')): # Warn user about GRUB and ask if we should open wiki page. boot_warn = _("IMPORTANT: There may have been a problem " "with the bootloader installation which " "could prevent your system from booting " "properly. Before rebooting, you may want " "to verify whether or not the bootloader is " "installed and configured.\n\n" "The Arch Linux Wiki contains " "troubleshooting information:\n" "\thttps://wiki.archlinux.org/index.php/GRUB\n\n" "Would you like to view the wiki page now?") response = show.question(self.get_main_window(), boot_warn) if response == Gtk.ResponseType.YES: import webbrowser misc.drop_privileges() wiki_url = 'https://wiki.archlinux.org/index.php/GRUB' webbrowser.open(wiki_url) install_ok = _("Installation Complete!\n" "Do you want to restart your system now?") response = show.question(self.get_main_window(), install_ok) misc.remove_temp_files() logging.shutdown() if response == Gtk.ResponseType.YES: self.reboot() else: sys.exit(0) return False elif event[0] == 'error': log_util = ContextFilter() log_util.send_install_result("False") self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() # Show the error show.fatal_error(self.get_main_window(), event[1]) elif event[0] == 'info': logging.info(event[1]) if self.should_pulse: self.progress_bar.set_text(event[1]) else: self.set_message(event[1]) elif event[0] == 'cache_pkgs_md5_check_failed': logging.debug( 'Adding %s to cache_pkgs_md5_check_failed list', event[1]) self.settings.set('cache_pkgs_md5_check_failed', event[1]) self.callback_queue.task_done() return True
class Location(Page): def __init__(self, params, prev_page="location_grp", next_page="timezone", **kwargs): super().__init__(self, params, name="location", prev_page=prev_page, next_page=next_page, **kwargs) self.listbox = self.ui.get_object("listbox") self.listbox.connect("row-selected", self.on_listbox_row_selected) self.listbox.set_selection_mode(Gtk.SelectionMode.BROWSE) self.listbox.get_style_context().add_class('list_box') self.label_choose_country = self.ui.get_object("label_choose_country") self.label_help = self.ui.get_object("label_help") self.locales = {} self.load_locales() self.title = _('Location') self.selected_country = "" self.show_all_locations = False self.in_group = True self.context_filter = ContextFilter() button = self.ui.get_object("show_all_locations_checkbutton") button.connect("toggled", self.on_show_all_locations_checkbox_toggled, "") self.scrolledwindow = self.ui.get_object("scrolledwindow1") def on_show_all_locations_checkbox_toggled(self, button, name): self.show_all_locations = button.get_active() self.hide_all() self.fill_listbox() self.select_first_listbox_item() self.show_all() def translate_ui(self): """ Translates all ui elements """ pass def select_first_listbox_item(self): listbox_row = self.listbox.get_children()[0] self.listbox.select_row(listbox_row) def hide_all(self): names = [ "location_box", "label_help", "label_choose_country", "box1", "eventbox1", "eventbox2", "scrolledwindow1", "listbox_countries" ] for name in names: control = self.ui.get_object(name) if control is not None: control.hide() def prepare(self, direction): self.hide_all() self.fill_listbox() self.select_first_listbox_item() self.translate_ui() self.set_valign(Gtk.Align.CENTER) self.show_all() self.forward_button.set_sensitive(True) if not self.context_filter.have_install_id: logging.debug('Getting install_id from build server...') self.get_and_save_install_id() def load_locales(self): data_dir = self.settings.get('data') xml_path = os.path.join(data_dir, "locale", "locales.xml") self.locales = {} try: tree = eTree.parse(xml_path) except FileNotFoundError as file_error: logging.error(file_error) sys.exit(1) root = tree.getroot() locale_name = "" language_name = "" for child in root.iter("language"): for item in child: if item.tag == 'language_name': language_name = item.text elif item.tag == 'locale_name': locale_name = item.text if len(locale_name) > 0 and len(language_name) > 0: self.locales[locale_name] = language_name xml_path = os.path.join(data_dir, "locale", "iso3366-1.xml") countries = {} try: tree = eTree.parse(xml_path) except FileNotFoundError as file_error: logging.error(file_error) sys.exit(1) root = tree.getroot() for child in root: code = child.attrib['value'] name = child.text countries[code] = name for locale_name in self.locales: language_name = self.locales[locale_name] for country_code in countries: if country_code in language_name: self.locales[locale_name] = self.locales[ locale_name] + ", " + countries[country_code] def get_areas(self): areas = [] lang_code = self.settings.get("language_code") for locale_name in self.locales: # logging.debug(locale_name) if self.show_all_locations or lang_code in locale_name: areas.append(self.locales[locale_name]) if len(areas) == 0: # When we don't find any country we put all language codes. # This happens with Esperanto and Asturianu at least. for locale_name in self.locales: areas.append(self.locales[locale_name]) areas.sort() return areas def fill_listbox(self): areas = self.get_areas() for listbox_row in self.listbox.get_children(): listbox_row.destroy() labels = [] country = self.settings.get('timezone_country') for area in areas: label = Gtk.Label.new() label.set_markup(area) list_box_row = Gtk.ListBoxRow.new() list_box_row.get_style_context().add_class('list_box_row') list_box_row.show_all() list_box_row.add(label) if country and '(' + country + ')' in area: self.listbox.add(list_box_row) else: labels.append(list_box_row) for label in labels: self.listbox.add(label) self.selected_country = areas[0] def on_listbox_row_selected(self, listbox, listbox_row): if listbox_row is not None: label = listbox_row.get_children()[0] if label is not None: self.selected_country = label.get_text() def set_locale(self, mylocale): self.settings.set("locale", mylocale) # LANG=en_US.UTF-8 locale_vars = [ locale.LC_CTYPE, locale.LC_NUMERIC, locale.LC_TIME, locale.LC_COLLATE, locale.LC_MONETARY, locale.LC_MESSAGES ] try: locale.setlocale(locale.LC_ALL, mylocale) except locale.Error as err: logging.debug('Unable to set locale for all categories at once.') try: for var in locale_vars: locale.setlocale(var, mylocale) logging.debug("Locale changed to : %s", mylocale) except locale.Error as err: logging.warning("Cannot change to locale '%s': %s", mylocale, err) if mylocale.endswith(".UTF-8"): # Try without the .UTF-8 trailing mylocale = mylocale[:-len(".UTF-8")] try: for var in locale_vars: locale.setlocale(var, mylocale) logging.debug("Locale changed to : %s", mylocale) self.settings.set("locale", mylocale) except locale.Error as err: logging.warning("Cannot change to locale '%s': %s", mylocale, err) else: logging.warning("Cannot change to locale '%s'", mylocale) def store_values(self): location = self.selected_country logging.debug("Selected location: %s", location) self.settings.set('location', location) for mylocale in self.locales: if self.locales[mylocale] == location: self.set_locale(mylocale) if ',' in location: country_name = location.split(',')[1].strip() match = re.search('\(\w+\)', location) if match: country_code = match.group()[1:-1].lower() else: logging.error(_("Can't get country code from %s location"), location) country_code = 'us' else: country_name = 'USA' country_code = 'us' logging.debug("Selected country name: %s", country_name) logging.debug("Selected country code: %s", country_code) self.settings.set('country_name', country_name) self.settings.set('country_code', country_code) return True def get_and_save_install_id(self): self.context_filter.get_and_save_install_id(is_location_screen=True)
class Location(Page): def __init__(self, params, prev_page="location_grp", next_page="timezone", **kwargs): super().__init__(self, params, name="location", prev_page=prev_page, next_page=next_page, **kwargs) self.listbox = self.ui.get_object("listbox") self.listbox.connect("row-selected", self.on_listbox_row_selected) self.listbox.set_selection_mode(Gtk.SelectionMode.BROWSE) self.listbox.get_style_context().add_class('list_box') self.label_choose_country = self.ui.get_object("label_choose_country") self.label_help = self.ui.get_object("label_help") self.locales = {} self.load_locales() self.title = _('Location') self.selected_country = "" self.show_all_locations = False self.in_group = True self.context_filter = ContextFilter() button = self.ui.get_object("show_all_locations_checkbutton") button.connect( "toggled", self.on_show_all_locations_checkbox_toggled, "") self.scrolledwindow = self.ui.get_object("scrolledwindow1") def on_show_all_locations_checkbox_toggled(self, button, name): self.show_all_locations = button.get_active() self.hide_all() self.fill_listbox() self.select_first_listbox_item() self.show_all() def translate_ui(self): """ Translates all ui elements """ pass def select_first_listbox_item(self): listbox_row = self.listbox.get_children()[0] self.listbox.select_row(listbox_row) def hide_all(self): names = [ "location_box", "label_help", "label_choose_country", "box1", "eventbox1", "eventbox2", "scrolledwindow1", "listbox_countries"] for name in names: control = self.ui.get_object(name) if control is not None: control.hide() def prepare(self, direction): self.hide_all() self.fill_listbox() self.select_first_listbox_item() self.translate_ui() self.set_valign(Gtk.Align.CENTER) self.show_all() self.forward_button.set_sensitive(True) if not self.context_filter.have_install_id: logging.debug('Getting install_id from build server...') self.get_and_save_install_id() def load_locales(self): data_dir = self.settings.get('data') xml_path = os.path.join(data_dir, "locale", "locales.xml") self.locales = {} try: tree = eTree.parse(xml_path) except FileNotFoundError as file_error: logging.error(file_error) sys.exit(1) root = tree.getroot() locale_name = "" language_name = "" for child in root.iter("language"): for item in child: if item.tag == 'language_name': language_name = item.text elif item.tag == 'locale_name': locale_name = item.text if len(locale_name) > 0 and len(language_name) > 0: self.locales[locale_name] = language_name xml_path = os.path.join(data_dir, "locale", "iso3366-1.xml") countries = {} try: tree = eTree.parse(xml_path) except FileNotFoundError as file_error: logging.error(file_error) sys.exit(1) root = tree.getroot() for child in root: code = child.attrib['value'] name = child.text countries[code] = name for locale_name in self.locales: language_name = self.locales[locale_name] for country_code in countries: if country_code in language_name: self.locales[locale_name] = self.locales[locale_name] + ", " + countries[country_code] def get_areas(self): areas = [] lang_code = self.settings.get("language_code") for locale_name in self.locales: # logging.debug(locale_name) if self.show_all_locations or lang_code in locale_name: areas.append(self.locales[locale_name]) if len(areas) == 0: # When we don't find any country we put all language codes. # This happens with Esperanto and Asturianu at least. for locale_name in self.locales: areas.append(self.locales[locale_name]) areas.sort() return areas def fill_listbox(self): areas = self.get_areas() for listbox_row in self.listbox.get_children(): listbox_row.destroy() labels = [] country = self.settings.get('timezone_country') for area in areas: label = Gtk.Label.new() label.set_markup(area) list_box_row = Gtk.ListBoxRow.new() list_box_row.get_style_context().add_class('list_box_row') list_box_row.show_all() list_box_row.add(label) if country and '(' + country + ')' in area: self.listbox.add(list_box_row) else: labels.append(list_box_row) for label in labels: self.listbox.add(label) self.selected_country = areas[0] def on_listbox_row_selected(self, listbox, listbox_row): if listbox_row is not None: label = listbox_row.get_children()[0] if label is not None: self.selected_country = label.get_text() def set_locale(self, mylocale): self.settings.set("locale", mylocale) # LANG=en_US.UTF-8 locale_vars = [ locale.LC_CTYPE, locale.LC_NUMERIC, locale.LC_TIME, locale.LC_COLLATE, locale.LC_MONETARY, locale.LC_MESSAGES] try: locale.setlocale(locale.LC_ALL, mylocale) except locale.Error as err: logging.debug('Unable to set locale for all categories at once.') try: for var in locale_vars: locale.setlocale(var, mylocale) logging.debug("Locale changed to : %s", mylocale) except locale.Error as err: logging.warning("Cannot change to locale '%s': %s", mylocale, err) if mylocale.endswith(".UTF-8"): # Try without the .UTF-8 trailing mylocale = mylocale[:-len(".UTF-8")] try: for var in locale_vars: locale.setlocale(var, mylocale) logging.debug("Locale changed to : %s", mylocale) self.settings.set("locale", mylocale) except locale.Error as err: logging.warning( "Cannot change to locale '%s': %s", mylocale, err) else: logging.warning("Cannot change to locale '%s'", mylocale) def store_values(self): location = self.selected_country logging.debug("Selected location: %s", location) self.settings.set('location', location) for mylocale in self.locales: if self.locales[mylocale] == location: self.set_locale(mylocale) if ',' in location: country_name = location.split(',')[1].strip() match = re.search('\(\w+\)', location) if match: country_code = match.group()[1:-1].lower() else: logging.error( _("Can't get country code from %s location"), location) country_code = 'us' else: country_name = 'USA' country_code = 'us' logging.debug("Selected country name: %s", country_name) logging.debug("Selected country code: %s", country_code) self.settings.set('country_name', country_name) self.settings.set('country_code', country_code) return True def get_and_save_install_id(self): self.context_filter.get_and_save_install_id(is_location_screen=True)