[PATCH 6/7] Rework the Langsupport spoke to work with all locales
Radek Vykydal
rvykydal at redhat.com
Tue Sep 3 12:43:36 UTC 2013
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.
> 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.
commit 72debbc57f8f72853f1cae4188fc012aae1f0ec1
Author: Radek Vykydal <rvykydal at redhat.com>
Date: Wed Apr 24 18:23:39 2013 +0200
langsupport spoke: keep data.lang.lang first in status of spoke
>
> @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
> + if model[itr][2]:
> + renderer.set_property("weight", Pango.Weight.BOLD.real)
> + else:
> + renderer.set_property("weight", Pango.Weight.NORMAL.real)
> +
> + def _mark_selected_language_bold(self, column, renderer, model, itr, user_data=None):
> + lang_locales = set(localization.get_language_locales(model[itr][2]))
> + if not lang_locales.isdisjoint(self._selected_locales):
> + renderer.set_property("weight", Pango.Weight.BOLD.real)
> + else:
> + renderer.set_property("weight", Pango.Weight.NORMAL.real)
> +
> + # Signal handlers.
> + def on_lang_selection_changed(self, selection):
> + (store, selected) = selection.get_selected_rows()
> +
> + if selected:
> + lang = store[selected[0]][2]
> + self._refresh_locale_store(lang)
> + else:
> + self._localeStore.clear()
> +
> + def on_locale_toggled(self, renderer, path):
> + itr = self._localeStore.get_iter(path)
> + row = self._localeStore[itr]
>
> - def on_langsupport_toggled(self, renderer, path):
> - selected = not self._langsupportStoreFilter[path][COL_SELECTED]
> - itr = self._langsupportStoreFilter.get_iter(path)
> - itr = self._langsupportStoreFilter.convert_iter_to_child_iter(itr)
> - self._langsupportStore[itr][COL_SELECTED] = selected
> + row[2] = not row[2]
> +
> + if row[2]:
> + self._selected_locales.add(row[1])
> + else:
> + self._selected_locales.remove(row[1])
>
> def on_clear_icon_clicked(self, entry, icon_pos, event):
> if icon_pos == Gtk.EntryIconPosition.SECONDARY:
> entry.set_text("")
>
> def on_entry_changed(self, *args):
> - self._langsupportStoreFilter.refilter()
> + self._languageStoreFilter.refilter()
More information about the anaconda-patches
mailing list