Ejemplo n.º 1
0
    def check_all(self):
        """ Check that all requirements are meet """
        if os.path.exists("/tmp/.cnchi_partitioning_completed"):
            msg = "You must reboot before retrying again."
            logging.error(msg)
            msg = _("You must reboot before retrying again.")
            show.fatal_error(self.main_window, msg)
            return False

        has_internet = misc.has_connection()
        self.prepare_network_connection.set_state(has_internet)

        on_power = not self.on_battery()
        self.prepare_power_source.set_state(on_power)

        space = self.has_enough_space()
        self.prepare_enough_space.set_state(space)

        if has_internet:
            updated = self.is_updated()
        else:
            updated = False

        self.updated.set_state(updated)

        if self.checks_are_optional:
            return True

        if has_internet and space:
            return True

        return False
Ejemplo n.º 2
0
    def manage_events_from_cb_queue(self):
        if self.fatal_error:
            return False

        while self.callback_queue.empty() == False:
            try:
                event = self.callback_queue.get_nowait()
            except queue.Empty:
                return True

            if event[0] == 'percent':
                self.progress_bar.set_fraction(event[1])
            elif event[0] == 'global_percent':
                self.show_global_progress_bar_if_hidden()
                self.global_progress_bar.set_fraction(event[1])
            elif event[0] == 'finished':
                logging.info(event[1])
                self.set_message(self.install_ok)
                response = show.question(self.install_ok)
                if response == Gtk.ResponseType.YES:
                    self.reboot()
                else:
                    tmp_files = [".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup", "Cnchi.log"]
                    for t in tmp_files:
                        p = os.path.join("/tmp", t)
                        if os.path.exists(p):
                            # TODO: some of these tmp files are created with sudo privileges
                            # (this should be fixed) meanwhile, we need sudo privileges to remove them
                            with misc.raised_privileges():
                                os.remove(p)
                    while Gtk.events_pending():
                        Gtk.main_iteration()
                    Gtk.main_quit()
                        
                self.exit_button.show()
                return False
            elif event[0] == 'error':
                self.callback_queue.task_done()
                # a fatal error has been issued. We empty the queue
                self.empty_queue()
                self.fatal_error = True
                show.fatal_error(event[1])
                return False
            elif event[0] == 'debug':
                logging.debug(event[1])
            elif event[0] == 'warning':
                logging.warning(event[1])
            else:
                # TODO: Check if logging slows down showing messages
                #       remove logging.info in that case (and at least
                #       use the one at pac.py:queue_event)
                logging.info(event[1])
                self.set_message(event[1])
                            
            self.callback_queue.task_done()
        
        return True
Ejemplo n.º 3
0
    def populate_treeview(self):
        if self.treeview_store is not None:
            self.treeview_store.clear()

        self.treeview_store = Gtk.TreeStore(str, str, str)

        oses = {}
        oses = bootinfo.get_os_dict()

        self.partitions = {}

        try:
            device_list = parted.getAllDevices()
        except:
            txt = _("pyparted3 not found!")
            logging.error(txt)
            show.fatal_error(txt)
            device_list = []

        for dev in device_list:
            ## avoid cdrom and any raid, lvm volumes or encryptfs
            if not dev.path.startswith("/dev/sr") and \
               not dev.path.startswith("/dev/mapper"):
                try:
                    disk = parted.Disk(dev)
                    # create list of partitions for this device (p.e. /dev/sda)
                    partition_list = disk.partitions

                    for p in partition_list:
                        if p.type != pm.PARTITION_EXTENDED:
                            ## Get filesystem
                            fs_type = ""
                            if p.fileSystem and p.fileSystem.type:
                                fs_type = p.fileSystem.type
                            if "swap" not in fs_type:
                                if p.path in oses:
                                    row = [p.path, oses[p.path], fs_type]
                                else:
                                    row = [p.path, _("unknown"), fs_type]
                                self.treeview_store.append(None, row)
                        self.partitions[p.path] = p
                except Exception as e:
                    txt = _("Unable to create list of partitions for alongside installation.")
                    logging.warning(txt)
                    #show.warning(txt)

        # assign our new model to our treeview
        self.treeview.set_model(self.treeview_store)
        self.treeview.expand_all()
Ejemplo n.º 4
0
    def on_treeview_cursor_changed(self, widget):
        selection = self.treeview.get_selection()

        if not selection:
            return

        model, tree_iter = selection.get_selected()

        if tree_iter is None:
            return

        self.row = model[tree_iter]

        partition_path = self.row[0]
        other_os_name = self.row[1]

        self.min_size = 0
        self.max_size = 0
        self.new_size = 0

        try:
            subprocess.call(["mount", partition_path, "/mnt"], stderr=subprocess.DEVNULL)
            x = subprocess.check_output(['df', partition_path]).decode()
            subprocess.call(["umount", "-l", "/mnt"], stderr=subprocess.DEVNULL)
            x = x.split('\n')
            x = x[1].split()
            self.max_size = int(x[1]) / 1000
            self.min_size = int(x[2]) / 1000
        except subprocess.CalledProcessError as e:
            txt = "CalledProcessError.output = %s" % e.output
            logging.error(txt)
            show.fatal_error(txt)

        if self.min_size + MIN_ROOT_SIZE < self.max_size:
            self.new_size = self.ask_shrink_size(other_os_name)
        else:
            txt = _("Can't shrink the partition (maybe it's nearly full?)")
            logging.error(txt)
            show.error(txt)
            return

        if self.new_size > 0 and self.is_room_available():
            self.forward_button.set_sensitive(True)
        else:
            self.forward_button.set_sensitive(False)
Ejemplo n.º 5
0
    def manage_events_from_cb_queue(self):
        '''
        try:
            event = self.callback_queue.get_nowait()
        except queue.Empty:
            event = ()
        '''
        event = self.get_newest_event()

        if len(event) > 0:
            if event[0] == "percent":
                self.progress_bar.set_fraction(event[1])
            elif event[0] == "finished":
                log.debug(event[1])
                self.set_message(self.install_ok)
                response = show.question(self.install_ok)
                if response == Gtk.ResponseType.YES:
                    self.reboot()
                else:
                    tmp_files = [".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup", "Cnchi.log"]
                    for t in tmp_files:
                        p = os.path.join("/tmp", t)
                        if os.path.exists(p):
                            # TODO: some of these tmp files are created with sudo privileges
                            # (this should be fixed) meanwhile, we need sudo privileges to remove them
                            with misc.raised_privileges():
                                os.remove(p)
                    Gtk.main_quit()
                        
                self.exit_button.show()
                return False
            elif event[0] == "error":
                show.fatal_error(event[1])
            else:
                #with self.lock:
                log.debug(event[1])
                self.set_message(event[1])
                # remove old messages from the event queue 
                #self.callback_queue.clear()
                
        return True
Ejemplo n.º 6
0
Archivo: check.py Proyecto: Wyn10/Cnchi
    def check_all(self):
        """ Check that all requirements are meet """
        if os.path.exists("/tmp/.cnchi_partitioning_completed"):
            msg = "You must reboot before retrying again."
            logging.error(msg)
            msg = _("You must reboot before retrying again.")
            show.fatal_error(self.main_window, msg)
            return False

        has_internet = misc.has_connection()
        self.prepare_network_connection.set_state(has_internet)

        self.latest_iso.set_state(self.iso_version_ok)

        #if has_internet and not self.cnchi_notified:
        #    self.cnchi_main.on_has_internet_connection()
        #    logging.debug('on_has_internet_connection() is running')
        #    self.cnchi_notified = True

        on_power = not self.on_battery()
        self.prepare_power_source.set_state(on_power)

        space = self.has_enough_space() if not self.has_space else True
        self.prepare_enough_space.set_state(space)

        if self.has_internet or 'development' == info.CNCHI_RELEASE_STAGE:
            updated = self.is_updated_check() if not self.is_updated else True
        else:
            updated = False

        self.updated.set_state(updated)

        if self.checks_are_optional:
            return True

        if has_internet and space:
            return True

        return False
Ejemplo n.º 7
0
    def manage_events_from_cb_queue(self):
        try:
            event = self.callback_queue.get_nowait()
        except queue.Empty:
            event = ()

        if len(event) > 0:
            if event[0] == "percent":
                self.progress_bar.set_fraction(event[1])
            elif event[0] == "finished":
                log.debug(event[1])
                self.set_message(self.install_ok)
                response = show.message(self.install_ok)
                if response == Gtk.ResponseType.YES:
                    # TODO: This needs testing
                    #subp = subprocess.Popen(['reboot'], stdout=subprocess.PIPE)
                    with misc.raised_privileges():
                        subp = subprocess.Popen(['shutdown', '-r', 'now'])
                else:
                    tmp_files = [".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup" ]
                    for t in tmp_files:
                        p = os.path.join("/tmp", t)
                        if os.path.exists(p):
                            os.remove(p)
                    Gtk.main_quit()
                        
                self.exit_button.show()
                return False
            elif event[0] == "error":
                show.fatal_error(event[1])
            else:
                log.debug(event[1])
                self.set_message(event[1])
                # remove old messages from the event queue 
                with self.callback_queue.mutex:
                    self.callback_queue.queue.clear()

        return True
Ejemplo n.º 8
0
    def __init__(self):
        ## This allows to translate all py texts (not the glade ones)
        #gettext.textdomain(APP_NAME)
        #gettext.bindtextdomain(APP_NAME, LOCALE_DIR)
        #
        #locale_code, encoding = locale.getdefaultlocale()
        #lang = gettext.translation(APP_NAME, LOCALE_DIR, [locale_code], None, True)
        #lang.install()
        #
        ## With this we can use _("string") to translate
        #gettext.install(APP_NAME, localedir=LOCALE_DIR, codeset=None, names=[locale_code])

        # Check if we have administrative privileges
        if os.getuid() != 0:
            show.fatal_error(_('This installer must be run with administrative'
                         ' privileges and cannot continue without them.'))

        setup_logging()

        # Check if we're already running
        tmp_running = "/tmp/.setup-running"
        if os.path.exists(tmp_running):
            show.error(_('You cannot run two instances of this installer.\n\n'
                          'If you are sure that another installer is not already running\n'
                          'you can manually delete the file %s\n'
                          'and run this installer again.') % tmp_running)
            sys.exit(1)

        super().__init__()

        # workaround for dconf
        os.system("mkdir -p /root/.cache/dconf")
        os.system("chmod -R 777 /root/.cache")

        logging.info(_("Thus installer version %s"), info.THUS_VERSION)

        current_process = multiprocessing.current_process()
        logging.debug("[%d] %s started", current_process.pid, current_process.name)

        self.settings = config.Settings()

        thus_dir = os.path.join(os.path.dirname(__file__), './')
        if os.path.exists(thus_dir):
            self.settings.set('thus', thus_dir)
        else:
            thus_dir = self.settings.get('thus')

        ui_dir = os.path.join(os.path.dirname(__file__), 'ui/')
        if os.path.exists(ui_dir):
            self.settings.set('ui', ui_dir)
        else:
            ui_dir = self.settings.get('ui')

        data_dir = os.path.join(os.path.dirname(__file__), 'data/')
        if os.path.exists(data_dir):
            self.settings.set('data', data_dir)
        else:
            data_dir = self.settings.get('data')

        if os.path.exists("/sys/firmware/efi"):
            self.settings.set('efi', True)

        self.ui = Gtk.Builder()
        self.ui.add_from_file(ui_dir + "thus.ui")

        self.add(self.ui.get_object("main"))

        self.header = self.ui.get_object("header")

        self.forward_button = self.ui.get_object("forward_button")

        self.logo = self.ui.get_object("logo")

        logo_dir = os.path.join(data_dir, "manjaro-logo-mini.png")

        self.logo.set_from_file(logo_dir)

        self.title = self.ui.get_object("title")

        # To honor our css
        self.title.set_name("header")
        self.logo.set_name("header")

        self.main_box = self.ui.get_object("main_box")
        self.progressbar = self.ui.get_object("progressbar1")

        self.forward_button = self.ui.get_object("forward_button")
        self.exit_button = self.ui.get_object("exit_button")
        self.backwards_button = self.ui.get_object("backwards_button")

        # Create a queue. Will be used to report pacman messages (pac.py)
        # to the main thread (installer_*.py)
        self.callback_queue = multiprocessing.JoinableQueue()

        # Load all pages
        # (each one is a screen, a step in the install process)

        self.pages = dict()

        params = dict()
        params['title'] = self.title
        params['forward_button'] = self.forward_button
        params['backwards_button'] = self.backwards_button
        params['exit_button'] = self.exit_button
        params['callback_queue'] = self.callback_queue
        params['settings'] = self.settings
        params['main_progressbar'] = self.ui.get_object('progressbar1')
        params['alternate_package_list'] = ""
        params['testing'] = cmd_line.testing

        self.pages["language"] = language.Language(params)
        self.pages["location"] = location.Location(params)
        self.pages["check"] = check.Check(params)
        self.pages["keymap"] = keymap.Keymap(params)
        self.pages["timezone"] = timezone.Timezone(params)
        self.pages["installation_ask"] = installation_ask.InstallationAsk(params)
        self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params)
        self.pages["installation_alongside"] = installation_alongside.InstallationAlongside(params)
        self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params)
        self.pages["user_info"] = user_info.UserInfo(params)
        self.pages["slides"] = slides.Slides(params)

        self.connect("delete-event", Gtk.main_quit)
        self.ui.connect_signals(self)

        self.set_title(_('Manjaro Installer'))
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_resizable(False)
        self.set_size_request(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT)

        # Set window icon
        icon_dir = os.path.join(data_dir, 'manjaro-icon.png')

        self.set_icon_from_file(icon_dir)

        # Set the first page to show
        self.current_page = self.pages["language"]

        self.main_box.add(self.current_page)

        # Header style testing

        style_provider = Gtk.CssProvider()

        style_css = os.path.join(data_dir, "css", "gtk-style.css")

        with open(style_css, 'rb') as css:
            css_data = css.read()

        style_provider.load_from_data(css_data)

        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(), style_provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )

        # Show main window
        self.show_all()

        self.current_page.prepare('forwards')

        # Hide backwards button
        self.backwards_button.hide()

        # Hide titlebar but show border decoration
        self.get_window().set_accept_focus(True)
        #self.get_window().set_decorations(Gdk.WMDecoration.BORDER)

        # Hide progress bar as it's value is zero
        self.progressbar.set_fraction(0)
        self.progressbar.hide()
        self.progressbar_step = 1.0 / (len(self.pages) - 2)

        with open(tmp_running, "w") as tmp_file:
            tmp_file.write("Thus %d\n" % 1234)

        GLib.timeout_add(1000, self.pages["slides"].manage_events_from_cb_queue)
Ejemplo n.º 9
0
    def __init__(self):
        # This allows to translate all py texts (not the glade ones)
        gettext.textdomain(APP_NAME)
        gettext.bindtextdomain(APP_NAME, LOCALE_DIR)

        locale_code, encoding = locale.getdefaultlocale()
        lang = gettext.translation(APP_NAME, LOCALE_DIR, [locale_code], None, True)
        lang.install()

        # With this we can use _("string") to translate
        gettext.install(APP_NAME, localedir=LOCALE_DIR, codeset=None, names=[locale_code])

        # Check if we have administrative privileges
        if os.getuid() != 0:
            show.fatal_error(_('This installer must be run with administrative'
                         ' privileges, and cannot continue without them.'))
        
        setup_logging()

        # Check if we're already running
        tmp_running = "/tmp/.setup-running"
        if os.path.exists(tmp_running):
            show.error(_('You cannot run two instances of this installer.\n\n'
                          'If you are sure that the installer is not already running\n'
                          'you can manually delete the file %s\n'
                          'and run this installer again.') % tmp_running)
            sys.exit(1)
                
        super().__init__()       
        
        logging.info("Cnchi installer version %s" % info.cnchi_VERSION)
        
        p = multiprocessing.current_process()
        logging.debug("[%d] %s started" % (p.pid, p.name))
        
        self.settings = config.Settings()        
        self.ui_dir = self.settings.get('ui')

        if not os.path.exists(self.ui_dir):
            cnchi_dir = os.path.join(os.path.dirname(__file__), './')
            self.settings.set('cnchi', cnchi_dir)
            
            ui_dir = os.path.join(os.path.dirname(__file__), 'ui/')
            self.settings.set('ui', ui_dir)
            
            data_dir = os.path.join(os.path.dirname(__file__), 'data/')
            self.settings.set('data', data_dir)           
            
            self.ui_dir = self.settings.get('ui')

        self.settings.set('cache', _cache_dir)
            
        # Set enabled desktops
        self.settings.set("desktops", _desktops)
        
        # Set if a grub type must be installed (user choice)
        self.settings.set("force_grub_type", _force_grub_type)

        self.ui = Gtk.Builder()
        self.ui.add_from_file(self.ui_dir + "cnchi.ui")

        self.add(self.ui.get_object("main"))

        self.header = self.ui.get_object("header")

        self.forward_button = self.ui.get_object("forward_button")
        
        self.logo = self.ui.get_object("logo")
        data_dir = self.settings.get('data')
        logo_dir = os.path.join(data_dir, "antergos-logo-mini.png")
        self.logo.set_from_file(logo_dir)
        
        self.title = self.ui.get_object("title")

        # To honor our css
        self.title.set_name("title")
        self.logo.set_name("logo")

        self.main_box = self.ui.get_object("main_box")
        self.progressbar = self.ui.get_object("progressbar1")

        self.forward_button = self.ui.get_object("forward_button")
        self.exit_button = self.ui.get_object("exit_button")
        self.backwards_button = self.ui.get_object("backwards_button")
        
        # Create a queue. Will be used to report pacman messages (pac.py)
        # to the main thread (installer_*.py)
        self.callback_queue = multiprocessing.JoinableQueue()

        # Save in config if we have to use aria2 to download pacman packages
        self.settings.set("use_aria2", _use_aria2)
        if _use_aria2:
            logging.info(_("Using Aria2 to download packages - EXPERIMENTAL"))

        # Load all pages
        # (each one is a screen, a step in the install process)

        self.pages = dict()

        params = dict()
        params['title'] = self.title
        params['ui_dir'] = self.ui_dir
        params['forward_button'] = self.forward_button
        params['backwards_button'] = self.backwards_button
        params['exit_button'] = self.exit_button
        params['callback_queue'] = self.callback_queue
        params['settings'] = self.settings
        params['main_progressbar'] = self.ui.get_object('progressbar1')
        params['alternate_package_list'] = _alternate_package_list
        params['disable_tryit'] = _disable_tryit
        
        if len(_alternate_package_list) > 0:
            logging.info(_("Using '%s' file as package list") % _alternate_package_list)
        
        self.pages["welcome"] = welcome.Welcome(params)
        self.pages["language"] = language.Language(params)
        self.pages["location"] = location.Location(params)
        self.pages["check"] = check.Check(params)
        self.pages["desktop"] = desktop.DesktopAsk(params)
        self.pages["features"] = features.Features(params)
        self.pages["keymap"] = keymap.Keymap(params)
        self.pages["timezone"] = timezone.Timezone(params)
        self.pages["installation_ask"] = installation_ask.InstallationAsk(params)
        self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params)
        self.pages["installation_alongside"] = installation_alongside.InstallationAlongside(params)
        self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params)
        self.pages["user_info"] = user_info.UserInfo(params)
        self.pages["slides"] = slides.Slides(params)

        self.connect("delete-event", Gtk.main_quit)
        self.ui.connect_signals(self)

        self.set_title(_('Antergos Installer'))
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_resizable(False)
        self.set_size_request(_main_window_width, _main_window_height);

        # Set window icon
        icon_dir = os.path.join(data_dir, 'antergos-icon.png')
        
        self.set_icon_from_file(icon_dir)

        # Set the first page to show
        self.current_page = self.pages["welcome"]

        self.main_box.add(self.current_page)

        # Header style testing
        style_provider = Gtk.CssProvider()

        style_css = os.path.join(data_dir, "css", "gtk-style.css")

        with open(style_css, 'rb') as css:
            css_data = css.read()

        style_provider.load_from_data(css_data)

        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(), style_provider,     
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )

        # Show main window
        self.show_all()

        self.vertical_image = self.ui.get_object('vertical_image')
        self.vertical_image.hide()
        #logo_90_dir = os.path.join(data_dir, "antergos-logo-mini-90.png")
        #self.vertical_image.set_from_file(logo_90_dir)

        self.current_page.prepare('forwards')

        # Hide backwards button
        self.backwards_button.hide()

        # Hide titlebar but show border decoration
        self.get_window().set_accept_focus(True)
        self.get_window().set_decorations(Gdk.WMDecoration.BORDER)
        
        # Hide progress bar as it's value is zero
        self.progressbar.set_fraction(0)
        self.progressbar.hide()
        self.progressbar_step = 1.0 / (len(self.pages) - 2)

        # We drop privileges, but where we should do it? before this? ¿?
        misc.drop_privileges()

        with open(tmp_running, "wt") as tmp_file:
            tmp_file.write("Cnchi %d\n" % 1234)

        GLib.timeout_add(1000, self.pages["slides"].manage_events_from_cb_queue)
Ejemplo n.º 10
0
    def manage_events_from_cb_queue(self):
        """ We should do as less as possible here, we want to maintain our
            queue message as empty as possible """
        
        if self.fatal_error:
            return False

        while self.callback_queue.empty() == False:
            try:
                event = self.callback_queue.get_nowait()
            except queue.Empty:
                return True

            if event[0] == 'percent':
                self.progress_bar.set_fraction(event[1])
            elif event[0] == 'text':
                if event[1] == 'hide':
                    self.progress_bar.set_show_text(False)
                    self.progress_bar.set_text("")
                else:
                    self.progress_bar.set_show_text(True)
                    self.progress_bar.set_text(event[1])
            elif event[0] == 'pulse':
                if event[1] == 'stop':
                    self.stop_pulse()
                elif event[1] == 'start':
                    self.start_pulse()
            elif event[0] == 'progress_bar':
                if event[1] == 'hide':
                    self.progress_bar.hide()
            elif event[0] == 'finished':
                logging.info(event[1])
                if not self.settings.get('bootloader_ok'):
                    # Warn user about GRUB and ask if we should open wiki page.
                    boot_warn = _("IMPORTANT: There may have been a problem with the Grub(2) bootloader\n"
                                  "installation which could prevent your system from booting properly. Before\n"
                                  "rebooting, you may want to verify whether or not GRUB(2) is installed and\n"
                                  "configured. The Arch Linux Wiki contains troubleshooting information:\n"
                                  "\thttps://wiki.archlinux.org/index.php/GRUB\n"
                                  "\nWould you like to view the wiki page now?")
                    response = show.question(boot_warn)
                    if response == Gtk.ResponseType.YES:
                        import webbrowser
                        misc.drop_privileges()
                        webbrowser.open('https://wiki.archlinux.org/index.php/GRUB')

                install_ok = _("Installation Complete!\nDo you want to restart your system now?")
                response = show.question(install_ok)
                self.remove_temp_files()
                self.settings.set('stop_all_threads', True)
                #while Gtk.events_pending():
                #    Gtk.main_iteration()
                logging.shutdown()
                if response == Gtk.ResponseType.YES:
                    self.reboot()
                else:
                    sys.exit(0)
                return False
            elif event[0] == 'error':
                self.callback_queue.task_done()
                # A fatal error has been issued. We empty the queue
                self.empty_queue()

                # Show the error
                show.fatal_error(event[1])

                # Ask if user wants to retry
                res = show.question(_("Do you want to retry the installation using the same configuration?"))
                if res == GTK_RESPONSE_YES:
                    # Restart installation process
                    logging.debug(_("Restarting installation process..."))
                    p = self.settings.get('installer_thread_call')

                    self.process = installation_process.InstallationProcess(self.settings, self.callback_queue,
                        p['mount_devices'], p['fs_devices'], p['ssd'], p['alternate_package_list'], p['blvm'])

                    self.process.start()
                    return True
                else:
                    self.fatal_error = True
                    return False
            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])

            self.callback_queue.task_done()

        return True
Ejemplo n.º 11
0
    def manage_events_from_cb_queue(self):
        """ We should do as less as possible here, we want to maintain our
            queue message as empty 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 queue.Empty:
                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] == 'text':
                if event[1] == 'hide':
                    self.progress_bar.set_show_text(False)
                    self.progress_bar.set_text("")
                else:
                    self.progress_bar.set_show_text(True)
                    self.progress_bar.set_text(event[1])
            elif event[0] == 'pulse':
                if event[1] == 'stop':
                    self.stop_pulse()
                elif event[1] == 'start':
                    self.start_pulse()
            elif event[0] == 'progress_bar':
                if event[1] == 'hide':
                    self.progress_bar.hide()
            elif event[0] == 'downloads_progress_bar':
                if event[1] == 'hide':
                    self.downloads_progress_bar.hide()
                if event[1] == 'show':
                    self.downloads_progress_bar.show()
            elif event[0] == 'finished':
                logging.info(event[1])
                if 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\n"
                                  "installation which could prevent your system from booting properly. Before\n"
                                  "rebooting, you may want to verify whether or not the bootloader is installed and\n"
                                  "configured. The Arch Linux Wiki contains troubleshooting information:\n"
                                  "\thttps://wiki.archlinux.org/index.php/GRUB\n"
                                  "\nWould you like to view the wiki page now?")
                    response = show.question(self.get_toplevel(), boot_warn)
                    if response == Gtk.ResponseType.YES:
                        import webbrowser

                        misc.drop_privileges()
                        webbrowser.open('https://wiki.archlinux.org/index.php/GRUB')

                install_ok = _("Installation Complete!\nDo you want to restart your system now?")
                response = show.question(self.get_toplevel(), install_ok)
                misc.remove_temp_files()
                self.settings.set('stop_all_threads', True)
                logging.shutdown()
                if response == Gtk.ResponseType.YES:
                    self.reboot()
                else:
                    sys.exit(0)
                return False
            elif event[0] == 'error':
                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_toplevel(), 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])

            self.callback_queue.task_done()

        return True
Ejemplo n.º 12
0
    def manage_events_from_cb_queue(self):
        """ This function is called from cnchi.py with a timeout function
            We should do as less as possible here, we want to maintain our
            queue message as empty as possible """
        if self.fatal_error:
            return False

        while self.callback_queue.empty() is False:
            try:
                event = self.callback_queue.get_nowait()
            except queue.Empty:
                return True

            if event[0] == 'percent':
                self.progress_bar.set_fraction(event[1])
            elif event[0] == 'global_percent':
                self.show_global_progress_bar_if_hidden()
                self.global_progress_bar.set_fraction(event[1])
            elif event[0] == 'pulse':
                self.do_progress_pulse()
            elif event[0] == 'stop_pulse':
                self.stop_pulse()
            elif event[0] == 'finished':
                logging.info(event[1])
                self.should_pulse = False

                # Warn user about GRUB and ask if we should open wiki page.
                if not self.settings.get('bootloader_ok'):
                    import webbrowser
                    self.boot_warn = _("IMPORTANT: There may have been a problem with the Grub(2) bootloader\n"
                                       "installation which could prevent your system from booting properly. Before\n"
                                       "rebooting, you may want to verify whether or not GRUB(2) is installed and\n"
                                       "configured. The Arch Linux Wiki contains troubleshooting information:\n"
                                       "\thttps://wiki.archlinux.org/index.php/GRUB\n"
                                       "\nWould you like to view the wiki page now?")
                    response = show.question(self.boot_warn)
                    if response == Gtk.ResponseType.YES:
                        webbrowser.open('https://wiki.archlinux.org/index.php/GRUB')

                self.set_message(self.install_ok)
                response = show.question(self.install_ok)

                if response == Gtk.ResponseType.YES:
                    logging.shutdown()
                    self.reboot()
                else:
                    tmp_files = [".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup", "thus.log"]
                    for t in tmp_files:
                        p = os.path.join("/tmp", t)
                        if os.path.exists(p):
                            # TODO: some of these tmp files are created with sudo privileges
                            # (this should be fixed) meanwhile, we need sudo privileges to remove them
                            with misc.raised_privileges():
                                os.remove(p)
                    self.callback_queue.task_done()
                    logging.shutdown()
                    os._exit(0)

                return False
            elif event[0] == 'error':
                self.callback_queue.task_done()
                # A fatal error has been issued. We empty the queue
                self.empty_queue()
                self.fatal_error = True
                show.fatal_error(event[1])
                # Ask if user wants to retry
                res = show.question(_("Do you want to retry?"))
                if res == GTK_RESPONSE_YES:
                    # Restart installation process
                    logging.debug("Restarting installation process...")
                    p = self.settings.get('installer_thread_call')

                    self.process = installation_process.InstallationProcess(
                        self.settings,
                        self.callback_queue,
                        p['mount_devices'],
                        p['fs_devices'],
                        p['ssd'],
                        p['alternate_package_list'],
                        p['blvm'])

                    self.process.start()
                    return True
                else:
                    self.fatal_error = True
                    return False
            elif event[0] == 'debug':
                logging.debug(event[1])
            elif event[0] == 'warning':
                logging.warning(event[1])
            else:
                logging.info(event[1])
                self.set_message(event[1])

            self.callback_queue.task_done()

        return True
Ejemplo n.º 13
0
    def manage_events_from_cb_queue(self):
        """ This function is called from cnchi.py with a timeout function
            We should do as less as possible here, we want to maintain our
            queue message as empty as possible """
        if self.fatal_error:
            return False

        while self.callback_queue.empty() is False:
            try:
                event = self.callback_queue.get_nowait()
            except queue.Empty:
                return True

            if event[0] == "percent":
                self.progress_bar.set_fraction(event[1])
            elif event[0] == "global_percent":
                self.show_global_progress_bar_if_hidden()
                self.global_progress_bar.set_fraction(event[1])
            elif event[0] == "pulse":
                self.do_progress_pulse()
            elif event[0] == "stop_pulse":
                self.stop_pulse()
            elif event[0] == "finished":
                logging.info(event[1])
                self.should_pulse = False
                self.set_message(self.install_ok)
                response = show.question(self.install_ok)
                if response == Gtk.ResponseType.YES:
                    self.reboot()
                else:
                    tmp_files = [
                        ".setup-running",
                        ".km-running",
                        "setup-pacman-running",
                        "setup-mkinitcpio-running",
                        ".tz-running",
                        ".setup",
                        "thus.log",
                    ]
                    for t in tmp_files:
                        p = os.path.join("/tmp", t)
                        if os.path.exists(p):
                            # TODO: some of these tmp files are created with sudo privileges
                            # (this should be fixed) meanwhile, we need sudo privileges to remove them
                            with misc.raised_privileges():
                                os.remove(p)
                    self.callback_queue.task_done()
                    os._exit(0)

                return False
            elif event[0] == "error":
                self.callback_queue.task_done()
                # A fatal error has been issued. We empty the queue
                self.empty_queue()
                self.fatal_error = True
                show.fatal_error(event[1])
                # Ask if user wants to retry
                res = show.question(_("Do you want to retry?"))
                if res == GTK_RESPONSE_YES:
                    # Restart installation process
                    logging.debug("Restarting installation process...")
                    p = self.settings.get("installer_thread_call")

                    self.process = installation_process.InstallationProcess(
                        self.settings,
                        self.callback_queue,
                        p["mount_devices"],
                        p["fs_devices"],
                        p["ssd"],
                        p["alternate_package_list"],
                        p["blvm"],
                    )

                    self.process.start()
                    return True
                else:
                    self.fatal_error = True
                    return False
            elif event[0] == "debug":
                logging.debug(event[1])
            elif event[0] == "warning":
                logging.warning(event[1])
            else:
                logging.info(event[1])
                self.set_message(event[1])

            self.callback_queue.task_done()

        return True
Ejemplo n.º 14
0
Archivo: cnchi.py Proyecto: axaxs/Cnchi
    def __init__(self):
       
        # This allows to translate all py texts (not the glade ones)
        gettext.textdomain(APP)
        gettext.bindtextdomain(APP, DIR)

        locale_code, encoding = locale.getdefaultlocale()
        lang = gettext.translation (APP, DIR, [locale_code], None, True)
        lang.install()

        # With this we can use _("string") to translate
        gettext.install(APP, localedir=DIR, codeset=None, names=[locale_code])

        if os.getuid() != 0:
            fatal_error(_('This installer must be run with administrative'
                         ' privileges, and cannot continue without them.'))
        
        super().__init__()

        self.ui_dir = installer_settings["UI_DIR"]

        if not os.path.exists(self.ui_dir):
            cnchi_dir = os.path.join(os.path.dirname(__file__), './')
            installer_settings["CNCHI_DIR"] = cnchi_dir
            
            ui_dir = os.path.join(os.path.dirname(__file__), 'ui/')
            installer_settings["UI_DIR"] =  ui_dir
            
            data_dir = os.path.join(os.path.dirname(__file__), 'data/')
            installer_settings["DATA_DIR"] = data_dir
            
            self.ui_dir = installer_settings["UI_DIR"]

        self.ui = Gtk.Builder()
        self.ui.add_from_file(self.ui_dir + "cnchi.ui")

        self.add(self.ui.get_object("main"))

        self.header = self.ui.get_object("box5")

        self.forward_button = self.ui.get_object("forward_button")

        self.logo = self.ui.get_object("logo")

        logo_dir = os.path.join(installer_settings["DATA_DIR"], "logo_mini.png")
                                
        self.logo.set_from_file(logo_dir)

        self.title = self.ui.get_object("title")

        # To honor our css
        self.title.set_name("header")
        self.logo.set_name("header")

        self.main_box = self.ui.get_object("main_box")
        self.progressbar = self.ui.get_object("progressbar1")

        self.forward_button = self.ui.get_object("forward_button")
        self.exit_button = self.ui.get_object("exit_button")
        self.backwards_button = self.ui.get_object("backwards_button")

        # load all pages
        # (each one is a screen, a step in the install process)

        self.pages = dict()

        params = dict()
        params['title'] = self.title
        params['ui_dir'] = self.ui_dir
        params['forward_button'] = self.forward_button
        params['backwards_button'] = self.backwards_button
        params['exit_button'] = self.exit_button

        self.pages["language"] = language.Language(params)
        self.pages["check"] = check.Check(params)
        self.pages["keymap"] = keymap.Keymap(params)
        self.pages["timezone"] = timezone.Timezone(params)
        self.pages["installation_ask"] = installation_ask.InstallationAsk(params)
        self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params)
        self.pages["installation_easy"] = installation_easy.InstallationEasy(params)
        self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params)
        self.pages["user_info"] = user_info.UserInfo(params)
        self.pages["slides"] = slides.Slides(params)

        self.connect("delete-event", Gtk.main_quit)
        self.ui.connect_signals(self)

        self.set_title(_('Cinnarch Installer'))
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_resizable(False)
        self.set_size_request(_main_window_width, _main_window_height);

        # set window icon
        icon_dir = os.path.join(installer_settings["DATA_DIR"],
                                'cinnarch-icon.png')
        
        self.set_icon_from_file(icon_dir)

        # set the first page to show
        #self.current_page = self.pages["language"]
        
        #self.current_page = self.pages["installation_ask"]
        self.current_page = self.pages["installation_advanced"]
        #self.current_page = self.pages["installation_easy"]
        #self.current_page = self.pages["slides"]
        #self.current_page = self.pages["timezone"]

        self.main_box.add(self.current_page)

        # Header style testing
        style_provider = Gtk.CssProvider()

        style_css = os.path.join(installer_settings["DATA_DIR"],
                                "gtk-style.css")

        css = open(style_css, 'rb')
        css_data = css.read()
        css.close()

        style_provider.load_from_data(css_data)

        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(), style_provider,     
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )

        # show main window
        self.show_all()

        self.current_page.prepare()

        # hide backwards button
        self.backwards_button.hide()

        # Hide titlebar but show border decoration
        self.get_window().set_accept_focus(True)
        self.get_window().set_decorations(Gdk.WMDecoration.BORDER)

        # we drop privileges, but where we should do it? before this? ¿?
        misc.drop_privileges()
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
    def __init__(self):
       
        # This allows to translate all py texts (not the glade ones)
        gettext.textdomain(APP)
        gettext.bindtextdomain(APP, DIR)

        locale_code, encoding = locale.getdefaultlocale()
        lang = gettext.translation (APP, DIR, [locale_code], None, True)
        lang.install()

        # With this we can use _("string") to translate
        gettext.install(APP, localedir=DIR, codeset=None, names=[locale_code])

        if os.getuid() != 0:
            show.fatal_error(_('This installer must be run with administrative'
                         ' privileges, and cannot continue without them.'))
        
        # check if we're already running
        tmp_running = "/tmp/.setup-running"
        if os.path.exists(tmp_running):
            show.error(_('You cannot run two instances of this installer.\n\n'
                          'If you are sure that the installer is not already running\n'
                          'you can manually delete the file %s\n'
                          'and run this installer again.') % tmp_running)
            sys.exit(1)
                
        super().__init__()
        
        self.settings = config.Settings()

        self.ui_dir = self.settings.get("UI_DIR")

        if not os.path.exists(self.ui_dir):
            cnchi_dir = os.path.join(os.path.dirname(__file__), './')
            self.settings.set("CNCHI_DIR", cnchi_dir)
            
            ui_dir = os.path.join(os.path.dirname(__file__), 'ui/')
            self.settings.set("UI_DIR", ui_dir)
            
            data_dir = os.path.join(os.path.dirname(__file__), 'data/')
            self.settings.set("DATA_DIR", data_dir)
            
            self.ui_dir = self.settings.get("UI_DIR")

        self.ui = Gtk.Builder()
        self.ui.add_from_file(self.ui_dir + "cnchi.ui")

        self.add(self.ui.get_object("main"))

        self.header = self.ui.get_object("box5")

        self.forward_button = self.ui.get_object("forward_button")

        self.logo = self.ui.get_object("logo")

        logo_dir = os.path.join(self.settings.get("DATA_DIR"), "logo_mini.png")
                                
        self.logo.set_from_file(logo_dir)

        self.title = self.ui.get_object("title")

        # To honor our css
        self.title.set_name("header")
        self.logo.set_name("header")

        self.main_box = self.ui.get_object("main_box")
        self.progressbar = self.ui.get_object("progressbar1")

        self.forward_button = self.ui.get_object("forward_button")
        self.exit_button = self.ui.get_object("exit_button")
        self.backwards_button = self.ui.get_object("backwards_button")
        
        # Create a queue. Will be used to report pacman messages (pac.py)
        # to the main thread (installer_*.py)
        #self.callback_queue = queue.Queue(0)
        # Doing some tests with a LIFO queue
        self.callback_queue = queue.LifoQueue(0)

        # load all pages
        # (each one is a screen, a step in the install process)

        self.pages = dict()

        params = dict()
        params['title'] = self.title
        params['ui_dir'] = self.ui_dir
        params['forward_button'] = self.forward_button
        params['backwards_button'] = self.backwards_button
        params['exit_button'] = self.exit_button
        params['callback_queue'] = self.callback_queue
        params['settings'] = self.settings
        
        self.pages["welcome"] = welcome.Welcome(params)
        self.pages["language"] = language.Language(params)
        self.pages["location"] = location.Location(params)
        self.pages["check"] = check.Check(params)
        self.pages["keymap"] = keymap.Keymap(params)
        self.pages["timezone"] = timezone.Timezone(params)
        self.pages["installation_ask"] = installation_ask.InstallationAsk(params)
        self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params)
        self.pages["installation_easy"] = installation_easy.InstallationEasy(params)
        self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params)
        self.pages["user_info"] = user_info.UserInfo(params)
        self.pages["slides"] = slides.Slides(params)

        self.connect("delete-event", Gtk.main_quit)
        self.ui.connect_signals(self)

        self.set_title(_('Cinnarch Installer'))
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_resizable(False)
        self.set_size_request(_main_window_width, _main_window_height);

        # set window icon
        icon_dir = os.path.join(self.settings.get("DATA_DIR"), 'cinnarch-icon.png')
        
        self.set_icon_from_file(icon_dir)

        # set the first page to show
        #self.current_page = self.pages["language"]
        self.current_page = self.pages["welcome"]

        self.main_box.add(self.current_page)

        # Header style testing
        style_provider = Gtk.CssProvider()

        style_css = os.path.join(self.settings.get("DATA_DIR"), "gtk-style.css")

        css = open(style_css, 'rb')
        css_data = css.read()
        css.close()

        style_provider.load_from_data(css_data)

        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(), style_provider,     
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
        )

        # show main window
        self.show_all()

        self.current_page.prepare('forwards')

        # hide backwards button
        self.backwards_button.hide()

        # Hide titlebar but show border decoration
        self.get_window().set_accept_focus(True)
        self.get_window().set_decorations(Gdk.WMDecoration.BORDER)
        
        # hide progress bar as it's value is zero
        self.progressbar.set_fraction(0)
        self.progressbar.hide()
        self.progressbar_step = 1.0 / (len(self.pages) - 2)

        # we drop privileges, but where we should do it? before this? ¿?
        misc.drop_privileges()

        with open(tmp_running, "wt") as tmp_file:
            tmp_file.write("Cnchi %d\n" % 1234)

        GLib.timeout_add(100, self.pages["slides"].manage_events_from_cb_queue)
Ejemplo n.º 17
0
    def manage_events_from_cb_queue(self):
        """ We should do as less as possible here, we want to maintain our
            queue message as empty 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 queue.Empty:
                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] == 'text':
                if event[1] == 'hide':
                    self.progress_bar.set_show_text(False)
                    self.progress_bar.set_text("")
                else:
                    self.progress_bar.set_show_text(True)
                    self.progress_bar.set_text(event[1])
            elif event[0] == 'pulse':
                if event[1] == 'stop':
                    self.stop_pulse()
                elif event[1] == 'start':
                    self.start_pulse()
            elif event[0] == 'progress_bar':
                if event[1] == 'hide':
                    self.progress_bar.hide()
            elif event[0] == 'downloads_progress_bar':
                if event[1] == 'hide':
                    self.downloads_progress_bar.hide()
                if event[1] == 'show':
                    self.downloads_progress_bar.show()
            elif event[0] == 'finished':
                logging.info(event[1])
                if 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\n"
                        "installation which could prevent your system from booting properly. Before\n"
                        "rebooting, you may want to verify whether or not the bootloader is installed and\n"
                        "configured. The Arch Linux Wiki contains troubleshooting information:\n"
                        "\thttps://wiki.archlinux.org/index.php/GRUB\n"
                        "\nWould you like to view the wiki page now?")
                    response = show.question(self.get_toplevel(), boot_warn)
                    if response == Gtk.ResponseType.YES:
                        import webbrowser

                        misc.drop_privileges()
                        webbrowser.open(
                            'https://wiki.archlinux.org/index.php/GRUB')

                install_ok = _(
                    "Installation Complete!\nDo you want to restart your system now?"
                )
                response = show.question(self.get_toplevel(), install_ok)
                misc.remove_temp_files()
                self.settings.set('stop_all_threads', True)
                logging.shutdown()
                if response == Gtk.ResponseType.YES:
                    self.reboot()
                else:
                    sys.exit(0)
                return False
            elif event[0] == 'error':
                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_toplevel(), 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])

            self.callback_queue.task_done()

        return True