def check_memory(opts, display_mode=None): if not display_mode: display_mode = opts.display_mode reason = '' needed_ram = isys.MIN_RAM if not within_available_memory(needed_ram): from snack import SnackScreen, ButtonChoiceWindow screen = SnackScreen() ButtonChoiceWindow(screen, _('Fatal Error'), _('You do not have enough RAM to install %s ' 'on this machine%s.\n' '\n' 'Press <return> to reboot your system.\n') % (product.productName, reason), buttons=(_("OK"), )) screen.finish() sys.exit(0) # override display mode if machine cannot nicely run X if display_mode not in ('t', 'c') and not flags.usevnc: needed_ram = isys.MIN_GUI_RAM if not within_available_memory(needed_ram): stdoutLog.warning( _("You do not have enough RAM to use the graphical " "installer. Starting text mode.")) opts.display_mode = 't' time.sleep(2)
def show(self): self.screen = SnackScreen() action = self.show_menu(self.kconf.mainmenu_text, self.kconf.top_node.list) self.screen.finish() return action
def __init__(self, controller): """ @param: controller, a list of AssistantControllers """ from snack import SnackScreen self.controller = controller self.screen = SnackScreen() self.confignames = self.controller.getCompleteConfigSetNames()
def __init__(self, frontend): self._frontend = frontend self.screen = SnackScreen() self.textview_changes = None self.button_bar = None self.checkbox_tree_updates = None self.layout = None self._app = None self._updates_received = False
def __init__(self, margin, title, message=None, vendor_text=None, args=None): self.debug_mode = args is not None and args.debug self.screen = SnackScreen() # set usual colors for i in colorsets["ROOT"], colorsets["ROOTTEXT"], colorsets[ "HELPLINE"], colorsets["EMPTYSCALE"]: self.screen.setColor(i, "white", "blue") if not self.debug_mode else \ self.screen.setColor(i, "brightgreen", "black") # remove silly default help text self.screen.popHelpLine() # write static messages self.screen.drawRootText((self.screen.width - len(message)) // 2, 4, message) self.screen.drawRootText(-len(vendor_text) - 2, -2, vendor_text) if self.debug_mode: # write some static debug information self.screen.drawRootText(1, 1, _("DEBUG MODE")) self.screen.drawRootText( 2, 2, "screen {}×{}".format(self.screen.width, self.screen.height)) self.screen.drawRootText(2, 3, "file {}".format(args.input)) self.window_width = self.screen.width - margin * 2 # assemble our progress bar self.scale = Scale(self.window_width, 100) self.spacer = Label("") self.taskbox = Textbox(self.window_width - 2, 1, "") self.messagebox = Textbox(self.window_width - 8, 1, " . . . ") self.grid = Grid(1, 4) self.grid.setField(self.scale, 0, 0) self.grid.setField(self.spacer, 0, 1) self.grid.setField(self.taskbox, 0, 2) self.grid.setField(self.messagebox, 0, 3) self.grid.place(1, 1) self.screen.gridWrappedWindow(self.grid, title) self.form = Form() self.form.add(self.scale) self.form.add(self.taskbox) self.form.add(self.messagebox) self.form.draw() self.screen.refresh()
def welcome(): screen = SnackScreen() bb = ButtonBar(screen, (("Continue", "continue"), ("Cancel", "cancel"))) tb = Textbox( 65, 4, "Python Script to Initialize New openSUSE Tumbleweed Installation,\nlike Installing Applications, Enabling & Starting Services, \nand Performing Distrubution Update.", ) g = GridForm(screen, "TW-Init - by Trodskovich", 1, 4) g.add(tb, 0, 2) g.add(bb, 0, 3, growx=1) result = g.runOnce() screen.finish() return bb.buttonPressed(result)
def dup(): screen = SnackScreen() bb = ButtonBar(screen, (("Yes", "yes"), ("No", "no"))) tb = Textbox( 70, 4, "It's recomended to run the Distribution Update after Initiliazation. \nDo you want to run Distribution Update after Initiliazation ?", ) g = GridForm(screen, "Distribution Update", 1, 4) g.add(tb, 0, 2) g.add(bb, 0, 3, growx=1) result = g.runOnce() screen.finish() return bb.buttonPressed(result)
def __init__(self, controller): """ @param: controller, a list of AssistantControllers """ from snack import SnackScreen self.controller=controller self.screen = SnackScreen() self.confignames=self.controller.getCompleteConfigSetNames()
def add_repo(): screen = SnackScreen() bb = ButtonBar(screen, (("Add", "add"), ("Cancel", "cancel"))) tb = Textbox( 50, 5, "Multimedia Applications and Codecs require Packman Repositary to be added in order to work correctly. \nDo you want add Packman repo now ?", 0, 1, ) g = GridForm(screen, "Packman Repo", 1, 4) g.add(tb, 0, 2) g.add(bb, 0, 3, growx=1) result = g.runOnce() screen.finish() return bb.buttonPressed(result)
def __init__(self, controller, title="Com-EC Assistant"): """ @param: controller, a list of AssistantControllers """ from snack import SnackScreen self.title = title self.controller = controller self.infodict = self._build_infodict() self.screen = SnackScreen()
def __init__(self, datadir): self.screen = SnackScreen() # FIXME: self.screen.finish() clears the screen (and all messages) # there too #atexit.register(self.restoreScreen) self.button_bar = ButtonBar(self.screen, ((_("Cancel"), "cancel"), (_("Install"), "ok")), compact=True) self.textview_changes = Textbox(72, 8, _("Changelog"), True, True) self.checkbox_tree_updates = CheckboxTree(height=8, width=72, scroll=1) self.checkbox_tree_updates.setCallback(self.checkbox_changed) self.layout = GridForm(self.screen, _("Updates"), 1, 5) self.layout.add(self.checkbox_tree_updates, 0, 0) # empty line to make it look less crowded self.layout.add(Textbox(60, 1, " ", False, False), 0, 1) self.layout.add(self.textview_changes, 0, 2) # empty line to make it look less crowded self.layout.add(Textbox(60, 1, " ", False, False), 0, 3) self.layout.add(self.button_bar, 0, 4) # FIXME: better progress than the current suspend/resume screen thing self.screen.suspend() if not self.DEBUG: apt_pkg.pkgsystem_lock() self.openCache() print(_("Building Updates List")) self.fillstore() if self.list.distUpgradeWouldDelete > 0: print( _(""" A normal upgrade can not be calculated, please run: sudo apt-get dist-upgrade This can be caused by: * A previous upgrade which didn't complete * Problems with some of the installed software * Unofficial software packages not provided by Ubuntu * Normal changes of a pre-release version of Ubuntu""")) sys.exit(1) self.screen.resume()
def process(): global NvLtDrvURL, LatestFile, LatestHeader, DownloadFlag, SymlinkFlag screen = SnackScreen() bb = ButtonBar(screen, (("End", "end"), )) tbTittle = Textbox(65, 3, "Processing Input... ", 0, 1) tbDownload = Textbox(65, 3, " ", 0, 1) tbSymlink = Textbox(65, 3, " ", 0, 1) g = GridForm(screen, "chkltdr (NvDrIn) - by Trodskovich", 1, 6) g.add(tbTittle, 0, 2) g.add(tbDownload, 0, 3, growx=1) g.add(tbSymlink, 0, 4, growx=1) g.add(bb, 0, 5, growx=1) if DownloadFlag: tbDownload.setText("Downloading Please Wait...") result = g.runOnce() screen.finish() urllib.request.urlretrieve(NvLtDrvURL, "./" + LatestFile) else: tbDownload.setText("Download Skipped") if SymlinkFlag: subprocess.call( ["ln -nfs ./" + LatestFile + " NVIDIA-Linux-x86_64-Latest.run"], shell=True) tbSymlink.setText("Symlink Created") else: tbSymlink.setText("Symlink Skipped") result = g.runOnce() screen.finish() return bb.buttonPressed(result)
def select_packages(): global sellist screen = SnackScreen() ct = CheckboxTree(height=20, scroll=1) for idx, key in enumerate(packages): ct.append(key) for val in packages[key]: ct.addItem(val, (idx, snackArgs["append"])) ct.setEntryValue(val) bb = ButtonBar(screen, (("Next", "next"), ("Cancel", "cancel"))) g = GridForm(screen, "Packages", 1, 4) g.add(ct, 0, 2) g.add(bb, 0, 3, growx=1) result = g.runOnce() screen.finish() # format selected packages list for zypper and print(result) sellist = (str(ct.getSelection()).replace("[", "").replace("]", "").replace( "'", "").replace(",", "")) # to confirm Selected Packages screen = SnackScreen() bb = ButtonBar(screen, (("Next", "next"), ("Cancel", "cancel"))) tb = Textbox( 80, 10, "the packages selected to install are \n \n" + str(sellist.split(" ")), 1, 1) g = GridForm(screen, "Selected Packages", 1, 4) g.add(tb, 0, 2) g.add(bb, 0, 3, growx=1) result = g.runOnce() screen.finish() return bb.buttonPressed(result)
def __init__(self, datadir): self.screen = SnackScreen() # FIXME: self.screen.finish() clears the screen (and all messages) # there too #atexit.register(self.restoreScreen) self.button_bar = ButtonBar(self.screen, ( (_("Cancel"), "cancel"), (_("Install"), "ok")), compact = True) self.textview_changes = Textbox(72, 8, "Changelog", True, True) self.checkbox_tree_updates = CheckboxTree(height=8, width=72, scroll=1) self.checkbox_tree_updates.setCallback(self.checkbox_changed) self.layout = GridForm(self.screen, "Updates", 1, 5) self.layout.add(self.checkbox_tree_updates, 0, 0) # empty line to make it look less crowded self.layout.add(Textbox(60, 1," ",False, False), 0, 1) self.layout.add(self.textview_changes, 0, 2) # empty line to make it look less crowded self.layout.add(Textbox(60, 1," ",False, False), 0, 3) self.layout.add(self.button_bar, 0, 4) # FIXME: better progress than the current suspend/resume screen thing self.screen.suspend() if not self.DEBUG: apt_pkg.PkgSystemLock() self.openCache() print _("Building Updates List") self.fillstore() if self.list.distUpgradeWouldDelete > 0: print _(""" A normal upgrade can not be calculated, please run: sudo apt-get dist-upgrade This can be caused by: * A previous upgrade which didn't complete * Problems with some of the installed software * Unofficial software packages not provided by Ubuntu * Normal changes of a pre-release version of Ubuntu""") sys.exit(1) self.screen.resume()
def __init__(self, parent=None): self.screen = SnackScreen() self.screen.pushHelpLine(" ") super(NewtGUI, self).__init__()
class Menuconfig(): def __init__(self, kconf): self.kconf = kconf self.screen = None @staticmethod def value_str(sym): """ Returns the value part ("[*]", "(foo)" etc.) of a menu entry. """ if sym.type in (STRING, INT, HEX): return "({})".format(sym.str_value) # BOOL (TRISTATE not supported) # The choice mode is an upper bound on the visibility of choice # symbols, so we can check the choice symbols' own visibility to see # if the choice is in y mode if sym.choice and sym.visibility == 2: return "(*)" if sym.choice.selection is sym else "( )" tri_val_str = (" ", None, "*")[sym.tri_value] if len(sym.assignable) == 1: # Pinned to a single value return "-{}-".format(tri_val_str) if sym.type == BOOL: return "[{}]".format(tri_val_str) raise RuntimeError() @staticmethod def node_str(node, indent): """ Returns the complete menu entry text for a menu node, or "" for invisible menu nodes. Invisible menu nodes are those that lack a prompt or that do not have a satisfied prompt condition. Example return value: "[*] Bool symbol (BOOL)" The symbol name is printed in parentheses to the right of the prompt. This is so that symbols can easily be referred to in the configuration interface. """ if not node.prompt: return "" # Even for menu nodes for symbols and choices, it's wrong to check # Symbol.visibility / Choice.visibility here. The reason is that a # symbol (and a choice, in theory) can be defined in multiple # locations, giving it multiple menu nodes, which do not necessarily # all have the same prompt visibility. Symbol.visibility / # Choice.visibility is calculated as the OR of the visibility of all # the prompts. prompt, prompt_cond = node.prompt if not expr_value(prompt_cond): return "" if node.item == MENU: return " " + indent * " " + prompt + " --->" if type(node.item) == Choice: return " " + indent * " " + prompt if node.item == COMMENT: return " " + indent * " " + "*** {} ***".format(prompt) # Symbol sym = node.item if sym.type == UNKNOWN: return "" # {:3} sets the field width to three. Gives nice alignment for empty # string values. res = "{:3} {}{}".format(Menuconfig.value_str(sym), indent * " ", prompt) # Append a sub-menu arrow if menuconfig and enabled if node.is_menuconfig: res += " ---" + (">" if sym.tri_value > 0 else "-") return res @staticmethod def menu_node_strings(node, indent): items = [] while node: string = Menuconfig.node_str(node, indent) if string: items.append((string, node)) if (node.list and node.item != MENU and (type(node.item) == Choice or not node.is_menuconfig)): items.extend( Menuconfig.menu_node_strings(node.list, indent + 2)) node = node.next return items def show_menu(self, title, top_node): selection = 0 while True: items = Menuconfig.menu_node_strings(top_node, 0) height = len(items) scroll = 0 if height > self.screen.height - 13: height = self.screen.height - 13 scroll = 1 buttons = [('Save & Build', 'build', 'B'), ('Save & Exit', 'save', 'S'), (' Help ', 'help', 'h'), (' Exit ', 'exit', 'ESC')] buttonbar = ButtonBar(self.screen, buttons) listbox = Listbox(height, scroll=scroll, returnExit=1) count = 0 for string, _ in items: listbox.append(string, count) if (selection == count): listbox.setCurrent(count) count = count + 1 grid = GridFormHelp(self.screen, title, None, 1, 2) grid.add(listbox, 0, 0, padding=(0, 0, 0, 1)) grid.add(buttonbar, 0, 1, growx=1) grid.addHotKey(' ') rc = grid.runOnce() action = buttonbar.buttonPressed(rc) if action and action != 'help': return action if count == 0: continue selection = listbox.current() _, selected_node = items[selection] sym = selected_node.item if action == 'help': prompt, _ = selected_node.prompt if hasattr(selected_node, 'help') and selected_node.help: help = selected_node.help else: help = 'No help available.' ButtonChoiceWindow(screen=self.screen, title="Help on '{}'".format(prompt), text=help, width=60, buttons=[' Ok ']) continue show_submenu = False if type(sym) == Symbol: if rc == ' ': if sym.type == BOOL: sym.set_value('n' if sym.tri_value > 0 else 'y') else: if selected_node.is_menuconfig: show_submenu = True elif sym.type in (STRING, INT, HEX): action, values = EntryWindow( screen=self.screen, title=sym.name, text='Enter a %s value:' % TYPE_TO_STR[sym.type], prompts=[('', sym.str_value)], buttons=[(' Ok ', 'Ok'), ('Cancel', '', 'ESC')]) if action == 'Ok': self.kconf.warnings = [] val = values[0] if sym.type == HEX and not val.startswith('0x'): val = '0x' + val sym.set_value(val) # only fetching triggers range check - how ugly... sym.str_value if len(self.kconf.warnings) > 0: ButtonChoiceWindow(screen=self.screen, title="Invalid entry", text="\n".join( self.kconf.warnings), width=60, buttons=[' Ok ']) self.kconf.warnings = [] elif selected_node.is_menuconfig and type(sym) != Choice: show_submenu = True if show_submenu: submenu_title, _ = selected_node.prompt action = self.show_menu(submenu_title, selected_node.list) if action != 'exit': return action def show(self): self.screen = SnackScreen() action = self.show_menu(self.kconf.mainmenu_text, self.kconf.top_node.list) self.screen.finish() return action
class UpdateManagerText(object): DEBUG = False def __init__(self, datadir): self.screen = SnackScreen() # FIXME: self.screen.finish() clears the screen (and all messages) # there too #atexit.register(self.restoreScreen) self.button_bar = ButtonBar(self.screen, ((_("Cancel"), "cancel"), (_("Install"), "ok")), compact=True) self.textview_changes = Textbox(72, 8, _("Changelog"), True, True) self.checkbox_tree_updates = CheckboxTree(height=8, width=72, scroll=1) self.checkbox_tree_updates.setCallback(self.checkbox_changed) self.layout = GridForm(self.screen, _("Updates"), 1, 5) self.layout.add(self.checkbox_tree_updates, 0, 0) # empty line to make it look less crowded self.layout.add(Textbox(60, 1, " ", False, False), 0, 1) self.layout.add(self.textview_changes, 0, 2) # empty line to make it look less crowded self.layout.add(Textbox(60, 1, " ", False, False), 0, 3) self.layout.add(self.button_bar, 0, 4) # FIXME: better progress than the current suspend/resume screen thing self.screen.suspend() if not self.DEBUG: apt_pkg.pkgsystem_lock() self.openCache() print(_("Building Updates List")) self.fillstore() if self.list.distUpgradeWouldDelete > 0: print( _(""" A normal upgrade can not be calculated, please run: sudo apt-get dist-upgrade This can be caused by: * A previous upgrade which didn't complete * Problems with some of the installed software * Unofficial software packages not provided by Ubuntu * Normal changes of a pre-release version of Ubuntu""")) sys.exit(1) self.screen.resume() # def restoreScreen(self): # self.screen.finish() def openCache(self): # open cache progress = apt.progress.text.OpProgress() if hasattr(self, "cache"): self.cache.open(progress) self.cache._initDepCache() else: self.cache = MyCache(progress) self.actiongroup = apt_pkg.ActionGroup(self.cache._depcache) # lock the cache self.cache.lock = True def fillstore(self): # populate the list self.list = UpdateList(self) self.list.update(self.cache) origin_list = sorted(self.list.pkgs, key=operator.attrgetter("importance"), reverse=True) for (i, origin) in enumerate(origin_list): self.checkbox_tree_updates.append(origin.description, selected=True) for pkg in self.list.pkgs[origin]: self.checkbox_tree_updates.addItem(pkg.name, (i, snackArgs['append']), pkg, selected=True) def updateSelectionStates(self): """ helper that goes over the cache and updates the selection states in the UI based on the cache """ for pkg in self.cache: if pkg not in self.checkbox_tree_updates.item2key: continue # update based on the status if pkg.marked_upgrade or pkg.marked_install: self.checkbox_tree_updates.setEntryValue(pkg, True) else: self.checkbox_tree_updates.setEntryValue(pkg, False) self.updateUI() def updateUI(self): self.layout.draw() self.screen.refresh() def get_news_and_changelog(self, pkg): changes = "" name = pkg.name # if we don't have it, get it if (name not in self.cache.all_changes and name not in self.cache.all_news): self.textview_changes.setText(_("Downloading changelog")) lock = threading.Lock() lock.acquire() changelog_thread = threading.Thread( target=self.cache.get_news_and_changelog, args=(name, lock)) changelog_thread.start() # this lock should never take more than 2s even with network down while lock.locked(): time.sleep(0.03) # build changes from NEWS and changelog if name in self.cache.all_news: changes += self.cache.all_news[name] if name in self.cache.all_changes: changes += self.cache.all_changes[name] return changes def checkbox_changed(self): # item is either a apt.package.Package or a str (for the headers) pkg = self.checkbox_tree_updates.getCurrent() descr = "" if hasattr(pkg, "name"): need_refresh = False name = pkg.name if self.options.show_description: descr = getattr(pkg.candidate, "description", None) else: descr = self.get_news_and_changelog(pkg) # check if it is a wanted package selected = self.checkbox_tree_updates.getEntryValue(pkg)[1] marked_install_upgrade = pkg.marked_install or pkg.marked_upgrade if not selected and marked_install_upgrade: need_refresh = True pkg.mark_keep() if selected and not marked_install_upgrade: if not (name in self.list.held_back): # FIXME: properly deal with "fromUser" here need_refresh = True pkg.mark_install() # fixup any problems if self.cache._depcache.broken_count: need_refresh = True Fix = apt_pkg.ProblemResolver(self.cache._depcache) Fix.resolve_by_keep() # update the list UI to reflect the cache state if need_refresh: self.updateSelectionStates() self.textview_changes.setText(descr) self.updateUI() def main(self, options): self.options = options res = self.layout.runOnce() self.screen.finish() button = self.button_bar.buttonPressed(res) if button == "ok": self.screen.suspend() res = self.cache.commit(apt.progress.text.AcquireProgress(), apt.progress.base.InstallProgress())
def execute(self, first_key): """Display the panels. This resembles a state-machine, except that the transitions can be determined on the fly. """ self.results = {} screen = SnackScreen() try: # Move through the panels in a linked-list fashion, so that we can # reroute if told to. key = first_key quit = False loop = True posthook_cb = None loophook_cb = None while loop: logging.info("Processing panel expression with key [%s]." % (key)) try: expression = self.__panels.get_copy_by_key(key) except: logging.exception("Could not retrieve expression [%s]." % (key)) raise # Don't reprocess the expression more than once. result = self.__process_expression(expression, self.results, screen) (result_type, key, expression, quit_temp) = result if quit_temp: quit = True if result_type == "break": break elif result_type == "continue": continue try: meta_attributes = self.__slice_meta_attributes(expression) except: logging.exception("Could not slice meta-attributes from " "panel expression with key [%s]." % (key)) raise # Determine the panel to succeed this one. We do this early to # allow callback to adjust this. self._next_key = meta_attributes["next"] if "next" in meta_attributes else None if not self.__panels.exists(key): logging.error( "Key [%s] set as next from panel with " "key [%s] does not refer to a valid " "panel." % (key) ) logging.info("Processing expression with key [%s]." % (key)) try: result = self.__process_stanza(screen, key, expression, meta_attributes) # TODO: Move this to a separate call. if "post_cb" in meta_attributes: callback = meta_attributes["post_cb"] if not callable(callback): message = "Callback for key [%s] is not " "callable." % (key) logging.error(message) raise Exception(message) try: result_temp = callback(self, key, result, expression, screen) # Allow them to adjust the result, but don't # require it to be returned. if result_temp: result = result_temp except PostQuitAndExecuteException as e: logging.info("Post-callback for key [%s] has " "requested an exit-and-execute." % (key)) # We can't break the loop the same way as # everything else, because we have a result that we # want to have registered. So, just allow us to # reach the end of the loop and prevent us from # looping again. loop = False posthook_cb = e.posthook_cb result = e.result except QuitAndExecuteException as e: logging.info("Post-callback for key [%s] has " "requested an exit-and-execute." % (key)) quit = True posthook_cb = e.posthook_cb break except GotoPanelException as e: # Go to a different panel. new_key = e.key logging.info( "We were routed from panel with key " "[%s] to panel with key [%s] while in" " post callback." % (key, new_key) ) if not self.__panels.exists(key): message = ( "We were told to go to panel with " "invalid key [%s] while in post-" "callback for panel with key " "[%s]." % (new_key, key) ) logging.error(message) raise Exception(message) key = new_key continue except RedrawException as e: logging.info("Post-callback for key [%s] has " "requested a redraw." % (key)) # Reset state values that might've been affected by # a callback. quit = False self._next_key = None continue except QuitException as e: logging.info("Post-callback for key [%s] has " "requested emergency exit." % (key)) quit = True break except BreakSuccessionException as e: logging.info("Post-callback for key [%s] has " "instructed us to terminate." % (key)) break except: logging.exception("An exception occured in the " "post-callback for key [%s]." % (key)) raise # Static expression result handler. else: # If there's only one button, ignore what method they # used to close the window. if "buttons" in expression and len(expression["buttons"]) > 1: if ( "is_esc" in result and result["is_esc"] or "button" in result and result["button"] == BTN_CANCEL[1] ): break if "collect_results" in meta_attributes and meta_attributes["collect_results"]: if key in self.results: self.results[key].append(result) else: self.results[key] = [result] else: self.results[key] = result except: logging.exception("There was an exception while processing" " the stanza for key [%s]." % (key)) raise if self._next_key: key = self._next_key else: break except: logging.exception("There was an exception while processing " "config stanza with key [%s]." % (key)) raise finally: screen.finish() if posthook_cb: posthook_cb() return None if quit else self.results
class UpdateManagerText(object): DEBUG = False def __init__(self, datadir): self.screen = SnackScreen() # FIXME: self.screen.finish() clears the screen (and all messages) # there too #atexit.register(self.restoreScreen) self.button_bar = ButtonBar(self.screen, ( (_("Cancel"), "cancel"), (_("Install"), "ok")), compact = True) self.textview_changes = Textbox(72, 8, "Changelog", True, True) self.checkbox_tree_updates = CheckboxTree(height=8, width=72, scroll=1) self.checkbox_tree_updates.setCallback(self.checkbox_changed) self.layout = GridForm(self.screen, "Updates", 1, 5) self.layout.add(self.checkbox_tree_updates, 0, 0) # empty line to make it look less crowded self.layout.add(Textbox(60, 1," ",False, False), 0, 1) self.layout.add(self.textview_changes, 0, 2) # empty line to make it look less crowded self.layout.add(Textbox(60, 1," ",False, False), 0, 3) self.layout.add(self.button_bar, 0, 4) # FIXME: better progress than the current suspend/resume screen thing self.screen.suspend() if not self.DEBUG: apt_pkg.PkgSystemLock() self.openCache() print _("Building Updates List") self.fillstore() if self.list.distUpgradeWouldDelete > 0: print _(""" A normal upgrade can not be calculated, please run: sudo apt-get dist-upgrade This can be caused by: * A previous upgrade which didn't complete * Problems with some of the installed software * Unofficial software packages not provided by Ubuntu * Normal changes of a pre-release version of Ubuntu""") sys.exit(1) self.screen.resume() # def restoreScreen(self): # self.screen.finish() def openCache(self): # open cache progress = apt.progress.OpTextProgress() if hasattr(self, "cache"): self.cache.open(progress) self.cache._initDepCache() else: self.cache = MyCache(progress) self.actiongroup = apt_pkg.GetPkgActionGroup(self.cache._depcache) # lock the cache self.cache.lock = True def fillstore(self): # populate the list self.list = UpdateList(self) self.list.update(self.cache) origin_list = self.list.pkgs.keys() origin_list.sort(lambda x,y: cmp(x.importance, y.importance)) origin_list.reverse() for (i, origin) in enumerate(origin_list): self.checkbox_tree_updates.append(origin.description, selected=True) for pkg in self.list.pkgs[origin]: self.checkbox_tree_updates.addItem(pkg.name, (i, snackArgs['append']), pkg, selected = True) def updateSelectionStates(self): """ helper that goes over the cache and updates the selection states in the UI based on the cache """ for pkg in self.cache: if not self.checkbox_tree_updates.item2key.has_key(pkg): continue # update based on the status if pkg.markedUpgrade or pkg.markedInstall: self.checkbox_tree_updates.setEntryValue(pkg, True) else: self.checkbox_tree_updates.setEntryValue(pkg, False) self.updateUI() def updateUI(self): self.layout.draw() self.screen.refresh() def get_news_and_changelog(self, pkg): changes = "" name = pkg.name # if we don't have it, get it if (not self.cache.all_changes.has_key(name) and not self.cache.all_news.has_key(name)): self.textview_changes.setText(_("Downloading changelog")) lock = thread.allocate_lock() lock.acquire() thread.start_new_thread(self.cache.get_news_and_changelog,(name,lock)) # this lock should never take more than 2s even with network down while lock.locked(): time.sleep(0.03) # build changes from NEWS and changelog if self.cache.all_news.has_key(name): changes += self.cache.all_news[name] if self.cache.all_changes.has_key(name): changes += self.cache.all_changes[name] return changes def checkbox_changed(self): # item is either a apt.package.Package or a str (for the headers) pkg = self.checkbox_tree_updates.getCurrent() descr = "" if hasattr(pkg, "name"): need_refresh = False name = pkg.name if self.options.show_description: descr = pkg.description else: descr = self.get_news_and_changelog(pkg) # check if it is a wanted package selected = self.checkbox_tree_updates.getEntryValue(pkg)[1] marked_install_upgrade = pkg.markedInstall or pkg.markedUpgrade if not selected and marked_install_upgrade: need_refresh = True pkg.markKeep() if selected and not marked_install_upgrade: if not (name in self.list.held_back): # FIXME: properly deal with "fromUser" here need_refresh = True pkg.markInstall() # fixup any problems if self.cache._depcache.BrokenCount: need_refresh = True Fix = apt_pkg.GetPkgProblemResolver(self.cache._depcache) Fix.ResolveByKeep() # update the list UI to reflect the cache state if need_refresh: self.updateSelectionStates() self.textview_changes.setText(descr) self.updateUI() def main(self, options): self.options = options res = self.layout.runOnce() self.screen.finish() button = self.button_bar.buttonPressed(res) if button == "ok": self.screen.suspend() res = self.cache.commit(apt.progress.text.AcquireProgress(), apt.progress.base.InstallProgress())
class NewtUI(object): """ Newt UI implementation """ def __init__(self, frontend): self._frontend = frontend self.screen = SnackScreen() self.textview_changes = None self.button_bar = None self.checkbox_tree_updates = None self.layout = None self._app = None self._updates_received = False def create_ui(self): """ Creates/Draws the UI """ self.button_bar = ButtonBar(self.screen, ((_("Cancel"), "cancel"), (_("Install"), "ok")), compact=True) self.textview_changes = Textbox(72, 8, "Changelog", True, True) self.checkbox_tree_updates = CheckboxTree(height=8, width=72, scroll=1) self.checkbox_tree_updates.setCallback(self.checkbox_changed) self.layout = GridForm(self.screen, "Updates", 1, 5) self.layout.add(self.checkbox_tree_updates, 0, 0) # empty line to make it look less crowded self.layout.add(Textbox(60, 1, " ", False, False), 0, 1) self.layout.add(self.textview_changes, 0, 2) # empty line to make it look less crowded self.layout.add(Textbox(60, 1, " ", False, False), 0, 3) self.layout.add(self.button_bar, 0, 4) # FIXME: better progress than the current suspend/resume screen thing self.screen.suspend() def cache_reload_callback(self, percent, operation): """ Cache reloading callback :param percent: Percentage done :param operation: Current operation """ if percent == RELOAD_CACHE_STATUS.DONE: sys.stdout.write(_('Finished loading package cache.') + '\n') elif percent == RELOAD_CACHE_STATUS.BEGIN: sys.stdout.write(_('Loading package cache.') + '\n') else: sys.stdout.write('[%2d] %s\r' % (percent, operation)) def main(self, application): """ UI main loop :param application: class:`UpdateManager.Application.Application` object """ self._app = application while not self._updates_received: time.sleep(0.3) self.screen.resume() res = self.layout.runOnce() self.screen.finish() button = self.button_bar.buttonPressed(res) if button == "ok": self.screen.suspend() def get_updates(self): sys.stdout.write(_("Building Updates List") + "\n") sys.stdout.flush() packages = self._app.get_available_updates() # download_size = 0 categories = {} for pkg in packages: catid = pkg.get_update_category() if not catid in categories.keys(): categories[catid] = [ pkg, ] else: categories[catid].append(pkg) for (i, cat_id) in enumerate(categories.keys()): cat_name = self._app.get_update_category_name(cat_id) self.checkbox_tree_updates.append(cat_name, selected=True) for pkg in categories[cat_id]: self.checkbox_tree_updates.addItem(pkg.get_package_name(), (i, snackArgs['append']), pkg, selected=True) self._updates_received = True def update_ui(self): """ Redraws the UI """ self.layout.draw() self.screen.refresh() def checkbox_changed(self): """ Handler for checkbox state-changes """ pkg = self.checkbox_tree_updates.getCurrent() descr = "" if hasattr(pkg, "get_description"): descr = pkg.get_description() # TODO: changelog handling/selection of changelog instead of # description self.textview_changes.setText(descr) self.update_ui()
def welcome(): global NvLtDrvURL, LatestFile, LatestHeader, DownloadFlag, SymlinkFlag screen = SnackScreen() bb = ButtonBar(screen, (("Continue", "continue"), ("Cancel", "cancel"))) tbTittle = Textbox( 65, 3, "To check for latest Nvidia Driver form NVIDIA Website, download and optionaly create a symlink to the latest File", 0, 1) for File in os.listdir(path): if File.find('.run') > 0 and os.path.isfile(path + "/" + File): FList.append(File) FList.sort() FileText = urllib.request.urlopen(NvLtTxtURL).read().decode('utf-8') for i in range(0, len(FileText)): if FileText[i] == ' ': LatestHeader = FileText[0:i] for i in range(0, len(FileText)): if FileText[i] == '/': LatestFile = FileText[i + 1:len(FileText) - 1] NvLtDrvURL = NvLtDrvURL + LatestHeader + "/" + LatestFile tbLatestL = Textbox(110, 2, "Latest Local Version: " + FList[-1], 0, 1) tbLatestR = Textbox( 110, 4, "Latest Remote Version: " + LatestFile + "\nLatest Driver URL: " + NvLtDrvURL, 0, 1) if LatestFile > FList[-1]: cbDowload = Checkbox( "Download the Latest Driver", 1, ) cbSymlink = Checkbox( "Create / Update Symlink", 1, ) else: cbDowload = Checkbox( "Download the Latest Driver", 0, ) cbSymlink = Checkbox( "Create / Update Symlink", 0, ) g = GridForm(screen, "chkltdr (NvDrIn) - by Trodskovich", 1, 8) g.add(tbTittle, 0, 2) g.add(tbLatestL, 0, 3, growx=1) g.add(tbLatestR, 0, 4, growx=1) g.add(cbDowload, 0, 5, growx=1) g.add(cbSymlink, 0, 6, growx=1) g.add(bb, 0, 7, growx=1) result = g.runOnce() screen.finish() DownloadFlag = cbDowload.value() SymlinkFlag = cbSymlink.value() return bb.buttonPressed(result)
if opts.rescue: anaconda.rescue = True import rescue, instdata anaconda.id = instdata.InstallData(anaconda, [], opts.display_mode) if anaconda.isKickstart: instClass.setInstallData(anaconda) anaconda.id.setKsdata(ksdata) # We need an interface before running kickstart execute methods for # storage. from snack import * screen = SnackScreen() anaconda.intf = rescue.RescueInterface(screen) ksdata.execute() anaconda.intf = None screen.finish() # command line 'nomount' overrides kickstart /same for vnc/ anaconda.rescue_mount = not (opts.rescue_nomount or anaconda.id.ksdata.rescue.nomount) rescue.runRescue(anaconda, instClass) # shouldn't get back here sys.exit(1)
def __init__(self): InstallInterfaceBase.__init__(self) self.screen = SnackScreen() self._meh_interface = meh.ui.text.TextIntf()
class ConfigurationManagerTui(object): OK = 0 NEXT = 1 MODIFY = 2 SAVE = 3 RUN = 4 CANCEL = -1 def __init__(self, controller): """ @param: controller, a list of AssistantControllers """ from snack import SnackScreen self.controller = controller self.screen = SnackScreen() self.confignames = self.controller.getCompleteConfigSetNames() def run(self, warning=None): ''' @returns [name, type, direction] ''' #items=["a", "b"] from snack import ListboxChoiceWindow, ButtonChoiceWindow result = None while True: self.confignames = self.controller.getCompleteConfigSetNames() names = self.confignames.keys() names.sort() if len(names) != 0: _res = ListboxChoiceWindow(self.screen, "Configuration Sets", "Select configuration set", names, buttons=('Next', 'New', 'Rename', 'Delete', 'Cancel'), width=40, scroll=1, height=-1, default=None, help=None) else: _res = [ ButtonChoiceWindow(self.screen, "Configuration Sets", "No Configuration sets defined", buttons=['New', 'Cancel'], width=40, help=None) ] if _res[0] == "cancel": break if _res[0] == "new": self._run_create() if _res[0] == "rename": _name = names[_res[1]] _type = self.confignames.get(_name) _newname = self._run_rename(_name) if _newname: self.controller.renameConfigSet(_name, _type, _newname) if _res[0] == "delete": self._run_delete(names[_res[1]]) if _res[0] == "next": _name = names[_res[1]] _type = self.confignames.get(_name) set = self.controller.getConfigStore( ).getConfigTypeStoreByName(_type).getConfigset(_name) direction = self._run_direction( _name, set.getDirections(ordered=True)) if direction == None: continue result = [_name, _type, direction] break self.cleanup() return result def _run_direction(self, name, directions): from snack import ListboxChoiceWindow _res = ListboxChoiceWindow( self.screen, "Mode Selection", "You selected %s\nWhat do you want to do ?" % name, directions, buttons=('Next', 'Cancel'), width=40, scroll=0, height=-1, default=None, help=None) if _res[0] != "next": return direction = directions[_res[1]] return direction def _run_delete(self, name): if self._run_warning("This will delete configset %s" % name) == self.OK: self.controller.deleteConfigSet(name, self.confignames[name]) def _run_create(self): from snack import ListboxChoiceWindow, ButtonChoiceWindow, EntryWindow templatetypes = self.controller.getCompleteConfigTemplateSetNames() if len(templatetypes) != 0: _res = ListboxChoiceWindow(self.screen, "Configuration Types", "Select type of new configuration set", templatetypes, buttons=('Create', 'Cancel'), width=40, scroll=1, height=-1, default=None, help=None) else: _res = [ ButtonChoiceWindow( self.screen, "Error", "No valid configurationset templates defined", buttons=['Cancel']) ] if _res[0] != "create": return type = templatetypes[_res[1]] _res = EntryWindow(self.screen, "New Configuration", "Name of the new configuration set", ['Name'], allowCancel=1, width=40, entryWidth=20, buttons=['Ok', 'Cancel'], help=None) if _res[0] != "ok": return name = _res[1][0] self.controller.createConfigSet(name, type) def _run_rename(self, oldname=""): from snack import EntryWindow _res = EntryWindow( self.screen, "Rename configuration set", "Enter new name of the configuration set\nOld name: %s" % oldname, ['New name:'], allowCancel=1, width=40, entryWidth=20, buttons=['Ok', 'Cancel'], help=None) if _res[0] != "ok": return name = _res[1][0] return name def _run_warning(self, warning): from snack import ButtonChoiceWindow _rec = ButtonChoiceWindow(self.screen, "Are you sure ?", warning, buttons=['Ok', 'Back']) if _rec == "ok": return self.OK else: return self.CANCEL def _exit(self, val): self.cleanup() raise CancelException() def getEntryWindow(self, screen): from snack import EntryWindow w = EntryWindow(screen, "Com-ec Assistant", "text", ("a", "b", "c", "d", "e", "f", "g"), buttons=['Ok', 'Scan', 'Cancel']) w.run() def cleanup(self): self.screen.finish()
class NewtGUI(join_method): priority = 40 screen = None def __init__(self, parent=None): self.screen = SnackScreen() self.screen.pushHelpLine(" ") super(NewtGUI, self).__init__() def start_gui(self): pass @staticmethod def available(): global available return available def PopupWindow(self, title, text, width=50, sleep=None): t = TextboxReflowed(width, text) g = GridForm(self.screen, title, 1, 1) g.add(t, 0, 0, padding=(0, 0, 0, 0)) g.setTimer(1) g.run() # Just show us some seconds if sleep: time.sleep(sleep) self.screen.popWindow() # Else someone else needs to call "popWindow"... def JoinWindow(self, title, text, allowCancel=0, width=50, entryWidth=37, buttons=["Join"], hlp=None): bb = ButtonBar(self.screen, buttons) t = TextboxReflowed(width, text) sg = Grid(2, 2) entryList = [] e = Entry(entryWidth) sg.setField(Label("User name"), 0, 0, padding=(0, 0, 1, 0), anchorLeft=1) sg.setField(e, 1, 0, anchorLeft=1) entryList.append(e) e = Entry(entryWidth, password=1) sg.setField(Label("Password"), 0, 1, padding=(0, 0, 1, 0), anchorLeft=1) sg.setField(e, 1, 1, anchorLeft=1) entryList.append(e) g = GridForm(self.screen, title, 1, 3) g.add(t, 0, 0, padding=(0, 0, 0, 1)) g.add(sg, 0, 1, padding=(0, 0, 0, 1)) g.add(bb, 0, 2, growx=1) result = g.runOnce() entryValues = [] for entry in entryList: entryValues.append(entry.value()) return (bb.buttonPressed(result), tuple(entryValues)) def discover(self): self.PopupWindow(_("Clacks Infrastructure") + " v%s" % VERSION, _("Searching service provider...")) self.url = ZeroconfClient.discover(["_amqps._tcp", "_amqp._tcp"], domain=self.domain)[0] self.screen.popWindow() return self.url def join_dialog(self): logging.disable(logging.ERROR) key = None while not key: jw = self.JoinWindow( _("Clacks Infrastructure") + " v%s" % VERSION, _("Please enter the credentials of an administrative user to join this client."), ) username, password = jw[1] if not username or not password: self.show_error("Please enter a user name and a password!") continue key = self.join(username, password) self.screen.finish() def show_error(self, error): self.PopupWindow(_("Error"), error, sleep=3)
class ConfigurationManagerTui(object): OK=0 NEXT=1 MODIFY=2 SAVE=3 RUN=4 CANCEL=-1 def __init__(self, controller): """ @param: controller, a list of AssistantControllers """ from snack import SnackScreen self.controller=controller self.screen = SnackScreen() self.confignames=self.controller.getCompleteConfigSetNames() def run(self, warning=None): ''' @returns [name, type, direction] ''' #items=["a", "b"] from snack import ListboxChoiceWindow, ButtonChoiceWindow result=None while True: self.confignames=self.controller.getCompleteConfigSetNames() names=self.confignames.keys() names.sort() if len(names) != 0: _res=ListboxChoiceWindow(self.screen, "Configuration Sets", "Select configuration set", names, buttons = ('Next', 'New', 'Rename', 'Delete', 'Cancel'), width = 40, scroll = 1, height = -1, default = None, help = None) else: _res=[ButtonChoiceWindow(self.screen, "Configuration Sets", "No Configuration sets defined", buttons = ['New', 'Cancel'], width = 40, help = None)] if _res[0] == "cancel": break if _res[0] == "new": self._run_create() if _res[0] == "rename": _name=names[_res[1]] _type=self.confignames.get(_name) _newname=self._run_rename(_name) if _newname: self.controller.renameConfigSet(_name, _type, _newname) if _res[0] == "delete": self._run_delete(names[_res[1]]) if _res[0] == "next": _name=names[_res[1]] _type=self.confignames.get(_name) set = self.controller.getConfigStore().getConfigTypeStoreByName(_type).getConfigset(_name) direction = self._run_direction(_name, set.getDirections(ordered=True)) if direction == None: continue result=[_name,_type,direction] break self.cleanup() return result def _run_direction(self, name, directions): from snack import ListboxChoiceWindow _res=ListboxChoiceWindow(self.screen, "Mode Selection", "You selected %s\nWhat do you want to do ?" %name, directions, buttons = ('Next', 'Cancel'), width = 40, scroll = 0, height = -1, default = None, help = None) if _res[0] != "next": return direction = directions[_res[1]] return direction def _run_delete(self, name): if self._run_warning("This will delete configset %s" %name) == self.OK: self.controller.deleteConfigSet(name, self.confignames[name]) def _run_create(self): from snack import ListboxChoiceWindow, ButtonChoiceWindow, EntryWindow templatetypes=self.controller.getCompleteConfigTemplateSetNames() if len(templatetypes) != 0: _res=ListboxChoiceWindow(self.screen, "Configuration Types", "Select type of new configuration set", templatetypes, buttons = ('Create', 'Cancel'), width = 40, scroll = 1, height = -1, default = None, help = None) else: _res=[ ButtonChoiceWindow(self.screen, "Error", "No valid configurationset templates defined", buttons = [ 'Cancel' ]) ] if _res[0]!="create": return type=templatetypes[_res[1]] _res=EntryWindow(self.screen, "New Configuration", "Name of the new configuration set", ['Name'], allowCancel = 1, width = 40, entryWidth = 20, buttons = [ 'Ok', 'Cancel' ], help = None) if _res[0]!="ok": return name=_res[1][0] self.controller.createConfigSet(name, type) def _run_rename(self, oldname=""): from snack import EntryWindow _res=EntryWindow(self.screen, "Rename configuration set", "Enter new name of the configuration set\nOld name: %s" %oldname, ['New name:'], allowCancel = 1, width = 40, entryWidth = 20, buttons = [ 'Ok', 'Cancel' ], help = None) if _res[0]!="ok": return name=_res[1][0] return name def _run_warning(self, warning): from snack import ButtonChoiceWindow _rec=ButtonChoiceWindow(self.screen, "Are you sure ?", warning, buttons = [ 'Ok', 'Back' ]) if _rec == "ok": return self.OK else: return self.CANCEL def _exit(self, val): self.cleanup() raise CancelException() def getEntryWindow(self, screen): from snack import EntryWindow w = EntryWindow(screen ,"Com-ec Assistant", "text", ("a", "b", "c", "d", "e", "f", "g"), buttons = [ 'Ok', 'Scan', 'Cancel' ]) w.run() def cleanup(self): self.screen.finish()
def run(self): self.screen = SnackScreen() self.display_main_screen() self.screen.finish()
class OCMITester(object): def menu_exit(self): pass def _display_selection(self, list_of_items, subtitle, default = None): """Display a list of items, return selected one or None, if nothing was selected""" if len(list_of_items) > 0: if not isinstance(list_of_items[0], types.TupleType): # if we have a list of strings, we'd prefer to get these strings as the selection result list_of_items = zip(list_of_items, list_of_items) height = 10 scroll = 1 if len(list_of_items) > height else 0 action, selection = ListboxChoiceWindow(self.screen, TITLE, subtitle, list_of_items, ['Ok', 'Back'], scroll = scroll, height = height, default = default) if action != 'back': return selection else: ButtonChoiceWindow(self.screen, TITLE, 'Sorry, there are no items to choose from', ['Back']) return None def display_main_screen(self): """Display main menu of the OCMI Tester""" logic = {'exit': self.menu_exit, 'configure': self.display_configure, 'occi': self.display_occi, 'cdmi': self.display_cdmi, 'runall': self.display_run_all, } result = ButtonChoiceWindow(self.screen, TITLE, 'Welcome to the OCMI-tester', \ [('Exit', 'exit'), ('Configure', 'configure'), ('OCCI tests', 'occi'), ('CDMI tests', 'cdmi'), ('Run all tests', 'runall'), ], 42) logic[result]() def display_configure(self): """Display a selection menu for OCCI/CDMI configuration""" logic = {'exit': self.display_main_screen, 'occi': self.display_configure_occi, 'cdmi': self.display_configure_cdmi, } result = ButtonChoiceWindow(self.screen, TITLE, 'Please, choose endpoint to configure:', \ [('Exit', 'exit'), ('OCCI', 'occi'), ('CDMI', 'cdmi'), ], 42) logic[result]() def display_configure_occi(self): """Display OCCI configuration menu""" occi_entry = Entry(30, c('occi', 'server')) occi_input_entry = Entry(30, c('occi', 'input_rendering')) occi_output_entry = Entry(30, c('occi', 'output_rendering')) command, _ = EntryWindow(self.screen, TITLE, 'Please, enter OCCI endpoint parameters', [('OCCI endpoint', occi_entry), ('OCCI input rendering', occi_input_entry), ('OCCI output rendering', occi_output_entry)], buttons = [('Save', 'save'), ('Back', 'main_menu')]) if command == 'save': cs('occi', 'server', occi_entry.value().strip()) cs('occi', 'input_rendering', occi_input_entry.value().strip()) cs('occi', 'output_rendering', occi_output_entry.value().strip()) self.display_main_screen() def display_configure_cdmi(self): """Display CDMI configuration menu""" cdmi_entry = Entry(30, c('cdmi', 'cdmi_server')) cdmi_user_entry = Entry(30, c('cdmi', 'username')) cdmi_pass_entry = Entry(30, c('cdmi', 'password')) command, _ = EntryWindow(self.screen, TITLE, 'Please, enter CDMI endpoint parameters', [('CDMI endpoint', cdmi_entry), ('Username', cdmi_user_entry), ('Password', cdmi_pass_entry)], buttons = [('Save', 'save'), ('Back', 'main_menu')]) if command == 'save': cs('cdmi', 'server', cdmi_entry.value().strip()) cs('cdmi', 'username', cdmi_user_entry.value().strip()) cd('cdmi', 'password', cdmi_pass_entry.value().strip()) self.display_main_screen() def display_occi(self): """Displays a list of OCCI tests""" dummy_tests = ['OCCI test 1', 'OCCI test 2', 'OCCI test 3'] return self._display_selection(dummy_tests, "Select an OCCI test from" % dummy_tests) def display_cdmi(self): """Displays a list of CDMI tests""" dummy_tests = ['CDMI test 1', 'CDMI test 2', 'CDMI test 3'] return self._display_selection(dummy_tests, "Select a CDMI test from" % dummy_tests) def display_run_all(self): pass def run(self): self.screen = SnackScreen() self.display_main_screen() self.screen.finish()
def check_memory(opts, display_mode=None): if not display_mode: display_mode = opts.display_mode reason = '' needed_ram = isys.MIN_RAM if not within_available_memory(needed_ram): from snack import SnackScreen, ButtonChoiceWindow screen = SnackScreen() ButtonChoiceWindow(screen, _('Fatal Error'), _('You do not have enough RAM to install %s ' 'on this machine%s.\n' '\n' 'Press <return> to reboot your system.\n') %(product.productName, reason), buttons = (_("OK"),)) screen.finish() sys.exit(0) # override display mode if machine cannot nicely run X if display_mode not in ('t', 'c') and not flags.usevnc: needed_ram = isys.MIN_GUI_RAM if not within_available_memory(needed_ram): stdoutLog.warning(_("You do not have enough RAM to use the graphical " "installer. Starting text mode.")) opts.display_mode = 't' time.sleep(2)