#
# gui.py - Graphical front end for anaconda
#
# Matt Wilson <
[email protected]>
# Michael Fulbright <
[email protected]>
#
# Copyright 1999-2003 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.
#
import os
import iutil
import string
import isys
import sys
import parted
import gtk
import htmlbuffer
import rpm
import kudzu
from language import expandLangs
from splashscreen import splashScreenPop
from flags import flags
from constants import *
from rhpl.log import log
from rhpl.translate import _, N_
from product import *
rpm.addMacro("_i18ndomains", "redhat-dist")
isys.bind_textdomain_codeset("redhat-dist", "UTF-8")
StayOnScreen = "stayOnScreen"
mainWindow = None
stepToClass = {
"language" : ("language_gui", "LanguageWindow"),
"keyboard" : ("keyboard_gui", "KeyboardWindow"),
"mouse" : ("mouse_gui", "MouseWindow"),
"welcome" : ("welcome_gui", "WelcomeWindow"),
"installtype" : ("installpath_gui", "InstallPathWindow"),
"partitionmethod" : ("partmethod_gui", "PartitionMethodWindow"),
"partition" : ("partition_gui", "PartitionWindow"),
"autopartition" : ("partition_gui", "AutoPartitionWindow"),
"findinstall" : ("examine_gui", "UpgradeExamineWindow"),
"addswap" : ("upgrade_swap_gui", "UpgradeSwapWindow"),
"upgrademigratefs" : ("upgrade_migratefs_gui", "UpgradeMigrateFSWindow"),
"fdisk" : ("fdisk_gui", "FDiskWindow"),
"bootloader": ("bootloader_main_gui", "MainBootloaderWindow"),
"bootloaderadvanced": ("bootloader_advanced_gui", "AdvancedBootloaderWindow"),
"upgbootloader": ("upgrade_bootloader_gui", "UpgradeBootloaderWindow"),
"network" : ("network_gui", "NetworkWindow"),
"firewall" : ("firewall_gui", "FirewallWindow"),
"languagesupport" : ("language_support_gui", "LanguageSupportWindow"),
"timezone" : ("timezone_gui", "TimezoneWindow"),
"accounts" : ("account_gui", "AccountWindow"),
"authentication" : ("auth_gui", "AuthWindow"),
"desktopchoice": ("desktop_choice_gui", "DesktopChoiceWindow"),
"package-selection" : ("package_gui", "PackageSelectionWindow"),
"indivpackage" : ("package_gui", "IndividualPackageSelectionWindow"),
"dependencies" : ("dependencies_gui", "UnresolvedDependenciesWindow"),
"videocard" : ("xconfig_gui", "XConfigWindow"),
"monitor" : ("xconfig_gui", "MonitorWindow"),
"xcustom" : ("xconfig_gui", "XCustomWindow"),
"confirminstall" : ("confirm_gui", "InstallConfirmWindow"),
"confirmupgrade" : ("confirm_gui", "UpgradeConfirmWindow"),
"finishxconfig" : None,
"install" : ("progress_gui", "InstallProgressWindow"),
"bootdisk" : ("bootdisk_gui", "BootdiskWindow"),
"complete" : ("congrats_gui", "CongratulationWindow"),
}
if iutil.getArch() == 'sparc':
stepToClass["bootloader"] = ("silo_gui", "SiloWindow")
elif iutil.getArch() == 's390':
stepToClass["bootloader"] = ("zipl_gui", "ZiplWindow")
#
# Stuff for screenshots
#
screenshotDir = None
screenshotIndex = 0
def copyScreenshots():
global screenshotIndex
global screenshotDir
# see if any screenshots taken
if screenshotIndex == 0:
return
destDir = "/mnt/sysimage/root/anaconda-screenshots"
if not os.access(destDir, os.R_OK):
try:
os.mkdir(destDir, 0750)
except:
window = MessageWindow("Error Saving Screenshot",
_("An error occurred copying the "
"screenshots over."), type="warning")
return
# copy all png's over
for f in os.listdir(screenshotDir):
(path, fname) = os.path.split(f)
(b, ext) = os.path.splitext(f)
if ext == ".png":
iutil.copyFile(screenshotDir + '/' + f,
destDir + '/' + fname)
window = MessageWindow(_("Screenshots Copied"),
_("The screenshots have been saved into the "
"directory:\n\n"
"\t/root/anaconda-screenshots/\n\n"
"You can access these when you reboot and "
"login as root."))
def takeScreenShot():
global screenshotIndex
global screenshotDir
if screenshotDir is None:
screenshotDir = "/tmp/ramfs/anaconda-screenshots"
if not os.access(screenshotDir, os.R_OK):
try:
os.mkdir(screenshotDir)
except:
screenshotDir = None
return
try:
screenshot = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, gtk.FALSE, 8,
gtk.gdk.screen_width(), gtk.gdk.screen_height())
screenshot.get_from_drawable(gtk.gdk.get_default_root_window(),
gtk.gdk.colormap_get_system(),
0, 0, 0, 0,
gtk.gdk.screen_width(), gtk.gdk.screen_height())
if screenshot:
while (1):
sname = "screenshot-%04d.png" % ( screenshotIndex,)
if not os.access(screenshotDir + '/' + sname, os.R_OK):
break
screenshotIndex = screenshotIndex + 1
if screenshotIndex > 9999:
log("Too many screenshots!")
return
screenshot.save (screenshotDir + '/' + sname, "png")
screenshotIndex = screenshotIndex + 1
window = MessageWindow(_("Saving Screenshot"),
_("A screenshot named '%s' has been saved.") % (sname,) ,
type="ok")
except:
window = MessageWindow(_("Error Saving Screenshot"),
_("An error occurred while saving "
"the screenshot. If this occurred "
"during package installation, you may need "
"to try several times for it to succeed."),
type="warning")
def handleShiftPrintScrnRelease (window, event):
if (event.keyval == gtk.keysyms.Print and event.state & gtk.gdk.SHIFT_MASK):
takeScreenShot()
#
# HACK to make treeview work
#
def setupTreeViewFixupIdleHandler(view, store):
id = {}
id["id"] = gtk.idle_add(scrollToIdleHandler, (view, store, id))
def scrollToIdleHandler((view, store, iddict)):
if not view or not store or not iddict:
return
try:
id = iddict["id"]
except:
return
selection = view.get_selection()
if not selection:
return
model, iter = selection.get_selected()
if not iter:
return
path = store.get_path(iter)
col = view.get_column(0)
view.scroll_to_cell(path, col, gtk.TRUE, 0.5, 0.5)
if id:
gtk.idle_remove(id)
# setup globals
def processEvents():
gtk.gdk.flush()
while gtk.events_pending():
gtk.main_iteration(gtk.FALSE)
def partedExceptionWindow(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
print exc.type_string
print exc.message
print exc.options
win = gtk.Dialog(exc.type_string, mainWindow, gtk.DIALOG_MODAL)
addFrame(win)
win.set_position(gtk.WIN_POS_CENTER)
label = WrappingLabel(exc.message)
win.vbox.pack_start (label)
numButtons = 0
buttonToAction = {}
exflags = ((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, string in exflags:
if exc.options & flag:
win.add_button(_(string), flag)
win.show_all()
rc = win.run()
win.destroy()
return rc
def widgetExpander(widget, growTo=None):
widget.connect("size-allocate", growToParent, growTo)
def growToParent(widget, rect, growTo=None):
return
if not widget.parent:
return
ignore = widget.__dict__.get("ignoreEvents")
if not ignore:
if growTo:
x, y, width, height = growTo.get_allocation()
widget.set_size_request(width, -1)
else:
widget.set_size_request(rect.width, -1)
widget.ignoreEvents = 1
else:
widget.ignoreEvents = 0
_busyCursor = 0
def setCursorToBusy(process=1):
root = gtk.gdk.get_default_root_window()
cursor = gtk.gdk.Cursor(gtk.gdk.WATCH)
root.set_cursor(cursor)
if process:
processEvents()
def setCursorToNormal():
root = gtk.gdk.get_default_root_window()
cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR)
root.set_cursor(cursor)
def rootPushBusyCursor(process=1):
global _busyCursor
_busyCursor += 1
if _busyCursor > 0:
setCursorToBusy(process)
def rootPopBusyCursor():
global _busyCursor
_busyCursor -= 1
if _busyCursor <= 0:
setCursorToNormal()
def getBusyCursorStatus():
global _busyCursor
return _busyCursor
class MnemonicLabel(gtk.Label):
def __init__(self, text=""):
gtk.Label.__init__(self, "")
self.set_text_with_mnemonic(text)
class WrappingLabel(gtk.Label):
def __init__(self, label=""):
gtk.Label.__init__(self, label)
self.set_line_wrap(gtk.TRUE)
self.ignoreEvents = 0
# self.set_size_request(-1, 1)
widgetExpander(self)
def titleBarMousePressCB(widget, event, data):
if event.type & gtk.gdk.BUTTON_PRESS:
data["state"] = 1
data["button"] = event.button
data["deltax"] = event.x
data["deltay"] = event.y
def titleBarMouseReleaseCB(widget, event, data):
if data["state"] and event.button == data["button"]:
data["state"] = 0
data["button"] = 0
data["deltax"] = 0
data["deltay"] = 0
def titleBarMotionEventCB(widget, event, data):
if data["state"]:
newx = event.x_root-data["deltax"]
newy = event.y_root-data["deltay"]
if newx < 0:
newx = 0
if newy < 0:
newy = 0
(w, h) = data["window"].get_size()
if (newx+w) > gtk.gdk.screen_width():
newx = gtk.gdk.screen_width() - w
if (newy+20) > (gtk.gdk.screen_height()):
newy = gtk.gdk.screen_height() - 20
data["window"].move(newx, newy)
def addFrame(dialog, title=None):
contents = dialog.get_children()[0]
dialog.remove(contents)
frame = gtk.Frame()
frame.set_shadow_type(gtk.SHADOW_OUT)
box = gtk.VBox()
try:
if title is None:
title = dialog.get_title()
if title:
data = {}
data["state"] = 0
data["button"] = 0
data["deltax"] = 0
data["deltay"] = 0
data["window"] = dialog
eventBox = gtk.EventBox()
eventBox.connect("button-press-event", titleBarMousePressCB, data)
eventBox.connect("button-release-event", titleBarMouseReleaseCB, data)
eventBox.connect("motion-notify-event", titleBarMotionEventCB,data)
titleBox = gtk.HBox(gtk.FALSE, 5)
eventBox.add(titleBox)
eventBox.modify_bg(gtk.STATE_NORMAL,
eventBox.rc_get_style().bg[gtk.STATE_SELECTED])
titlelbl = gtk.Label("")
titlelbl.set_markup("<b>"+_(title)+"</b>")
titlelbl.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse ("white"))
titlelbl.set_property("ypad", 4)
titleBox.pack_start(titlelbl)
box.pack_start(eventBox, gtk.FALSE, gtk.FALSE)
except:
pass
frame2=gtk.Frame()
frame2.set_shadow_type(gtk.SHADOW_NONE)
frame2.set_border_width(4)
frame2.add(contents)
box.pack_start(frame2, gtk.TRUE, gtk.TRUE, padding=5)
frame.add(box)
frame.show()
dialog.add(frame)
# make screen shots work
dialog.connect ("key-release-event", handleShiftPrintScrnRelease)
class WaitWindow:
def __init__(self, title, text):
self.window = gtk.Window(gtk.WINDOW_POPUP)
self.window.set_title(title)
self.window.set_position(gtk.WIN_POS_CENTER)
self.window.set_modal(gtk.TRUE)
label = WrappingLabel(text)
box = gtk.Frame()
box.set_border_width(10)
box.add(label)
box.set_shadow_type(gtk.SHADOW_NONE)
frame = gtk.Frame ()
frame.set_shadow_type(gtk.SHADOW_OUT)
frame.add (box)
self.window.add(frame)
self.window.show_all()
rootPushBusyCursor()
def pop(self):
self.window.destroy()
rootPopBusyCursor()
class ProgressWindow:
def __init__(self, title, text, total):
self.window = gtk.Window (gtk.WINDOW_POPUP)
self.window.set_title (title)
self.window.set_position (gtk.WIN_POS_CENTER)
self.window.set_modal (gtk.TRUE)
box = gtk.VBox (gtk.FALSE, 5)
box.set_border_width (10)
label = WrappingLabel (text)
label.set_alignment (0.0, 0.5)
box.pack_start (label, gtk.FALSE)
self.total = total
self.progress = gtk.ProgressBar ()
box.pack_start (self.progress, gtk.TRUE)
frame = gtk.Frame ()
frame.set_shadow_type (gtk.SHADOW_OUT)
frame.add (box)
self.window.add (frame)
self.window.show_all ()
rootPushBusyCursor()
def set (self, amount):
# only update widget if we've changed by 5%
curval = self.progress.get_fraction()
newval = float (amount) / self.total
if newval < 0.998:
if (newval - curval) < 0.05 and newval > curval:
return
self.progress.set_fraction (newval)
processEvents ()
def pop(self):
self.window.destroy ()
rootPopBusyCursor()
class ExceptionWindow:
def __init__ (self, 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
win = gtk.Dialog("Exception Occured", mainWindow, gtk.DIALOG_MODAL)
win.add_button("_Debug", 0)
if floppyDevices > 0 or DEBUG:
win.add_button("_Save to floppy", 1)
win.add_button('gtk-ok', 2)
buffer = gtk.TextBuffer(None)
buffer.set_text(text)
textbox = gtk.TextView()
textbox.set_buffer(buffer)
textbox.set_property("editable", gtk.FALSE)
textbox.set_property("cursor_visible", gtk.FALSE)
sw = gtk.ScrolledWindow ()
sw.add (textbox)
sw.set_policy (gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
hbox = gtk.HBox (gtk.FALSE)
## file = pixmap_file('gnome-warning.png')
## if file:
## hbox.pack_start (GnomePixmap (file), gtk.FALSE)
if floppyDevices > 0:
info = WrappingLabel(exceptionText)
else:
info = WrappingLabel(exceptionTextNoFloppy)
info.set_size_request (400, -1)
hbox.pack_start (sw, gtk.TRUE)
win.vbox.pack_start (info, gtk.FALSE)
win.vbox.pack_start (hbox, gtk.TRUE)
win.set_size_request (500, 300)
win.set_position (gtk.WIN_POS_CENTER)
addFrame(win)
win.show_all ()
self.window = win
self.rc = self.window.run ()
# self.window.destroy()
def getrc (self):
# I did it this way for future expantion
# 0 is debug
if self.rc == 0:
try:
# switch to VC1 so we can debug
isys.vtActivate (1)
except SystemError:
pass
return 1
# 1 is save
if self.rc == 1:
return 2
# 2 is OK
elif self.rc == 2:
return 0
class MessageWindow:
def getrc (self):
return self.rc
def __init__ (self, title, text, type="ok", default=None, custom_buttons=None, custom_icon=None):
if flags.autostep:
self.rc = 1
return
self.rc = None
docustom = 0
if type == 'ok':
buttons = gtk.BUTTONS_OK
style = gtk.MESSAGE_INFO
elif type == 'warning':
buttons = gtk.BUTTONS_OK
style = gtk.MESSAGE_WARNING
elif type == 'okcancel':
buttons = gtk.BUTTONS_OK_CANCEL
style = gtk.MESSAGE_WARNING
elif type == 'yesno':
buttons = gtk.BUTTONS_YES_NO
style = gtk.MESSAGE_QUESTION
elif type == 'custom':
docustom = 1
buttons = gtk.BUTTONS_NONE
style = gtk.MESSAGE_QUESTION
if custom_icon == "warning":
style = gtk.MESSAGE_WARNING
elif custom_icon == "question":
style = gtk.MESSAGE_QUESTION
elif custom_icon == "error":
style = gtk.MESSAGE_ERROR
elif custom_icon == "info":
style = gtk.MESSAGE_INFO
dialog = gtk.MessageDialog(mainWindow, 0, style, buttons, text)
if docustom:
rid=0
for button in custom_buttons:
if button == _("Cancel"):
tbutton = "gtk-cancel"
else:
tbutton = button
widget = dialog.add_button(tbutton, rid)
rid = rid + 1
defaultchoice = rid - 1
else:
if default == "no":
defaultchoice = 0
elif default == "yes" or default == "ok":
defaultchoice = 1
else:
defaultchoice = 0
addFrame(dialog, title=title)
dialog.set_position (gtk.WIN_POS_CENTER)
dialog.set_default_response(defaultchoice)
dialog.show_all ()
# XXX - Messy - turn off busy cursor if necessary
busycursor = getBusyCursorStatus()
setCursorToNormal()
rc = dialog.run()
if rc == gtk.RESPONSE_OK or rc == gtk.RESPONSE_YES:
self.rc = 1
elif (rc == gtk.RESPONSE_CANCEL or rc == gtk.RESPONSE_NO
or rc == gtk.RESPONSE_CLOSE):
self.rc = 0
elif rc == gtk.RESPONSE_DELETE_EVENT:
self.rc = 0
else:
self.rc = rc
dialog.destroy()
# restore busy cursor
if busycursor:
setCursorToBusy()
class InstallInterface:
def __init__ (self):
# figure out if we want to run interface at 800x600 or 640x480
if gtk.gdk.screen_width() >= 800:
self.runres = "800x600"
else:
self.runres = "640x480"
def __del__ (self):
pass
def shutdown (self):
pass
def setPackageProgressWindow (self, ppw):
self.ppw = ppw
def waitWindow (self, title, text):
return WaitWindow (title, text)
def progressWindow (self, title, text, total):
return ProgressWindow (title, text, total)
def packageProgressWindow (self, total, totalSize):
self.ppw.setSizes (total, totalSize)
return self.ppw
def messageWindow(self, title, text, type="ok", default = None,
custom_buttons=None, custom_icon=None):
rc = MessageWindow (title, text, type, default,
custom_buttons, custom_icon).getrc()
return rc
def exceptionWindow(self, title, text):
print text
win = ExceptionWindow (text)
return win.getrc ()
def dumpWindow(self):
window = MessageWindow("Save Crash Dump",
_("Please insert a floppy now. All contents "
"of the disk will be erased, so please "
"choose your diskette carefully."),
"okcancel")
rc = window.getrc()
return not rc
def getBootdisk (self):
return None
def run(self, id, dispatch, configFileData):
## from xkb import XKB
## kb = XKB()
self.dispatch = dispatch
# XXX users complain when the keypad doesn't work for input.
## if 0 and flags.setupFilesystems:
## try:
## kb.setMouseKeys (1)
## except SystemError:
## pass
# XXX x_already_set is a hack
if id.keyboard and not id.x_already_set:
id.keyboard.activate()
## info = id.keyboard.getXKB()
## if info:
## (rules, model, layout, variant, options) = info
## kb.setRule (model, layout, variant, "complete")
id.fsset.registerMessageWindow(self.messageWindow)
id.fsset.registerProgressWindow(self.progressWindow)
id.fsset.registerWaitWindow(self.waitWindow)
parted.exception_set_handler(partedExceptionWindow)
lang = id.instLanguage.getCurrent()
lang = id.instLanguage.getLangNick(lang)
self.icw = InstallControlWindow (self, self.dispatch, lang)
self.icw.run (self.runres, configFileData)
class TextViewBrowser(gtk.TextView):
def __init__(self):
self.hadj = None
self.vadj = None
gtk.TextView.__init__(self)
self.set_property('editable', gtk.FALSE)
self.set_property('cursor_visible', gtk.FALSE)
self.set_left_margin(10)
self.set_wrap_mode(gtk.WRAP_WORD)
self.connect('move-cursor', self.moveCursor)
self.connect('set-scroll-adjustments', self.cacheAdjustments)
def swallowFocus(self, *args):
self.emit_stop_by_name('focus-in-event')
def cacheAdjustments(self, view, hadj, vadj):
self.hadj = hadj
self.vadj = vadj
def moveCursor(self, view, step, count, extend_selection):
if step == gtk.MOVEMENT_DISPLAY_LINES:
if count == -1 and self.vadj != None:
self.vadj.value = max(self.vadj.value - self.vadj.step_increment,
self.vadj.lower)
self.vadj.value_changed()
elif count == 1 and self.vadj != None:
self.vadj.value = min(self.vadj.value + self.vadj.step_increment - 1,
self.vadj.upper - self.vadj.page_increment - 1)
self.vadj.value_changed()
elif step == gtk.MOVEMENT_PAGES:
if count == -1 and self.vadj != None:
self.vadj.value = max(self.vadj.value - self.vadj.page_increment,
self.vadj.lower)
self.vadj.value_changed()
elif count == 1 and self.vadj != None:
self.vadj.value = min(self.vadj.value + self.vadj.page_increment - 1,
self.vadj.upper - self.vadj.page_increment - 1)
self.vadj.value_changed()
self.emit_stop_by_name ('move-cursor')
class InstallControlWindow:
def setLanguage (self, locale):
#gtk_set_locale ()
#gtk_rc_init ()
#gtk_rc_reparse_all ()
self.langSearchPath = expandLangs(locale) + ['C']
## found = 0
## for l in self.langSearchPath:
## if os.access ("/etc/gtk/gtkrc." + l, os.R_OK):
## rc_parse("/etc/gtk/gtkrc." + l)
## found = 1
## if not found:
## rc_parse("/etc/gtk/gtkrc")
## #_gtk_nuke_rc_mtimes ()
## gtk_rc_reparse_all ()
if not self.__dict__.has_key('window'): return
self.reloadRcQueued = 1
self.updateStockButtons()
self.helpFrame.set_label (_("Online Help"))
self.installFrame.set_label (_("Language Selection"))
self.loadReleaseNotes()
self.refreshHelp(recreate = 1)
def prevClicked (self, *args):
try:
self.currentWindow.getPrev ()
except StayOnScreen:
return
self.dispatch.gotoPrev()
self.dir = -1
self.setScreen ()
def nextClicked (self, *args):
try:
rc = self.currentWindow.getNext ()
except StayOnScreen:
return
self.dispatch.gotoNext()
self.dir = 1
self.setScreen ()
def helpClicked (self, widget, simulated=0):
self.hbox.remove (widget)
if widget == self.hideHelpButton:
self.bin.remove (self.table)
self.installFrame.reparent (self.bin)
self.showHelpButton.show ()
self.showHelpButton.set_state (gtk.STATE_NORMAL)
self.hbox.pack_start (self.showHelpButton, gtk.FALSE)
self.hbox.reorder_child (self.showHelpButton, 0)
self.showHelpButton.grab_focus()
self.displayHelp = gtk.FALSE
else:
self.bin.remove (self.installFrame)
self.table.attach (self.installFrame, 1, 3, 0, 1,
gtk.FILL | gtk.EXPAND,
gtk.FILL | gtk.EXPAND)
self.bin.add (self.table)
self.refreshHelp()
self.hideHelpButton.show ()
self.showHelpButton.set_state (gtk.STATE_NORMAL)
self.hbox.pack_start (self.hideHelpButton, gtk.FALSE)
self.hbox.reorder_child (self.hideHelpButton, 0)
self.hideHelpButton.grab_focus()
self.displayHelp = gtk.TRUE
def debugClicked (self, *args):
try:
# switch to VC1 so we can debug
isys.vtActivate (1)
except SystemError:
pass
import pdb
try:
pdb.set_trace()
except:
sys.exit(-1)
try:
# switch back
isys.vtActivate (7)
except SystemError:
pass
def refreshHelp(self, recreate = 0):
buffer = htmlbuffer.HTMLBuffer()
ics = self.currentWindow.getICS()
buffer.feed(ics.getHTML(self.langSearchPath))
textbuffer = buffer.get_buffer()
if recreate == 0:
self.help.set_buffer(textbuffer)
else:
self.help_sw.remove(self.help)
self.help = TextViewBrowser()
self.help_sw.add(self.help)
self.help.set_buffer(textbuffer)
self.help.show()
# scroll to the top. Do this with a mark so it's done in the idle loop
iter = textbuffer.get_iter_at_offset(0)
mark = textbuffer.create_mark("top", iter, gtk.FALSE)
self.help.scroll_to_mark(mark, 0.0, gtk.FALSE, 0.0, 0.0)
def relnotes_closed (self, *args):
self.textWin.destroy()
#
# XXX - disabling this behavior for now due to bug where if you pop up
# release notes during package selection, then close it after
# package selection is done and install has moved to next screen,
# the stockButtons get their state screwed up
#
# for (icon, name, text, func) in self.stockButtons:
# if self.__dict__.has_key(name):
# self.__dict__[name].set_sensitive(self.relnotes_buttonstate[name])
return
def releaseClicked (self, widget):
self.textWin = gtk.Dialog(parent=mainWindow, flags=gtk.DIALOG_MODAL)
#
# XXX - disabling this behavior for now due to bug where if you pop up
# release notes during package selection, then close it after
# package selection is done and install has moved to next screen,
# the stockButtons get their state screwed up
# self.relnotes_buttonstate={}
# for (icon, name, text, func) in self.stockButtons:
# if self.__dict__.has_key(name):
# self.relnotes_buttonstate[name] = self.__dict__[name].get_property("sensitive")
# self.__dict__[name].set_sensitive(gtk.FALSE)
table = gtk.Table(3, 3, gtk.FALSE)
self.textWin.vbox.pack_start(table)
self.textWin.add_button('gtk-close', gtk.RESPONSE_NONE)
self.textWin.connect("response", self.relnotes_closed)
vbox1 = gtk.VBox ()
vbox1.set_border_width (10)
frame = gtk.Frame (_("Release Notes"))
frame.add(vbox1)
frame.set_label_align (0.5, 0.5)
frame.set_shadow_type (gtk.SHADOW_NONE)
self.textWin.set_position (gtk.WIN_POS_CENTER)
if self.releaseNotesBuffer:
text = TextViewBrowser()
text.set_buffer(self.releaseNotesBuffer)
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
sw.set_shadow_type(gtk.SHADOW_IN)
sw.add(text)
vbox1.pack_start(sw)
a = gtk.Alignment (0, 0, 1.0, 1.0)
a.add (frame)
self.textWin.set_default_size (635, 393)
self.textWin.set_size_request (635, 393)
self.textWin.set_position (gtk.WIN_POS_CENTER)
table.attach (a, 1, 2, 1, 2,
gtk.FILL | gtk.EXPAND,
gtk.FILL | gtk.EXPAND, 5, 5)
self.textWin.set_border_width(0)
addFrame(self.textWin, _("Release Notes"))
self.textWin.show_all()
else:
self.textWin.set_position (gtk.WIN_POS_CENTER)
label = gtk.Label(_("Unable to load file!"))
table.attach (label, 1, 2, 1, 2,
gtk.FILL | gtk.EXPAND, gtk.FILL | gtk.EXPAND, 5, 5)
self.textWin.set_border_width(0)
addFrame(self.textWin)
self.textWin.show_all()
def loadReleaseNotes(self):
langList = self.langSearchPath + [ "" ]
sourcepath = self.dispatch.method.getSourcePath()
suffixList = []
for lang in langList:
if lang:
suffixList.append("-%s.html" % (lang,))
suffixList.append(".%s" % (lang,))
else:
suffixList.append(".html")
suffixList.append("")
for suffix in suffixList:
fn = "%s/RELEASE-NOTES%s" % (sourcepath, suffix)
if os.access(fn, os.R_OK):
file = open(fn, "r")
if suffix.endswith('.html'):
buffer = htmlbuffer.HTMLBuffer()
buffer.feed(file.read())
self.releaseNotesBuffer = buffer.get_buffer()
else:
buffer = gtk.TextBuffer(None)
buffer.set_text(file.read())
self.releaseNotesBuffer = buffer
file.close()
return
buffer = gtk.TextBuffer(None)
buffer.set_text(_("Release notes are missing.\n"))
self.releaseNotesBuffer = buffer
def handleRenderCallback(self):
self.currentWindow.renderCallback()
if flags.autostep:
self.nextClicked()
else:
gtk.idle_remove(self.handle)
def setScreen (self):
(step, args) = self.dispatch.currentStep()
if step is None:
gtk.mainquit()
return
if not stepToClass[step]:
if self.dir == 1:
return self.nextClicked()
else:
return self.prevClicked()
(file, className) = stepToClass[step]
newScreenClass = None
s = "from %s import %s; newScreenClass = %s" % (file, className,
className)
while 1:
try:
exec s
break
except ImportError, e:
print e
win = MessageWindow(_("Error!"),
_("An error occurred when attempting "
"to load an installer interface "
"component.\n\nclassName = %s") % (className,),
type="custom", custom_icon="warning",
custom_buttons=[_("_Exit"),
_("_Retry")])
if not win.getrc():
MessageWindow(_("Rebooting System"),
_("Your system will now be rebooted..."),
type="custom",
custom_icon="warning",
custom_buttons=[_("_Reboot")])
sys.exit(0)
ics = InstallControlState (self)
ics.setPrevEnabled(self.dispatch.canGoBack())
self.destroyCurrentWindow()
self.currentWindow = newScreenClass(ics)
new_screen = apply(self.currentWindow.getScreen, args)
if not new_screen:
return
self.update (ics)
self.installFrame.set_label(ics.getTitle ())
self.installFrame.add(new_screen)
self.installFrame.show_all()
self.handle = gtk.idle_add(self.handleRenderCallback)
if self.reloadRcQueued:
self.window.reset_rc_styles()
self.reloadRcQueued = 0
if self.displayHelp:
self.refreshHelp()
def destroyCurrentWindow(self):
children = self.installFrame.get_children ()
if children:
child = children[0]
self.installFrame.remove (child)
child.destroy ()
self.currentWindow = None
def update (self, ics):
self.installFrame.set_label (ics.getTitle ())
prevButton = self.prevButtonStock
nextButton = self.nextButtonStock
if ics.getNextButton():
(icon, text) = ics.getNextButton()
button = gtk.Button()
box = gtk.HBox(gtk.FALSE, 0)
image = gtk.Image()
image.set_from_stock(icon, gtk.ICON_SIZE_BUTTON)
box.pack_start(image, gtk.FALSE, gtk.FALSE)
label = gtk.Label(_(text))
label.set_property("use-underline", gtk.TRUE)
box.pack_start(label, gtk.TRUE, gtk.TRUE)
button.add(box)
button.connect("clicked", self.nextClicked)
button.show_all()
button.label = label
nextButton = button
children = self.buttonBox.get_children()
if not nextButton in children and self.nextButtonStock in children:
pos = children.index(self.nextButtonStock)
self.buttonBox.remove(self.nextButtonStock)
self.buttonBox.pack_end(nextButton)
self.buttonBox.reorder_child(nextButton, pos)
self.nextButtonStock = nextButton
prevButton.set_sensitive (ics.getPrevEnabled ())
nextButton.set_sensitive (ics.getNextEnabled ())
self.hideHelpButton.set_sensitive (ics.getHelpButtonEnabled ())
self.showHelpButton.set_sensitive (ics.getHelpButtonEnabled ())
if ics.getHelpEnabled () == gtk.FALSE:
if self.displayHelp:
self.helpClicked (self.hideHelpButton, 1)
elif ics.getHelpEnabled () == gtk.TRUE:
if not self.displayHelp:
self.helpClicked (self.showHelpButton, 1)
if (ics.getGrabNext ()):
nextButton.grab_focus ()
def __init__ (self, ii, dispatch, locale):
self.prevButtonStock = None
self.nextButtonStock = None
self.releaseButton = None
self.showHelpButton = None
self.hideHelpButton = None
self.debugButton = None
self.stockButtons = (('gtk-go-back', "prevButtonStock",
N_("_Back"), self.prevClicked),
('gtk-go-forward', "nextButtonStock",
N_("_Next"), self.nextClicked),
('gtk-new', "releaseButton",
N_("_Release Notes"), self.releaseClicked),
('gtk-help', "showHelpButton",
N_("Show _Help"), self.helpClicked),
('gtk-help', "hideHelpButton",
N_("Hide _Help"), self.helpClicked),
('gtk-execute', 'debugButton',
N_("_Debug"), self.debugClicked))
self.reloadRcQueued = 0
self.ii = ii
self.dispatch = dispatch
self.setLanguage(locale)
self.handle = None
def keyRelease (self, window, event):
if ((event.keyval == gtk.keysyms.KP_Delete
or event.keyval == gtk.keysyms.Delete)
and (event.state & (gtk.gdk.CONTROL_MASK | gtk.gdk.MOD1_MASK))):
gtk.mainquit()
os._exit(0)
# XXX hack: remove me when the accelerators work again.
elif (event.keyval == gtk.keysyms.F12
and self.currentWindow.getICS().getNextEnabled()):
self.nextClicked()
elif (event.keyval == gtk.keysyms.Print
and event.state & gtk.gdk.SHIFT_MASK):
takeScreenShot()
def buildStockButtons(self):
for (icon, item, text, action) in self.stockButtons:
button = gtk.Button()
box = gtk.HBox(gtk.FALSE, 0)
image = gtk.Image()
image.set_from_stock(icon, gtk.ICON_SIZE_BUTTON)
box.pack_start(image, gtk.FALSE, gtk.FALSE)
label = gtk.Label(_(text))
label.set_property("use-underline", gtk.TRUE)
box.pack_start(label, gtk.TRUE, gtk.TRUE)
button.add(box)
button.connect("clicked", action)
button.show_all()
button.label = label
self.__dict__[item] = button
def updateStockButtons(self):
for (icon, item, text, action) in self.stockButtons:
button = self.__dict__[item]
for child in button.get_children():
button.remove(child)
# FIXME: this is cut and pasted from above; make a nicer
# function that knows how to replace the contents in the
# button for a future release
box = gtk.HBox(gtk.FALSE, 0)
image = gtk.Image()
image.set_from_stock(icon, gtk.ICON_SIZE_BUTTON)
box.pack_start(image, gtk.FALSE, gtk.FALSE)
label = gtk.Label(_(text))
label.set_property("use-underline", gtk.TRUE)
box.pack_start(label, gtk.TRUE, gtk.TRUE)
button.add(box)
button.show_all()
button.label = label
button.queue_resize()
def findPixmap(self, file):
for path in ("/mnt/source/" + productSite + "/RHupdates/pixmaps/",
"/mnt/source/" + productSite + "/RHupdates/",
"/tmp/updates/pixmaps/", "/tmp/updates/",
"/mnt/source/RHupdates/pixmaps/",
"/mnt/source/RHupdates/",
"/tmp/product/pixmaps/", "/tmp/product/",
"/usr/share/anaconda/pixmaps/", "pixmaps/",
"/usr/share/pixmaps/",
"/usr/share/anaconda/", ""):
fn = path + file
if os.access(fn, os.R_OK):
return fn
return None
def setup_window (self, runres):
self.window = gtk.Window ()
global mainWindow
mainWindow = self.window
self.window.set_events (gtk.gdk.KEY_RELEASE_MASK)
if runres == '640x480':
self.window.set_default_size (640, 480)
self.window.set_size_request (640, 480)
else:
self.window.set_default_size (800, 600)
self.window.set_size_request (800, 600)
self.window.set_border_width (10)
title = _("%s Installer") % (productName,)
if os.environ["DISPLAY"][:1] != ':':
# from gnome.zvt import *
# zvtwin = gtk.Window ()
# shtitle = _("Red Hat Linux Install Shell")
try:
f = open ("/tmp/netinfo", "r")
except:
pass
else:
lines = f.readlines ()
f.close ()
for line in lines:
netinf = string.splitfields (line, '=')
if netinf[0] == "HOSTNAME":
title = _("%s Installer on %s") % (productName, string.strip (netinf[1]))
# shtitle = _("Red Hat Linux Install Shell on %s") % string.strip (netinf[1])
break
# zvtwin.set_title (shtitle)
# zvt = ZvtTerm (80, 24)
# if zvt.forkpty() == 0:
# os.execv ("/bin/sh", [ "/bin/sh" ])
# zvt.show ()
# zvtwin.add (zvt)
# zvtwin.show_all ()
self.window.set_title (title)
self.window.set_position (gtk.WIN_POS_CENTER)
self.window.set_border_width(0)
vbox = gtk.VBox (gtk.FALSE, 10)
image = self.configFileData["TitleBar"]
pixbuf = None
# Create header at the top of the installer
if runres != '640x480':
fn = self.findPixmap(image)
if not fn:
log("unable to load %s", image)
else :
pixbuf = gtk.gdk.pixbuf_new_from_file(fn)
if pixbuf:
p = gtk.Image()
p.set_from_pixbuf(pixbuf)
a = gtk.Alignment()
a.set(0.5, 0.5, 1.0, 1.0)
a.add(p)
vbox.pack_start(a, gtk.FALSE, gtk.TRUE, 0)
else:
print _("Unable to load title bar")
self.loadReleaseNotes()
vbox.set_spacing(0)
self.buttonBox = gtk.HButtonBox ()
self.buttonBox.set_layout (gtk.BUTTONBOX_END)
self.buttonBox.set_spacing (30)
self.buildStockButtons()
group = gtk.AccelGroup()
self.window.add_accel_group(group)
self.nextButtonStock.add_accelerator('clicked', group,
gtk.keysyms.F12,
gtk.gdk.RELEASE_MASK, 0);
# set up ctrl+alt+delete handler
self.window.connect ("key-release-event", self.keyRelease)
if DEBUG:
self.buttonBox.add (self.debugButton)
self.buttonBox.add (self.prevButtonStock)
self.buttonBox.add (self.nextButtonStock)
self.hbox = gtk.HBox ()
self.hbox.set_border_width(5)
self.hbox.pack_start (self.hideHelpButton, gtk.FALSE)
self.hbox.set_spacing (25)
self.hbox.pack_start (self.releaseButton, gtk.FALSE)
self.hbox.pack_start (self.buttonBox)
vbox.pack_end (self.hbox, gtk.FALSE)
self.help = TextViewBrowser()
self.displayHelp = gtk.TRUE
self.helpState = gtk.TRUE
self.helpFrame = gtk.Frame (_("Online Help"))
self.box = gtk.VBox (gtk.FALSE, 0)
self.box.set_spacing(0)
self.help_sw = gtk.ScrolledWindow()
self.help_sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.help_sw.set_shadow_type(gtk.SHADOW_IN)
self.help_sw.add(self.help)
self.box.pack_start(self.help_sw, gtk.TRUE)
self.helpFrame.add (self.box)
table = gtk.Table (1, 3, gtk.TRUE)
table.attach (self.helpFrame, 0, 1, 0, 1,
gtk.FILL | gtk.EXPAND,
gtk.FILL | gtk.EXPAND)
self.installFrame = gtk.Frame ()
self.windowList = []
#self.setStateList (self.steps, 0)
self.setScreen ()
table.attach (self.installFrame, 1, 3, 0, 1,
gtk.FILL | gtk.EXPAND,
gtk.FILL | gtk.EXPAND)
table.set_col_spacing (0, 5)
self.bin = gtk.Frame ()
self.bin.set_shadow_type (gtk.SHADOW_NONE)
self.bin.add (table)
vbox.pack_end (self.bin, gtk.TRUE, gtk.TRUE)
self.table = table
self.window.add (vbox)
# Popup the ICW and wait for it to wake us back up
self.window.show_all ()
splashScreenPop()
def busyCursorPush(self):
rootPushBusyCursor()
def busyCursorPop(self):
rootPopBusyCursor()
def run (self, runres, configFileData):
self.configFileData = configFileData
self.setup_window(runres)
gtk.main()
class InstallControlState:
def __init__ (self, cw):
self.searchPath = ("/mnt/source/RHupdates",
"./", "/usr/share/anaconda/")
self.cw = cw
self.prevEnabled = 1
self.nextEnabled = 1
self.nextButtonInfo = None
self.helpButtonEnabled = gtk.TRUE
self.title = _("Install Window")
self.html = ""
self.htmlFile = None
self.nextButton = 'gtk-next'
self.prevButton = 'gtk-prev'
self.nextButtonLabel = None
self.prevButtonLabel = None
# Values other than gtk.TRUE or gtk.FALSE don't change the help setting
self.helpEnabled = 3
self.grabNext = 0
def setTitle (self, title):
self.title = title
self.cw.update (self)
def getTitle (self):
return self.title
def setPrevEnabled (self, value):
if value == self.prevEnabled: return
self.prevEnabled = value
self.cw.update (self)
def getPrevEnabled (self):
return self.prevEnabled
def setNextEnabled (self, value):
if value != self.nextEnabled:
self.nextEnabled = value
self.cw.update (self)
def getNextEnabled (self):
return self.nextEnabled
def setHelpButtonEnabled (self, value):
if value == self.helpButtonEnabled: return
self.helpButtonEnabled = value
self.cw.update (self)
def getHelpButtonEnabled (self):
return self.helpButtonEnabled
def findPixmap(self, file):
for path in ("/mnt/source/" + productSite + "/RHupdates/pixmaps/",
"/mnt/source/" + productSite + "/RHupdates/",
"/tmp/updates/pixmaps/", "/tmp/updates/",
"/mnt/source/RHupdates/pixmaps/",
"/mnt/source/RHupdates/",
"/tmp/product/pixmaps/", "/tmp/product/",
"/usr/share/anaconda/pixmaps/", "pixmaps/",
"/usr/share/pixmaps/",
"/usr/share/anaconda/", ""):
fn = path + file
if os.access(fn, os.R_OK):
return fn
return None
def readPixmap (self, file, height = None, width = None):
fn = self.findPixmap(file)
if not fn:
log("unable to load %s", file)
return None
try:
pixbuf = gtk.gdk.pixbuf_new_from_file(fn)
except RuntimeError, msg:
log("unable to read %s: %s", file, msg)
return None
if (height is not None and width is not None
and height != pixbuf.get_height()
and width != pixbuf.get_width()):
sclpix = pixbuf.scale_simple(height, width,
gtk.gdk.INTERP_BILINEAR)
p = gtk.Image()
p.set_from_pixbuf(sclpix)
else:
source = gtk.IconSource()
source.set_pixbuf(pixbuf)
source.set_size(gtk.ICON_SIZE_DIALOG)
source.set_size_wildcarded(gtk.FALSE)
iconset = gtk.IconSet()
iconset.add_source(source)
p = gtk.image_new_from_icon_set(iconset, gtk.ICON_SIZE_DIALOG)
return p
def readPixmapDithered(self, file, height = None, width = None):
fn = self.findPixmap(file)
if not fn:
log("unable to load %s", file)
return None
try:
pixbuf = gtk.gdk.pixbuf_new_from_file(fn)
except RuntimeError, msg:
log("unable to read %s: %s", file, msg)
return None
if (height is not None and width is not None
and height != pixbuf.get_height()
and width != pixbuf.get_width()):
pixbuf = pixbuf.scale_simple(height, width,
gtk.gdk.INTERP_BILINEAR)
(pixmap, mask) = pixbuf.render_pixmap_and_mask()
pixbuf.render_to_drawable(pixmap, gtk.gdk.GC(pixmap), 0, 0, 0, 0,
pixbuf.get_width(), pixbuf.get_height(),
gtk.gdk.RGB_DITHER_MAX, 0, 0)
p = gtk.Image()
p.set_from_pixmap(pixmap, mask)
return p
def readHTML (self, file):
self.htmlFile = file
def setHTML (self, text):
self.html = text
self.cw.update (self)
def getHTML (self, langPath):
text = None
if self.htmlFile:
file = self.htmlFile
if self.cw.configFileData.has_key("helptag"):
helpTag = "-%s" % (self.cw.configFileData["helptag"],)
else:
helpTag = ""
arch = "-%s" % (iutil.getArch(),)
tags = [ "%s%s" % (helpTag, arch), "%s" % (helpTag,),
"%s" % (arch,), "" ]
found = 0
for path in self.searchPath:
if found:
break
for lang in langPath + ['C']:
if found:
break
for tag in tags:
try:
text = open("%s/help/%s/s1-help-screens-%s%s.html"
% (path, lang, file, tag)).read ()
found = 1
break
except IOError:
continue
if text:
break
if text:
text = text.replace("@RHL@", productName)
text = text.replace("@RHLVER@", productVersion)
return text
print "Unable to read %s help text" % (file,)
return self.html
def setScreenPrev (self):
self.cw.prevClicked ()
def setScreenNext (self):
self.cw.nextClicked ()
def setHelpEnabled (self, value):
self.helpEnabled = value
self.cw.update (self)
def getHelpEnabled (self):
return self.helpEnabled
def setGrabNext (self, value):
self.grabNext = value
self.cw.update (self)
def getGrabNext (self):
return self.grabNext
def getICW (self):
return self.cw
def setNextButton(self, icon, text):
self.nextButtonInfo = (icon, text)
def getNextButton(self):
return self.nextButtonInfo