def __init__(self, installer): BasePage.__init__(self) self.map = TimezoneMap.TimezoneMap() self.pack_start(self.map, True, True, 0) self.installer = installer # Set up timezone database self.db = Database() self.locations = Gtk.Entry() self.locations.set_placeholder_text(_("Search for your timezone...")) tz_model = Gtk.ListStore(str,str,str,str,float,float,str) for item in self.db.locations: tz_model.append([item.human_zone, item.human_country, None, item.country, item.longitude, item.latitude,item.zone]) completion = TimezoneMap.TimezoneCompletion() completion.set_model(tz_model) completion.set_text_column(0) completion.set_inline_completion(True) completion.set_inline_selection(True) completion.connect("match-selected", self.change_timezone) self.locations.set_completion(completion) self.map.connect("location-changed", self.changed) self.pack_end(self.locations, False, False, 3) self.timezone = None self.timezone_human = None self.installer.can_go_forward(False)
def __init__(self): BasePage.__init__(self) self.frame = Gtk.Frame() self.frame.set_shadow_type(Gtk.ShadowType.NONE) self.tmap = TimezoneMap.TimezoneMap() self.pack_start(self.frame, True, True, 0) self.frame.set_margin_end(0) self.frame.set_margin_start(0) self.frame.add(self.tmap) self.locations = Gtk.Entry() self.locations.set_property("margin-right", 30) self.locations.set_property("margin-start", 30) self.locations.set_property("margin-top", 10) self.pack_end(self.locations, False, False, 0) self.locations.set_placeholder_text("Search for your timezone" + u"…") completion = TimezoneMap.TimezoneCompletion() completion.set_text_column(0) completion.set_inline_completion(True) completion.set_inline_selection(True) completion.connect("match-selected", self.change_timezone) self.locations.set_completion(completion) self.tmap.connect("location-changed", self.changed)
def test_timezone_map(self): tzmap = TimezoneMap.TimezoneMap() self.win.add(tzmap) #tzmap.select_city('America/New_York') self.win.show_all() self.win.connect('destroy', Gtk.main_quit) gtkwidgets.refresh()
def setup_page(self): # TODO Put a frame around the completion to add contrast (LP: #605908) from gi.repository import Gtk, GLib from gi.repository import TimezoneMap self.tzdb = ubiquity.tz.Database() self.tzmap = TimezoneMap.TimezoneMap() self.tzmap.connect('location-changed', self.select_city) self.map_window.add(self.tzmap) self.tzmap.show() def is_separator(m, i): return m[i][0] is None self.timeout_id = 0 def queue_entry_changed(entry): if self.timeout_id: GLib.source_remove(self.timeout_id) self.timeout_id = GLib.timeout_add(300, self.changed, entry) self.city_entry.connect('changed', queue_entry_changed) completion = Gtk.EntryCompletion() self.city_entry.set_completion(completion) completion.set_inline_completion(True) completion.set_inline_selection(True) def match_selected(completion, model, iterator): # Select on map. lat = float(model[iterator][3]) lon = float(model[iterator][4]) self.tzmap.set_coords(lon, lat) self.city_entry.set_text(model[iterator][0]) self.city_entry.set_position(-1) return True completion.connect('match-selected', match_selected) def match_func(completion, key, iterator, data): # We've already determined that it's a match in entry_changed. return True def data_func(column, cell, model, iterator, data): row = model[iterator] if row[1]: # The result came from geonames, and thus has an administrative # zone attached to it. text = '%s <small>(%s, %s)</small>' % (row[0], row[1], row[2]) else: text = '%s <small>(%s)</small>' % (row[0], row[2]) cell.set_property('markup', text) cell = Gtk.CellRendererText() completion.pack_start(cell, True) completion.set_match_func(match_func, None) completion.set_cell_data_func(cell, data_func, None)
def run(self): # Wait until there is an Internet connection available while not self.has_connection(): if self.stop_event.is_set() or self.settings.get( 'stop_all_threads'): return time.sleep(1) # Delay and try again timezone = "" try: coords = self.coords_queue.get(True) self.coords_queue.put_nowait(coords) tzmap = TimezoneMap.TimezoneMap() timezone = tzmap.get_timezone_at_coords(float(coords[0]), float(coords[1])) loc = self.tzdb.get_loc(timezone) country_code = '' if loc: country_code = loc.country except (queue.Empty, IndexError) as e: logging.warning( _("Can't get the country code used to create a pacman mirrorlist" )) return try: url = 'https://www.archlinux.org/mirrorlist/?country=%s&protocol=http&ip_version=4&use_mirror_status=on' % country_code country_mirrorlist = urllib.request.urlopen(url).read() if '<!DOCTYPE' in str(country_mirrorlist, encoding='utf8'): # The country doesn't have mirrors so we keep using the mirrorlist generated by score country_mirrorlist = '' else: with open('/tmp/country_mirrorlist', 'wb') as f: f.write(country_mirrorlist) except URLError as e: logging.warning( _("Couldn't generate mirrorlist for pacman based on country code" )) logging.warning(e.reason) return if country_mirrorlist is '': pass else: try: script = os.path.join(self.scripts_dir, "generate-mirrorlist.sh") subprocess.check_call(['/usr/bin/bash', script]) logging.info( _("Downloaded a specific mirrorlist for pacman based on %s country code" ) % timezone) except subprocess.CalledProcessError as e: logging.warning( _("Couldn't generate mirrorlist for pacman based on country code" ))
def __init__(self, controller, *args, **kwargs): self.controller = controller try: from PyQt5 import uic from ubiquity.frontend.kde_components.Timezone import TimezoneMap self.page = uic.loadUi('/usr/share/ubiquity/qt/stepLocation.ui') self.tzmap = TimezoneMap(self.page.map_frame) self.page.map_frame.layout().addWidget(self.tzmap) self.tzmap.zoneChanged.connect(self.mapZoneChanged) self.page.timezone_zone_combo.currentIndexChanged[int].connect( self.regionChanged) self.page.timezone_city_combo.currentIndexChanged[int].connect( self.cityChanged) except Exception as e: self.debug('Could not create timezone page: %s', e) self.page = None self.plugin_widgets = self.page self.online = False
def __init__(self, params): self.title = params['title'] self.forward_button = params['forward_button'] self.backwards_button = params['backwards_button'] self.settings = params['settings'] super().__init__() self.ui = Gtk.Builder() self.ui_dir = self.settings.get('ui') self.ui.add_from_file(os.path.join(self.ui_dir, "timezone.ui")) self.ui.connect_signals(self) self.map_window = self.ui.get_object('timezone_map_window') self.combobox_zone = self.ui.get_object('comboboxtext_zone') self.combobox_region = self.ui.get_object('comboboxtext_region') # Show regions in three columns self.combobox_region.set_wrap_width(3) self.tzdb = tz.Database() self.timezone = None # this is for populate_cities self.old_zone = None # setup window self.tzmap = TimezoneMap.TimezoneMap() self.tzmap.connect('location-changed', self.on_location_changed) # Strip .UTF-8 from locale, icu doesn't parse it self.locale = os.environ['LANG'].rsplit('.', 1)[0] self.map_window.add(self.tzmap) self.tzmap.show() # autotimezone thread will store detected coords in this queue self.auto_timezone_coords = multiprocessing.Queue() # thread to try to determine timezone. self.auto_timezone_thread = None self.start_auto_timezone_thread() # thread to generate a pacman mirrorlist based on country code # Why do this? There're foreign mirrors faster than the Spanish ones... - Karasu self.mirrorlist_thread = None #self.start_mirrorlist_thread() super().add(self.ui.get_object('location')) self.autodetected_coords = None
def __init__(self, controller, *args, **kwargs): self.controller = controller try: from PyQt4 import uic from ubiquity.frontend.kde_components.Timezone import TimezoneMap self.page = uic.loadUi("/usr/share/ubiquity/qt/stepLocation.ui") self.tzmap = TimezoneMap(self.page.map_frame) self.page.map_frame.layout().addWidget(self.tzmap) self.tzmap.zoneChanged.connect(self.mapZoneChanged) self.page.timezone_zone_combo.currentIndexChanged[int].connect(self.regionChanged) self.page.timezone_city_combo.currentIndexChanged[int].connect(self.cityChanged) except Exception as e: self.debug("Could not create timezone page: %s", e) self.page = None self.plugin_widgets = self.page self.online = False
def __init__(self, params, prev_page="location", next_page="keymap"): super().__init__(self, params, "timezone", prev_page, next_page) self.map_window = self.ui.get_object('timezone_map_window') self.combobox_zone = self.ui.get_object('comboboxtext_zone') self.combobox_region = self.ui.get_object('comboboxtext_region') # Show regions in three columns self.combobox_region.set_wrap_width(3) self.tzdb = tz.Database() self.timezone = None # This is for populate_cities self.old_zone = None # Setup window self.tzmap = TimezoneMap.TimezoneMap() self.tzmap.connect('location-changed', self.on_location_changed) # Strip .UTF-8 from locale, icu doesn't parse it self.locale = os.environ['LANG'].rsplit('.', 1)[0] self.map_window.add(self.tzmap) self.tzmap.show() # Autotimezone thread will store detected coords in this queue self.auto_timezone_coords = multiprocessing.Queue() # Thread to try to determine timezone. self.auto_timezone_thread = None self.start_auto_timezone_thread() # Thread to generate a pacman mirrorlist based on country code # Why do this? There're foreign mirrors faster than the Spanish ones... - Karasu self.mirrorlist_thread = None #self.start_mirrorlist_thread() self.autodetected_coords = None
def run(self): # wait until there is an Internet connection available while not self.has_connection(): time.sleep(2) # Delay and try again if self.stop_event.is_set(): return timezone = "" try: coords = self.coords_queue.get(True) self.coords_queue.put_nowait(coords) tzmap = TimezoneMap.TimezoneMap() timezone = tzmap.get_timezone_at_coords(float(coords[0]), float(coords[1])) loc = self.tzdb.get_loc(timezone) country_code = '' if loc: country_code = loc.country except (queue.Empty, IndexError) as e: logging.warning(_("Can't get the country code used to create a pacman mirrorlist")) '''try:
class DatetimeSpoke(FirstbootSpokeMixIn, NormalSpoke): """ .. inheritance-diagram:: DatetimeSpoke :parts: 3 """ builderObjects = [ "datetimeWindow", "days", "months", "years", "regions", "cities", "upImage", "upImage1", "upImage2", "downImage", "downImage1", "downImage2", "downImage3", "configImage", "citiesFilter", "daysFilter", "cityCompletion", "regionCompletion", ] mainWidgetName = "datetimeWindow" uiFile = "spokes/datetime_spoke.glade" helpFile = "DateTimeSpoke.xml" category = LocalizationCategory icon = "preferences-system-time-symbolic" title = CN_("GUI|Spoke", "_TIME & DATE") # Hack to get libtimezonemap loaded for GtkBuilder # see https://bugzilla.gnome.org/show_bug.cgi?id=712184 _hack = TimezoneMap.TimezoneMap() del (_hack) def __init__(self, *args): NormalSpoke.__init__(self, *args) # taking values from the kickstart file? self._kickstarted = flags.flags.automatedInstall self._update_datetime_timer_id = None self._start_updating_timer_id = None self._shown = False self._tz = None def initialize(self): NormalSpoke.initialize(self) self._daysStore = self.builder.get_object("days") self._monthsStore = self.builder.get_object("months") self._yearsStore = self.builder.get_object("years") self._regionsStore = self.builder.get_object("regions") self._citiesStore = self.builder.get_object("cities") self._tzmap = self.builder.get_object("tzmap") self._dateBox = self.builder.get_object("dateBox") # we need to know it the new value is the same as previous or not self._old_region = None self._old_city = None self._regionCombo = self.builder.get_object("regionCombobox") self._cityCombo = self.builder.get_object("cityCombobox") self._daysFilter = self.builder.get_object("daysFilter") self._daysFilter.set_visible_func(self.existing_date, None) self._citiesFilter = self.builder.get_object("citiesFilter") self._citiesFilter.set_visible_func(self.city_in_region, None) self._hoursLabel = self.builder.get_object("hoursLabel") self._minutesLabel = self.builder.get_object("minutesLabel") self._amPmUp = self.builder.get_object("amPmUpButton") self._amPmDown = self.builder.get_object("amPmDownButton") self._amPmLabel = self.builder.get_object("amPmLabel") self._radioButton24h = self.builder.get_object("timeFormatRB") self._amPmRevealer = self.builder.get_object("amPmRevealer") # create widgets for displaying/configuring date day_box, self._dayCombo, day_label = _new_date_field_box( self._daysFilter) self._dayCombo.connect("changed", self.on_day_changed) month_box, self._monthCombo, month_label = _new_date_field_box( self._monthsStore) self._monthCombo.connect("changed", self.on_month_changed) year_box, self._yearCombo, year_label = _new_date_field_box( self._yearsStore) self._yearCombo.connect("changed", self.on_year_changed) # get the right order for date widgets and respective formats and put # widgets in place widgets, formats = resolve_date_format(year_box, month_box, day_box) for widget in widgets: self._dateBox.pack_start(widget, False, False, 0) self._day_format, suffix = formats[widgets.index(day_box)] day_label.set_text(suffix) self._month_format, suffix = formats[widgets.index(month_box)] month_label.set_text(suffix) self._year_format, suffix = formats[widgets.index(year_box)] year_label.set_text(suffix) self._ntpSwitch = self.builder.get_object("networkTimeSwitch") self._regions_zones = get_all_regions_and_timezones() # Set the initial sensitivity of the AM/PM toggle based on the time-type selected self._radioButton24h.emit("toggled") if not flags.can_touch_runtime_system("modify system time and date"): self._set_date_time_setting_sensitive(False) self._config_dialog = NTPconfigDialog(self.data) self._config_dialog.initialize() threadMgr.add( AnacondaThread(name=constants.THREAD_DATE_TIME, target=self._initialize)) def _initialize(self): # a bit hacky way, but should return the translated strings for i in range(1, 32): day = datetime.date(2000, 1, i).strftime(self._day_format) self.add_to_store_idx(self._daysStore, i, day) for i in range(1, 13): month = datetime.date(2000, i, 1).strftime(self._month_format) self.add_to_store_idx(self._monthsStore, i, month) for i in range(1990, 2051): year = datetime.date(i, 1, 1).strftime(self._year_format) self.add_to_store_idx(self._yearsStore, i, year) cities = set() xlated_regions = ((region, get_xlated_timezone(region)) for region in self._regions_zones.keys()) for region, xlated in sorted( xlated_regions, key=functools.cmp_to_key(_compare_regions)): self.add_to_store_xlated(self._regionsStore, region, xlated) for city in self._regions_zones[region]: cities.add((city, get_xlated_timezone(city))) for city, xlated in sorted(cities, key=functools.cmp_to_key(_compare_cities)): self.add_to_store_xlated(self._citiesStore, city, xlated) self._update_datetime_timer_id = None if is_valid_timezone(self.data.timezone.timezone): self._set_timezone(self.data.timezone.timezone) elif not flags.flags.automatedInstall: log.warning( "%s is not a valid timezone, falling back to default (%s)", self.data.timezone.timezone, DEFAULT_TZ) self._set_timezone(DEFAULT_TZ) self.data.timezone.timezone = DEFAULT_TZ time_init_thread = threadMgr.get(constants.THREAD_TIME_INIT) if time_init_thread is not None: hubQ.send_message(self.__class__.__name__, _("Restoring hardware time...")) threadMgr.wait(constants.THREAD_TIME_INIT) hubQ.send_ready(self.__class__.__name__, False) @property def status(self): if self.data.timezone.timezone: if is_valid_timezone(self.data.timezone.timezone): return _("%s timezone") % get_xlated_timezone( self.data.timezone.timezone) else: return _("Invalid timezone") else: location = self._tzmap.get_location() if location and location.get_property("zone"): return _("%s timezone") % get_xlated_timezone( location.get_property("zone")) else: return _("Nothing selected") def apply(self): self._shown = False # we could use self._tzmap.get_timezone() here, but it returns "" if # Etc/XXXXXX timezone is selected region = self._get_active_region() city = self._get_active_city() # nothing selected, just leave the spoke and # return to hub without changing anything if not region or not city: return old_tz = self.data.timezone.timezone new_tz = region + "/" + city self.data.timezone.timezone = new_tz if old_tz != new_tz: # new values, not from kickstart self.data.timezone.seen = False self._kickstarted = False self.data.timezone.nontp = not self._ntpSwitch.get_active() def execute(self): if self._update_datetime_timer_id is not None: GLib.source_remove(self._update_datetime_timer_id) self._update_datetime_timer_id = None @property def ready(self): return not threadMgr.get("AnaDateTimeThread") @property def completed(self): if self._kickstarted and not self.data.timezone.seen: # taking values from kickstart, but not specified return False else: return is_valid_timezone(self.data.timezone.timezone) @property def mandatory(self): return True def refresh(self): self._shown = True #update the displayed time self._update_datetime_timer_id = GLib.timeout_add_seconds( 1, self._update_datetime) self._start_updating_timer_id = None if is_valid_timezone(self.data.timezone.timezone): self._tzmap.set_timezone(self.data.timezone.timezone) self._update_datetime() has_active_network = nm.nm_is_connected() if not has_active_network: self._show_no_network_warning() else: self.clear_info() gtk_call_once(self._config_dialog.refresh_servers_state) if flags.can_touch_runtime_system("get NTP service state"): ntp_working = has_active_network and iutil.service_running( NTP_SERVICE) else: ntp_working = not self.data.timezone.nontp self._ntpSwitch.set_active(ntp_working) @gtk_action_wait def _set_timezone(self, timezone): """ Sets timezone to the city/region comboboxes and the timezone map. :param timezone: timezone to set :type timezone: str :return: if successfully set or not :rtype: bool """ parts = timezone.split("/", 1) if len(parts) != 2: # invalid timezone cannot be set return False region, city = parts self._set_combo_selection(self._regionCombo, region) self._set_combo_selection(self._cityCombo, city) return True @gtk_action_nowait def add_to_store_xlated(self, store, item, xlated): store.append([item, xlated]) @gtk_action_nowait def add_to_store(self, store, item): store.append([item]) @gtk_action_nowait def add_to_store_idx(self, store, idx, item): store.append([idx, item]) def existing_date(self, days_model, days_iter, user_data=None): if not days_iter: return False day = days_model[days_iter][0] #days 1-28 are in every month every year if day < 29: return True months_model = self._monthCombo.get_model() months_iter = self._monthCombo.get_active_iter() if not months_iter: return True years_model = self._yearCombo.get_model() years_iter = self._yearCombo.get_active_iter() if not years_iter: return True try: datetime.date(years_model[years_iter][0], months_model[months_iter][0], day) return True except ValueError: return False def _get_active_city(self): cities_model = self._cityCombo.get_model() cities_iter = self._cityCombo.get_active_iter() if not cities_iter: return None return cities_model[cities_iter][0] def _get_active_region(self): regions_model = self._regionCombo.get_model() regions_iter = self._regionCombo.get_active_iter() if not regions_iter: return None return regions_model[regions_iter][0] def city_in_region(self, model, itr, user_data=None): if not itr: return False city = model[itr][0] region = self._get_active_region() if not region: return False return city in self._regions_zones[region] def _set_amPm_part_sensitive(self, sensitive): for widget in (self._amPmUp, self._amPmDown, self._amPmLabel): widget.set_sensitive(sensitive) def _to_amPm(self, hours): if hours >= 12: day_phase = _("PM") else: day_phase = _("AM") new_hours = ((hours - 1) % 12) + 1 return (new_hours, day_phase) def _to_24h(self, hours, day_phase): correction = 0 if day_phase == _("AM") and hours == 12: correction = -12 elif day_phase == _("PM") and hours != 12: correction = 12 return (hours + correction) % 24 def _update_datetime(self): now = datetime.datetime.now(self._tz) if self._radioButton24h.get_active(): self._hoursLabel.set_text("%0.2d" % now.hour) else: hours, amPm = self._to_amPm(now.hour) self._hoursLabel.set_text("%0.2d" % hours) self._amPmLabel.set_text(amPm) self._minutesLabel.set_text("%0.2d" % now.minute) self._set_combo_selection(self._dayCombo, now.day) self._set_combo_selection(self._monthCombo, now.month) self._set_combo_selection(self._yearCombo, now.year) #GLib's timer is driven by the return value of the function. #It runs the fuction periodically while the returned value #is True. return True def _save_system_time(self): """ Returning False from this method removes the timer that would otherwise call it again and again. """ self._start_updating_timer_id = None if not flags.can_touch_runtime_system("save system time"): return False month = self._get_combo_selection(self._monthCombo)[0] if not month: return False year = self._get_combo_selection(self._yearCombo)[0] if not year: return False hours = int(self._hoursLabel.get_text()) if not self._radioButton24h.get_active(): hours = self._to_24h(hours, self._amPmLabel.get_text()) minutes = int(self._minutesLabel.get_text()) day = self._get_combo_selection(self._dayCombo)[0] #day may be None if there is no such in the selected year and month if day: isys.set_system_date_time(year, month, day, hours, minutes, tz=self._tz) #start the timer only when the spoke is shown if self._shown and not self._update_datetime_timer_id: self._update_datetime_timer_id = GLib.timeout_add_seconds( 1, self._update_datetime) #run only once (after first 2 seconds of inactivity) return False def _stop_and_maybe_start_time_updating(self, interval=2): """ This method is called in every date/time-setting button's callback. It removes the timer for updating displayed date/time (do not want to change it while user does it manually) and allows us to set new system date/time only after $interval seconds long idle on time-setting buttons. This is done by the _start_updating_timer that is reset in this method. So when there is $interval seconds long idle on date/time-setting buttons, self._save_system_time method is invoked. Since it returns False, this timer is then removed and only reactivated in this method (thus in some date/time-setting button's callback). """ #do not start timers if the spoke is not shown if not self._shown: self._update_datetime() self._save_system_time() return #stop time updating if self._update_datetime_timer_id: GLib.source_remove(self._update_datetime_timer_id) self._update_datetime_timer_id = None #stop previous $interval seconds timer (see below) if self._start_updating_timer_id: GLib.source_remove(self._start_updating_timer_id) #let the user change date/time and after $interval seconds of inactivity #save it as the system time and start updating the displayed date/time self._start_updating_timer_id = GLib.timeout_add_seconds( interval, self._save_system_time) def _set_combo_selection(self, combo, item): model = combo.get_model() if not model: return False itr = model.get_iter_first() while itr: if model[itr][0] == item: combo.set_active_iter(itr) return True itr = model.iter_next(itr) return False def _get_combo_selection(self, combo): """ Get the selected item of the combobox. :return: selected item or None """ model = combo.get_model() itr = combo.get_active_iter() if not itr or not model: return None, None return model[itr][0], model[itr][1] def _restore_old_city_region(self): """Restore stored "old" (or last valid) values.""" # check if there are old values to go back to if self._old_region and self._old_city: self._set_timezone(self._old_region + "/" + self._old_city) def on_up_hours_clicked(self, *args): self._stop_and_maybe_start_time_updating() hours = int(self._hoursLabel.get_text()) if self._radioButton24h.get_active(): new_hours = (hours + 1) % 24 else: amPm = self._amPmLabel.get_text() #let's not deal with magical AM/PM arithmetics new_hours = self._to_24h(hours, amPm) new_hours, new_amPm = self._to_amPm((new_hours + 1) % 24) self._amPmLabel.set_text(new_amPm) new_hours_str = "%0.2d" % new_hours self._hoursLabel.set_text(new_hours_str) def on_down_hours_clicked(self, *args): self._stop_and_maybe_start_time_updating() hours = int(self._hoursLabel.get_text()) if self._radioButton24h.get_active(): new_hours = (hours - 1) % 24 else: amPm = self._amPmLabel.get_text() #let's not deal with magical AM/PM arithmetics new_hours = self._to_24h(hours, amPm) new_hours, new_amPm = self._to_amPm((new_hours - 1) % 24) self._amPmLabel.set_text(new_amPm) new_hours_str = "%0.2d" % new_hours self._hoursLabel.set_text(new_hours_str) def on_up_minutes_clicked(self, *args): self._stop_and_maybe_start_time_updating() minutes = int(self._minutesLabel.get_text()) minutes_str = "%0.2d" % ((minutes + 1) % 60) self._minutesLabel.set_text(minutes_str) def on_down_minutes_clicked(self, *args): self._stop_and_maybe_start_time_updating() minutes = int(self._minutesLabel.get_text()) minutes_str = "%0.2d" % ((minutes - 1) % 60) self._minutesLabel.set_text(minutes_str) def on_updown_ampm_clicked(self, *args): self._stop_and_maybe_start_time_updating() if self._amPmLabel.get_text() == _("AM"): self._amPmLabel.set_text(_("PM")) else: self._amPmLabel.set_text(_("AM")) def on_region_changed(self, combo, *args): """ :see: on_city_changed """ region = self._get_active_region() if not region or region == self._old_region: # region entry being edited or old_value chosen, no action needed # @see: on_city_changed return self._citiesFilter.refilter() # Set the city to the first one available in this newly selected region. zone = self._regions_zones[region] firstCity = sorted(list(zone))[0] self._set_combo_selection(self._cityCombo, firstCity) self._old_region = region self._old_city = firstCity def on_city_changed(self, combo, *args): """ ComboBox emits ::changed signal not only when something is selected, but also when its entry's text is changed. We need to distinguish between those two cases ('London' typed in the entry => no action until ENTER is hit etc.; 'London' chosen in the expanded combobox => update timezone map and do all necessary actions). Fortunately when entry is being edited, self._get_active_city returns None. """ timezone = None region = self._get_active_region() city = self._get_active_city() if not region or not city or (region == self._old_region and city == self._old_city): # entry being edited or no change, no actions needed return if city and region: timezone = region + "/" + city else: # both city and region are needed to form a valid timezone return if region == "Etc": # Etc timezones cannot be displayed on the map, so let's reset the # location and manually set a highlight with no location pin. self._tzmap.clear_location() if city in ("GMT", "UTC"): offset = 0.0 # The tzdb data uses POSIX-style signs for the GMT zones, which is # the opposite of whatever everyone else expects. GMT+4 indicates a # zone four hours west of Greenwich; i.e., four hours before. Reverse # the sign to match the libtimezone map. else: # Take the part after "GMT" offset = -float(city[3:]) self._tzmap.set_selected_offset(offset) else: # we don't want the timezone-changed signal to be emitted self._tzmap.set_timezone(timezone) # update "old" values self._old_city = city def on_entry_left(self, entry, *args): # user clicked somewhere else or hit TAB => finished editing entry.emit("activate") def on_city_region_key_released(self, entry, event, *args): if event.type == Gdk.EventType.KEY_RELEASE and \ event.keyval == Gdk.KEY_Escape: # editing canceled self._restore_old_city_region() def on_completion_match_selected(self, combo, model, itr): item = None if model and itr: item = model[itr][0] if item: self._set_combo_selection(combo, item) def on_city_region_text_entry_activated(self, entry): combo = entry.get_parent() model = combo.get_model() entry_text = entry.get_text().lower() for row in model: if entry_text == row[0].lower(): self._set_combo_selection(combo, row[0]) return # non-matching value entered, reset to old values self._restore_old_city_region() def on_month_changed(self, *args): self._stop_and_maybe_start_time_updating(interval=5) self._daysFilter.refilter() def on_day_changed(self, *args): self._stop_and_maybe_start_time_updating(interval=5) def on_year_changed(self, *args): self._stop_and_maybe_start_time_updating(interval=5) self._daysFilter.refilter() def on_location_changed(self, tz_map, location): if not location: return timezone = location.get_property('zone') # Updating the timezone will update the region/city combo boxes to match. # The on_city_changed handler will attempt to convert the timezone back # to a location and set it in the map, which we don't want, since we # already have a location. That's why we're here. with blockedHandler(self._cityCombo, self.on_city_changed): if self._set_timezone(timezone): # timezone successfully set self._tz = get_timezone(timezone) self._update_datetime() def on_timeformat_changed(self, button24h, *args): hours = int(self._hoursLabel.get_text()) amPm = self._amPmLabel.get_text() #connected to 24-hour radio button if button24h.get_active(): self._set_amPm_part_sensitive(False) new_hours = self._to_24h(hours, amPm) self._amPmRevealer.set_reveal_child(False) else: self._set_amPm_part_sensitive(True) new_hours, new_amPm = self._to_amPm(hours) self._amPmLabel.set_text(new_amPm) self._amPmRevealer.set_reveal_child(True) self._hoursLabel.set_text("%0.2d" % new_hours) 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) def _show_no_network_warning(self): self.set_warning(_("You need to set up networking first if you "\ "want to use NTP")) def _show_no_ntp_server_warning(self): self.set_warning(_("You have no working NTP server configured")) def on_ntp_switched(self, switch, *args): if switch.get_active(): #turned ON if not flags.can_touch_runtime_system("start NTP service"): #cannot touch runtime system, not much to do here return if not nm.nm_is_connected(): self._show_no_network_warning() switch.set_active(False) return else: self.clear_info() working_server = self._config_dialog.working_server if working_server is None: self._show_no_ntp_server_warning() else: #we need a one-time sync here, because chronyd would not change #the time as drastically as we need ntp.one_time_sync_async(working_server) ret = iutil.start_service(NTP_SERVICE) self._set_date_time_setting_sensitive(False) #if starting chronyd failed and chronyd is not running, #set switch back to OFF if (ret != 0) and not iutil.service_running(NTP_SERVICE): switch.set_active(False) else: #turned OFF if not flags.can_touch_runtime_system("stop NTP service"): #cannot touch runtime system, nothing to do here return self._set_date_time_setting_sensitive(True) ret = iutil.stop_service(NTP_SERVICE) #if stopping chronyd failed and chronyd is running, #set switch back to ON if (ret != 0) and iutil.service_running(NTP_SERVICE): switch.set_active(True) self.clear_info() def on_ntp_config_clicked(self, *args): self._config_dialog.refresh() with self.main_window.enlightbox(self._config_dialog.window): response = self._config_dialog.run() if response == 1: pools, servers = self._config_dialog.pools_servers self.data.timezone.ntpservers = ntp.pools_servers_to_internal( pools, servers) if self._config_dialog.working_server is None: self._show_no_ntp_server_warning() else: self.clear_info()
class PageKde(plugin.PluginUI): plugin_breadcrumb = 'ubiquity/text/breadcrumb_timezone' def __init__(self, controller, *args, **kwargs): self.controller = controller try: from PyQt5 import uic from ubiquity.frontend.kde_components.Timezone import TimezoneMap self.page = uic.loadUi('/usr/share/ubiquity/qt/stepLocation.ui') self.tzmap = TimezoneMap(self.page.map_frame) self.page.map_frame.layout().addWidget(self.tzmap) self.tzmap.zoneChanged.connect(self.mapZoneChanged) self.page.timezone_zone_combo.currentIndexChanged[int].connect( self.regionChanged) self.page.timezone_city_combo.currentIndexChanged[int].connect( self.cityChanged) except Exception as e: self.debug('Could not create timezone page: %s', e) self.page = None self.plugin_widgets = self.page self.online = False def plugin_set_online_state(self, state): self.online = state @plugin.only_this_page def refresh_timezones(self): lang = os.environ['LANG'].split('_', 1)[0] shortlist = self.controller.dbfilter.build_shortlist_region_pairs(lang) longlist = self.controller.dbfilter.build_region_pairs() self.page.timezone_zone_combo.clear() for pair in shortlist: self.page.timezone_zone_combo.addItem(pair[0], pair[1]) self.page.timezone_zone_combo.insertSeparator( self.page.timezone_zone_combo.count()) for pair in longlist: self.page.timezone_zone_combo.addItem(pair[0], pair[2]) @plugin.only_this_page def populateCities(self, regionIndex): self.page.timezone_city_combo.clear() code = str( self.page.timezone_zone_combo.itemData(regionIndex)) countries = self.controller.dbfilter.get_countries_for_region(code) if not countries: # must have been a country code itself countries = [code] shortlist, longlist = self.controller.dbfilter.build_timezone_pairs( countries) for pair in shortlist: self.page.timezone_city_combo.addItem(pair[0], pair[1]) if shortlist: self.page.timezone_city_combo.insertSeparator( self.page.timezone_city_combo.count()) for pair in longlist: self.page.timezone_city_combo.addItem(pair[0], pair[1]) return (len(countries) == 1 and self.controller.dbfilter.get_default_for_region(countries[0])) # called when the region(zone) combo changes @plugin.only_this_page def regionChanged(self, regionIndex): if self.controller.dbfilter is None: return self.page.timezone_city_combo.blockSignals(True) # self.page.timezone_city_combo.currentIndexChanged[int].disconnect( # self.cityChanged) default = self.populateCities(regionIndex) self.page.timezone_city_combo.blockSignals(False) # self.page.timezone_city_combo.currentIndexChanged[int].connect( # self.cityChanged) if default: self.tzmap.set_timezone(default) else: self.cityChanged(0) # called when the city combo changes def cityChanged(self, cityindex): zone = str( self.page.timezone_city_combo.itemData(cityindex)) self.tzmap.zoneChanged.disconnect(self.mapZoneChanged) self.tzmap.set_timezone(zone) self.tzmap.zoneChanged.connect(self.mapZoneChanged) @plugin.only_this_page def mapZoneChanged(self, loc, zone): self.page.timezone_zone_combo.blockSignals(True) self.page.timezone_city_combo.blockSignals(True) for i in range(self.page.timezone_zone_combo.count()): code = str(self.page.timezone_zone_combo.itemData(i)) countries = self.controller.dbfilter.get_countries_for_region(code) if not countries: # must have been a country code itself countries = [code] if loc.country in countries: self.page.timezone_zone_combo.setCurrentIndex(i) self.populateCities(i) break for i in range(self.page.timezone_city_combo.count()): code = str(self.page.timezone_city_combo.itemData(i)) if zone == code: self.page.timezone_city_combo.setCurrentIndex(i) self.cityChanged(i) break self.page.timezone_zone_combo.blockSignals(False) self.page.timezone_city_combo.blockSignals(False) def set_timezone(self, timezone): self.refresh_timezones() self.tzmap.set_timezone(timezone) def get_timezone(self): return self.tzmap.get_timezone()
#!/usr/bin/python from gi.repository import Gtk, TimezoneMap def on_timezone_changed(tz_map, timezone): print(timezone) def on_destroy(window): Gtk.main_quit() if __name__ == "__main__": window = Gtk.Window() tz_map = TimezoneMap.TimezoneMap() window.connect("destroy", on_destroy) tz_map.connect('location-changed', on_timezone_changed) window.add(tz_map) window.show_all() tz_map.set_timezone("Europe/Prague") Gtk.main()