diff options
-rw-r--r-- | constants.py | 5 | ||||
-rw-r--r-- | exception.py | 273 | ||||
-rwxr-xr-x | gui.py | 139 | ||||
-rw-r--r-- | partedUtils.py | 21 | ||||
-rw-r--r-- | text.py | 127 | ||||
-rw-r--r-- | ui/exn.glade | 18 | ||||
-rw-r--r-- | ui/exnSave.glade | 407 |
7 files changed, 725 insertions, 265 deletions
diff --git a/constants.py b/constants.py index ea101c7da..06f2151ef 100644 --- a/constants.py +++ b/constants.py @@ -23,6 +23,11 @@ DISPATCH_BACK = -1 DISPATCH_FORWARD = 1 DISPATCH_NOOP = None +EXN_OK = 0 +EXN_DEBUG = 1 +EXN_SAVE = 2 +EXN_CANCEL = 3 + # different types of partition requests # REQUEST_PREEXIST is a placeholder for a pre-existing partition on the system # REQUEST_NEW is a request for a partition which will be automatically diff --git a/exception.py b/exception.py index 21a1408f2..06bdcf436 100644 --- a/exception.py +++ b/exception.py @@ -15,6 +15,7 @@ # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # +from constants import * import isys import sys import os @@ -205,69 +206,61 @@ def scpAuthenticate(master, childpid, password): (pid, childstatus) = os.waitpid (childpid, 0) return childstatus -# Returns 0 on success, 1 on cancel, 2 on error. -def copyExceptionToRemote(intf): +# Save the traceback to a remote system via SCP. Returns success or not. +def copyExceptionToRemote(intf, scpInfo): import pty - scpWin = intf.scpWindow() - while 1: - # Bail if they hit the cancel button. - scpWin.run() - scpInfo = scpWin.getrc() - - if scpInfo == None: - scpWin.pop() - return 1 - - (host, path, user, password) = scpInfo - - if host.find(":") != -1: - (host, port) = host.split(":") - - # Try to convert the port to an integer just as a check to see - # if it's a valid port number. If not, they'll get a chance to - # correct the information when scp fails. - try: - int(port) - portArgs = ["-P", port] - except ValueError: - portArgs = [] - else: - portArgs = [] - - # Thanks to Will Woods <wwoods@redhat.com> for the scp control - # here and in scpAuthenticate. - - # Fork ssh into its own pty - (childpid, master) = pty.fork() - if childpid < 0: - log.critical("Could not fork process to run scp") - scpWin.pop() - return 2 - elif childpid == 0: - # child process - run scp - args = ["scp", "-oNumberOfPasswordPrompts=1", - "-oStrictHostKeyChecking=no"] + portArgs + \ - ["/tmp/anacdump.txt", "%s@%s:%s" % (user, host, path)] - os.execvp("scp", args) - - # parent process - try: - childstatus = scpAuthenticate(master, childpid, password) - except OSError: - scpWin.pop() - return 2 + (host, path, user, password) = scpInfo - os.close(master) + if host.find(":") != -1: + (host, port) = host.split(":") - if os.WIFEXITED(childstatus) and os.WEXITSTATUS(childstatus) == 0: - return 0 - else: - scpWin.pop() - return 2 - -def copyExceptionToFloppy (anaconda): - # in test mode have save to floppy option just copy to new name + # Try to convert the port to an integer just as a check to see + # if it's a valid port number. If not, they'll get a chance to + # correct the information when scp fails. + try: + int(port) + portArgs = ["-P", port] + except ValueError: + portArgs = [] + else: + portArgs = [] + + # Thanks to Will Woods <wwoods@redhat.com> for the scp control + # here and in scpAuthenticate. + + # Fork ssh into its own pty + (childpid, master) = pty.fork() + if childpid < 0: + log.critical("Could not fork process to run scp") + return False + elif childpid == 0: + # child process - run scp + args = ["scp", "-oNumberOfPasswordPrompts=1", + "-oStrictHostKeyChecking=no"] + portArgs + \ + ["/tmp/anacdump.txt", "%s@%s:%s" % (user, host, path)] + os.execvp("scp", args) + + # parent process + try: + childstatus = scpAuthenticate(master, childpid, password) + except OSError: + return False + + os.close(master) + + if os.WIFEXITED(childstatus) and os.WEXITSTATUS(childstatus) == 0: + return True + else: + return False + +# Save the traceback to a removable storage device, such as a floppy disk +# or a usb/firewire drive. In the event of a floppy disk, it is assumed to +# be unformatted and safe for us to destroy. For all other devices, it is +# assumed that they are already formatted and we will only attempt to write +# the traceback file to the device. Returns success or not. +def copyExceptionToDisk(anaconda, device): + # in test mode have save to disk option just copy to new name if not flags.setupFilesystems: try: shutil.copyfile("/tmp/anacdump.txt", "/tmp/test-anacdump.txt") @@ -276,51 +269,45 @@ def copyExceptionToFloppy (anaconda): pass anaconda.intf.__del__ () - return 2 + return False - while 1: - # Bail if they hit the cancel button. - rc = anaconda.intf.dumpWindow() - if rc: - return 1 - - device = anaconda.id.floppyDevice - file = "/tmp/floppy" - try: - isys.makeDevInode(device, file) - except SystemError: - pass + file = "/tmp/exndev" + try: + isys.makeDevInode(device, file) + except SystemError: + pass - try: - fd = os.open(file, os.O_RDONLY) - except: - continue + try: + fd = os.open(file, os.O_RDONLY) + except: + return False - os.close(fd) + os.close(fd) - if rhpl.getArch() != "ia64": - cmd = "/usr/sbin/mkdosfs" + # Only format floppy devices, not usb storage devices. + if device in isys.floppyDriveDict().keys() and rhpl.getArch() != "ia64": + cmd = "/usr/sbin/mkdosfs" - if os.access("/sbin/mkdosfs", os.X_OK): - cmd = "/sbin/mkdosfs" + if os.access("/sbin/mkdosfs", os.X_OK): + cmd = "/sbin/mkdosfs" - iutil.execWithRedirect (cmd, ["/tmp/floppy"], stdout = '/dev/tty5', - stderr = '/dev/tty5') + iutil.execWithRedirect (cmd, ["/tmp/floppy"], stdout = '/dev/tty5', + stderr = '/dev/tty5') - try: - isys.mount(device, "/tmp/crash", fstype = "vfat") - except SystemError: - continue + try: + isys.mount(device, "/tmp/crash", fstype = "vfat") + except SystemError: + return False - # copy trace dump we wrote to local storage to floppy - try: - shutil.copyfile("/tmp/anacdump.txt", "/tmp/crash/anacdump.txt") - except: - log.error("Failed to copy anacdump.txt to floppy") - return 2 + # copy trace dump we wrote to local storage to disk + try: + shutil.copyfile("/tmp/anacdump.txt", "/tmp/crash/anacdump.txt") + except: + log.error("Failed to copy anacdump.txt to device %s" % device) + return False - isys.umount("/tmp/crash") - return 0 + isys.umount("/tmp/crash") + return True # Reverse the order that tracebacks are printed so people will hopefully quit # giving us the least useful part of the exception in bug reports. @@ -332,6 +319,54 @@ def formatException (type, value, tb): lst.extend(traceback.format_exception_only(type, value)) return lst +def runSaveDialog(anaconda, longTracebackFile): + saveWin = anaconda.intf.saveExceptionWindow(anaconda, longTracebackFile) + if not saveWin: + anaconda.intf.__del__() + os.kill(os.getpid(), signal.SIGKILL) + + while 1: + saveWin.run() + rc = saveWin.getrc() + + if rc == EXN_OK: + if saveWin.saveToDisk(): + device = saveWin.getDest() + cpSucceeded = copyExceptionToDisk(anaconda, device) + + if cpSucceeded: + anaconda.intf.messageWindow(_("Dump Written"), + _("Your system's state has been successfully written to " + "the disk. The installer will now exit."), + type="custom", custom_icon="info", + custom_buttons=[_("_Exit installer")]) + sys.exit(0) + else: + anaconda.intf.messageWindow(_("Dump Not Written"), + _("There was a problem writing the system state to the " + "disk.")) + continue + else: + scpInfo = saveWin.getDest() + scpSucceeded = copyExceptionToRemote(anaconda.intf, scpInfo) + + if scpSucceeded: + anaconda.intf.messageWindow(_("Dump Written"), + _("Your system's state has been successfully written to " + "the remote host. The installer will now exit."), + type="custom", custom_icon="info", + custom_buttons=[_("_Exit installer")]) + sys.exit(0) + else: + anaconda.intf.messageWindow(_("Dump Not Written"), + _("There was a problem writing the system state to the " + "remote host.")) + continue + elif rc == EXN_CANCEL: + break + + saveWin.pop() + def handleException(anaconda, (type, value, tb)): if isinstance(value, bdb.BdbQuit): sys.exit(1) @@ -363,19 +398,19 @@ def handleException(anaconda, (type, value, tb)): except: pass - win = anaconda.intf.exceptionWindow(text, "/tmp/anacdump.txt") - if not win: + mainWin = anaconda.intf.mainExceptionWindow(text, "/tmp/anacdump.txt") + if not mainWin: anaconda.intf.__del__() os.kill(os.getpid(), signal.SIGKILL) while 1: - win.run() - rc = win.getrc() + mainWin.run() + rc = mainWin.getrc() - if rc == 0: + if rc == EXN_OK: anaconda.intf.__del__ () os.kill(os.getpid(), signal.SIGKILL) - elif rc == 1: + elif rc == EXN_DEBUG: anaconda.intf.__del__ () print text @@ -406,37 +441,5 @@ def handleException(anaconda, (type, value, tb)): import pdb pdb.post_mortem (tb) os.kill(os.getpid(), signal.SIGKILL) - elif rc == 2: - floppyRc = copyExceptionToFloppy(anaconda) - - if floppyRc == 0: - anaconda.intf.messageWindow(_("Dump Written"), - _("Your system's state has been successfully written to " - "the floppy. The installer will now exit."), - type="custom", custom_icon="info", - custom_buttons=[_("_Exit installer")]) - sys.exit(0) - elif floppyRc == 1: - continue - elif floppyRc == 2: - anaconda.intf.messageWindow(_("Dump Not Written"), - _("There was a problem writing the system state to the " - "floppy.")) - continue - elif rc == 3: - scpRc = copyExceptionToRemote(anaconda.intf) - - if scpRc == 0: - anaconda.intf.messageWindow(_("Dump Written"), - _("Your system's state has been successfully written to " - "the remote host. The installer will now exit."), - type="custom", custom_icon="info", - custom_buttons=[_("_Exit installer")]) - sys.exit(0) - elif scpRc == 1: - continue - elif scpRc == 2: - anaconda.intf.messageWindow(_("Dump Not Written"), - _("There was a problem writing the system state to the " - "remote host.")) - continue + elif rc == EXN_SAVE: + runSaveDialog(anaconda, "/tmp/anacdump.txt") @@ -562,33 +562,6 @@ class ProgressWindow: self.window.destroy () rootPopBusyCursor() -class ScpWindow: - def __init__(self, screen=None): - self.scpxml = gtk.glade.XML(findGladeFile("scp.glade"), - domain="anaconda") - self.win = self.scpxml.get_widget("saveRemoteDlg") - - addFrame(self.win) - self.win.show_all() - self.window = self.win - - def getrc(self): - if self.rc == 0: - return None - else: - host = self.scpxml.get_widget("hostEntry") - remotePath = self.scpxml.get_widget("remotePathEntry") - userName = self.scpxml.get_widget("userNameEntry") - password = self.scpxml.get_widget("passwordEntry") - return (host.get_text(), remotePath.get_text(), - userName.get_text(), password.get_text()) - - def run(self): - self.rc = self.window.run() - - def pop(self): - self.window.destroy() - class InstallKeyWindow: def __init__(self, anaconda, key): (keyxml, self.win) = getGladeWidget("instkey.glade", "instkeyDialog") @@ -644,9 +617,79 @@ class InstallKeyWindow: def destroy(self): self.win.destroy() - -class ExceptionWindow: +class SaveExceptionWindow: + def __init__(self, anaconda, longTracebackFile=None, screen=None): + exnxml = gtk.glade.XML(findGladeFile("exnSave.glade"), domain="anaconda") + + self.hostEntry = exnxml.get_widget("hostEntry") + self.destEntry = exnxml.get_widget("destEntry") + self.usernameEntry = exnxml.get_widget("usernameEntry") + self.passwordEntry = exnxml.get_widget("passwordEntry") + + self.diskButton = exnxml.get_widget("diskButton") + self.diskCombo = exnxml.get_widget("diskCombo") + self.remoteButton = exnxml.get_widget("remoteButton") + self.remoteBox = exnxml.get_widget("remoteHBox") + self.win = exnxml.get_widget("saveDialog") + + self.diskButton.connect("toggled", self.diskButton_changed) + + cell = gtk.CellRendererText() + self.diskCombo.pack_start(cell, True) + self.diskCombo.set_attributes(cell, text=1) + + store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) + + dests = anaconda.id.diskset.exceptionDisks(anaconda) + + if len(dests) > 0: + for d in dests: + iter = store.append(None) + store[iter] = (d[0], "/dev/%s - %s" % (d[0], d[1])) + + self.diskCombo.set_model(store) + self.diskCombo.set_active(0) + else: + self.diskButton.set_sensitive(False) + self.remoteButton.set_active(True) + self.diskCombo.set_sensitive(False) + self.remoteBox.set_sensitive(True) + + addFrame(self.win) + self.win.show_all() + self.window = self.win + + def diskButton_changed(self, args): + self.diskCombo.set_sensitive(self.diskButton.get_active()) + self.remoteBox.set_sensitive(not self.diskButton.get_active()) + + def getrc(self): + if self.rc == gtk.RESPONSE_OK: + return EXN_OK + elif self.rc == gtk.RESPONSE_CANCEL: + return EXN_CANCEL + + def getDest(self): + if self.saveToDisk(): + active = self.diskCombo.get_active() + if active < 0: + return None + + return self.diskCombo.get_model()[active][0] + else: + return map(lambda e: e.get_text(), [self.hostEntry, self.destEntry, self.usernameEntry, self.passwordEntry]) + + def pop(self): + self.window.destroy() + + def run(self): + self.rc = self.window.run () + + def saveToDisk(self): + return self.diskButton.get_active() + +class MainExceptionWindow: def __init__ (self, shortTraceback, longTracebackFile=None, screen=None): # Get a bunch of widgets from the XML file. exnxml = gtk.glade.XML(findGladeFile("exn.glade"), domain="anaconda") @@ -669,21 +712,11 @@ class ExceptionWindow: textbuf = gtk.TextBuffer() textbuf.set_text(shortTraceback) - # Remove the debug button since it doesn't work in livecd mode anyway + # Remove the debug button since it doesn't work in livecd mode anyway. if flags.livecdInstall: debugButton = exnxml.get_widget("debugButton") buttonBox.remove(debugButton) - # Remove the floppy button if we don't need it. - if not floppy.hasFloppyDevice() and not flags.debug: - floppyButton = exnxml.get_widget("floppyButton") - buttonBox.remove(floppyButton) - - # Remove the remote button if there's no network. - if not hasActiveNetDev() and not flags.debug: - remoteButton = exnxml.get_widget("remoteButton") - buttonBox.remove(remoteButton) - # If there's an anacdump.txt file, add it to the lower view in the # expander. If not, remove the expander. if longTracebackFile: @@ -708,32 +741,25 @@ class ExceptionWindow: vbox.remove(expander) addFrame(self.win) - self.win.show_all () + self.win.show_all() self.window = self.win def run(self): self.rc = self.window.run () 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 to floppy + return EXN_DEBUG if self.rc == 1: - return 2 - # 2 is OK + return EXN_SAVE elif self.rc == 2: - return 0 - # 3 is save to remote host - elif self.rc == 3: - return 3 - + return EXN_OK + def pop(self): self.window.destroy() @@ -942,13 +968,14 @@ class InstallInterface: d.destroy() return rc - def exceptionWindow(self, shortText, longTextFile): + def mainExceptionWindow(self, shortText, longTextFile): log.critical(shortText) - win = ExceptionWindow (shortText, longTextFile) + win = MainExceptionWindow (shortText, longTextFile) return win - def scpWindow(self): - return ScpWindow() + def saveExceptionWindow(self, anaconda, longTextFile): + win = SaveExceptionWindow (anaconda, longTextFile) + return win def getInstallKey(self, anaconda, key = ""): d = InstallKeyWindow(anaconda, key) diff --git a/partedUtils.py b/partedUtils.py index b2a014cc6..273f37232 100644 --- a/partedUtils.py +++ b/partedUtils.py @@ -1322,7 +1322,28 @@ class DiskSet: return False + def exceptionDisks(self, anaconda, probe=True): + if probe: + self.refreshDevices() + isys.flushDriveDict() + drives = isys.floppyDriveDict().items() + + for d in isys.hardDriveDict().items(): + if isys.driveUsesModule(d[0], ["usb-storage", "ub", "sbp2", "firewire-sbp2"]): + func = lambda p: not p.get_flag(parted.PARTITION_RAID) and not p.get_flag(parted.PARTITION_LVM) and p.fs_type.name in ["ext3", "ext2", "vfat"] + + disk = self.disks[d[0]] + parts = filter_partitions(disk, func) + + if len(parts) == 0: + drives.append(d) + else: + for part in parts: + name = "%s%s" % (part.disk.dev.path, part.num) + drives.append((os.path.basename(name), d[1])) + + return drives # XXX is this all of the possibilities? dosPartitionTypes = [ 1, 6, 7, 11, 12, 14, 15 ] @@ -142,83 +142,95 @@ class ProgressWindow: g.draw() self.screen.refresh() -class ExceptionWindow: - def __init__ (self, shortTraceback, longTracebackFile=None, screen=None): - self.text = "%s\n\n" % shortTraceback +class SaveExceptionWindow: + def __init__(self, anaconda, longTracebackFile=None, screen=None): + self.anaconda = anaconda + self.text = "OH NOES!\n\n" self.screen = screen - self.buttons=[TEXT_OK_BUTTON] - - if floppy.hasFloppyDevice() or flags.debug: - self.buttons.append(_("Save")) - - if hasActiveNetDev() or flags.debug: - self.buttons.append(_("Remote")) - - if not flags.livecdInstall: - self.buttons.append(_("Debug")) - - def run(self): - log.info ("in run, screen = %s" % self.screen) - self.rc = ButtonChoiceWindow(self.screen, _("Exception Occurred"), - self.text, self.buttons) - def getrc(self): - if self.rc == string.lower(_("Debug")): - return 1 - elif self.rc == string.lower(_("Save")): - return 2 - elif self.rc == string.lower(_("Remote")): - return 3 + if self.rc == TEXT_OK_CHECK: + return EXN_OK + elif self.rc == TEXT_CANCEL_CHECK: + return EXN_CANCEL + + def getDest(self): + if self.saveToDisk(): + return self.diskList.current() else: - return 0 + return map(lambda e: e.value(), [self.hostEntry, self.destEntry, self.usernameEntry, self.passwordEntry]) def pop(self): self.screen.popWindow() - self.screen.refresh() - -class ScpWindow: - def __init__(self, screen=None): - self.screen = screen - pass + self.screen.refresh() def run(self): + toplevel = GridForm(self.screen, _("Save"), 1, 5) + + self.rg = RadioGroup() + diskButton = self.rg.add(_("Save to Disk"), "disk", True) + remoteButton = self.rg.add(_("Save to Remote"), "remote", False) + buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON]) self.hostEntry = Entry(24) - self.pathEntry = Entry(24) + self.destEntry = Entry(24) self.usernameEntry = Entry(24) self.passwordEntry = Entry(24, password=1) - win = GridForm(self.screen, _("Save to Remote Host"), 1, 2) + diskList = Listbox(height=3, scroll=1) + for (dev, desc) in self.anaconda.id.diskset.exceptionDisks(self.anaconda): + distList.append("/dev/%s - %s" % (dev, desc), dev) + + diskList.setCurrent(0) + + remoteGrid = Grid(2, 4) + remoteGrid.setField(Label(_("Host")), 0, 0, anchorLeft=1) + remoteGrid.setField(self.hostEntry, 1, 0) + remoteGrid.setField(Label(_("Remote path")), 0, 1, anchorLeft=1) + remoteGrid.setField(self.destEntry, 1, 1) + remoteGrid.setField(Label(_("User name")), 0, 2, anchorLeft=1) + remoteGrid.setField(self.usernameEntry, 1, 2) + remoteGrid.setField(Label(_("Password")), 0, 3, anchorLeft=1) + remoteGrid.setField(self.passwordEntry, 1, 3) + + toplevel.add(diskButton, 0, 0, (0, 0, 0, 1)) + toplevel.add(diskList, 0, 1, (0, 0, 0, 1)) + toplevel.add(remoteButton, 0, 2, (0, 0, 0, 1)) + toplevel.add(remoteGrid, 0, 3, (0, 0, 0, 1)) + toplevel.add(buttons, 0, 4, growx=1) + + result = toplevel.run() + self.rc = buttons.buttonPressed(result) - subgrid = Grid(2, 4) - subgrid.setField(Label(_("Host")), 0, 0, anchorLeft=1) - subgrid.setField(self.hostEntry, 1, 0) - subgrid.setField(Label(_("Remote path")), 0, 1, anchorLeft=1) - subgrid.setField(self.pathEntry, 1, 1) - subgrid.setField(Label(_("User name")), 0, 2, anchorLeft=1) - subgrid.setField(self.usernameEntry, 1, 2) - subgrid.setField(Label(_("Password")), 0, 3, anchorLeft=1) - subgrid.setField(self.passwordEntry, 1, 3) + def saveToDisk(self): + return self.rg.getSelection() == "disk" - win.add(subgrid, 0, 0, (0, 0, 0, 1)) - win.add(buttons, 0, 1) +class MainExceptionWindow: + def __init__ (self, shortTraceback, longTracebackFile=None, screen=None): + self.text = "%s\n\n" % shortTraceback + self.screen = screen - result = win.run() - self.rc = buttons.buttonPressed(result) + self.buttons=[TEXT_OK_BUTTON] + + if not flags.livecdInstall: + self.buttons.append(_("Debug")) + + def run(self): + log.info ("in run, screen = %s" % self.screen) + self.rc = ButtonChoiceWindow(self.screen, _("Exception Occurred"), + self.text, self.buttons) def getrc(self): - if self.rc == TEXT_CANCEL_CHECK: - return None - elif self.rc == TEXT_OK_CHECK: - retval = (self.hostEntry.value(), self.pathEntry.value(), - self.usernameEntry.value(), self.passwordEntry.value()) - return retval + if self.rc == string.lower(_("Debug")): + return EXN_DEBUG + elif self.rc == string.lower(_("Save")): + return EXN_SAVE + else: + return EXN_OK def pop(self): self.screen.popWindow() self.screen.refresh() - pass class InstallInterface: def helpWindow(self, screen, key): @@ -422,12 +434,9 @@ class InstallInterface: return 0 - def scpWindow(self): - return ScpWindow(self.screen) - - def exceptionWindow(self, shortText, longTextFile): + def mainExceptionWindow(self, shortText, longTextFile): log.critical(shortText) - exnWin = ExceptionWindow(shortText, longTextFile, self.screen) + exnWin = MainExceptionWindow(shortText, longTextFile, self.screen) return exnWin def partedExceptionWindow(self, exc): diff --git a/ui/exn.glade b/ui/exn.glade index 2a69affce..a41bbf8dd 100644 --- a/ui/exn.glade +++ b/ui/exn.glade @@ -34,23 +34,11 @@ <property name="layout_style">GTK_BUTTONBOX_END</property> <child> - <widget class="GtkButton" id="remoteButton"> + <widget class="GtkButton" id="saveButton"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">Save to _Remote</property> - <property name="use_underline">True</property> - <property name="relief">GTK_RELIEF_NORMAL</property> - <property name="focus_on_click">True</property> - <property name="response_id">3</property> - </widget> - </child> - - <child> - <widget class="GtkButton" id="floppyButton"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="label" translatable="yes">_Save to floppy</property> - <property name="use_underline">True</property> + <property name="label">gtk-save</property> + <property name="use_stock">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> <property name="response_id">1</property> diff --git a/ui/exnSave.glade b/ui/exnSave.glade new file mode 100644 index 000000000..15932e57f --- /dev/null +++ b/ui/exnSave.glade @@ -0,0 +1,407 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkDialog" id="saveDialog"> + <property name="visible">True</property> + <property name="title" translatable="yes">Save</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_CENTER</property> + <property name="modal">True</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="decorated">True</property> + <property name="skip_taskbar_hint">False</property> + <property name="skip_pager_hint">False</property> + <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> + <property name="gravity">GDK_GRAVITY_NORTH_WEST</property> + <property name="focus_on_map">True</property> + <property name="urgency_hint">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="cancelbutton1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-6</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="okbutton1"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-ok</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="response_id">-5</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">Select a destination for the exception information.</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="xpad">0</property> + <property name="ypad">5</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="diskButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Disk</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">True</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">0</property> + <property name="bottom_padding">0</property> + <property name="left_padding">10</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkComboBox" id="diskCombo"> + <property name="visible">True</property> + <property name="add_tearoffs">False</property> + <property name="focus_on_click">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">3</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkRadioButton" id="remoteButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">_Remote</property> + <property name="use_underline">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="focus_on_click">True</property> + <property name="active">False</property> + <property name="inconsistent">False</property> + <property name="draw_indicator">True</property> + <property name="group">diskButton</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">1</property> + <property name="yscale">1</property> + <property name="top_padding">0</property> + <property name="bottom_padding">0</property> + <property name="left_padding">10</property> + <property name="right_padding">0</property> + + <child> + <widget class="GtkHBox" id="remoteHBox"> + <property name="visible">True</property> + <property name="sensitive">False</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label">Host (host:port)</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label">Destination file</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label">User name</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="label">Password</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property> + <property name="width_chars">-1</property> + <property name="single_line_mode">False</property> + <property name="angle">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="border_width">5</property> + <property name="visible">True</property> + <property name="homogeneous">True</property> + <property name="spacing">5</property> + + <child> + <widget class="GtkEntry" id="hostEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="destEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="usernameEntry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">True</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="passwordEntry"> + <property name="can_focus">True</property> + <property name="editable">True</property> + <property name="visibility">False</property> + <property name="max_length">0</property> + <property name="text" translatable="yes"></property> + <property name="has_frame">True</property> + <property name="invisible_char">•</property> + <property name="activates_default">False</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> |