source: ubiquity/trunk/fuentes/ubiquity/plugins/ubi-timezone.py @ 3069

Last change on this file since 3069 was 3069, checked in by kbut, 3 years ago

Update from upstream

File size: 28.3 KB
Line 
1# -*- coding: utf-8; Mode: Python; indent-tabs-mode: nil; tab-width: 4 -*-
2
3# Copyright (C) 2006, 2007, 2008 Canonical Ltd.
4# Written by Colin Watson <cjwatson@ubuntu.com>.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
20from __future__ import print_function
21
22import os
23import re
24import time
25from urllib.parse import quote
26
27import debconf
28import icu
29
30from ubiquity import i18n, misc, plugin
31import ubiquity.tz
32
33
34NAME = 'timezone'
35# after partman for default install, but language for oem install
36AFTER = ['partman', 'language']
37WEIGHT = 10
38
39_geoname_url = 'http://geoname-lookup.ubuntu.com/?query=%s&release=%s'
40
41
42class PageGtk(plugin.PluginUI):
43    plugin_title = 'ubiquity/text/timezone_heading_label'
44
45    def __init__(self, controller, *args, **kwargs):
46        self.controller = controller
47        from gi.repository import Gtk
48        builder = Gtk.Builder()
49        self.controller.add_builder(builder)
50        builder.add_from_file(os.path.join(
51            os.environ['UBIQUITY_GLADE'], 'stepLocation.ui'))
52        builder.connect_signals(self)
53        self.page = builder.get_object('stepLocation')
54        self.city_entry = builder.get_object('timezone_city_entry')
55        self.map_window = builder.get_object('timezone_map_window')
56        self.setup_page()
57        self.timezone = None
58        self.zones = []
59        self.plugin_widgets = self.page
60        self.geoname_cache = {}
61        self.geoname_session = None
62        self.geoname_timeout_id = None
63        self.online = False
64
65    def plugin_set_online_state(self, state):
66        self.online = state
67
68    def plugin_translate(self, lang):
69        # c = self.controller
70        # if c.get_string('ubiquity/imported/time-format', lang) == '12-hour':
71        #    fmt = c.get_string('ubiquity/imported/12-hour', lang)
72        # else:
73        #    fmt = c.get_string('ubiquity/imported/24-hour', lang)
74        # self.tzmap.set_time_format(fmt)
75        inactive = self.controller.get_string(
76            'timezone_city_entry_inactive_label', lang)
77        self.city_entry.set_placeholder_text(inactive)
78
79    def set_timezone(self, timezone):
80        self.zones = self.controller.dbfilter.build_timezone_list()
81        self.tzmap.set_timezone(timezone)
82
83    def get_timezone(self):
84        return self.timezone
85
86    def select_city(self, unused_widget, city):
87        city = city.get_property('zone')
88        loc = self.tzdb.get_loc(city)
89        if not loc:
90            self.controller.allow_go_forward(False)
91        else:
92            self.city_entry.set_text(loc.human_zone)
93            self.city_entry.set_position(-1)
94            self.timezone = city
95            self.controller.allow_go_forward(True)
96
97    def changed(self, entry):
98        from gi.repository import Gtk, GObject, GLib, Soup
99
100        text = misc.utf8(self.city_entry.get_text())
101        if not text:
102            return
103        # TODO if the completion widget has a selection, return?  How do we
104        # determine this?
105        if text in self.geoname_cache:
106            model = self.geoname_cache[text]
107            self.city_entry.get_completion().set_model(model)
108        else:
109            model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING,
110                                  GObject.TYPE_STRING, GObject.TYPE_STRING,
111                                  GObject.TYPE_STRING)
112
113            if self.geoname_session is None:
114                self.geoname_session = Soup.SessionAsync()
115            url = _geoname_url % (quote(text), misc.get_release().version)
116            message = Soup.Message.new('GET', url)
117            message.request_headers.append('User-agent', 'Ubiquity/1.0')
118            self.geoname_session.abort()
119            if self.geoname_timeout_id is not None:
120                GLib.source_remove(self.geoname_timeout_id)
121            self.geoname_timeout_id = \
122                GLib.timeout_add_seconds(2, self.geoname_timeout,
123                                         (text, model))
124            self.geoname_session.queue_message(message, self.geoname_cb,
125                                               (text, model))
126
127    def geoname_add_tzdb(self, text, model):
128        if len(model):
129            # already added
130            return
131
132        # TODO benchmark this
133        results = [
134            (name, self.tzdb.get_loc(city))
135            for name, city in [
136                (x[0], x[1])
137                for x in self.zones
138                if x[0].lower().split('(', 1)[-1].startswith(text.lower())]]
139        for result in results:
140            # We use name rather than loc.human_zone for i18n.
141            # TODO this looks pretty awful for US results:
142            # United States (New York) (United States)
143            # Might want to match the debconf format.
144            name, loc = result
145            if loc:
146                model.append([name, '', loc.human_country,
147                              str(loc.latitude), str(loc.longitude)])
148
149    def geoname_timeout(self, user_data):
150        text, model = user_data
151        self.geoname_add_tzdb(text, model)
152        self.geoname_timeout_id = None
153        self.city_entry.get_completion().set_model(model)
154        return False
155
156    def geoname_cb(self, session, message, user_data):
157        import syslog
158        import json
159        from gi.repository import GLib, Soup
160
161        text, model = user_data
162
163        if self.geoname_timeout_id is not None:
164            GLib.source_remove(self.geoname_timeout_id)
165            self.geoname_timeout_id = None
166        self.geoname_add_tzdb(text, model)
167
168        if message.status_code == Soup.KnownStatusCode.CANCELLED:
169            # Silently ignore cancellation.
170            pass
171        elif message.status_code != Soup.KnownStatusCode.OK:
172            # Log but otherwise ignore failures.
173            syslog.syslog(
174                'Geoname lookup for "%s" failed: %d %s' %
175                (text, message.status_code, message.reason_phrase))
176        else:
177            try:
178                for result in json.loads(message.response_body.data):
179                    model.append([
180                        result['name'], result['admin1'], result['country'],
181                        result['latitude'], result['longitude']])
182
183                # Only cache positive results.
184                self.geoname_cache[text] = model
185
186            except ValueError:
187                syslog.syslog(
188                    'Server return does not appear to be valid JSON.')
189
190        self.city_entry.get_completion().set_model(model)
191
192    def setup_page(self):
193        # TODO Put a frame around the completion to add contrast (LP: # 605908)
194        from gi.repository import Gtk, GLib
195        from gi.repository import TimezoneMap
196        self.tzdb = ubiquity.tz.Database()
197        self.tzmap = TimezoneMap.TimezoneMap()
198        self.tzmap.connect('location-changed', self.select_city)
199        self.map_window.add(self.tzmap)
200        self.tzmap.show()
201
202        def is_separator(m, i):
203            return m[i][0] is None
204
205        self.timeout_id = 0
206
207        def queue_entry_changed(entry):
208            if self.timeout_id:
209                GLib.source_remove(self.timeout_id)
210            self.timeout_id = GLib.timeout_add(300, self.changed, entry)
211
212        self.city_entry.connect('changed', queue_entry_changed)
213        completion = Gtk.EntryCompletion()
214        self.city_entry.set_completion(completion)
215        completion.set_inline_completion(True)
216        completion.set_inline_selection(True)
217
218        def match_selected(completion, model, iterator):
219            # Select on map.
220            lat = float(model[iterator][3])
221            lon = float(model[iterator][4])
222            self.tzmap.set_coords(lon, lat)
223
224            self.city_entry.set_text(model[iterator][0])
225            self.city_entry.set_position(-1)
226            return True
227        completion.connect('match-selected', match_selected)
228
229        def match_func(completion, key, iterator, data):
230            # We've already determined that it's a match in entry_changed.
231            return True
232
233        def data_func(column, cell, model, iterator, data):
234            row = model[iterator]
235            if row[1]:
236                # The result came from geonames, and thus has an administrative
237                # zone attached to it.
238                text = '%s <small>(%s, %s)</small>' % (row[0], row[1], row[2])
239            else:
240                text = '%s <small>(%s)</small>' % (row[0], row[2])
241            cell.set_property('markup', text)
242        cell = Gtk.CellRendererText()
243        completion.pack_start(cell, True)
244        completion.set_match_func(match_func, None)
245        completion.set_cell_data_func(cell, data_func, None)
246
247
248class PageKde(plugin.PluginUI):
249    plugin_breadcrumb = 'ubiquity/text/breadcrumb_timezone'
250
251    def __init__(self, controller, *args, **kwargs):
252        self.controller = controller
253        try:
254            from PyQt4 import uic
255            from ubiquity.frontend.kde_components.Timezone import TimezoneMap
256
257            self.page = uic.loadUi('/usr/share/ubiquity/qt/stepLocation.ui')
258            self.tzmap = TimezoneMap(self.page.map_frame)
259            self.page.map_frame.layout().addWidget(self.tzmap)
260
261            self.tzmap.zoneChanged.connect(self.mapZoneChanged)
262            self.page.timezone_zone_combo.currentIndexChanged[int].connect(
263                self.regionChanged)
264            self.page.timezone_city_combo.currentIndexChanged[int].connect(
265                self.cityChanged)
266        except Exception as e:
267            self.debug('Could not create timezone page: %s', e)
268            self.page = None
269
270        self.plugin_widgets = self.page
271        self.online = False
272
273    def plugin_set_online_state(self, state):
274        self.online = state
275
276    @plugin.only_this_page
277    def refresh_timezones(self):
278        lang = os.environ['LANG'].split('_', 1)[0]
279        shortlist = self.controller.dbfilter.build_shortlist_region_pairs(lang)
280        longlist = self.controller.dbfilter.build_region_pairs()
281
282        self.page.timezone_zone_combo.clear()
283        for pair in shortlist:
284            self.page.timezone_zone_combo.addItem(pair[0], pair[1])
285        self.page.timezone_zone_combo.insertSeparator(
286            self.page.timezone_zone_combo.count())
287        for pair in longlist:
288            self.page.timezone_zone_combo.addItem(pair[0], pair[2])
289
290    @plugin.only_this_page
291    def populateCities(self, regionIndex):
292        self.page.timezone_city_combo.clear()
293
294        code = str(
295            self.page.timezone_zone_combo.itemData(regionIndex).toPyObject())
296        countries = self.controller.dbfilter.get_countries_for_region(code)
297        if not countries:  # must have been a country code itself
298            countries = [code]
299
300        shortlist, longlist = self.controller.dbfilter.build_timezone_pairs(
301            countries)
302
303        for pair in shortlist:
304            self.page.timezone_city_combo.addItem(pair[0], pair[1])
305        if shortlist:
306            self.page.timezone_city_combo.insertSeparator(
307                self.page.timezone_city_combo.count())
308        for pair in longlist:
309            self.page.timezone_city_combo.addItem(pair[0], pair[1])
310
311        return (len(countries) == 1 and
312                self.controller.dbfilter.get_default_for_region(countries[0]))
313
314    # called when the region(zone) combo changes
315    @plugin.only_this_page
316    def regionChanged(self, regionIndex):
317        if self.controller.dbfilter is None:
318            return
319
320        self.page.timezone_city_combo.blockSignals(True)
321        # self.page.timezone_city_combo.currentIndexChanged[int].disconnect(
322        #    self.cityChanged)
323        default = self.populateCities(regionIndex)
324        self.page.timezone_city_combo.blockSignals(False)
325        # self.page.timezone_city_combo.currentIndexChanged[int].connect(
326        #    self.cityChanged)
327
328        if default:
329            self.tzmap.set_timezone(default)
330        else:
331            self.cityChanged(0)
332
333    # called when the city combo changes
334    def cityChanged(self, cityindex):
335        zone = str(
336            self.page.timezone_city_combo.itemData(cityindex).toPyObject())
337        self.tzmap.zoneChanged.disconnect(self.mapZoneChanged)
338        self.tzmap.set_timezone(zone)
339        self.tzmap.zoneChanged.connect(self.mapZoneChanged)
340
341    @plugin.only_this_page
342    def mapZoneChanged(self, loc, zone):
343        self.page.timezone_zone_combo.blockSignals(True)
344        self.page.timezone_city_combo.blockSignals(True)
345
346        for i in range(self.page.timezone_zone_combo.count()):
347            code = str(self.page.timezone_zone_combo.itemData(i).toPyObject())
348            countries = self.controller.dbfilter.get_countries_for_region(code)
349            if not countries:  # must have been a country code itself
350                countries = [code]
351            if loc.country in countries:
352                self.page.timezone_zone_combo.setCurrentIndex(i)
353                self.populateCities(i)
354                break
355
356        for i in range(self.page.timezone_city_combo.count()):
357            code = str(self.page.timezone_city_combo.itemData(i).toPyObject())
358            if zone == code:
359                self.page.timezone_city_combo.setCurrentIndex(i)
360                self.cityChanged(i)
361                break
362
363        self.page.timezone_zone_combo.blockSignals(False)
364        self.page.timezone_city_combo.blockSignals(False)
365
366    def set_timezone(self, timezone):
367        self.refresh_timezones()
368        self.tzmap.set_timezone(timezone)
369
370    def get_timezone(self):
371        return self.tzmap.get_timezone()
372
373
374class PageDebconf(plugin.PluginUI):
375    plugin_title = 'ubiquity/text/timezone_heading_label'
376
377    def __init__(self, controller, *args, **kwargs):
378        self.controller = controller
379        self.online = False
380
381    def plugin_set_online_state(self, state):
382        self.online = state
383
384
385class PageNoninteractive(plugin.PluginUI):
386    def __init__(self, controller, *args, **kwargs):
387        self.controller = controller
388        self.online = False
389
390    def plugin_set_online_state(self, state):
391        self.online = state
392
393    def set_timezone(self, timezone):
394        """Set the current selected timezone."""
395        self.timezone = timezone
396
397    def get_timezone(self):
398        """Get the current selected timezone."""
399        return self.timezone
400
401
402class Page(plugin.Plugin):
403    def prepare(self, unfiltered=False):
404        # TODO: This can go away once we have the ability to abort wget/rdate
405        if not self.ui.online:
406            self.preseed('tzsetup/geoip_server', '')
407            self.preseed('clock-setup/ntp', 'false')
408
409        clock_script = '/usr/share/ubiquity/clock-setup'
410        env = {'PATH': '/usr/share/ubiquity:' + os.environ['PATH']}
411
412        # TODO: replace with more general version pushed down into
413        # is_automatic or similar
414        try:
415            self.automatic_page = (
416                self.db.get("ubiquity/automatic/timezone") == "true")
417        except debconf.DebconfError:
418            self.automatic_page = False
419
420        if unfiltered:
421            # In unfiltered mode, localechooser is responsible for selecting
422            # the country, so there's no need to repeat the job here.
423            env['TZSETUP_NO_LOCALECHOOSER'] = '1'
424            return ([clock_script], ['CAPB', 'PROGRESS'], env)
425
426        self.timezones = []
427        self.regions = {}
428        self.tzdb = ubiquity.tz.Database()
429        self.multiple = False
430        try:
431            # Strip .UTF-8 from locale, icu doesn't parse it
432            locale = os.environ['LANG'].rsplit('.', 1)[0]
433            self.collator = icu.Collator.createInstance(icu.Locale(locale))
434        except:
435            self.collator = None
436        if self.is_automatic or self.automatic_page:
437            if self.db.fget('time/zone', 'seen') == 'true':
438                self.set_di_country(self.db.get('time/zone'))
439        else:
440            self.db.fset('time/zone', 'seen', 'false')
441            cc = self.db.get('debian-installer/country')
442            try:
443                self.db.get('tzsetup/country/%s' % cc)
444                # ... and if that succeeded:
445                self.multiple = True
446            except debconf.DebconfError:
447                pass
448        self.preseed('tzsetup/selected', 'false')
449        questions = ['^time/zone$', '^tzsetup/detected$', 'CAPB', 'PROGRESS']
450        return [clock_script], questions, env
451
452    def capb(self, capabilities):
453        self.frontend.debconf_progress_cancellable(
454            'progresscancel' in capabilities)
455
456    def run(self, priority, question):
457        if question == 'tzsetup/detected':
458            zone = self.db.get('time/zone')
459            self.ui.set_timezone(zone)
460        elif question == 'time/zone':
461            if self.multiple:
462                # Work around a debconf bug: REGISTER does not appear to
463                # give a newly-registered question the same default as the
464                # question associated with its template, unless we also
465                # RESET it.
466                self.db.reset(question)
467            zone = self.db.get(question)
468            # Some countries don't have a default zone, so just pick the
469            # first choice in the list.
470            if not zone:
471                choices_c = self.choices_untranslated(question)
472                if choices_c:
473                    zone = choices_c[0]
474            self.ui.set_timezone(zone)
475
476        if self.automatic_page:
477            # TODO: invade frontend's privacy to avoid entering infinite
478            # loop when trying to back up over timezone question (which
479            # isn't possible anyway since it's just after partitioning);
480            # this needs to be tidied up substantially when generalising
481            # ubiquity/automatic/*
482            self.frontend.backup = False
483            return True
484        else:
485            return plugin.Plugin.run(self, priority, question)
486
487    def get_default_for_region(self, region):
488        try:
489            return self.db.get('tzsetup/country/%s' % region)
490        except debconf.DebconfError:
491            return None
492
493    def collation_key(self, s):
494        if self.collator:
495            try:
496                return self.collator.getCollationKey(s[0]).getByteArray()
497            except:
498                pass
499        return s[0]
500
501    def get_countries_for_region(self, region):
502        if region in self.regions:
503            return self.regions[region]
504
505        try:
506            codes = self.choices_untranslated(
507                'localechooser/countrylist/%s' % region)
508        except debconf.DebconfError:
509            codes = []
510        self.regions[region] = codes
511        return codes
512
513    # Returns ['timezone', ...]
514    def build_timezone_list(self):
515        total = []
516        continents = self.choices_untranslated('localechooser/continentlist')
517        for continent in continents:
518            country_codes = self.choices_untranslated(
519                'localechooser/countrylist/%s' % continent.replace(' ', '_'))
520            for c in country_codes:
521                shortlist = self.build_shortlist_timezone_pairs(c, sort=False)
522                longlist = self.build_longlist_timezone_pairs(c, sort=False)
523                shortcopy = shortlist[:]
524                # TODO set() | set() instead.
525                for short_item in shortcopy:
526                    for long_item in longlist:
527                        if short_item[1] == long_item[1]:
528                            shortlist.remove(short_item)
529                            break
530                total += shortlist + longlist
531        return total
532
533    # Returns [('translated country name', None, 'region code')...] list
534    def build_region_pairs(self):
535        continents = self.choices_display_map('localechooser/continentlist')
536        names, codes = list(zip(*continents.items()))
537        codes = [c.replace(' ', '_') for c in codes]
538
539        nones = [None for _ in continents]
540        pairs = list(zip(names, nones, codes))
541        pairs.sort(key=self.collation_key)
542        return pairs
543
544    # Returns [('translated short list of countries', 'timezone')...] list
545    def build_shortlist_region_pairs(self, language_code):
546        try:
547            shortlist = self.choices_display_map(
548                'localechooser/shortlist/%s' % language_code)
549            # Remove any 'other' entry
550            for pair in shortlist.items():
551                if pair[1] == 'other':
552                    del shortlist[pair[0]]
553                    break
554            names, codes = list(zip(*shortlist.items()))
555            nones = [None for _ in names]
556            shortlist = list(zip(names, codes, nones))
557            shortlist.sort(key=self.collation_key)
558            return shortlist
559        except debconf.DebconfError:
560            return []
561
562    # Returns (shortlist, longlist)
563    def build_timezone_pairs(self, country_codes):
564        if len(country_codes) == 1:
565            shortlist = self.build_shortlist_timezone_pairs(country_codes[0])
566        else:
567            shortlist = []
568
569        longlist = []
570        for country_code in country_codes:
571            longlist += self.build_longlist_timezone_pairs(
572                country_code, sort=False)
573        longlist.sort(key=self.collation_key)
574
575        # There may be duplicate entries in the shortlist and longlist.
576        # Basically, the shortlist is most useful when there are non-city
577        # timezones that may be more familiar to denizens of that country.
578        # Big examples are the US in which people tend to think in terms of
579        # Eastern/Mountain/etc.  If we see a match in tz code, prefer the
580        # longlist's translation and strip it from the shortlist.
581        # longlist tends to be more complete in terms of translation coverage
582        # (i.e. libicu is more translated than tzsetup)
583        shortcopy = shortlist[:]
584        for short_item in shortcopy:
585            for long_item in longlist:
586                if short_item[1] == long_item[1]:
587                    shortlist.remove(short_item)
588                    break
589
590        return (shortlist, longlist)
591
592    def build_shortlist_timezone_pairs(self, country_code, sort=True):
593        try:
594            shortlist = self.choices_display_map(
595                'tzsetup/country/%s' % country_code)
596            for pair in list(shortlist.items()):
597                # Remove any 'other' entry, we don't need it
598                if pair[1] == 'other':
599                    del shortlist[pair[0]]
600            shortlist = list(shortlist.items())
601            if sort:
602                shortlist.sort(key=self.collation_key)
603            return shortlist
604        except debconf.DebconfError:
605            return []
606
607    def get_country_name(self, country):
608        # Relatively expensive algorithmically, but we don't call this often.
609        try:
610            continents = self.choices_untranslated(
611                'localechooser/continentlist')
612            for continent in continents:
613                choices = self.choices_display_map(
614                    'localechooser/countrylist/%s' %
615                    continent.replace(' ', '_'))
616                for name, code in choices.items():
617                    if code == country:
618                        return name
619        except debconf.DebconfError as e:
620            print("Couldn't get country name for %s: %s" % (country, e))
621        return None
622
623    def get_city_name_from_tzdata(self, tz):
624        city = tz.split('/', 1)[1]
625        # Iterate through tzdata's regions, check each region's tz list for
626        # our city.  Like get_country_name, this is inefficient (we could
627        # cache this info), but we don't need to run this often.
628        try:
629            areas = self.choices_untranslated('tzdata/Areas')
630            for area in areas:
631                zones = self.choices_display_map('tzdata/Zones/%s' % area)
632                for name, code in zones.items():
633                    if code == city:
634                        return name
635        except debconf.DebconfError as e:
636            print("Couldn't get city name for %s: %s" % (tz, e))
637        return None
638
639    def get_fallback_translation_for_tz(self, country, tz):
640        # We want to return either 'Country' or 'Country (City)', translated
641        # First, get country name.  We need that regardless
642        country_name = self.get_country_name(country)
643        if country_name is None:
644            return None
645        show_city = len(self.tzdb.cc_to_locs[country]) > 1
646        if show_city:
647            # First, try tzdata's translation.
648            city_name = self.get_city_name_from_tzdata(tz)
649            if city_name is None:
650                city_name = tz  # fall back to ASCII name
651            city_name = city_name.split('/')[-1]
652            return "%s (%s)" % (country_name, city_name)
653        else:
654            return country_name
655
656    # Returns [('translated long list of timezones', 'timezone')...] list
657    def build_longlist_timezone_pairs(self, country_code, sort=True):
658        if 'LANG' not in os.environ:
659            return []  # ?!
660        locale = os.environ['LANG'].rsplit('.', 1)[0]
661        tz_format = icu.SimpleDateFormat('VVVV', icu.Locale(locale))
662        now = time.time() * 1000
663        rv = []
664        try:
665            locs = self.tzdb.cc_to_locs[country_code]  # BV failed?
666        except:
667            # Some countries in tzsetup don't exist in zone.tab...
668            # Specifically BV (Bouvet Island) and
669            # HM (Heard and McDonald Islands).  Both are uninhabited.
670            locs = []
671        for location in locs:
672            timezone = icu.TimeZone.createTimeZone(location.zone)
673            if timezone.getID() == 'Etc/Unknown':
674                translated = None
675            else:
676                tz_format.setTimeZone(timezone)
677                translated = tz_format.format(now)
678            # Check if icu had a valid translation for this timezone.  If it
679            # doesn't, the returned string will look like GMT+0002 or somesuch.
680            # Sometimes the GMT is translated (like in Chinese), so we check
681            # for the number part.  icu does not indicate a 'translation
682            # failure' like this in any way...
683            if (translated is None or
684                    re.search('.*[-+][0-9][0-9]:?[0-9][0-9]$', translated)):
685                # Wasn't something that icu understood...
686                name = self.get_fallback_translation_for_tz(
687                    country_code, location.zone)
688                rv.append((name, location.zone))
689            else:
690                rv.append((translated, location.zone))
691        if sort:
692            rv.sort(key=self.collation_key)
693        return rv
694
695    # Returns [('translated long list of timezones', 'timezone')...] list
696    def build_longlist_timezone_pairs_by_continent(self, continent):
697        if 'LANG' not in os.environ:
698            return []  # ?
699        rv = []
700        try:
701            regions = self.choices_untranslated(
702                'localechooser/countrylist/%s' % continent)
703            for region in regions:
704                rv += self.build_longlist_timezone_pairs(region, sort=False)
705            rv.sort(key=self.collation_key)
706        except debconf.DebconfError:
707            pass
708        return rv
709
710    def set_di_country(self, zone):
711        location = self.tzdb.get_loc(zone)
712        if location:
713            self.preseed('debian-installer/country', location.country)
714
715    def ok_handler(self):
716        zone = self.ui.get_timezone()
717        if zone is None:
718            zone = self.db.get('time/zone')
719        else:
720            self.preseed('time/zone', zone)
721        self.set_di_country(zone)
722        plugin.Plugin.ok_handler(self)
723
724    def cleanup(self):
725        plugin.Plugin.cleanup(self)
726        self.ui.controller.set_locale(i18n.reset_locale(self.frontend))
727
728
729class Install(plugin.InstallPlugin):
730    def prepare(self, unfiltered=False):
731        tzsetup_script = '/usr/lib/ubiquity/tzsetup/post-base-installer'
732        clock_script = '/usr/share/ubiquity/clock-setup-apply'
733
734        if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
735            tzsetup_script += '-oem'
736
737        return (['sh', '-c', '%s && %s' % (tzsetup_script, clock_script)], [])
738
739    def install(self, target, progress, *args, **kwargs):
740        progress.info('ubiquity/install/timezone')
741        return plugin.InstallPlugin.install(
742            self, target, progress, *args, **kwargs)
Note: See TracBrowser for help on using the repository browser.