Following our discussion in a-d-l I am proposing this simple patchset for F18. It just adds the option to network spoke. We can fine-tune it for dependencies (storage, realm?) from UX point of view in F19.
I am open also to suggestions of better placement / width / whatever of the entry in network spoke.
Not that I am pushing this to F18 hard, but I think the option to set hostname in UI would be missed.
updates image for f18 tc2: http://rvykydal.fedorapeople.org/updates.hostnameui.img
screenshots: http://rvykydal.fedorapeople.org/hostname.png http://rvykydal.fedorapeople.org/hostname_sanity.png
Note: The entry is updated automatically if the hostname has not been set yet ("localhost.localdomain" value) and NetworkManager updates hostname based on successfull connecting (e.g. finshed dhcp) and his policy (which is: static configuration, dhcp, static configuration in time of NM start, reverse DNS lookup) --- pyanaconda/network.py | 15 ++++-- pyanaconda/ui/gui/spokes/network.glade | 93 +++++++++++++++------------------- pyanaconda/ui/gui/spokes/network.py | 44 +++++++++++++--- 3 files changed, 87 insertions(+), 65 deletions(-)
diff --git a/pyanaconda/network.py b/pyanaconda/network.py index 6e57f0b..2bf7832 100644 --- a/pyanaconda/network.py +++ b/pyanaconda/network.py @@ -965,11 +965,18 @@ def wait_for_dhcp(): log.debug("not connected, waited %d of %d secs" % (i, CONNECTION_TIMEOUT)) return False
-def update_hostname(ksdata): - hostname = getHostname() +def update_hostname(ksdata, hostname=None): + if not hostname: + hostname = getHostname() log.debug("updating hostname %s" % hostname) - nd = kickstartNetworkData(hostname=hostname) - ksdata.network.network.append(nd) + hostname_found = False + for nd in ksdata.network.network: + if nd.hostname: + nd.hostname = hostname + hostname_found = True + if not hostname_found: + nd = kickstartNetworkData(hostname=hostname) + ksdata.network.network.append(nd)
def get_device_name(devspec):
diff --git a/pyanaconda/ui/gui/spokes/network.glade b/pyanaconda/ui/gui/spokes/network.glade index 27afea8..d8af275 100644 --- a/pyanaconda/ui/gui/spokes/network.glade +++ b/pyanaconda/ui/gui/spokes/network.glade @@ -121,11 +121,11 @@ updates available for you.</property> </child> <child internal-child="alignment"> <object class="GtkAlignment" id="AnacondaSpokeWindow-alignment1"> - <property name="margin_top">12</property> <property name="can_focus">False</property> + <property name="margin_top">12</property> <property name="yalign">0</property> - <property name="xscale">1</property> - <property name="yscale">1</property> + <property name="xscale">0</property> + <property name="yscale">0.5</property> <property name="bottom_padding">48</property> <property name="left_padding">24</property> <property name="right_padding">24</property> @@ -190,7 +190,6 @@ updates available for you.</property> <object class="GtkToolButton" id="add_toolbutton"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="icon_name">list-add-symbolic</property> </object> @@ -203,7 +202,6 @@ updates available for you.</property> <object class="GtkToolButton" id="remove_toolbutton"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="icon_name">list-remove-symbolic</property> </object> @@ -519,7 +517,6 @@ updates available for you.</property> <property name="can_focus">True</property> <property name="halign">end</property> <property name="valign">start</property> - <property name="use_action_appearance">False</property> </object> </child> </object> @@ -554,7 +551,6 @@ updates available for you.</property> <property name="valign">end</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="use_action_appearance">False</property> <property name="use_underline">True</property> </object> <packing> @@ -567,27 +563,6 @@ updates available for you.</property> <child> <placeholder/> </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> </object> <packing> <property name="expand">True</property> @@ -867,7 +842,6 @@ updates available for you.</property> <property name="can_focus">True</property> <property name="halign">end</property> <property name="valign">start</property> - <property name="use_action_appearance">False</property> </object> </child> </object> @@ -1025,7 +999,6 @@ updates available for you.</property> <property name="valign">end</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="use_action_appearance">False</property> <property name="use_underline">True</property> </object> <packing> @@ -1045,7 +1018,6 @@ updates available for you.</property> <property name="valign">end</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="use_action_appearance">False</property> <property name="use_underline">True</property> </object> <packing> @@ -1065,7 +1037,6 @@ updates available for you.</property> <property name="valign">end</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <property name="use_action_appearance">False</property> <property name="use_underline">True</property> </object> <packing> @@ -1075,24 +1046,6 @@ updates available for you.</property> <property name="height">1</property> </packing> </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> </object> <packing> <property name="expand">True</property> @@ -1432,7 +1385,6 @@ updates available for you.</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> <property name="use_underline">True</property> </object> </child> @@ -1718,7 +1670,6 @@ updates available for you.</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> <property name="use_underline">True</property> </object> </child> @@ -2196,7 +2147,6 @@ updates available for you.</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> - <property name="use_action_appearance">False</property> </object> <packing> <property name="expand">False</property> @@ -2237,6 +2187,43 @@ updates available for you.</property> <property name="position">1</property> </packing> </child> + <child> + <object class="GtkBox" id="box1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="label_hostname"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xpad">9</property> + <property name="label" translatable="yes">Hostname:</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="entry_hostname"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="invisible_char">●</property> + <property name="width_chars">40</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> </object> <packing> <property name="expand">False</property> diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py index 31145e2..45b0d5d 100644 --- a/pyanaconda/ui/gui/spokes/network.py +++ b/pyanaconda/ui/gui/spokes/network.py @@ -41,7 +41,7 @@ from pyanaconda.ui.gui.categories.software import SoftwareCategory from pyanaconda.ui.gui.hubs.summary import SummaryHub from pyanaconda.ui.gui.utils import gtk_call_once
-from pyanaconda.network import NetworkDevice, netscriptsDir, kickstartNetworkData, getActiveNetDevs, logIfcfgFiles +from pyanaconda.network import NetworkDevice, netscriptsDir, kickstartNetworkData, getActiveNetDevs, logIfcfgFiles, update_hostname
from gi.repository import GLib, GObject, Pango, Gio, NetworkManager, NMClient import dbus @@ -222,7 +222,7 @@ class CellRendererSecurity(Gtk.CellRendererPixbuf):
self.set_property("icon-name", self.icon_name)
-class NetworkControlBox(): +class NetworkControlBox(object):
supported_device_types = [ NetworkManager.DeviceType.ETHERNET, @@ -949,6 +949,14 @@ class NetworkControlBox(): return [row[DEVICES_COLUMN_OBJECT] for row in self.builder.get_object("liststore_devices")]
+ @property + def hostname(self): + return self.builder.get_object("entry_hostname").get_text() + + @hostname.setter + def hostname(self, value): + self.builder.get_object("entry_hostname").set_text(value) + class NetworkSpoke(NormalSpoke): builderObjects = ["networkWindow", "liststore_wireless_network", "liststore_devices"] mainWidgetName = "networkWindow" @@ -962,6 +970,7 @@ class NetworkSpoke(NormalSpoke): def __init__(self, *args, **kwargs): NormalSpoke.__init__(self, *args, **kwargs) self.network_control_box = NetworkControlBox(self.builder) + self.network_control_box.hostname = self.data.network.hostname self.network_control_box.client.connect("notify::%s" % NMClient.CLIENT_STATE, self.on_nm_state_changed) @@ -969,14 +978,14 @@ class NetworkSpoke(NormalSpoke): device.connect("state-changed", self.on_device_state_changed)
def apply(self): - hostname = self.data.network.hostname + # TODO: sanity check self.data.network.network = [] for dev in self.network_control_box.listed_devices: network_data = getKSNetworkData(dev) if network_data is not None: self.data.network.network.append(network_data) - nd = kickstartNetworkData(hostname=hostname) - self.data.network.network.append(nd) + hostname = self.network_control_box.hostname + update_hostname(self.data, hostname)
@property def completed(self): @@ -1036,6 +1045,7 @@ class NetworkSpoke(NormalSpoke):
def on_nm_state_changed(self, *args): gtk_call_once(self._update_status) + gtk_call_once(self._update_hostname)
def on_device_state_changed(self, *args): new_state = args[1] @@ -1047,6 +1057,11 @@ class NetworkSpoke(NormalSpoke): def _update_status(self): communication.send_message(self.__class__.__name__, self.status)
+ def _update_hostname(self): + if self.network_control_box.hostname == "localhost.localdomain": + update_hostname(self.data) + self.network_control_box.hostname = self.data.network.hostname + class NetworkStandaloneSpoke(StandaloneSpoke): builderObjects = ["networkStandaloneWindow", "networkControlBox_vbox", "liststore_wireless_network", "liststore_devices"] mainWidgetName = "networkStandaloneWindow" @@ -1058,22 +1073,26 @@ class NetworkStandaloneSpoke(StandaloneSpoke): def __init__(self, *args, **kwargs): StandaloneSpoke.__init__(self, *args, **kwargs) self.network_control_box = NetworkControlBox(self.builder) + self.network_control_box.hostname = self.data.network.hostname parent = self.builder.get_object("AnacondaStandaloneWindow-action_area5") parent.add(self.network_control_box.vbox)
+ self.network_control_box.client.connect("notify::%s" % + NMClient.CLIENT_STATE, + self.on_nm_state_changed) + self._initially_available = self.completed log.debug("network standalone spoke (init): completed: %s" % self._initially_available) self._now_available = False
def apply(self): - hostname = self.data.network.hostname self.data.network.network = [] for dev in self.network_control_box.listed_devices: network_data = getKSNetworkData(dev) if network_data is not None: self.data.network.network.append(network_data) - nd = kickstartNetworkData(hostname=hostname) - self.data.network.network.append(nd) + hostname = self.network_control_box.hostname + update_hostname(self.data, hostname)
self._now_available = self.completed
@@ -1104,6 +1123,15 @@ class NetworkStandaloneSpoke(StandaloneSpoke): self.window.hide() Gtk.main_quit()
+ # Use case: slow dhcp has connected when on spoke + def on_nm_state_changed(self, *args): + gtk_call_once(self._update_hostname) + + def _update_hostname(self): + if self.network_control_box.hostname == "localhost.localdomain": + update_hostname(self.data) + self.network_control_box.hostname = self.data.network.hostname + def getKSNetworkData(device): retval = None
diff --git a/pyanaconda/ui/gui/spokes/network.glade b/pyanaconda/ui/gui/spokes/network.glade index 27afea8..d8af275 100644 --- a/pyanaconda/ui/gui/spokes/network.glade +++ b/pyanaconda/ui/gui/spokes/network.glade @@ -121,11 +121,11 @@ updates available for you.</property> </child> <child internal-child="alignment"> <object class="GtkAlignment" id="AnacondaSpokeWindow-alignment1">
<property name="margin_top">12</property> <property name="can_focus">False</property>
<property name="margin_top">12</property> <property name="yalign">0</property>
<property name="xscale">1</property><property name="yscale">1</property>
<property name="xscale">0</property><property name="yscale">0.5</property> <property name="bottom_padding">48</property> <property name="left_padding">24</property> <property name="right_padding">24</property>
Unless you changed these numbers on purpose, you almost certainly do not want to make this change.
- Chris
--- pyanaconda/ui/gui/spokes/network.py | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/pyanaconda/ui/gui/spokes/network.py b/pyanaconda/ui/gui/spokes/network.py index 45b0d5d..887b0b4 100644 --- a/pyanaconda/ui/gui/spokes/network.py +++ b/pyanaconda/ui/gui/spokes/network.py @@ -41,7 +41,7 @@ from pyanaconda.ui.gui.categories.software import SoftwareCategory from pyanaconda.ui.gui.hubs.summary import SummaryHub from pyanaconda.ui.gui.utils import gtk_call_once
-from pyanaconda.network import NetworkDevice, netscriptsDir, kickstartNetworkData, getActiveNetDevs, logIfcfgFiles, update_hostname +from pyanaconda.network import NetworkDevice, netscriptsDir, kickstartNetworkData, getActiveNetDevs, logIfcfgFiles, update_hostname, sanityCheckHostname
from gi.repository import GLib, GObject, Pango, Gio, NetworkManager, NMClient import dbus @@ -301,6 +301,8 @@ class NetworkControlBox(object): self.on_edit_connection) self.builder.get_object("button_wireless_options").connect("clicked", self.on_edit_connection) + self.entry_hostname = self.builder.get_object("entry_hostname") +
@property def vbox(self): @@ -951,11 +953,11 @@ class NetworkControlBox(object):
@property def hostname(self): - return self.builder.get_object("entry_hostname").get_text() + return self.entry_hostname.get_text()
@hostname.setter def hostname(self, value): - self.builder.get_object("entry_hostname").set_text(value) + self.entry_hostname.set_text(value)
class NetworkSpoke(NormalSpoke): builderObjects = ["networkWindow", "liststore_wireless_network", "liststore_devices"] @@ -1062,6 +1064,19 @@ class NetworkSpoke(NormalSpoke): update_hostname(self.data) self.network_control_box.hostname = self.data.network.hostname
+ def on_back_clicked(self, button): + hostname = self.network_control_box.hostname + (valid, error) = sanityCheckHostname(hostname) + if not valid: + self.clear_info() + msg = _("Hostname is not valid: %s" % error) + self.set_warning(msg) + self.network_control_box.entry_hostname.grab_focus() + self.window.show_all() + else: + self.clear_info() + NormalSpoke.on_back_clicked(self, button) + class NetworkStandaloneSpoke(StandaloneSpoke): builderObjects = ["networkStandaloneWindow", "networkControlBox_vbox", "liststore_wireless_network", "liststore_devices"] mainWidgetName = "networkStandaloneWindow" @@ -1119,6 +1134,19 @@ class NetworkStandaloneSpoke(StandaloneSpoke): StandaloneSpoke.refresh(self) self.network_control_box.refresh()
+ def _on_continue_clicked(self, cb): + hostname = self.network_control_box.hostname + (valid, error) = sanityCheckHostname(hostname) + if not valid: + self.clear_info() + msg = _("Hostname is not valid: %s" % error) + self.set_warning(msg) + self.network_control_box.entry_hostname.grab_focus() + self.window.show_all() + else: + self.clear_info() + StandaloneSpoke._on_continue_clicked(self, cb) + def on_back_clicked(self, window): self.window.hide() Gtk.main_quit()
class NetworkSpoke(NormalSpoke): builderObjects = ["networkWindow", "liststore_wireless_network", "liststore_devices"] @@ -1062,6 +1064,19 @@ class NetworkSpoke(NormalSpoke): update_hostname(self.data) self.network_control_box.hostname = self.data.network.hostname
- def on_back_clicked(self, button):
hostname = self.network_control_box.hostname(valid, error) = sanityCheckHostname(hostname)if not valid:self.clear_info()msg = _("Hostname is not valid: %s" % error)
The substitution needs to be done outside of the translation marker, like so:
msg = _("Hostname is not valid: %s") % error
@@ -1119,6 +1134,19 @@ class NetworkStandaloneSpoke(StandaloneSpoke): StandaloneSpoke.refresh(self) self.network_control_box.refresh()
- def _on_continue_clicked(self, cb):
hostname = self.network_control_box.hostname(valid, error) = sanityCheckHostname(hostname)if not valid:self.clear_info()msg = _("Hostname is not valid: %s" % error)
Same here.
- Chris
On Mon, Dec 17, 2012 at 03:48:50PM +0100, Radek Vykydal wrote:
Following our discussion in a-d-l I am proposing this simple patchset for F18. It just adds the option to network spoke. We can fine-tune it for dependencies (storage, realm?) from UX point of view in F19.
I am open also to suggestions of better placement / width / whatever of the entry in network spoke.
Not that I am pushing this to F18 hard, but I think the option to set hostname in UI would be missed.
updates image for f18 tc2: http://rvykydal.fedorapeople.org/updates.hostnameui.img
screenshots: http://rvykydal.fedorapeople.org/hostname.png http://rvykydal.fedorapeople.org/hostname_sanity.png
I think it would look better if the label was above instead of to the left. Left align the label and text entry with the network device list above it.
Other than that this looks ok.
anaconda-patches@lists.fedorahosted.org