[PATCH 6/7] Rework the Langsupport spoke to work with all locales

Vratislav Podzimek vpodzime at redhat.com
Tue Sep 3 14:27:08 UTC 2013


On Tue, 2013-09-03 at 14:43 +0200, Radek Vykydal wrote:
> On 08/30/2013 11:15 AM, Vratislav Podzimek wrote:
> > diff --git a/pyanaconda/ui/gui/spokes/langsupport.py b/pyanaconda/ui/gui/spokes/langsupport.py
> > index 5f44599..6f75ebc 100644
> > --- a/pyanaconda/ui/gui/spokes/langsupport.py
> > +++ b/pyanaconda/ui/gui/spokes/langsupport.py
> > @@ -17,6 +17,7 @@
> >   # Red Hat, Inc.
> >   #
> >   # Red Hat Author(s): Radek Vykydal <rvykydal at redhat.com>
> > +#                    Vratislav Podzimek <vpodzime at redhat.com>
> >   #
> >   
> >   from gi.repository import Gtk, Pango
> > @@ -25,6 +26,7 @@ from pyanaconda.i18n import N_
> >   from pyanaconda.iutil import strip_accents
> >   from pyanaconda.ui.gui.spokes import NormalSpoke
> >   from pyanaconda.ui.gui.categories.localization import LocalizationCategory
> > +from pyanaconda.ui.gui.utils import set_treeview_selection
> >   from pyanaconda import localization
> >   
> >   import re
> > @@ -34,14 +36,8 @@ log = logging.getLogger("anaconda")
> >   
> >   __all__ = ["LangsupportSpoke"]
> >   
> > -COL_NATIVE_NAME   = 0
> > -COL_ENGLISH_NAME  = 1
> > -COL_LANG_SETTING  = 2
> > -COL_SELECTED      = 3
> > -COL_IS_ADDITIONAL = 4
> > -
> >   class LangsupportSpoke(NormalSpoke):
> > -    builderObjects = ["langsupportStore", "langsupportStoreFilter", "langsupportWindow"]
> > +    builderObjects = ["languageStore", "languageStoreFilter", "localeStore", "langsupportWindow"]
> >       mainWidgetName = "langsupportWindow"
> >       uiFile = "spokes/langsupport.glade"
> >   
> > @@ -52,60 +48,57 @@ class LangsupportSpoke(NormalSpoke):
> >   
> >       def __init__(self, *args, **kwargs):
> >           NormalSpoke.__init__(self, *args, **kwargs)
> > +        self._selected_locales = set()
> >   
> >       def initialize(self):
> > -        self._langsupportStore = self.builder.get_object("langsupportStore")
> > -        self._langsupportEntry = self.builder.get_object("langsupportEntry")
> > -        self._langsupportStoreFilter = self.builder.get_object("langsupportStoreFilter")
> > -        self._langsupportStoreFilter.set_visible_func(self._matches_entry, None)
> > -
> > -        # mark selected items in language list bold
> > -        for col, rend, idx in (("englishNameCol", "englishNameRenderer", COL_ENGLISH_NAME),
> > -                               ("nativeNameCol", "nativeNameRenderer", COL_NATIVE_NAME)):
> > +        self._languageStore = self.builder.get_object("languageStore")
> > +        self._languageEntry = self.builder.get_object("languageEntry")
> > +        self._languageStoreFilter = self.builder.get_object("languageStoreFilter")
> > +        self._languageStoreFilter.set_visible_func(self._matches_entry, None)
> > +        self._langView = self.builder.get_object("languageView")
> > +        self._langSelectedRenderer = self.builder.get_object("langSelectedRenderer")
> > +        self._langSelectedColumn = self.builder.get_object("langSelectedColumn")
> > +        self._langSelection = self.builder.get_object("languageViewSelection")
> > +        self._localeStore = self.builder.get_object("localeStore")
> > +        self._localeView = self.builder.get_object("localeView")
> > +
> > +        # fill the list with available translations
> > +        for lang in localization.get_available_translations():
> > +            self._add_language(self._languageStore,
> > +                               localization.get_native_name(lang),
> > +                               localization.get_english_name(lang), lang)
> > +
> > +        # render a right arrow for the chosen language
> > +        self._right_arrow = Gtk.Image.new_from_file("/usr/share/anaconda/pixmaps/right-arrow-icon.png")
> > +        self._langSelectedColumn.set_cell_data_func(self._langSelectedRenderer,
> > +                                                    self._render_lang_selected)
> > +
> > +        # mark selected locales and languages with selected locales bold
> > +        localeNativeColumn = self.builder.get_object("localeNativeName")
> > +        localeNativeNameRenderer = self.builder.get_object("localeNativeNameRenderer")
> > +        localeNativeColumn.set_cell_data_func(localeNativeNameRenderer,
> > +                                              self._mark_selected_locale_bold)
> > +
> > +        for col, rend in [("nativeName", "nativeNameRenderer"),
> > +                          ("englishName", "englishNameRenderer")]:
> >               column = self.builder.get_object(col)
> >               renderer = self.builder.get_object(rend)
> > -            column.set_cell_data_func(renderer, self._mark_selected_bold, idx)
> > -
> > -        # source of lang code <-> UI name mapping
> > -        # (localization.get_available_translations() returns a generator)
> > -        self.locale_infos_for_data = list(localization.get_available_translations())
> > -        self.locale_infos_for_ui = self.locale_infos_for_data[:]
> > -
> > -        for locale in sorted(self.locale_infos_for_ui):
> > -            self._add_language(self._langsupportStore,
> > -                               localization.get_native_name(locale),
> > -                               localization.get_english_name(locale),
> > -                               locale,
> > -                               False, True)
> > -
> > -        self._select_language(self._langsupportStore, self.data.lang.lang)
> > +            column.set_cell_data_func(renderer, self._mark_selected_language_bold)
> >   
> >       def apply(self):
> > -        self.data.lang.addsupport = [row[COL_LANG_SETTING]
> > -                                     for row in self._langsupportStore
> > -                                     if row[COL_SELECTED] and row[COL_IS_ADDITIONAL]]
> > +        # store only additional langsupport locales
> > +        self.data.lang.addsupport = list(sorted(self._selected_locales - set([self.data.lang.lang])))
> >   
> 
> The list constructor is not needed here.
Yeah, I've found out sorted() returns a list instead of generator while
I was writing those patches. Thanks!

> 
> 
> >       def refresh(self):
> > -        self._langsupportEntry.set_text("")
> > -        lang_infos = self._find_localeinfos_for_code(self.data.lang.lang, self.locale_infos_for_ui)
> > -        if len(lang_infos) > 1:
> > -            log.warning("Found multiple locales for lang %s: %s, picking first",
> > -                        self.data.lang.lang, lang_infos)
> > -        # Just take the first found
> > -        # TODO - for corner cases choose the one that is common prefix
> > -        lang_infos = lang_infos[:1]
> > -
> > -        addsupp_infos = []
> > -        for code in self.data.lang.addsupport:
> > -            code_infos = self._find_localeinfos_for_code(code, self.locale_infos_for_ui)
> > -            addsupp_infos.extend(code_infos)
> > -
> > -        for row in self._langsupportStore:
> > -            if row[COL_LANG_SETTING] in addsupp_infos:
> > -                row[COL_SELECTED] = True
> > -            if row[COL_LANG_SETTING] in lang_infos:
> > -                row[COL_SELECTED] = True
> > -                row[COL_IS_ADDITIONAL] = False
> > +        self._languageEntry.set_text("")
> > +        self._selected_locales = set(self._installed_langsupports)
> > +
> > +        # select the first locale from the "to be installed" langsupports
> > +        self._select_locale(self._installed_langsupports[0])
> > +
> > +    @property
> > +    def _installed_langsupports(self):
> > +        return sorted(self.data.lang.addsupport + [self.data.lang.lang])
> >   
> >       @property
> >       def showable(self):
> > @@ -113,13 +106,8 @@ class LangsupportSpoke(NormalSpoke):
> >   
> >       @property
> >       def status(self):
> > -        # TODO: translate
> > -        infos = self._find_localeinfos_for_code(self.data.lang.lang, self.locale_infos_for_data)[:1]
> > -        for code in self.data.lang.addsupport:
> > -            for info in self._find_localeinfos_for_code(code, self.locale_infos_for_data):
> > -                if info not in infos:
> > -                    infos.append(info)
> > -        return ", ".join(localization.get_english_name(info) for info in infos)
> > +        return ", ".join(localization.get_native_name(locale)
> > +                         for locale in self._installed_langsupports)
> 
> IIRC, on proposal in a review I added a patch to keep data.lang.lang first,
> we might want to keep it.
okay, will change that.

> 
> >   
> >       @property
> >       def mandatory(self):
> > @@ -129,42 +117,64 @@ class LangsupportSpoke(NormalSpoke):
> >       def completed(self):
> >           return True
> >   
> > -    def _find_localeinfos_for_code(self, code, infos):
> > -        if code in infos:
> > -            return [code]
> > -        else:
> > -            retval = [info for info in infos
> > -                      if code in localization.expand_langs(info)]
> > -            log.debug("locale infos found for %s: %s", code, retval)
> > -            return retval
> > -
> > -    def _add_language(self, store, native, english, setting, selected, additional):
> > -        store.append(['<span lang="%s">%s</span>' % (re.sub(r'\..*', '', setting), native),
> > -                     english, setting, selected, additional])
> > -
> > -    def _select_language(self, store, language):
> > -        itr = store.get_iter_first()
> > -        while itr and language not in localization.expand_langs(store[itr][COL_LANG_SETTING]):
> > -            itr = store.iter_next(itr)
> > -
> > -        # If we were provided with an unsupported language, just use the default.
> > -        if not itr:
> > -            return
> > -
> > -        treeview = self.builder.get_object("langsupportView")
> > -        selection = treeview.get_selection()
> > -        selection.select_iter(itr)
> > -        path = store.get_path(itr)
> > -        treeview.scroll_to_cell(path)
> > +    def _add_language(self, store, native, english, lang):
> > +        native_span = '<span lang="%s">%s</span>' % (lang, native)
> > +        store.append([native_span, english, lang])
> > +
> > +    def _addLocale(self, store, native, locale):
> > +        native_span = '<span lang="%s">%s</span>' % (re.sub(r'\..*', '', locale), native)
> > +
> > +        # native, locale, selected, additional
> > +        store.append([native_span, locale, locale in self._selected_locales,
> > +                      locale != self.data.lang.lang])
> > +
> > +    def _refresh_locale_store(self, lang):
> > +        """Refresh the localeStore with locales for the given language."""
> > +
> > +        self._localeStore.clear()
> > +        locales = localization.get_language_locales(lang)
> > +        for locale in locales:
> > +            self._addLocale(self._localeStore,
> > +                            localization.get_native_name(locale),
> > +                            locale)
> > +
> > +        # select the first locale (with the highest rank)
> > +        set_treeview_selection(self._localeView, locales[0], col=1)
> > +
> > +    def _select_locale(self, locale):
> > +        """
> > +        Try to select the given locale in the language and locale
> > +        treeviews. This method tries to find the best match for the given
> > +        locale.
> > +
> > +        :return: a pair of selected iterators (language and locale)
> > +        :rtype: a pair of GtkTreeIter or None objects
> > +
> > +        """
> > +
> > +        # get lang and select it
> > +        parts = localization.parse_langcode(locale)
> > +        if "language" not in parts:
> > +            # invalid locale, cannot select
> > +            return (None, None)
> > +
> > +        lang_itr = set_treeview_selection(self._langView, parts["language"], col=2)
> > +        self._refresh_locale_store(parts["language"]) #XXX: needed?
> > +
> > +        # find matches and use the one with the highest rank
> > +        locales = localization.get_language_locales(locale)
> > +        locale_itr = set_treeview_selection(self._localeView, locales[0], col=1)
> > +
> > +        return (lang_itr, locale_itr)
> >   
> >       def _matches_entry(self, model, itr, *args):
> >           # Need to strip out the pango markup before attempting to match.
> >           # Otherwise, starting to type "span" for "spanish" will match everything
> >           # due to the enclosing span tag.
> >           # (success, attrs, native, accel)
> > -        native = Pango.parse_markup(model[itr][COL_NATIVE_NAME], -1, "_")[2]
> > -        english = model[itr][COL_ENGLISH_NAME]
> > -        entry = self._langsupportEntry.get_text().strip()
> > +        native = Pango.parse_markup(model[itr][0], -1, "_")[2]
> > +        english = model[itr][1]
> > +        entry = self._languageEntry.get_text().strip()
> >   
> >           # Nothing in the text entry?  Display everything.
> >           if not entry:
> > @@ -179,21 +189,53 @@ class LangsupportSpoke(NormalSpoke):
> >           else:
> >               return False
> >   
> > -    def _mark_selected_bold(self, column, renderer, model, itr, idx):
> > -        value = model[itr][idx]
> > -        if model[itr][COL_SELECTED]:
> > -            value = "<b>%s</b>" % value
> > -        renderer.set_property("markup", value)
> > +    def _render_lang_selected(self, column, renderer, model, itr, user_data=None):
> > +        (lang_store, sel_itr) = self._langSelection.get_selected()
> > +
> > +        lang_locales = set(localization.get_language_locales(model[itr][2]))
> > +        if sel_itr and lang_store[sel_itr][2] == model[itr][2]:
> > +            renderer.set_property("pixbuf", self._right_arrow.get_pixbuf())
> > +        else:
> > +            renderer.set_property("pixbuf", None)
> > +
> > +    def _mark_selected_locale_bold(self, column, renderer, model, itr, user_data=None):
> > +        value = model[itr][0]
> 
> value is unused
Good catch, thanks!

-- 
Vratislav Podzimek

Anaconda Rider | Red Hat, Inc. | Brno - Czech Republic



More information about the anaconda-patches mailing list