#
# text.py - text mode frontend to anaconda
#
# Erik Troan <
[email protected]>
# Matt Wilson <
[email protected]>
#
# 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(_(" <F1> for help | <Tab> between elements | <Space> selects | <F12> next screen"))
else:
self.screen.pushHelpLine(_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> 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 <Ctrl+Z>
# handy for quick debugging.
# self.screen.suspendCallback(killSelf, self.screen)
# uncomment this line to drop into the python debugger on <Ctrl+Z>
# --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 <exit> to return to the install program.\n"
iutil.execWithRedirect("/bin/sh", ["-/bin/sh"])
time.sleep(5)
screen.resume()