Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSayamindu Dasgupta <sayamindu@gmail.com>2008-11-14 16:36:15 (GMT)
committer Sayamindu Dasgupta <sayamindu@gmail.com>2008-11-14 16:36:15 (GMT)
commit1417167ba7e80852d95431f7734496c5aab13798 (patch)
tree07388de76559f805da8bf0c4b5b7c8dc57abd3da
parent7b4fb9054d97c8a3755860efd0ce292295124141 (diff)
dlo #8876: Make sugar control panel support selection of multiple languages
-rw-r--r--extensions/cpsection/language/Makefile.am2
-rw-r--r--extensions/cpsection/language/model.py97
-rw-r--r--extensions/cpsection/language/view.py250
3 files changed, 229 insertions, 120 deletions
diff --git a/extensions/cpsection/language/Makefile.am b/extensions/cpsection/language/Makefile.am
index ed8992c..209fc32 100644
--- a/extensions/cpsection/language/Makefile.am
+++ b/extensions/cpsection/language/Makefile.am
@@ -1,4 +1,4 @@
-sugardir = $(pythondir)/jarabe/controlpanel/language
+sugardir = $(pkgdatadir)/extensions/cpsection/language
sugar_PYTHON = \
__init__.py \
diff --git a/extensions/cpsection/language/model.py b/extensions/cpsection/language/model.py
index 404d9dd..aa831fb 100644
--- a/extensions/cpsection/language/model.py
+++ b/extensions/cpsection/language/model.py
@@ -53,82 +53,97 @@ def read_all_languages():
return locales
def _initialize():
- if set_language.__doc__ is None:
+ if set_languages.__doc__ is None:
# when running under 'python -OO', all __doc__ fields are None,
# so += would fail -- and this function would be unnecessary anyway.
return
languages = read_all_languages()
- set_language.__doc__ += '\n'
+ set_languages.__doc__ += '\n'
for lang in languages:
- set_language.__doc__ += '%s \n' % (lang[0].replace(' ', '_') + '/' +
+ set_languages.__doc__ += '%s \n' % (lang[0].replace(' ', '_') + '/' +
lang[1].replace(' ', '_'))
-def _write_i18n(lang):
+def _write_i18n(langs):
+ colon = ':'
+ langstr = colon.join(langs)
path = os.path.join(os.environ.get("HOME"), '.i18n')
- if os.access(path, os.W_OK) == 0:
+ if not os.access(path, os.W_OK):
print _standard_msg
fd = open(path, 'w')
fd.write('LANG="%s"\n' % _default_lang)
+ fd.write('LANGUAGE="%s"\n' % _default_lang)
fd.close()
else:
- fd = open(path, 'r')
- lines = fd.readlines()
- fd.close()
- for i in range(len(lines)):
- if lines[i][:5] == "LANG=":
- lines[i] = 'LANG="%s"\n' % lang
- fd = open(path, 'w')
- fd.writelines(lines)
- fd.close()
+ fd = open(path, 'w')
+ fd.write('LANG="%s"\n' % langs[0])
+ fd.write('LANGUAGE="%s"\n' % langstr)
+ fd.close()
-def get_language():
+def get_languages():
path = os.path.join(os.environ.get("HOME"), '.i18n')
- if os.access(path, os.R_OK) == 0:
+ if not os.access(path, os.R_OK):
print _standard_msg
fd = open(path, 'w')
fd.write('LANG="%s"\n' % _default_lang)
+ fd.write('LANGUAGE="%s"\n' % _default_lang)
fd.close()
- return _default_lang
+ return [_default_lang]
fd = open(path, "r")
lines = fd.readlines()
fd.close()
- lang = None
+ langlist = None
for line in lines:
- if line[:5] == "LANG=":
- lang = line[5:].replace('"', '')
+ if line.startswith("LANGUAGE="):
+ lang = line[9:].replace('"', '')
lang = lang.strip()
+ langlist = lang.split(':')
+ elif line.startswith("LANG="):
+ lang = line[9:].replace('"', '')
- return lang
+ # There might be cases where .i18n may not contain a LANGUAGE field
+ if langlist == None:
+ return [lang]
+ else:
+ return langlist
-def print_language():
- code = get_language()
+def print_languages():
+ codes = get_languages()
languages = read_all_languages()
- for lang in languages:
- if lang[2].split('.')[0] == code.split('.')[0]:
- print lang[0].replace(' ', '_') + '/' + lang[1].replace(' ', '_')
- return
- print (_("Language for code=%s could not be determined.") % code)
+ for code in codes:
+ found_lang = False
+ for lang in languages:
+ if lang[2].split('.')[0] == code.split('.')[0]:
+ print lang[0].replace(' ', '_') + '/' + lang[1].replace(' ', '_')
+ found_lang = True
+ break
+ if not found_lang:
+ print (_("Language for code=%s could not be determined.") % code)
-def set_language(language):
+def set_languages(languages):
"""Set the system language.
languages :
"""
- if language.endswith('utf8'):
- _write_i18n(language)
- return 1
- else:
- languages = read_all_languages()
- for lang, territory, locale in languages:
- code = lang.replace(' ', '_') + '/' \
- + territory.replace(' ', '_')
- if code == language:
- _write_i18n(locale)
- return 1
- print (_("Sorry I do not speak \'%s\'.") % language)
+ if isinstance(languages, str):
+ # This came from the commandline
+ #TODO: Support multiple languages from the command line
+ if languages.endswith('utf8'):
+ _write_i18n(languages)
+ return 1
+ else:
+ langs = read_all_languages()
+ for lang, territory, locale in langs:
+ code = lang.replace(' ', '_') + '/' \
+ + territory.replace(' ', '_')
+ if code == languages:
+ _write_i18n(locale)
+ return 1
+ print (_("Sorry I do not speak \'%s\'.") % language)
+ else:
+ _write_i18n(languages)
# inilialize the docstrings for the language
_initialize()
diff --git a/extensions/cpsection/language/view.py b/extensions/cpsection/language/view.py
index 71a185f..82bc9ff 100644
--- a/extensions/cpsection/language/view.py
+++ b/extensions/cpsection/language/view.py
@@ -16,14 +16,22 @@
import gtk
import gobject
-from gettext import gettext as _
+import gettext
from sugar.graphics import style
from sugar.graphics import iconentry
+from sugar.graphics.icon import Icon
from jarabe.controlpanel.sectionview import SectionView
from jarabe.controlpanel.inlinealert import InlineAlert
+_translate_language = lambda msg: gettext.dgettext('iso_639', msg)
+_translate_country = lambda msg: gettext.dgettext('iso_3166', msg)
+
+CLASS = 'Language'
+ICON = 'module-language'
+TITLE = gettext.gettext('Language')
+
class Language(SectionView):
def __init__(self, model, alerts):
SectionView.__init__(self)
@@ -31,51 +39,23 @@ class Language(SectionView):
self._model = model
self.restart_alerts = alerts
self._lang_sid = 0
+ self._selected_lang_count = 0
+ self._labels = []
+ self._stores = []
+ self._comboboxes = []
+ self._add_remove_boxes = []
+ self._changed = False
self._cursor_change_handler = None
+ self._available_locales = self._model.read_all_languages()
+ self._selected_locales = self._model.get_languages()
+
self.set_border_width(style.DEFAULT_SPACING * 2)
self.set_spacing(style.DEFAULT_SPACING)
- self.connect("realize", self.__realize_cb)
-
- self._entry = iconentry.IconEntry()
- self._entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
- 'system-search')
- self._entry.add_clear_button()
- self._entry.modify_bg(gtk.STATE_INSENSITIVE,
- style.COLOR_WHITE.get_gdk_color())
- self._entry.modify_base(gtk.STATE_INSENSITIVE,
- style.COLOR_WHITE.get_gdk_color())
- self.pack_start(self._entry, False)
- self._entry.show()
-
- self._scrolled_window = gtk.ScrolledWindow()
- self._scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
- self._scrolled_window.set_shadow_type(gtk.SHADOW_IN)
-
- self._store = gtk.ListStore(gobject.TYPE_STRING,
- gobject.TYPE_STRING)
- locales = model.read_all_languages()
- for locale in locales:
- self._store.append([locale[2], '%s (%s)' %
- (locale[0], locale[1])])
-
- self._treeview = gtk.TreeView(self._store)
- self._treeview.set_search_entry(self._entry)
- self._treeview.set_search_equal_func(self._search)
- self._treeview.set_search_column(1)
- self._scrolled_window.add(self._treeview)
- self._treeview.show()
-
- self._language_column = gtk.TreeViewColumn(_('Language'))
- self._cell = gtk.CellRendererText()
- self._language_column.pack_start(self._cell, True)
- self._language_column.add_attribute(self._cell, 'text', 1)
- self._language_column.set_sort_column_id(1)
- self._treeview.append_column(self._language_column)
-
- self.pack_start(self._scrolled_window)
- self._scrolled_window.show()
+ self._table = gtk.Table(rows=1, columns=3, homogeneous=False)
+ self.pack_start(self._table, False)
+ self._table.show()
self._lang_alert_box = gtk.HBox(spacing=style.DEFAULT_SPACING)
self.pack_start(self._lang_alert_box, False)
@@ -89,54 +69,168 @@ class Language(SectionView):
self.setup()
- def setup(self):
- lang_code = self._model.get_language()
- for row in self._store:
- lang = lang_code.split('.')[0]
- lang_column = row[0].split('.')[0]
- if lang in lang_column:
- self._treeview.set_cursor(row.path, self._language_column,
- False)
- self._treeview.scroll_to_cell(row.path, self._language_column,
- True, 0.5, 0.5)
- break
+ def _add_row(self, locale_code=None):
+ '''Adds a row to the table'''
+
+ self._selected_lang_count += 1
+
+ self._table.resize(self._selected_lang_count, 3)
+
+ label = gtk.Label(str=str(self._selected_lang_count))
+ self._labels.append(label)
+ self._attach_to_table(label, 0, 1, padding=1)
+ label.show()
+
+
+ store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
+ for language, country, code in self._available_locales:
+ description = '%s (%s)' % (_translate_language(language), \
+ _translate_country(country))
+ store.append([code, description])
+
+ combobox = gtk.ComboBox(model=store)
+ cell = gtk.CellRendererText()
+ combobox.pack_start(cell)
+ combobox.add_attribute(cell, 'text', 1)
+
+ if locale_code:
+ for row in store:
+ lang = locale_code.split('.')[0]
+ lang_column = row[0].split('.')[0]
+ if lang in lang_column:
+ combobox.set_active_iter(row.iter)
+ break
+ else:
+ combobox.set_active(1)
+
+ combobox.connect('changed', self.__combobox_changed_cb)
+
+ self._stores.append(store)
+ self._comboboxes.append(combobox)
+ self._attach_to_table(combobox, 1, 2, yoptions=gtk.SHRINK)
+
+ add_remove_box = self._create_add_remove_box()
+ self._add_remove_boxes.append(add_remove_box)
+ self._attach_to_table(add_remove_box, 2, 3)
+
+ add_remove_box.show_all()
+
+ if self._selected_lang_count > 1:
+ previous_add_removes = self._add_remove_boxes[-2]
+ previous_add_removes.hide_all()
+
+ combobox.show()
+
+ def _attach_to_table(self, widget, row, column, padding=20, yoptions=gtk.FILL):
+ self._table.attach(widget, row, column, \
+ self._selected_lang_count - 1, self._selected_lang_count, \
+ xoptions=gtk.FILL, yoptions=yoptions, xpadding=padding, ypadding=padding)
+
+ def _delete_last_row(self):
+ '''Deletes the last row of the table'''
+
+ self._selected_lang_count -= 1
+
+ label, add_remove_box, combobox, store = self._get_last_row()
- self.needs_restart = False
- self._cursor_change_handler = self._treeview.connect( \
- "cursor-changed", self.__lang_changed_cd)
-
+ label.destroy()
+ add_remove_box.destroy()
+ combobox.destroy()
+ del(store)
+
+ self._table.resize(self._selected_lang_count, 3)
+
+ self._add_remove_boxes[-1].show_all()
+
+ def _get_last_row(self):
+ label = self._labels.pop()
+ add_remove_box = self._add_remove_boxes.pop()
+ combobox = self._comboboxes.pop()
+ store = self._stores.pop()
+
+ return label, add_remove_box, combobox, store
+
+ def setup(self):
+ for locale in self._selected_locales:
+ self._add_row(locale_code=locale)
+
def undo(self):
- self._treeview.disconnect(self._cursor_change_handler)
self._model.undo()
self._lang_alert.hide()
- def __realize_cb(self, widget):
- self._entry.grab_focus()
-
- def _search(self, model, column, key, iterator, data=None):
- value = model.get_value(iterator, column)
- if key.lower() in value.lower():
- return False
- return True
-
- def __lang_changed_cd(self, treeview, data=None):
- row = treeview.get_selection().get_selected()
- if not row[1]:
- return False
- if self._model.get_language() == self._store.get_value(row[1], 0):
+ def _create_add_remove_box(self):
+ '''Creates gtk.Hbox with add/remove buttons'''
+ add_icon = Icon(icon_name='list-add')
+
+ add_button = gtk.Button()
+ add_button.set_image(add_icon)
+ add_button.connect('clicked',
+ self.__add_button_clicked_cb)
+
+ remove_icon = Icon(icon_name='list-remove')
+ remove_button = gtk.Button()
+ remove_button.set_image(remove_icon)
+ remove_button.connect('clicked',
+ self.__remove_button_clicked_cb)
+
+ if self._selected_lang_count == 1:
+ remove_button.set_sensitive(False)
+
+ add_remove_box = gtk.HButtonBox()
+ add_remove_box.set_layout(gtk.BUTTONBOX_START)
+ add_remove_box.set_spacing(10)
+ add_remove_box.pack_start(add_button)
+ add_remove_box.pack_start(remove_button)
+
+ return add_remove_box
+
+ def __add_button_clicked_cb(self, button):
+ self._add_row()
+ self._check_change()
+
+ def __remove_button_clicked_cb(self, button):
+ self._delete_last_row()
+ self._check_change()
+
+ def __combobox_changed_cb(self, button):
+ self._check_change()
+
+ def _check_change(self):
+ selected_langs = self._get_selected_langs()
+ self._changed = (selected_langs != self._selected_locales)
+
+ if self._changed == False:
+ # The user reverted back to the original config
+ self.needs_restart = False
+ if 'lang' in self.restart_alerts:
+ self.restart_alerts.remove('lang')
+ self._lang_alert.hide()
+ if self._lang_sid:
+ gobject.source_remove(self._lang_sid)
+ self._model.undo()
return False
if self._lang_sid:
gobject.source_remove(self._lang_sid)
- self._lang_sid = gobject.timeout_add(self._APPLY_TIMEOUT,
- self.__lang_timeout_cb,
- self._store.get_value(row[1], 0))
+ self._lang_sid = gobject.timeout_add(self._APPLY_TIMEOUT,
+ self.__lang_timeout_cb,
+ selected_langs)
+
+ def _get_selected_langs(self):
+ new_codes = []
+ for combobox in self._comboboxes:
+ iter = combobox.get_active_iter()
+ model = combobox.get_model()
+ lang_code = model.get(iter, 0)[0]
+ new_codes.append(lang_code)
+
+ return new_codes
- def __lang_timeout_cb(self, code):
- self._lang_sid = 0
- self._model.set_language(code)
+ def __lang_timeout_cb(self, codes):
+ self._lang_sid = 0
+ self._model.set_languages(codes)
self.restart_alerts.append('lang')
- self.needs_restart = True
+ self.needs_restart = True
self._lang_alert.props.msg = self.restart_msg
self._lang_alert.show()
return False