diff options
author | Chris Lumens <clumens@redhat.com> | 2008-07-22 13:05:42 -0400 |
---|---|---|
committer | Chris Lumens <clumens@redhat.com> | 2008-07-22 15:59:01 -0400 |
commit | dc1d8a5dacf62d640f6e01bea665b97243e63b11 (patch) | |
tree | 330df8457d24e5217d1ac88cd3b7c82e1fdd295f | |
parent | 1b632ee2e4c64148a942db567f4e4ef6de6af571 (diff) | |
download | anaconda-dc1d8a5dacf62d640f6e01bea665b97243e63b11.tar.gz anaconda-dc1d8a5dacf62d640f6e01bea665b97243e63b11.tar.xz anaconda-dc1d8a5dacf62d640f6e01bea665b97243e63b11.zip |
Add support for saving via scp back in.
-rw-r--r-- | exception.py | 86 | ||||
-rwxr-xr-x | gui.py | 38 | ||||
-rw-r--r-- | text.py | 89 | ||||
-rw-r--r-- | ui/exnSave.glade | 268 |
4 files changed, 440 insertions, 41 deletions
diff --git a/exception.py b/exception.py index 4572eefb7..a363c1d7e 100644 --- a/exception.py +++ b/exception.py @@ -227,6 +227,76 @@ class AnacondaExceptionDump: self.dump(fd, anaconda) fd.close() +def scpAuthenticate(master, childpid, password): + while 1: + # Read up to password prompt. Propagate OSError exceptions, which + # can occur for anything that causes scp to immediately die (bad + # hostname, host down, etc.) + buf = os.read(master, 4096) + if buf.lower().find("password: ") != -1: + os.write(master, password+"\n") + # read the space and newline that get echoed back + os.read(master, 2) + break + + while 1: + buf = "" + try: + buf = os.read(master, 4096) + except (OSError, EOFError): + break + + (pid, childstatus) = os.waitpid (childpid, 0) + return childstatus + +# Save the traceback to a remote system via SCP. Returns success or not. +def copyExceptionToRemote(intf, scpInfo): + import pty + + (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") + 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. If there's no filesystem on the disk/partition, # write a vfat one. @@ -416,6 +486,22 @@ def runSaveDialog(anaconda, exn): _("There was a problem writing the system state to the " "disk.")) continue + elif saveWin.saveToRemote(): + 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 else: if not saveToBugzilla(anaconda, exn, saveWin.getDest()): continue @@ -730,23 +730,31 @@ class SaveExceptionWindow: def __init__(self, anaconda, longTracebackFile=None, screen=None): exnxml = gtk.glade.XML(findGladeFile("exnSave.glade"), domain="anaconda") - self.usernameEntry = exnxml.get_widget("usernameEntry") - self.passwordEntry = exnxml.get_widget("passwordEntry") + self.bugzillaNameEntry = exnxml.get_widget("bugzillaNameEntry") + self.bugzillaPasswordEntry = exnxml.get_widget("bugzillaPasswordEntry") self.bugDesc = exnxml.get_widget("bugDesc") + self.scpNameEntry = exnxml.get_widget("scpNameEntry") + self.scpPasswordEntry = exnxml.get_widget("scpPasswordEntry") + self.scpHostEntry = exnxml.get_widget("scpHostEntry") + self.scpDestEntry = exnxml.get_widget("scpDestEntry") + 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.bugzillaButton = exnxml.get_widget("bugzillaButton") + self.bugzillaBox = exnxml.get_widget("bugzillaHBox") + self.scpButton = exnxml.get_widget("scpButton") + self.scpBox = exnxml.get_widget("scpHBox") self.localButton = exnxml.get_widget("localButton") self.localChooser = exnxml.get_widget("localChooser") self.win = exnxml.get_widget("saveDialog") self.diskButton.connect("toggled", self.radio_changed) - self.remoteButton.connect("toggled", self.radio_changed) + self.bugzillaButton.connect("toggled", self.radio_changed) self.localButton.connect("toggled", self.radio_changed) + self.scpButton.connect("toggled", self.radio_changed) - self.remoteButton.set_label(self.remoteButton.get_label() % product.bugUrl) + self.bugzillaButton.set_label(self.bugzillaButton.get_label() % product.bugUrl) cell = gtk.CellRendererText() self.diskCombo.pack_start(cell, True) @@ -769,9 +777,9 @@ class SaveExceptionWindow: self.diskCombo.set_active(0) else: self.diskButton.set_sensitive(False) - self.remoteButton.set_active(True) + self.bugzillaButton.set_active(True) self.diskCombo.set_sensitive(False) - self.remoteBox.set_sensitive(True) + self.bugzillaBox.set_sensitive(True) addFrame(self.win) self.win.show() @@ -779,8 +787,9 @@ class SaveExceptionWindow: def radio_changed(self, args): self.diskCombo.set_sensitive(self.diskButton.get_active()) - self.remoteBox.set_sensitive(self.remoteButton.get_active()) + self.bugzillaBox.set_sensitive(self.bugzillaButton.get_active()) self.localChooser.set_sensitive(self.localButton.get_active()) + self.scpBox.set_sensitive(self.scpButton.get_active()) def getrc(self): if self.rc == gtk.RESPONSE_OK: @@ -797,8 +806,14 @@ class SaveExceptionWindow: return self.diskCombo.get_model()[active][0] elif self.saveToLocal(): return self.localChooser.get_filename() + elif self.saveToRemote(): + return map(lambda e: e.get_text(), [self.scpNameEntry, + self.scpPasswordEntry, + self.hostEntry, + self.destEntry]) else: - return map(lambda e: e.get_text(), [self.usernameEntry, self.passwordEntry, + return map(lambda e: e.get_text(), [self.bugzillaNameEntry, + self.bugzillaPasswordEntry, self.bugDesc]) def pop(self): @@ -813,6 +828,9 @@ class SaveExceptionWindow: def saveToLocal(self): return self.localButton.get_active() + def saveToRemote(self): + return self.scpButton.get_active() + class MessageWindow: def getrc (self): return self.rc @@ -156,13 +156,29 @@ class SaveExceptionWindow: def _destCb(self, *args): if self.rg.getSelection() == "disk": - self.usernameEntry.setFlags(FLAG_DISABLED, FLAGS_SET) - self.passwordEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.bugzillaNameEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.bugzillaPasswordEntry.setFlags(FLAG_DISABLED, FLAGS_SET) self.bugDesc.setFlags(FLAG_DISABLED, FLAGS_SET) + self.scpNameEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.scpPasswordEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.scpHostEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.scpDestEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + elif self.rg.getSelection() == "remote": + self.bugzillaNameEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.bugzillaPasswordEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.bugDesc.setFlags(FLAG_DISABLED, FLAGS_SET) + self.scpNameEntry.setFlags(FLAG_DISABLED, FLAGS_RESET) + self.scpPasswordEntry.setFlags(FLAG_DISABLED, FLAGS_RESET) + self.scpHostEntry.setFlags(FLAG_DISABLED, FLAGS_RESET) + self.scpDestEntry.setFlags(FLAG_DISABLED, FLAGS_RESET) else: - self.usernameEntry.setFlags(FLAG_DISABLED, FLAGS_RESET) - self.passwordEntry.setFlags(FLAG_DISABLED, FLAGS_RESET) + self.bugzillaNameEntry.setFlags(FLAG_DISABLED, FLAGS_RESET) + self.bugzillaPasswordEntry.setFlags(FLAG_DISABLED, FLAGS_RESET) self.bugDesc.setFlags(FLAG_DISABLED, FLAGS_RESET) + self.scpNameEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.scpPasswordEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.scpHostEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.scpDestEntry.setFlags(FLAG_DISABLED, FLAGS_SET) def getrc(self): if self.rc == TEXT_OK_CHECK: @@ -173,8 +189,14 @@ class SaveExceptionWindow: def getDest(self): if self.saveToDisk(): return self.diskList.current() + elif self.saveToRemote(): + return map(lambda e: e.value(), [self.scpNameEntry, + self.scpPasswordEntry, + self.scpHostEntry, + self.scpDestEntry]) else: - return map(lambda e: e.value(), [self.usernameEntry, self.passwordEntry, + return map(lambda e: e.value(), [self.bugzillaNameEntry, + self.bugzillaPasswordEntry, self.bugDesc]) def pop(self): @@ -182,35 +204,54 @@ class SaveExceptionWindow: self.screen.refresh() def run(self): - toplevel = GridForm(self.screen, _("Save"), 1, 5) + toplevel = GridForm(self.screen, _("Save"), 1, 7) self.rg = RadioGroup() - self.diskButton = self.rg.add(_("Save to Disk"), "disk", True) - self.remoteButton = self.rg.add(_("Save to Remote (%s)") % product.bugUrl, "remote", False) + self.diskButton = self.rg.add(_("Save to local disk"), "disk", True) + self.bugzillaButton = self.rg.add(_("Send to bugzilla (%s)") % product.bugUrl, "bugzilla", False) + self.remoteButton = self.rg.add(_("Send to remote server (scp)"), "remote", False) self.diskButton.setCallback(self._destCb, None) + self.bugzillaButton.setCallback(self._destCb, None) self.remoteButton.setCallback(self._destCb, None) buttons = ButtonBar(self.screen, [TEXT_OK_BUTTON, TEXT_CANCEL_BUTTON]) - self.usernameEntry = Entry(24) - self.passwordEntry = Entry(24, password=1) + self.bugzillaNameEntry = Entry(24) + self.bugzillaPasswordEntry = Entry(24, password=1) self.bugDesc = Entry(24) self.diskList = Listbox(height=3, scroll=1) - remoteGrid = Grid(2, 3) + bugzillaGrid = Grid(2, 3) + bugzillaGrid.setField(Label(_("User name")), 0, 0, anchorLeft=1) + bugzillaGrid.setField(self.bugzillaNameEntry, 1, 0) + bugzillaGrid.setField(Label(_("Password")), 0, 1, anchorLeft=1) + bugzillaGrid.setField(self.bugzillaPasswordEntry, 1, 1) + bugzillaGrid.setField(Label(_("Bug Description")), 0, 2, anchorLeft=1) + bugzillaGrid.setField(self.bugDesc, 1, 2) + + self.remoteNameEntry = Entry(24) + self.remotePasswordEntry = Entry(24, password=1) + self.remoteHostEntry = Entry(24) + self.remoteDestEntry = Entry(24) + + remoteGrid = Grid(2, 4) remoteGrid.setField(Label(_("User name")), 0, 0, anchorLeft=1) - remoteGrid.setField(self.usernameEntry, 1, 0) + remoteGrid.setField(self.remoteNameEntry, 1, 0) remoteGrid.setField(Label(_("Password")), 0, 1, anchorLeft=1) - remoteGrid.setField(self.passwordEntry, 1, 1) - remoteGrid.setField(Label(_("Bug Description")), 0, 2, anchorLeft=1) - remoteGrid.setField(self.bugDesc, 1, 2) + remoteGrid.setField(self.remotePasswordEntry, 1, 1) + remoteGrid.setField(Label(_("Host (host:port)")), 0, 2, anchorLeft=1) + remoteGrid.setField(self.remoteHostEntry, 1, 2) + remoteGrid.setField(Label(_("Destination file")), 0, 3, anchorLeft=1) + remoteGrid.setField(self.remoteDestEntry, 1, 3) toplevel.add(self.diskButton, 0, 0, (0, 0, 0, 1)) toplevel.add(self.diskList, 0, 1, (0, 0, 0, 1)) - toplevel.add(self.remoteButton, 0, 2, (0, 0, 0, 1)) - toplevel.add(remoteGrid, 0, 3, (0, 0, 0, 1)) - toplevel.add(buttons, 0, 4, growx=1) + toplevel.add(self.bugzillaButton, 0, 2, (0, 0, 0, 1)) + toplevel.add(bugzillaGrid, 0, 3, (0, 0, 0, 1)) + toplevel.add(self.remoteButton, 0, 4, (0, 0, 0, 1)) + toplevel.adD(remoteGrid, 0, 5, (0, 0, 0, 1)) + toplevel.add(buttons, 0, 6, growx=1) dests = self.anaconda.id.diskset.exceptionDisks(self.anaconda) @@ -220,22 +261,26 @@ class SaveExceptionWindow: # self.diskList.setCurrent("sda") - self.usernameEntry.setFlags(FLAG_DISABLED, FLAGS_SET) - self.passwordEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.bugzillaNameEntry.setFlags(FLAG_DISABLED, FLAGS_SET) + self.bugzillaPasswordEntry.setFlags(FLAG_DISABLED, FLAGS_SET) else: self.diskButton.w.checkboxSetFlags(FLAG_DISABLED, FLAGS_SET) self.diskButton.w.checkboxSetValue(" ") - self.remoteButton.w.checkboxSetFlags(FLAG_DISABLED, FLAGS_RESET) - self.remoteButton.w.checkboxSetValue("*") + self.bugzillaButton.w.checkboxSetFlags(FLAG_DISABLED, FLAGS_RESET) + self.bugzillaButton.w.checkboxSetValue("*") result = toplevel.run() self.rc = buttons.buttonPressed(result) def saveToDisk(self): return self.rg.getSelection() == "disk" + def saveToLocal(self): return False + def saveToRemote(self): + return self.rg.getSelection() == "remote" + class MainExceptionWindow: def __init__ (self, shortTraceback, longTracebackFile=None, screen=None): self.text = "%s\n\n" % shortTraceback diff --git a/ui/exnSave.glade b/ui/exnSave.glade index 6c22e2fb9..216e82f01 100644 --- a/ui/exnSave.glade +++ b/ui/exnSave.glade @@ -106,7 +106,7 @@ <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="label" translatable="yes">Save to local _disk</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> @@ -164,7 +164,7 @@ <widget class="GtkRadioButton" id="localButton"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">_Disk</property> + <property name="label" translatable="yes">Save to local _disk</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> @@ -219,16 +219,16 @@ </child> <child> - <widget class="GtkVBox" id="remoteBox"> + <widget class="GtkVBox" id="bugzillaBox"> <property name="visible">True</property> <property name="homogeneous">False</property> <property name="spacing">0</property> <child> - <widget class="GtkRadioButton" id="remoteButton"> + <widget class="GtkRadioButton" id="bugzillaButton"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="label" translatable="yes">_Remote (%s)</property> + <property name="label" translatable="yes">Send to _bugzilla (%s)</property> <property name="use_underline">True</property> <property name="relief">GTK_RELIEF_NORMAL</property> <property name="focus_on_click">True</property> @@ -257,7 +257,7 @@ <property name="right_padding">0</property> <child> - <widget class="GtkHBox" id="remoteHBox"> + <widget class="GtkHBox" id="bugzillaHBox"> <property name="visible">True</property> <property name="sensitive">False</property> <property name="homogeneous">False</property> @@ -323,7 +323,7 @@ <child> <widget class="GtkLabel" id="label7"> <property name="visible">True</property> - <property name="label" translatable="yes">_Bug description</property> + <property name="label" translatable="yes">Bug _description</property> <property name="use_underline">True</property> <property name="use_markup">False</property> <property name="justify">GTK_JUSTIFY_LEFT</property> @@ -360,7 +360,7 @@ <property name="spacing">5</property> <child> - <widget class="GtkEntry" id="usernameEntry"> + <widget class="GtkEntry" id="bugzillaNameEntry"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="editable">True</property> @@ -379,7 +379,7 @@ </child> <child> - <widget class="GtkEntry" id="passwordEntry"> + <widget class="GtkEntry" id="bugzillaPasswordEntry"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="editable">True</property> @@ -438,6 +438,256 @@ <property name="fill">True</property> </packing> </child> + + <child> + <widget class="GtkVBox" id="scpBox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkRadioButton" id="scpButton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">Send to _remote server (scp)</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="GtkHBox" id="scpHBox"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkVBox" id="vbox5"> + <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="label8"> + <property name="visible">True</property> + <property name="label" translatable="yes">_User name</property> + <property name="use_underline">True</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.5</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">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Password</property> + <property name="use_underline">True</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.5</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">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Host (host:port)</property> + <property name="use_underline">True</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.5</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">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="label" translatable="yes">Destination _file</property> + <property name="use_underline">True</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.5</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">False</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="vbox6"> + <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="scpNameEntry"> + <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">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="scpPasswordEntry"> + <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">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="scpHostEntry"> + <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">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkEntry" id="scpDestEntry"> + <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">False</property> + <property name="fill">False</property> + </packing> + </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> + <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> |