[PATCH 2/2] Add language support spoke

Radek Vykydal rvykydal at redhat.com
Mon Mar 25 09:22:28 UTC 2013


---
 pyanaconda/ui/gui/spokes/langsupport.glade | 201 +++++++++++++++++++++++++++++
 pyanaconda/ui/gui/spokes/langsupport.py    | 195 ++++++++++++++++++++++++++++
 2 files changed, 396 insertions(+)
 create mode 100644 pyanaconda/ui/gui/spokes/langsupport.glade
 create mode 100644 pyanaconda/ui/gui/spokes/langsupport.py

diff --git a/pyanaconda/ui/gui/spokes/langsupport.glade b/pyanaconda/ui/gui/spokes/langsupport.glade
new file mode 100644
index 0000000..b7ef1ce
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/langsupport.glade
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <!-- interface-requires AnacondaWidgets 1.0 -->
+  <object class="GtkListStore" id="langsupportStore">
+    <columns>
+      <!-- column-name nativeName -->
+      <column type="gchararray"/>
+      <!-- column-name englishName -->
+      <column type="gchararray"/>
+      <!-- column-name langSetting -->
+      <column type="gchararray"/>
+      <!-- column-name langSupportSelected -->
+      <column type="gboolean"/>
+      <!-- column-name isAdditional -->
+      <column type="gboolean"/>
+    </columns>
+  </object>
+  <object class="GtkTreeModelFilter" id="langsupportStoreFilter">
+    <property name="child_model">langsupportStore</property>
+  </object>
+  <object class="AnacondaSpokeWindow" id="langsupportWindow">
+    <property name="startup_id">filler</property>
+    <property name="can_focus">False</property>
+    <property name="startup_id">filler</property>
+    <property name="window_name" translatable="yes">LANGUAGE SUPPORT</property>
+    <signal name="button-clicked" handler="on_back_clicked" swapped="no"/>
+    <child internal-child="main_box">
+      <object class="GtkBox" id="AnacondaSpokeWindow-main_box1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">6</property>
+        <child internal-child="nav_box">
+          <object class="GtkEventBox" id="AnacondaSpokeWindow-nav_box1">
+            <property name="app_paintable">True</property>
+            <property name="can_focus">False</property>
+            <child internal-child="nav_area">
+              <object class="GtkGrid" id="AnacondaSpokeWindow-nav_area1">
+                <property name="can_focus">False</property>
+                <property name="margin_left">6</property>
+                <property name="margin_right">6</property>
+                <property name="margin_top">6</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child internal-child="alignment">
+          <object class="GtkAlignment" id="AnacondaSpokeWindow-alignment1">
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="yalign">0</property>
+            <property name="top_padding">12</property>
+            <property name="bottom_padding">48</property>
+            <property name="left_padding">24</property>
+            <property name="right_padding">24</property>
+            <child internal-child="action_area">
+              <object class="GtkBox" id="AnacondaSpokeWindow-action_area1">
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkLabel" id="selectLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="label" translatable="yes">Select additional language support to be installed</property>
+                    <attributes>
+                      <attribute name="font-desc" value="Cantarell 12"/>
+                      <attribute name="weight" value="normal"/>
+                      <attribute name="scale" value="1"/>
+                    </attributes>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkBox" id="box1">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="orientation">vertical</property>
+                    <child>
+                      <object class="GtkScrolledWindow" id="langsupportScrolledwindow1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="hexpand">True</property>
+                        <property name="vexpand">True</property>
+                        <property name="shadow_type">in</property>
+                        <child>
+                          <object class="GtkTreeView" id="langsupportView">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="hexpand">True</property>
+                            <property name="vexpand">True</property>
+                            <property name="model">langsupportStoreFilter</property>
+                            <property name="headers_visible">False</property>
+                            <property name="headers_clickable">False</property>
+                            <property name="search_column">0</property>
+                            <child internal-child="selection">
+                              <object class="GtkTreeSelection" id="langsupportViewSelection"/>
+                            </child>
+                            <child>
+                              <object class="GtkTreeViewColumn" id="langsupportSelectedCol">
+                                <property name="title" translatable="yes">column</property>
+                                <signal name="clicked" handler="on_langsupport_toggled" swapped="no"/>
+                                <child>
+                                  <object class="GtkCellRendererToggle" id="langsupportSelectedRenderer">
+                                    <signal name="toggled" handler="on_langsupport_toggled" swapped="no"/>
+                                  </object>
+                                  <attributes>
+                                    <attribute name="sensitive">4</attribute>
+                                    <attribute name="activatable">4</attribute>
+                                    <attribute name="active">3</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkTreeViewColumn" id="nativeNameCol">
+                                <property name="title" translatable="yes">column</property>
+                                <property name="expand">True</property>
+                                <child>
+                                  <object class="GtkCellRendererText" id="nativeNameRenderer"/>
+                                  <attributes>
+                                    <attribute name="markup">0</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkTreeViewColumn" id="englishNameCol">
+                                <property name="title" translatable="yes">column</property>
+                                <property name="expand">True</property>
+                                <child>
+                                  <object class="GtkCellRendererText" id="englishNameRenderer"/>
+                                  <attributes>
+                                    <attribute name="markup">1</attribute>
+                                  </attributes>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkEntry" id="langsupportEntry">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="valign">start</property>
+                        <property name="margin_top">6</property>
+                        <property name="hexpand">True</property>
+                        <property name="invisible_char">●</property>
+                        <property name="invisible_char_set">True</property>
+                        <property name="secondary_icon_name">edit-clear-symbolic</property>
+                        <signal name="changed" handler="on_entry_changed" swapped="no"/>
+                        <signal name="icon-release" handler="on_clear_icon_clicked" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">2</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <placeholder/>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/pyanaconda/ui/gui/spokes/langsupport.py b/pyanaconda/ui/gui/spokes/langsupport.py
new file mode 100644
index 0000000..c586346
--- /dev/null
+++ b/pyanaconda/ui/gui/spokes/langsupport.py
@@ -0,0 +1,195 @@
+# Language support selection spoke classes
+#
+# Copyright (C) 2011-2012  Red Hat, Inc.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# the GNU General Public License v.2, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY expressed or implied, including the implied warranties of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
+# Public License for more details.  You should have received a copy of the
+# GNU General Public License along with this program; if not, write to the
+# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the
+# source code or documentation are not subject to the GNU General Public
+# License and may only be used or replicated with the express permission of
+# Red Hat, Inc.
+#
+# Red Hat Author(s): Radek Vykydal <rvykydal at redhat.com>
+#
+
+import gettext
+_ = lambda x: gettext.ldgettext("anaconda", x)
+N_ = lambda x: x
+
+from gi.repository import Gtk, Pango
+from pyanaconda.flags import flags
+from pyanaconda.ui.gui.spokes import NormalSpoke
+from pyanaconda.ui.gui.categories.localization import LocalizationCategory
+from pyanaconda.localization import Language, LOCALE_PREFERENCES, expand_langs
+
+import re
+
+import logging
+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"]
+    mainWidgetName = "langsupportWindow"
+    uiFile = "spokes/langsupport.glade"
+
+    category = LocalizationCategory
+
+    icon = "accessories-character-map-symbolic"
+    title = N_("_LANGUAGE SUPPORT")
+
+    def __init__(self, *args, **kwargs):
+        NormalSpoke.__init__(self, *args, **kwargs)
+
+    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)):
+            column = self.builder.get_object(col)
+            renderer = self.builder.get_object(rend)
+            column.set_cell_data_func(renderer, self._mark_selected_bold, idx)
+
+        language = Language(LOCALE_PREFERENCES, territory=None)
+        # source of lang code <-> UI name mapping
+        self.locale_infos_for_data = language.translations
+        self.locale_infos_for_ui = language.translations
+
+        for code, info in sorted(self.locale_infos_for_ui.items()):
+            self._add_language(self._langsupportStore, info.display_name,
+                               info.english_name, info.short_name,
+                               False, True)
+
+        self._select_language(self._langsupportStore, self.data.lang.lang)
+
+    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]]
+
+    def refresh(self):
+        lang_infos = self._find_localeinfos_for_code(self.data.lang.lang, self.locale_infos_for_ui)
+        lang_short_names = [info.short_name for info in lang_infos]
+        if len(lang_short_names) > 1:
+            log.warning("Found multiple locales for lang %s: %s, picking first" %
+                        (self.data.lang.lang, lang_short_names))
+        # Just take the first found
+        # TODO - for corner cases choose the one that is common prefix
+        lang_short_names = lang_short_names[:1]
+
+        addsupp_short_names = []
+        for code in self.data.lang.addsupport:
+            code_infos = self._find_localeinfos_for_code(code, self.locale_infos_for_ui)
+            addsupp_short_names.extend(info.short_name for info in code_infos)
+
+        for row in self._langsupportStore:
+            if row[COL_LANG_SETTING] in addsupp_short_names:
+                row[COL_SELECTED] = True
+            if row[COL_LANG_SETTING] in lang_short_names:
+                row[COL_SELECTED] = True
+                row[COL_IS_ADDITIONAL] = False
+
+    @property
+    def showable(self):
+        return not flags.livecdInstall
+
+    @property
+    def status(self):
+        # TODO: translate
+        infos = set(self._find_localeinfos_for_code(self.data.lang.lang, self.locale_infos_for_data)[:1])
+        for code in self.data.lang.addsupport:
+            infos.update(self._find_localeinfos_for_code(code, self.locale_infos_for_data))
+        return ", ".join(info.english_name for info in infos)
+
+    @property
+    def mandatory(self):
+        return False
+
+    @property
+    def completed(self):
+        return True
+
+    def _find_localeinfos_for_code(self, code, infos):
+        try:
+            retval = [infos[code]]
+        except KeyError:
+            retval = [info for _code, info in infos.items()
+                      if code in expand_langs(_code)]
+            log.debug("locale info 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('\..*', '', setting), native),
+                     english, setting, selected, additional])
+
+    def _select_language(self, store, language):
+        itr = store.get_iter_first()
+        while itr and language not in 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 _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) = Pango.parse_markup(model[itr][COL_NATIVE_NAME], -1, "_")
+        english = model[itr][COL_ENGLISH_NAME]
+        entry = self._langsupportEntry.get_text().strip()
+
+        # Nothing in the text entry?  Display everything.
+        if not entry:
+            return True
+
+        # Otherwise, filter the list showing only what is matched by the
+        # text entry.  Either the English or native names can match.
+        lowered = entry.lower()
+        if lowered in native.lower() or lowered in english.lower():
+            return True
+        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 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
+
+    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()
-- 
1.7.11.7



More information about the anaconda-patches mailing list