From 1417167ba7e80852d95431f7734496c5aab13798 Mon Sep 17 00:00:00 2001 From: Sayamindu Dasgupta Date: Fri, 14 Nov 2008 16:36:15 +0000 Subject: dlo #8876: Make sugar control panel support selection of multiple languages --- (limited to 'extensions') 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 -- cgit v0.9.1