diff --git a/docs/release-notes/redesign_gui_time_date_spoke.rst b/docs/release-notes/redesign_gui_time_date_spoke.rst new file mode 100644 index 000000000000..dd3f76815902 --- /dev/null +++ b/docs/release-notes/redesign_gui_time_date_spoke.rst @@ -0,0 +1,11 @@ +:Type: GUI +:Summary: Redesign the Time & Date spoke in GUI + +:Description: + The timezone map was removed from the Time & Date spoke in the GKT-based user interface + and the spoke was redesigned to accommodate the changes. The installer no longer depends + on the the ``libtimezonemap`` package. + +:Links: + - https://github.com/rhinstaller/anaconda/issues/5404 + - https://github.com/rhinstaller/anaconda/discussions/5355 diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.glade b/pyanaconda/ui/gui/spokes/datetime_spoke.glade index 32d66a7d60f4..899f76dcb569 100644 --- a/pyanaconda/ui/gui/spokes/datetime_spoke.glade +++ b/pyanaconda/ui/gui/spokes/datetime_spoke.glade @@ -124,175 +124,454 @@ True False + center + start + 12 + 12 + 12 + 12 + True vertical + top - + True False - 1 - 0.949999988079071 + start + 4 + 12 + Time zone + + + + + + False + True + 0 + + + + + True + False + 4 + 30 + 5 + + + True + False + _Region: + True + regionCombobox + + + False + True + 0 + + + + + True + False + regions + True + 1 + + + + True + GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK + 20 + regionCompletion + + + + + + Region + + + + + + + False + True + 1 + + + + + True + False + 6 + 6 + _City: + True + cityCombobox + + + False + True + 2 + + + + + True + False + citiesFilter + True + 1 + + + + True + GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK + 20 + cityCompletion + + + + + + City + + + + + + + False + True + 3 + + + + + False + True + 1 + + + + + True + True + False + 4 + 12 + True + + + + True + False + _Automatic date & time + True + ntpRadioButton + + + + + + + + False + True + 2 + + + + + True + False + start + 28 + 12 + This feature requires connecting to an NTP (Network Time Protocol) server. + True + 60 + + + False + True + 3 + + + + + Configure _NTP ... + True + True + True + start + 28 + 24 + configImage + True + True + + + + Configure NTP + + + + + False + False + 1 + 4 + + + + + True + True + False + 4 + 12 + True + ntpRadioButton + + + True + False + _Manual date & time + True + manualRadioButton + + + + + + + + False + True + 5 + + + + + + True + False + 28 + 24 + 6 + 6 - + + True False - + True False - _Region: - True - regionCombobox + 00 + + + + + + Hours + + - False - True - 3 - 0 + 0 + 1 - + True False - regions - True - 1 - - - - True - GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK - 20 - regionCompletion - - - - - - Region - - + : + + + + + + 1 + 1 + + + + + True + False + 00 + + + + + + Minutes - False - True - 2 - 1 + 2 + 1 - + True - False - 6 - _City: - True - cityCombobox + True + True + upImage + + + + Hour Up + + - False - True - 5 - 2 + 0 + 0 - + True - False - citiesFilter - True - 1 - - - - True - GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK - 20 - cityCompletion - - - - - - City - - + True + True + downImage + + + + Hour Down + + + + + 0 + 2 + + + + + True + True + True + upImage2 + + + + Minutes Up - False - True - 3 + 2 + 0 - + + True + True + True + downImage2 + + + + Minutes Down + + + + + 2 + 2 + + + + + True + False + + + + + + + 3 + 1 + + + + True False - 1 - 0.20000000298023224 - 24 + crossfade + True - + True False - end + center + vertical - + True - False - _Network Time - True - networkTimeSwitch + True + True + upImage1 + + + + AM/PM Up + + False True - 3 0 - + True - True - center - 6 - - - - Use Network Time - - + False + 4 + 5 + PM + + + False True - 1 1 - + True True True - configImage - + downImage1 + - - Configure NTP + + AM/PM Down False True - 1 2 @@ -300,375 +579,146 @@ - True - True - 4 + 4 + 0 + 3 + + + + + + + + + + + + + + 1 + 1 + - - - False - True - 0 - - - - - True - False - 1 - 24 - + True False - 6 + 1 + 0.5 - - + True False + vertical - - True - False - 00 - - - - - - Hours - - - - - 0 - 1 - - - - - True - False - : - - - - - - 1 - 1 - - - - - True - False - 00 - - - - - - Minutes - - - - - 2 - 1 - - - - + + 24-_hour True True - True - upImage - - - - Hour Up - - + False + True + 0 + True + True + - 0 - 0 + False + True + 0 - + + _AM/PM True True - True - downImage - - - - Hour Down - - + False + True + 0 + True + timeFormatRB - 0 - 2 + False + True + 1 - - - True - True - True - upImage2 - - - - Minutes Up - - - - - 2 - 0 - - - - - True - True - True - downImage2 - - - - Minutes Down - - - - - 2 - 2 - - - - - True - False - - - - - - - 3 - 1 - - - - - True - False - crossfade - True - - - True - False - center - vertical - - - True - True - True - upImage1 - - - - AM/PM Up - - - - - False - True - 0 - - - - - True - False - 4 - 5 - PM - - - - - - False - True - 1 - - - - - True - True - True - downImage1 - - - - AM/PM Down - - - - - False - True - 2 - - - - - - - 4 - 0 - 3 - - - - - - - - - - - - - - - - False - True - 0 - + + + 2 + 1 + + + + + True + False + start + start + 28 + 3 - - True - False - 1 - 0.5 - - - True - False - vertical - - - 24-_hour - True - True - False - True - 0 - True - True - - - - False - True - 0 - - - - - _AM/PM - True - True - False - True - 0 - True - timeFormatRB - - - False - True - 1 - - - - - - - False - True - 8 - 1 - + - - True - False - 1 - 0.30000001192092896 - 0.20000000298023224 - 24 - - - True - False - end - 3 - - - - - - - - - - - - - - True - True - 2 - + - - - Set Date & Time - + + + + 0 + 1 + + + + + True + False + start + Date + + + 0 + 0 + + + + + True + False + start + Time + + + 1 + 0 + + + + False True - end - 2 + 6 + + + - True + False True 0 diff --git a/pyanaconda/ui/gui/spokes/datetime_spoke.py b/pyanaconda/ui/gui/spokes/datetime_spoke.py index d0c90b22f375..c18897a8a7fe 100644 --- a/pyanaconda/ui/gui/spokes/datetime_spoke.py +++ b/pyanaconda/ui/gui/spokes/datetime_spoke.py @@ -41,7 +41,7 @@ from pyanaconda.ui.common import FirstbootSpokeMixIn from pyanaconda.ui.gui.spokes import NormalSpoke from pyanaconda.ui.categories.localization import LocalizationCategory -from pyanaconda.ui.gui.utils import blockedHandler +from pyanaconda.ui.gui.utils import blockedHandler as blocked_handler from pyanaconda.ui.gui.spokes.lib.ntp_dialog import NTPConfigDialog from pyanaconda.timezone import NTP_SERVICE, get_all_regions_and_timezones, get_timezone, \ is_valid_timezone, set_system_date_time, parse_timezone @@ -258,7 +258,9 @@ def initialize(self): self._year_format, suffix = formats[widgets.index(year_box)] year_label.set_text(suffix) - self._ntpSwitch = self.builder.get_object("networkTimeSwitch") + self._ntp_radio_button = self.builder.get_object("ntpRadioButton") + self._ntp_config_button = self.builder.get_object("ntpConfigButton") + self._manual_radio_button = self.builder.get_object("manualRadioButton") self._regions_zones = get_all_regions_and_timezones() @@ -337,7 +339,7 @@ def apply(self): region + "/" + city, constants.TIMEZONE_PRIORITY_USER ) - self._timezone_module.NTPEnabled = self._ntpSwitch.get_active() + self._timezone_module.NTPEnabled = self._ntp_radio_button.get_active() self._kickstarted = False def execute(self): @@ -379,6 +381,7 @@ def refresh(self): self._timezone_module.TimeSources ) + # Set up the NTP servers. if not self._ntp_servers: try: self._ntp_servers = ntp.get_servers_from_config() @@ -388,22 +391,12 @@ def refresh(self): self._ntp_servers_states = NTPServerStatusCache() self._ntp_servers_states.changed.connect(self._update_ntp_server_warning) - has_active_network = self._network_module.Connected - - if not has_active_network: - self._show_no_network_warning() - else: - self.clear_info() - + if self._network_module.Connected: for server in self._ntp_servers: self._ntp_servers_states.check_status(server) - if conf.system.can_set_time_synchronization: - ntp_working = has_active_network and is_service_running(NTP_SERVICE) - else: - ntp_working = self._timezone_module.NTPEnabled - - self._ntpSwitch.set_active(ntp_working) + # Set up the NTP widgets. + self._set_ntp_enabled(self._timezone_module.NTPEnabled) @async_action_nowait def add_to_store_xlated(self, store, item, xlated): @@ -784,7 +777,7 @@ def _get_valid_timezone(self, preferred_timezone): def _set_region_and_city_from_timezone(self, timezone): """Set up the region and the city from the specified timezone.""" # Set up the region and city widgets. - with blockedHandler(self._cityCombo, self.on_city_changed): + with blocked_handler(self._cityCombo, self.on_city_changed): region, city = parse_timezone(timezone) self._set_combo_selection(self._regionCombo, region) self._set_combo_selection(self._cityCombo, city) @@ -817,14 +810,14 @@ def on_timeformat_changed(self, button24h, *args): def _hide_date_time_setting(self): #contains all date/time setting widgets - footer_alignment = self.builder.get_object("footerAlignment") - footer_alignment.set_no_show_all(True) - footer_alignment.hide() + container_widget = self.builder.get_object("manualGrid") + container_widget.set_no_show_all(True) + container_widget.hide() def _set_date_time_setting_sensitive(self, sensitive): #contains all date/time setting widgets - footer_alignment = self.builder.get_object("footerAlignment") - footer_alignment.set_sensitive(sensitive) + container_widget = self.builder.get_object("manualGrid") + container_widget.set_sensitive(sensitive) def _get_working_server(self): """Get a working NTP server.""" @@ -848,51 +841,91 @@ def _cancel_planned_update(self): if self._start_updating_timer: self._start_updating_timer.cancel() self._start_updating_timer = None + # re-enable UI update because it will not be done by the # system time update we've just cancelled if not self._update_datetime_timer: self._update_datetime_timer = Timer() self._update_datetime_timer.timeout_sec(1, self._update_datetime) - def on_ntp_switched(self, switch, *args): - if switch.get_active(): + def on_ntp_button_toggled(self, button): + """Toggle the NTP configuration.""" + log.debug("Toggled the NTP configuration.") + self._set_ntp_enabled(self._ntp_radio_button.get_active()) + + def _set_ntp_enabled(self, ntp_requested): + """Set the NTP enabled configuration.""" + # Clear warnings. + self.clear_info() + + # Try to configure the NTP service. + ntp_enabled = self._start_ntp_service() if ntp_requested else self._stop_ntp_service() + + # Update the widgets. + with blocked_handler(self._ntp_radio_button, self.on_ntp_button_toggled): + self._ntp_radio_button.set_active(ntp_enabled) + self._ntp_config_button.set_sensitive(ntp_enabled) + + self._manual_radio_button.set_active(not ntp_enabled) + self._set_date_time_setting_sensitive(not ntp_enabled) + + # Update the timers. + if ntp_enabled: self._cancel_planned_update() - #turned ON - if not conf.system.can_set_time_synchronization: - #cannot touch runtime system, not much to do here - return + def _start_ntp_service(self): + """Start the NTP service. - if not self._network_module.Connected: - self._show_no_network_warning() - switch.set_active(False) - return - else: - self._update_ntp_server_warning() + :return bool: True if NTP is enabled, otherwise False + """ + log.debug("Starting the NTP service...") - ret = start_service(NTP_SERVICE) - self._set_date_time_setting_sensitive(False) + # Cannot touch runtime system, not much to do here. + # Pretend that the NTP service is enabled. + if not conf.system.can_set_time_synchronization: + return True - #if starting chronyd failed and chronyd is not running, - #set switch back to OFF - if (ret != 0) and not is_service_running(NTP_SERVICE): - switch.set_active(False) + # Check the network connection. + if not self._network_module.Connected: + log.debug("No network. The NTP service cannot be started.") + self._show_no_network_warning() + return False - else: - #turned OFF - if not conf.system.can_set_time_synchronization: - #cannot touch runtime system, nothing to do here - return + # Start the NTP service. + if start_service(NTP_SERVICE) == 0: + self._update_ntp_server_warning() + return True + + # Or check if it's running. + if is_service_running(NTP_SERVICE): + self._update_ntp_server_warning() + return True + + log.debug("Failed to start the NTP service.") + return False - self._set_date_time_setting_sensitive(True) - ret = stop_service(NTP_SERVICE) + def _stop_ntp_service(self): + """Stop the NTP service. - #if stopping chronyd failed and chronyd is running, - #set switch back to ON - if (ret != 0) and is_service_running(NTP_SERVICE): - switch.set_active(True) + :return bool: True if NTP is enabled, otherwise False + """ + log.debug("Stopping the NTP service...") - self.clear_info() + # Cannot touch runtime system, not much to do here. + # Pretend that the NTP service isn't enabled. + if not conf.system.can_set_time_synchronization: + return False + + # Stop the NTP service. + if stop_service(NTP_SERVICE) == 0: + return False + + # Or check if it's NOT running. + if not is_service_running(NTP_SERVICE): + return False + + log.debug("Failed to stop the NTP service.") + return True def on_ntp_config_clicked(self, *args): servers = copy.deepcopy(self._ntp_servers) @@ -919,7 +952,7 @@ def on_ntp_config_clicked(self, *args): def _update_ntp_server_warning(self): """Update the warning about working NTP servers.""" - if not self._ntpSwitch.get_active(): + if not self._ntp_radio_button.get_active(): return self.clear_info()