# # text.py - text mode frontend to anaconda # # Erik Troan # Matt Wilson # # Copyright 1999-2002 Red Hat, Inc. # # This software may be freely redistributed under the terms of the GNU # library public license. # # You should have received a copy of the GNU Library Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # from snack import * import sys import os import isys import iutil import time import signal import parted import string import kudzu from language import expandLangs from flags import flags from constants_text import * from constants import * from rhpl.log import log from rhpl.translate import _, cat, N_ stepToClasses = { "language" : ("language_text", "LanguageWindow"), "keyboard" : ("keyboard_text", "KeyboardWindow"), "mouse" : ("mouse_text", ("MouseWindow", "MouseDeviceWindow")), "welcome" : ("welcome_text", "WelcomeWindow"), "installtype" : ("installpath_text", "InstallPathWindow"), "autopartition" : ("partition_text", "AutoPartitionWindow"), "custom-upgrade" : ("upgrade_text", "UpgradeExamineWindow"), "addswap" : ("upgrade_text", "UpgradeSwapWindow"), "upgrademigratefs" : ("upgrade_text", "UpgradeMigrateFSWindow"), "fdisk" : ("fdisk_text", "fdiskPartitionWindow"), "partitionmethod" : ("partmethod_text", ("PartitionMethod")), "partition": ("partition_text", ("PartitionWindow")), "findinstall" : ("upgrade_text", "UpgradeExamineWindow"), "addswap" : ("upgrade_text", "UpgradeSwapWindow"), "upgbootloader": ("upgrade_bootloader_text", "UpgradeBootloaderWindow"), "bootloader" : ("bootloader_text", ("BootloaderChoiceWindow", "BootloaderAppendWindow", "BootloaderPasswordWindow")), "bootloaderadvanced" : ("bootloader_text", ("BootloaderImagesWindow", "BootloaderLocationWindow")), "network" : ("network_text", ("NetworkDeviceWindow", "NetworkGlobalWindow", "HostnameWindow")), "firewall" : ("firewall_text", "FirewallWindow"), "languagesupport" : ("language_text", ("LanguageSupportWindow", "LanguageDefaultWindow")), "timezone" : ("timezone_text", "TimezoneWindow"), "accounts" : ("userauth_text", "RootPasswordWindow"), "authentication" : ("userauth_text", ("AuthConfigWindow")), "desktopchoice": ("desktop_choice_text", "DesktopChoiceWindow"), "package-selection" : ("packages_text", "PackageGroupWindow"), "indivpackage" : ("packages_text", ("IndividualPackageWindow")), "dependencies" : ("packages_text", "PackageDepWindow"), "videocard" : ("xconfig_text", "XConfigWindowCard"), "monitor" : ("xconfig_text", "MonitorWindow"), "xcustom" : ("xconfig_text", "XCustomWindow"), "confirminstall" : ("confirm_text", "BeginInstallWindow"), "confirmupgrade" : ("confirm_text", "BeginUpgradeWindow"), "install" : ("progress_text", "setupForInstall"), "bootdisk" : ("bootdisk_text", ("BootDiskWindow")), "complete" : ("complete_text", "FinishedWindow"), } if iutil.getArch() == 'sparc': stepToClasses["bootloader"] = ("silo_text", ("SiloAppendWindow", "SiloWindow" "SiloImagesWindow")) if iutil.getArch() == 's390': stepToClasses["bootloader"] = ("zipl_text", ( "ZiplWindow")) class InstallWindow: def __call__ (self, screen): raise RuntimeError, "Unimplemented screen" class WaitWindow: def pop(self): self.screen.popWindow() self.screen.refresh() def __init__(self, screen, title, text): self.screen = screen width = 40 if (len(text) < width): width = len(text) t = TextboxReflowed(width, text) g = GridForm(self.screen, title, 1, 1) g.add(t, 0, 0) g.draw() self.screen.refresh() class OkCancelWindow: def getrc(self): return self.rc def __init__(self, screen, title, text): rc = ButtonChoiceWindow(screen, title, text, buttons=[TEXT_OK_BUTTON, _("Cancel")]) if rc == string.lower(_("Cancel")): self.rc = 1 else: self.rc = 0 class ProgressWindow: def pop(self): self.screen.popWindow() self.screen.refresh() del self.scale self.scale = None def set(self, amount): self.scale.set(amount) self.screen.refresh() def __init__(self, screen, title, text, total): self.screen = screen width = 55 if (len(text) > width): width = len(text) t = TextboxReflowed(width, text) g = GridForm(self.screen, title, 1, 2) g.add(t, 0, 0, (0, 0, 0, 1), anchorLeft=1) self.scale = Scale(width, total) g.add(self.scale, 0, 1) g.draw() self.screen.refresh() class InstallInterface: def helpWindow(self, screen, key): lang = self.instLanguage.getCurrent() lang = self.instLanguage.getLangNick(lang) self.langSearchPath = expandLangs(lang) + ['C'] if key == "helponhelp": if self.showingHelpOnHelp: return None else: self.showingHelpOnHelp = 1 try: f = None if self.configFileData.has_key("helptag"): helpTag = "-%s" % (self.configFileData["helptag"],) else: helpTag = "" arch = "-%s" % (iutil.getArch(),) tags = [ "%s%s" % (helpTag, arch), "%s" % (helpTag,), "%s" % (arch,), "" ] # XXX # # HelpWindow can't get to the langauge found = 0 for path in ("./text-", "/mnt/source/RHupdates/", "/usr/share/anaconda/"): if found: break for lang in self.langSearchPath: for tag in tags: fn = "%shelp/%s/s1-help-screens-%s%s.txt" \ % (path, lang, key, tag) try: f = open(fn) except IOError, msg: continue found = 1 break if not f: ButtonChoiceWindow(screen, _("Help not available"), _("No help is available for this " "step of the install."), buttons=[TEXT_OK_BUTTON]) return None lines = f.readlines() for l in lines: l = l.replace("@RHL@", productName) l = l.replace("@RHLVER@", productVersion) while not string.strip(l[0]): l = l[1:] title = string.strip(l[0]) l = l[1:] while not string.strip(l[0]): l = l[1:] f.close() height = 10 scroll = 1 if len(l) < height: height = len(l) scroll = 0 width = len(title) + 6 stream = "" for line in l: line = string.strip(line) stream = stream + line + "\n" if len(line) > width: width = len(line) bb = ButtonBar(screen, [TEXT_OK_BUTTON]) t = Textbox(width, height, stream, scroll=scroll) g = GridFormHelp(screen, title, "helponhelp", 1, 2) g.add(t, 0, 0, padding=(0, 0, 0, 1)) g.add(bb, 0, 1, growx=1) g.runOnce() self.showingHelpOnHelp = 0 except: import traceback (type, value, tb) = sys.exc_info() from string import joinfields list = traceback.format_exception(type, value, tb) text = joinfields(list, "") rc = self.exceptionWindow(_("Exception Occurred"), text) if rc: import pdb pdb.post_mortem(tb) os._exit(1) def progressWindow(self, title, text, total): return ProgressWindow(self.screen, title, text, total) def messageWindow(self, title, text, type="ok", default = None, custom_icon=None, custom_buttons=[]): if type == "ok": ButtonChoiceWindow(self.screen, title, text, buttons=[TEXT_OK_BUTTON]) elif type == "yesno": if default and default == "no": btnlist = [TEXT_NO_BUTTON, TEXT_YES_BUTTON] else: btnlist = [TEXT_YES_BUTTON, TEXT_NO_BUTTON] rc = ButtonChoiceWindow(self.screen, title, text, buttons=btnlist) if rc == "yes": return 1 else: return 0 elif type == "custom": tmpbut = [] for but in custom_buttons: tmpbut.append(string.replace(but,"_","")) rc = ButtonChoiceWindow(self.screen, title, text, width=60, buttons=tmpbut) idx = 0 for b in tmpbut: if string.lower(b) == rc: return idx != 0 idx = idx + 1 return 0 else: return OkCancelWindow(self.screen, title, text) def dumpWindow(self): rc = ButtonChoiceWindow(self.screen, _("Save Crash Dump"), _("Please insert a floppy now. All contents of the disk " "will be erased, so please choose your diskette carefully."), [TEXT_OK_BUTTON, _("Cancel")]) if rc == string.lower(_("Cancel")): return 1 return 0 def exceptionWindow(self, title, text): try: floppyDevices = 0 for dev in kudzu.probe(kudzu.CLASS_FLOPPY, kudzu.BUS_UNSPEC, kudzu.PROBE_ALL): if not dev.detached: floppyDevices = floppyDevices + 1 except: floppyDevices = 0 if floppyDevices > 0 or DEBUG: ugh = "%s\n\n" % (exceptionText,) buttons=[TEXT_OK_BUTTON, _("Save"), _("Debug")] else: ugh = "%s\n\n" % (exceptionTextNoFloppy,) buttons=[TEXT_OK_BUTTON, _("Debug")] rc = ButtonChoiceWindow(self.screen, title, ugh + text, buttons) if rc == string.lower(_("Debug")): return 1 elif rc == string.lower(_("Save")): return 2 return None def partedExceptionWindow(self, exc): # if our only option is to cancel, let us handle the exception # in our code and avoid popping up the exception window here. if exc.options == parted.EXCEPTION_CANCEL: return parted.EXCEPTION_UNHANDLED buttons = [] buttonToAction = {} flags = ((parted.EXCEPTION_FIX, N_("Fix")), (parted.EXCEPTION_YES, N_("Yes")), (parted.EXCEPTION_NO, N_("No")), (parted.EXCEPTION_OK, N_("OK")), (parted.EXCEPTION_RETRY, N_("Retry")), (parted.EXCEPTION_IGNORE, N_("Ignore")), (parted.EXCEPTION_CANCEL, N_("Cancel"))) for flag, errorstring in flags: if exc.options & flag: buttons.append(_(errorstring)) buttonToAction[string.lower(_(errorstring))] = flag rc = None while not buttonToAction.has_key(rc): rc = ButtonChoiceWindow(self.screen, exc.type_string, exc.message, buttons=buttons) return buttonToAction[rc] def waitWindow(self, title, text): return WaitWindow(self.screen, title, text) def drawFrame(self): self.welcomeText = _("%s ") % (productName,) self.screen.drawRootText (0, 0, self.welcomeText) self.screen.drawRootText (len(_(self.welcomeText)), 0, (self.screen.width - len(_(self.welcomeText))) * " ") if (os.access("/usr/share/anaconda/help/C/s1-help-screens-lang.txt", os.R_OK)): self.screen.pushHelpLine(_(" for help | between elements | selects | next screen")) else: self.screen.pushHelpLine(_(" / between elements | selects | next screen")) def setScreen(self, screen): self.screen = screen def shutdown(self): self.screen.finish() self.screen = None def __init__(self): signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGTSTP, signal.SIG_IGN) self.screen = None self.showingHelpOnHelp = 0 def __del__(self): if self.screen: self.screen.finish() def run(self, id, dispatch, configFileData): # set up for CJK text mode if needed if (flags.setupFilesystems and (id.instLanguage.getFontFile(id.instLanguage.getCurrent()) == "bterm") and not isys.isPsudoTTY(0) and not flags.serial): log("starting bterm") try: rc = isys.startBterm() time.sleep(1) except Exception, e: log("got an exception starting bterm: %s" %(e,)) self.screen = SnackScreen() self.configFileData = configFileData self.screen.helpCallback(self.helpWindow) # uncomment this line to make the installer quit on # handy for quick debugging. # self.screen.suspendCallback(killSelf, self.screen) # uncomment this line to drop into the python debugger on # --VERY handy-- if DEBUG or flags.test: self.screen.suspendCallback(debugSelf, self.screen) if flags.serial or isys.isPsudoTTY(0) or isys.isVioConsole(): self.screen.suspendCallback(spawnShell, self.screen) # clear out the old root text by writing spaces in the blank # area on the right side of the screen #self.screen.drawRootText (len(_(self.welcomeText)), 0, #(self.screen.width - len(_(self.welcomeText))) * " ") #self.screen.drawRootText (0 - len(_(step[0])), 0, _(step[0])) langname = id.instLanguage.getCurrent() lang = id.instLanguage.getLangNick(langname) self.langSearchPath = expandLangs(lang) + ['C'] self.instLanguage = id.instLanguage # draw the frame after setting up the fallback self.drawFrame() # draw the frame after setting up the fallback self.drawFrame() id.fsset.registerMessageWindow(self.messageWindow) id.fsset.registerProgressWindow(self.progressWindow) id.fsset.registerWaitWindow(self.waitWindow) parted.exception_set_handler(self.partedExceptionWindow) lastrc = INSTALL_OK (step, args) = dispatch.currentStep() while step: (file, classNames) = stepToClasses[step] if type(classNames) != type(()): classNames = (classNames,) if lastrc == INSTALL_OK: step = 0 else: step = len(classNames) - 1 while step >= 0 and step < len(classNames): # reget the args. they could change (especially direction) (foo, args) = dispatch.currentStep() nextWindow = None s = "from %s import %s; nextWindow = %s" % \ (file, classNames[step], classNames[step]) exec s win = nextWindow() #log("TUI running step %s (class %s, file %s)" % #(step, file, classNames)) rc = apply(win, (self.screen, ) + args) if rc == INSTALL_NOOP: rc = lastrc if rc == INSTALL_BACK: step = step - 1 dispatch.dir = DISPATCH_BACK elif rc == INSTALL_OK: step = step + 1 dispatch.dir = DISPATCH_FORWARD lastrc = rc if step == -1: if not dispatch.canGoBack(): ButtonChoiceWindow(self.screen, _("Cancelled"), _("I can't go to the previous step " "from here. You will have to try " "again."), buttons=[_("OK")]) dispatch.gotoPrev() else: dispatch.gotoNext() (step, args) = dispatch.currentStep() self.screen.finish() def killSelf(screen): screen.finish() os._exit(0) def debugSelf(screen): screen.suspend() import pdb try: pdb.set_trace() except: sys.exit(-1) screen.resume() def spawnShell(screen): screen.suspend() print "\n\nType to return to the install program.\n" iutil.execWithRedirect("/bin/sh", ["-/bin/sh"]) time.sleep(5) screen.resume()