class GtkLanguageSelector(LanguageSelectorBase): def __init__(self, datadir, options): LanguageSelectorBase.__init__(self, datadir) self._datadir = datadir self.widgets = Gtk.Builder() self.widgets.set_translation_domain('language-selector') self.widgets.add_from_file(datadir + "/data/LanguageSelector.ui") self.widgets.connect_signals(self) try: in_grp_admin = grp.getgrnam("admin")[2] in os.getgroups() except KeyError: in_grp_admin = False try: in_grp_sudo = grp.getgrnam("sudo")[2] in os.getgroups() except KeyError: in_grp_sudo = False self.is_admin = (os.getuid() == 0 or in_grp_sudo or in_grp_admin) # see if we have any other human users on this system self.has_other_users = False num = 0 for l in pwd.getpwall(): if l.pw_uid >= 500 and l.pw_uid < 65534: num += 1 if num >= 2: self.has_other_users = True break #build the comboboxes (with model) combo = self.combobox_locale_chooser model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) cell = Gtk.CellRendererText() combo.pack_start(cell, True) combo.add_attribute(cell, 'text', LANGTREEVIEW_LANGUAGE) combo.set_model(model) # self.combo_syslang_dirty = False # combo = self.combobox_user_language # model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) # cell = Gtk.CellRendererText() # combo.pack_start(cell, True) # combo.add_attribute(cell, 'text', COMBO_LANGUAGE) # combo.set_model(model) # self.combo_userlang_dirty = False self.options = options # get aptdaemon client self.ac = aptdaemon.client.AptClient() combo = self.combobox_input_method model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) cell = Gtk.CellRendererText() combo.pack_start(cell, True) combo.add_attribute(cell, 'text', IM_NAME) combo.set_model(model) self.imSwitch = ImSwitch() self._blockSignals = False # remove dangling ImSwitch symlinks if present self.imSwitch.removeDanglingSymlinks() # build the treeview self.setupLanguageTreeView() if self.is_admin: self.setupInstallerTreeView() self.updateLanguageView() # self.updateUserDefaultCombo() self.updateLocaleChooserCombo() self.check_input_methods() # self.updateSyncButton() # apply button self.button_apply.set_sensitive(False) # 'Apply System-Wide...' and 'Install/Remove Languages...' buttons if self.is_admin: self.button_apply_system_wide_languages.set_sensitive(True) self.button_install_remove_languages.set_sensitive(True) self.button_apply_system_wide_locale.set_sensitive(True) else: self.button_apply_system_wide_languages.set_sensitive(False) self.button_install_remove_languages.set_sensitive(False) self.button_apply_system_wide_locale.set_sensitive(False) # show it self.window_main.show() self.setSensitive(False) if self.is_admin: # check if the package list is up-to-date if not self._cache.havePackageLists: d = Gtk.MessageDialog(parent=self.window_main, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.CANCEL) d.set_markup( "<big><b>%s</b></big>\n\n%s" % (_("No language information available"), _("The system does not have information about the " "available languages yet. Do you want to perform " "a network update to get them now? "))) d.set_title = ("") d.add_button(_("_Update"), Gtk.ResponseType.YES) res = d.run() d.destroy() if res == Gtk.ResponseType.YES: self.setSensitive(False) self.update() self.updateLanguageView() self.setSensitive(True) # see if something is missing if self.options.verify_installed: self.verifyInstalledLangPacks() if not self.imSwitch.available(): self.combobox_input_method.set_sensitive(False) self.setSensitive(True) def __getattr__(self, name): '''Convenient access to GtkBuilder objects''' o = self.widgets.get_object(name) if o is None: raise AttributeError, 'No such widget: ' + name return o def run(self): Gtk.main() def setSensitive(self, value): if value: self.window_main.set_sensitive(True) self.window_main.get_window().set_cursor(None) else: self.window_main.set_sensitive(False) self.window_main.get_window().set_cursor( Gdk.Cursor.new(Gdk.CursorType.WATCH)) while Gtk.events_pending(): Gtk.main_iteration() # @blockSignals # def updateSyncButton(self): # " check if the sync languages button should be enabled or not " # button = self.checkbutton_sync_languages # combo = self.combobox_system_language # # no admin user, gray out # if self.is_admin == False: # button.set_active(False) # button.set_sensitive(False) # combo.set_sensitive(False) # return # # admin user, check stuff # button.set_sensitive(True) # combo.set_sensitive(True) # # do not enable the keep the same button if the system has other # # users or if the language settings are inconsistent already # userlang = self.combobox_user_language.get_active() # systemlang = self.combobox_system_language.get_active() # if (not self.has_other_users and userlang == systemlang): # button.set_active(True) # else: # button.set_active(False) def setupInstallerTreeView(self): """ do all the treeview setup here """ def toggle_cell_func(column, cell, model, iter, data): langInfo = model.get_value(iter, LIST_LANG_INFO) # check for active and inconsitent inconsistent = langInfo.inconsistent #if inconsistent: # print "%s is inconsistent" % langInfo.language cell.set_property("active", langInfo.fullInstalled) cell.set_property("inconsistent", inconsistent) def lang_view_func(cell_layout, renderer, model, iter, data): langInfo = model.get_value(iter, LIST_LANG_INFO) langName = model.get_value(iter, LIST_LANG) if (langInfo.changes): markup = "<b>%s</b>" % langName else: markup = "%s" % langName renderer.set_property("markup", markup) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(_("Language"), renderer, text=LIST_LANG) column.set_property("expand", True) column.set_cell_data_func(renderer, lang_view_func, None) self.treeview_languages.append_column(column) renderer = Gtk.CellRendererToggle() renderer.connect("toggled", self.on_toggled) column = Gtk.TreeViewColumn(_("Installed"), renderer) column.set_cell_data_func(renderer, toggle_cell_func, None) self.treeview_languages.append_column(column) # build the store self._langlist = Gtk.ListStore(str, GObject.TYPE_PYOBJECT) self.treeview_languages.set_model(self._langlist) def setupLanguageTreeView(self): """ do all the treeview setup here """ def lang_view_func(cell_layout, renderer, model, iter, data): langInfo = model.get_value(iter, LANGTREEVIEW_CODE) greyFlag = False myiter = model.get_iter_first() while myiter: str = model.get_value(myiter, LANGTREEVIEW_CODE) if str == langInfo: greyFlag = False break if str == "en": greyFlag = True break myiter = model.iter_next(myiter) if greyFlag: markup = "<span foreground=\"grey\">%s</span>" \ % self._localeinfo.translate(langInfo, native=True, allCountries=True) else: markup = "%s" % self._localeinfo.translate( langInfo, native=True, allCountries=True) renderer.set_property("markup", markup) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(_("Language"), renderer, text=LANGTREEVIEW_LANGUAGE) column.set_property("expand", True) column.set_cell_data_func(renderer, lang_view_func, None) self.treeview_locales.append_column(column) # build the store self._language_options = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) self.treeview_locales.set_model(self._language_options) def _get_langinfo_on_cursor(self): (path, column) = self.treeview_languages.get_cursor() if not path: return None iter = self._langlist.get_iter(path) langInfo = self._langlist.get_value(iter, LIST_LANG_INFO) return langInfo def debug_pkg_status(self): langInfo = self._get_langinfo_on_cursor() for pkg in langInfo.languagePkgList.items(): print( "%s, available: %s, installed: %s, doChange: %s" % (pkg[0], pkg[1].available, pkg[1].installed, pkg[1].doChange)) print("inconsistent? : %s" % langInfo.inconsistent) def check_status(self): changed = False countInstall = 0 countRemove = 0 for (lang, langInfo) in self._langlist: if langInfo.changes: changed = True for item in langInfo.languagePkgList.values(): if item.doChange: if item.installed: countRemove = countRemove + 1 else: countInstall = countInstall + 1 #print "%(INSTALL)d to install, %(REMOVE)d to remove" % (countInstall, countRemove) # Translators: %(INSTALL)d is parsed; either keep it exactly as is or remove it entirely, but don't translate "INSTALL". textInstall = gettext.ngettext("%(INSTALL)d to install", "%(INSTALL)d to install", countInstall) % { 'INSTALL': countInstall } # Translators: %(REMOVE)d is parsed; either keep it exactly as is or remove it entirely, but don't translate "REMOVE". textRemove = gettext.ngettext("%(REMOVE)d to remove", "%(REMOVE)d to remove", countRemove) % { 'REMOVE': countRemove } if countRemove == 0 and countInstall == 0: self.label_install_remove.set_text("") elif countRemove == 0: self.label_install_remove.set_text(textInstall) elif countInstall == 0: self.label_install_remove.set_text(textRemove) else: # Translators: this string will concatenate the "%n to install" and "%n to remove" strings, you can replace the comma if you need to. self.label_install_remove.set_text( _("%s, %s") % (textInstall, textRemove)) if changed: self.button_apply.set_sensitive(True) else: self.button_apply.set_sensitive(False) # @honorBlockedSignals # @insensitive # def on_combobox_system_language_changed(self, widget): # #print "on_combobox_system_language_changed()" # if self.writeSystemDefaultLang(): # # queue a restart of gdm (if it is runing) to make the new # # locales usable # gdmscript = "/etc/init.d/gdm" # if os.path.exists("/var/run/gdm.pid") and os.path.exists(gdmscript): # self.runAsRoot(["invoke-rc.d","gdm","reload"]) # self.updateSystemDefaultCombo() # if self.checkbutton_sync_languages.get_active() == True: # self.combobox_user_language.set_active(self.combobox_system_language.get_active()) # self.updateUserDefaultCombo() # @honorBlockedSignals # @insensitive # def on_combobox_user_language_changed(self, widget): # #print "on_combobox_user_language_changed()" # self.check_input_methods() # self.writeUserDefaultLang() # self.updateUserDefaultCombo() # if self.checkbutton_sync_languages.get_active() == True: # self.combobox_system_language.set_active(self.combobox_user_language.get_active()) # self.updateSystemDefaultCombo() @blockSignals def check_input_methods(self): """ check if the selected langauge has input method support and set checkbutton_enable_input_methods accordingly """ if not self.imSwitch.available(): return # get the current first item in the user LANGUAGE list, # but with country code added if not already present loc = language2locale(self.userEnvLanguage) code = re.split('[.@]', loc)[0] combo = self.combobox_input_method #cell = combo.get_child().get_cell_renderers()[0] # FIXME: use something else than a hardcoded value here #cell.set_property("wrap-width",300) #cell.set_property("wrap-mode",Pango.WRAP_WORD) model = combo.get_model() model.clear() # find the default currentIM = self.imSwitch.getInputMethodForLocale(code) if currentIM in (None, 'default'): currentIM = 'none' #print "Current IM: "+currentIM # find out about the other options for (i, IM) in enumerate(self.imSwitch.getAvailableInputMethods()): iter = model.append() name = _('none') if IM == 'none' else IM model.set_value(iter, IM_CHOICE, IM) model.set_value(iter, IM_NAME, name) if IM == currentIM: combo.set_active(i) # self.check_status() # def writeInputMethodConfig(self): # """ # write new input method defaults - currently we only support all_ALL # """ # combo = self.combobox_user_language # model = combo.get_model() # if combo.get_active() < 0: # return # (lang, code) = model[combo.get_active()] # # check if we need to do something # new_value = self.checkbutton_enable_input_methods.get_active() # if self.imSwitch.enabledForLocale(code) != new_value: # if new_value: # self.imSwitch.enable(code) # else: # self.imSwitch.disable(code) # #self.showRebootRequired() # #self.checkReloginNotification() # @honorBlockedSignals # def on_checkbutton_enable_input_methods_toggled(self, widget): # #print "on_checkbutton_enable_input_methods_toggled()" # active = self.checkbutton_enable_input_methods.get_active() # self.combo_userlang_dirty = True # self.setSensitive(False) # self.writeInputMethodConfig() # self.setSensitive(True) # @honorBlockedSignals # def on_checkbutton_sync_languages_toggled(self, widget): # #print "on_checkbutton_sync_languages_toggled()" # if self.checkbutton_sync_languages.get_active() == True: # self.combobox_user_language.set_active(self.combobox_system_language.get_active()) # self.updateSystemDefaultCombo() def build_commit_lists(self): print self._cache.get_changes() try: for (lang, langInfo) in self._langlist: self._cache.tryChangeDetails(langInfo) except ExceptionPkgCacheBroken: self.error( _("Software database is broken"), _("It is impossible to install or remove any software. " "Please use the package manager \"Synaptic\" or run " "\"sudo apt-get install -f\" in a terminal to fix " "this issue at first.")) sys.exit(1) (to_inst, to_rm) = self._cache.getChangesList() #print "inst: %s" % to_inst #print "rm: %s" % to_rm print self._cache.get_changes() return (to_inst, to_rm) def error(self, summary, msg): d = Gtk.MessageDialog(parent=self.window_main, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE) d.set_markup("<big><b>%s</b></big>\n\n%s" % (summary, msg)) d.set_title = ("") d.run() d.destroy() def _show_error_dialog(self, error): msg = str(error) self.error(msg, "") def verify_commit_lists(self, inst_list, rm_list): """ verify if the selected package can actually be installed """ res = True try: for pkg in inst_list: if pkg in self._cache: self._cache[pkg].mark_install() for pkg in rm_list: if pkg in self._cache: self._cache[pkg].mark_delete() except SystemError: res = False # undo the selections self._cache.clear() if self._cache._depcache.broken_count != 0: self.error( _("Could not install the selected language support"), _("This is perhaps a bug of this application. Please " "file a bug report at " "https://bugs.launchpad.net/ubuntu/+source/language-selector/+filebug" )) # something went pretty bad, re-get a cache progress = GtkProgress(self.dialog_progress, self.progressbar_cache, self.window_main) self._cache = apt.Cache(self._localeinfo, progress) progress.hide() res = False return res def commitAllChanges(self): """ commit helper, builds the commit lists, verifies it returns the number of install/removed packages """ self.setSensitive(False) # install the new packages (if any) (inst_list, rm_list) = self.build_commit_lists() if not self.verify_commit_lists(inst_list, rm_list): self.error( _("Could not install the full language support"), _("Usually this is related to an error in your " "software archive or software manager. Check your " "preferences in Software Sources (click the icon " "at the very right of the top bar and select " "\"System Settings... -> Software Sources\").")) self.setSensitive(True) return 0 #print "inst_list: %s " % inst_list #print "rm_list: %s " % rm_list self.commit(inst_list, rm_list) self.setSensitive(True) return len(inst_list) + len(rm_list) def _run_transaction(self, transaction): dia = AptProgressDialog(transaction, parent=self.window_main) dia.connect("finished", self._on_finished) dia.run(error_handler=self._on_error) def _wait_for_aptdaemon_finish(self): while not self._transaction_finished: while Gtk.events_pending(): Gtk.main_iteration() time.sleep(0.02) def _on_finished(self, dialog): dialog.hide() self._transaction_finished = True def _on_error(self, error): if hasattr(error, 'get_dbus_name') and error.get_dbus_name() == \ 'org.freedesktop.PolicyKit.Error.NotAuthorized': self.error(_("Could not install the full language support"), _('Failed to authorize to install packages.')) else: self.error(_("Could not install the full language support"), str(error)) self._transaction_finished = True def update_aptdaemon(self): self._transaction_finished = False self._update_aptdaemon() self._wait_for_aptdaemon_finish() @inline_callbacks def _update_aptdaemon(self): try: trans = yield self.ac.update_cache(defer=True) self._run_transaction(trans) except Exception, e: self._show_error_dialog(e)
class GtkLanguageSelector(LanguageSelectorBase): def __init__(self, datadir, options): LanguageSelectorBase.__init__(self, datadir) self._datadir = datadir self.widgets = Gtk.Builder() self.widgets.set_translation_domain("language-selector") self.widgets.add_from_file(datadir + "/data/LanguageSelector.ui") self.widgets.connect_signals(self) try: in_grp_admin = grp.getgrnam("admin")[2] in os.getgroups() except KeyError: in_grp_admin = False try: in_grp_sudo = grp.getgrnam("sudo")[2] in os.getgroups() except KeyError: in_grp_sudo = False self.is_admin = os.getuid() == 0 or in_grp_sudo or in_grp_admin # see if we have any other human users on this system self.has_other_users = False num = 0 for l in pwd.getpwall(): if l.pw_uid >= 500 and l.pw_uid < 65534: num += 1 if num >= 2: self.has_other_users = True break # build the comboboxes (with model) combo = self.combobox_locale_chooser model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) cell = Gtk.CellRendererText() combo.pack_start(cell, True) combo.add_attribute(cell, "text", LANGTREEVIEW_LANGUAGE) combo.set_model(model) # self.combo_syslang_dirty = False # combo = self.combobox_user_language # model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) # cell = Gtk.CellRendererText() # combo.pack_start(cell, True) # combo.add_attribute(cell, 'text', COMBO_LANGUAGE) # combo.set_model(model) # self.combo_userlang_dirty = False self.options = options # get aptdaemon client self.ac = aptdaemon.client.AptClient() combo = self.combobox_input_method model = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) cell = Gtk.CellRendererText() combo.pack_start(cell, True) combo.add_attribute(cell, "text", IM_NAME) combo.set_model(model) self.imSwitch = ImSwitch() self._blockSignals = False # remove dangling ImSwitch symlinks if present self.imSwitch.removeDanglingSymlinks() # build the treeview self.setupLanguageTreeView() if self.is_admin: self.setupInstallerTreeView() self.updateLanguageView() # self.updateUserDefaultCombo() self.updateLocaleChooserCombo() self.check_input_methods() # self.updateSyncButton() # apply button self.button_apply.set_sensitive(False) # 'Apply System-Wide...' and 'Install/Remove Languages...' buttons if self.is_admin: self.button_apply_system_wide_languages.set_sensitive(True) self.button_install_remove_languages.set_sensitive(True) self.button_apply_system_wide_locale.set_sensitive(True) else: self.button_apply_system_wide_languages.set_sensitive(False) self.button_install_remove_languages.set_sensitive(False) self.button_apply_system_wide_locale.set_sensitive(False) # show it self.window_main.show() self.setSensitive(False) if self.is_admin: # check if the package list is up-to-date if not self._cache.havePackageLists: d = Gtk.MessageDialog( parent=self.window_main, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.INFO, buttons=Gtk.ButtonsType.CANCEL, ) d.set_markup( "<big><b>%s</b></big>\n\n%s" % ( _("No language information available"), _( "The system does not have information about the " "available languages yet. Do you want to perform " "a network update to get them now? " ), ) ) d.set_title = "" d.add_button(_("_Update"), Gtk.ResponseType.YES) res = d.run() d.destroy() if res == Gtk.ResponseType.YES: self.setSensitive(False) self.update() self.updateLanguageView() self.setSensitive(True) # see if something is missing if self.options.verify_installed: self.verifyInstalledLangPacks() if not self.imSwitch.available(): self.combobox_input_method.set_sensitive(False) self.setSensitive(True) def __getattr__(self, name): """Convenient access to GtkBuilder objects""" o = self.widgets.get_object(name) if o is None: raise AttributeError, "No such widget: " + name return o def run(self): Gtk.main() def setSensitive(self, value): if value: self.window_main.set_sensitive(True) self.window_main.get_window().set_cursor(None) else: self.window_main.set_sensitive(False) self.window_main.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) while Gtk.events_pending(): Gtk.main_iteration() # @blockSignals # def updateSyncButton(self): # " check if the sync languages button should be enabled or not " # button = self.checkbutton_sync_languages # combo = self.combobox_system_language # # no admin user, gray out # if self.is_admin == False: # button.set_active(False) # button.set_sensitive(False) # combo.set_sensitive(False) # return # # admin user, check stuff # button.set_sensitive(True) # combo.set_sensitive(True) # # do not enable the keep the same button if the system has other # # users or if the language settings are inconsistent already # userlang = self.combobox_user_language.get_active() # systemlang = self.combobox_system_language.get_active() # if (not self.has_other_users and userlang == systemlang): # button.set_active(True) # else: # button.set_active(False) def setupInstallerTreeView(self): """ do all the treeview setup here """ def toggle_cell_func(column, cell, model, iter, data): langInfo = model.get_value(iter, LIST_LANG_INFO) # check for active and inconsitent inconsistent = langInfo.inconsistent # if inconsistent: # print "%s is inconsistent" % langInfo.language cell.set_property("active", langInfo.fullInstalled) cell.set_property("inconsistent", inconsistent) def lang_view_func(cell_layout, renderer, model, iter, data): langInfo = model.get_value(iter, LIST_LANG_INFO) langName = model.get_value(iter, LIST_LANG) if langInfo.changes: markup = "<b>%s</b>" % langName else: markup = "%s" % langName renderer.set_property("markup", markup) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(_("Language"), renderer, text=LIST_LANG) column.set_property("expand", True) column.set_cell_data_func(renderer, lang_view_func, None) self.treeview_languages.append_column(column) renderer = Gtk.CellRendererToggle() renderer.connect("toggled", self.on_toggled) column = Gtk.TreeViewColumn(_("Installed"), renderer) column.set_cell_data_func(renderer, toggle_cell_func, None) self.treeview_languages.append_column(column) # build the store self._langlist = Gtk.ListStore(str, GObject.TYPE_PYOBJECT) self.treeview_languages.set_model(self._langlist) def setupLanguageTreeView(self): """ do all the treeview setup here """ def lang_view_func(cell_layout, renderer, model, iter, data): langInfo = model.get_value(iter, LANGTREEVIEW_CODE) greyFlag = False myiter = model.get_iter_first() while myiter: str = model.get_value(myiter, LANGTREEVIEW_CODE) if str == langInfo: greyFlag = False break if str == "en": greyFlag = True break myiter = model.iter_next(myiter) if greyFlag: markup = '<span foreground="grey">%s</span>' % self._localeinfo.translate( langInfo, native=True, allCountries=True ) else: markup = "%s" % self._localeinfo.translate(langInfo, native=True, allCountries=True) renderer.set_property("markup", markup) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(_("Language"), renderer, text=LANGTREEVIEW_LANGUAGE) column.set_property("expand", True) column.set_cell_data_func(renderer, lang_view_func, None) self.treeview_locales.append_column(column) # build the store self._language_options = Gtk.ListStore(GObject.TYPE_STRING, GObject.TYPE_STRING) self.treeview_locales.set_model(self._language_options) def _get_langinfo_on_cursor(self): (path, column) = self.treeview_languages.get_cursor() if not path: return None iter = self._langlist.get_iter(path) langInfo = self._langlist.get_value(iter, LIST_LANG_INFO) return langInfo def debug_pkg_status(self): langInfo = self._get_langinfo_on_cursor() for pkg in langInfo.languagePkgList.items(): print ( "%s, available: %s, installed: %s, doChange: %s" % (pkg[0], pkg[1].available, pkg[1].installed, pkg[1].doChange) ) print ("inconsistent? : %s" % langInfo.inconsistent) def check_status(self): changed = False countInstall = 0 countRemove = 0 for (lang, langInfo) in self._langlist: if langInfo.changes: changed = True for item in langInfo.languagePkgList.values(): if item.doChange: if item.installed: countRemove = countRemove + 1 else: countInstall = countInstall + 1 # print "%(INSTALL)d to install, %(REMOVE)d to remove" % (countInstall, countRemove) # Translators: %(INSTALL)d is parsed; either keep it exactly as is or remove it entirely, but don't translate "INSTALL". textInstall = gettext.ngettext("%(INSTALL)d to install", "%(INSTALL)d to install", countInstall) % { "INSTALL": countInstall } # Translators: %(REMOVE)d is parsed; either keep it exactly as is or remove it entirely, but don't translate "REMOVE". textRemove = gettext.ngettext("%(REMOVE)d to remove", "%(REMOVE)d to remove", countRemove) % { "REMOVE": countRemove } if countRemove == 0 and countInstall == 0: self.label_install_remove.set_text("") elif countRemove == 0: self.label_install_remove.set_text(textInstall) elif countInstall == 0: self.label_install_remove.set_text(textRemove) else: # Translators: this string will concatenate the "%n to install" and "%n to remove" strings, you can replace the comma if you need to. self.label_install_remove.set_text(_("%s, %s") % (textInstall, textRemove)) if changed: self.button_apply.set_sensitive(True) else: self.button_apply.set_sensitive(False) # @honorBlockedSignals # @insensitive # def on_combobox_system_language_changed(self, widget): # #print "on_combobox_system_language_changed()" # if self.writeSystemDefaultLang(): # # queue a restart of gdm (if it is runing) to make the new # # locales usable # gdmscript = "/etc/init.d/gdm" # if os.path.exists("/var/run/gdm.pid") and os.path.exists(gdmscript): # self.runAsRoot(["invoke-rc.d","gdm","reload"]) # self.updateSystemDefaultCombo() # if self.checkbutton_sync_languages.get_active() == True: # self.combobox_user_language.set_active(self.combobox_system_language.get_active()) # self.updateUserDefaultCombo() # @honorBlockedSignals # @insensitive # def on_combobox_user_language_changed(self, widget): # #print "on_combobox_user_language_changed()" # self.check_input_methods() # self.writeUserDefaultLang() # self.updateUserDefaultCombo() # if self.checkbutton_sync_languages.get_active() == True: # self.combobox_system_language.set_active(self.combobox_user_language.get_active()) # self.updateSystemDefaultCombo() @blockSignals def check_input_methods(self): """ check if the selected langauge has input method support and set checkbutton_enable_input_methods accordingly """ if not self.imSwitch.available(): return # get the current first item in the user LANGUAGE list, # but with country code added if not already present loc = language2locale(self.userEnvLanguage) code = re.split("[.@]", loc)[0] combo = self.combobox_input_method # cell = combo.get_child().get_cell_renderers()[0] # FIXME: use something else than a hardcoded value here # cell.set_property("wrap-width",300) # cell.set_property("wrap-mode",Pango.WRAP_WORD) model = combo.get_model() model.clear() # find the default currentIM = self.imSwitch.getInputMethodForLocale(code) if currentIM in (None, "default"): currentIM = "none" # print "Current IM: "+currentIM # find out about the other options for (i, IM) in enumerate(self.imSwitch.getAvailableInputMethods()): iter = model.append() name = _("none") if IM == "none" else IM model.set_value(iter, IM_CHOICE, IM) model.set_value(iter, IM_NAME, name) if IM == currentIM: combo.set_active(i) # self.check_status() # def writeInputMethodConfig(self): # """ # write new input method defaults - currently we only support all_ALL # """ # combo = self.combobox_user_language # model = combo.get_model() # if combo.get_active() < 0: # return # (lang, code) = model[combo.get_active()] # # check if we need to do something # new_value = self.checkbutton_enable_input_methods.get_active() # if self.imSwitch.enabledForLocale(code) != new_value: # if new_value: # self.imSwitch.enable(code) # else: # self.imSwitch.disable(code) # #self.showRebootRequired() # #self.checkReloginNotification() # @honorBlockedSignals # def on_checkbutton_enable_input_methods_toggled(self, widget): # #print "on_checkbutton_enable_input_methods_toggled()" # active = self.checkbutton_enable_input_methods.get_active() # self.combo_userlang_dirty = True # self.setSensitive(False) # self.writeInputMethodConfig() # self.setSensitive(True) # @honorBlockedSignals # def on_checkbutton_sync_languages_toggled(self, widget): # #print "on_checkbutton_sync_languages_toggled()" # if self.checkbutton_sync_languages.get_active() == True: # self.combobox_user_language.set_active(self.combobox_system_language.get_active()) # self.updateSystemDefaultCombo() def build_commit_lists(self): print self._cache.get_changes() try: for (lang, langInfo) in self._langlist: self._cache.tryChangeDetails(langInfo) except ExceptionPkgCacheBroken: self.error( _("Software database is broken"), _( "It is impossible to install or remove any software. " 'Please use the package manager "Synaptic" or run ' '"sudo apt-get install -f" in a terminal to fix ' "this issue at first." ), ) sys.exit(1) (to_inst, to_rm) = self._cache.getChangesList() # print "inst: %s" % to_inst # print "rm: %s" % to_rm print self._cache.get_changes() return (to_inst, to_rm) def error(self, summary, msg): d = Gtk.MessageDialog( parent=self.window_main, flags=Gtk.DialogFlags.MODAL, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE, ) d.set_markup("<big><b>%s</b></big>\n\n%s" % (summary, msg)) d.set_title = "" d.run() d.destroy() def _show_error_dialog(self, error): msg = str(error) self.error(msg, "") def verify_commit_lists(self, inst_list, rm_list): """ verify if the selected package can actually be installed """ res = True try: for pkg in inst_list: if pkg in self._cache: self._cache[pkg].mark_install() for pkg in rm_list: if pkg in self._cache: self._cache[pkg].mark_delete() except SystemError: res = False # undo the selections self._cache.clear() if self._cache._depcache.broken_count != 0: self.error( _("Could not install the selected language support"), _( "This is perhaps a bug of this application. Please " "file a bug report at " "https://bugs.launchpad.net/ubuntu/+source/language-selector/+filebug" ), ) # something went pretty bad, re-get a cache progress = GtkProgress(self.dialog_progress, self.progressbar_cache, self.window_main) self._cache = apt.Cache(self._localeinfo, progress) progress.hide() res = False return res def commitAllChanges(self): """ commit helper, builds the commit lists, verifies it returns the number of install/removed packages """ self.setSensitive(False) # install the new packages (if any) (inst_list, rm_list) = self.build_commit_lists() if not self.verify_commit_lists(inst_list, rm_list): self.error( _("Could not install the full language support"), _( "Usually this is related to an error in your " "software archive or software manager. Check your " "preferences in Software Sources (click the icon " "at the very right of the top bar and select " '"System Settings... -> Software Sources").' ), ) self.setSensitive(True) return 0 # print "inst_list: %s " % inst_list # print "rm_list: %s " % rm_list self.commit(inst_list, rm_list) self.setSensitive(True) return len(inst_list) + len(rm_list) def _run_transaction(self, transaction): dia = AptProgressDialog(transaction, parent=self.window_main) dia.connect("finished", self._on_finished) dia.run(error_handler=self._on_error) def _wait_for_aptdaemon_finish(self): while not self._transaction_finished: while Gtk.events_pending(): Gtk.main_iteration() time.sleep(0.02) def _on_finished(self, dialog): dialog.hide() self._transaction_finished = True def _on_error(self, error): if hasattr(error, "get_dbus_name") and error.get_dbus_name() == "org.freedesktop.PolicyKit.Error.NotAuthorized": self.error(_("Could not install the full language support"), _("Failed to authorize to install packages.")) else: self.error(_("Could not install the full language support"), str(error)) self._transaction_finished = True def update_aptdaemon(self): self._transaction_finished = False self._update_aptdaemon() self._wait_for_aptdaemon_finish() @inline_callbacks def _update_aptdaemon(self): try: trans = yield self.ac.update_cache(defer=True) self._run_transaction(trans) except Exception, e: self._show_error_dialog(e)
class QtLanguageSelector(KCModule, LanguageSelectorBase): """ actual implementation of the qt GUI """ def __init__(self, datadir, component_data=None, parent=None): LanguageSelectorBase.__init__(self, datadir) KCModule.__init__(self, component_data, parent) self.parentApp = KApplication.kApplication() self.ui = Ui_QtLanguageSelectorGUI() self.ui.setupUi(self) self.about = MakeAboutData() self.setAboutData(self.about) self.setWindowIcon(KIcon("preferences-desktop-locale")) self.imSwitch = ImSwitch() # remove dangling ImSwitch symlinks if present self.imSwitch.removeDanglingSymlinks() self.init() # connect the signals self.connect(self.ui.listViewLanguagesInst, SIGNAL("itemSelectionChanged()"), self.checkInstallableComponents) self.connect(self.ui.listViewLanguagesUninst, SIGNAL("itemSelectionChanged()"), self.onChanged) self.connect(self.ui.ktabwidget, SIGNAL("currentChanged(int)"), self.onTabChangeRevertApply) self.connect(self.ui.listBoxDefaultLanguage, SIGNAL("itemSelectionChanged()"), self.checkInputMethods) self.connect(self.ui.checkBoxTr, SIGNAL("stateChanged(int)"), self.onChanged) self.connect(self.ui.checkBoxIm, SIGNAL("stateChanged(int)"), self.onChanged) self.connect(self.ui.checkBoxSpell, SIGNAL("stateChanged(int)"), self.onChanged) self.connect(self.ui.checkBoxFonts, SIGNAL("stateChanged(int)"), self.onChanged) def init(self): self.translateUI() try: self.openCache(apt.progress.OpProgress()) except ExceptionPkgCacheBroken: s = _("Software database is broken") t = _("It is impossible to install or remove any software. " "Please use the package manager \"Adept\" or run " "\"sudo apt-get install -f\" in a terminal to fix " "this issue at first.") KMessageBox.error(self, t, s) sys.exit(1) self.updateLanguagesList() self.updateSystemDefaultListbox() if not self._cache.havePackageLists: yesText = _("_Update").replace("_", "&") noText = _("_Remind Me Later").replace("_", "&") yes = KGuiItem(yesText, "dialog-ok") no = KGuiItem(noText, "process-stop") text = "<big><b>%s</b></big>\n\n%s" % ( _("No language information available"), _("The system does not have information about the " "available languages yet. Do you want to perform " "a network update to get them now? ")) text = text.replace("\n", "<br />") res = KMessageBox.questionYesNo(self, text, "", yes, no) if res == KMessageBox.Yes: self.setEnabled(False) self.update() self.openCache(apt.progress.OpProgress()) self.updateLanguagesList() self.setEnabled(True) def load(self): # See if something is missing self.verifyInstalledLangPacks() def save(self): idx = self.ui.ktabwidget.currentIndex() if idx == 0: self.pkgChanges("install") elif idx == 1: self.pkgChanges("uninstall") else: self.onSystemLanguageApply() def translateUI(self): """ translate the strings in the UI, needed because Qt designer doesn't use gettext """ self.ui.ktabwidget.setTabText(self.ui.ktabwidget.indexOf(self.ui.SystemDefaultTab), _("Set System Language")) self.ui.defaultSystemLabel.setText(_("Default system language:")) self.ui.labelInputMethod.setText(_("Keyboard input method:")) self.ui.selectLanguageLabel.setText(_("Select language to install:")) self.ui.selectLanguageLabel_2.setText(_("Select language to uninstall:")) self.ui.checkBoxTr.setText(_("Translations")) self.ui.checkBoxIm.setText(_("Input methods")) self.ui.checkBoxSpell.setText(_("Spellchecking and writing aids")) self.ui.checkBoxFonts.setText(_("Extra fonts")) self.ui.ComponentsLabel.setText(_("Components:")) def updateSystemDefaultListbox(self): self.ui.listBoxDefaultLanguage.clear() self._localeinfo.localeToCodeMap = {} # get the current default lang defaultLangName = None defaultLangCode = self._localeinfo.getSystemDefaultLanguage()[0] if defaultLangCode: defaultLangName = utf8(self._localeinfo.translate(defaultLangCode, native=True)) locales = [] for locale in self._localeinfo.generated_locales(): name = utf8(self._localeinfo.translate(locale, native=True)) locales.append(name) self._localeinfo.localeToCodeMap[name] = locale locales.sort() for localeName in locales: item = QListWidgetItem(utf8(localeName), self.ui.listBoxDefaultLanguage) if defaultLangName == localeName: item.setSelected(True) if (not os.path.exists("/etc/alternatives/xinput-all_ALL") or not os.path.exists("/usr/bin/im-switch")): self.ui.comboBoxInputMethod.setEnabled(False) def verifyInstalledLangPacks(self): """ called at the start to inform about possible missing langpacks (e.g. gnome/kde langpack transition) """ print "verifyInstalledLangPacks" missing = self.getMissingLangPacks() print "Missing: %s " % missing if len(missing) > 0: # FIXME: add "details" yesText = _("_Install").replace("_", "&") noText = _("_Remind Me Later").replace("_", "&") yes = KGuiItem(yesText, "dialog-ok") no = KGuiItem(noText, "process-stop") text = "<big><b>%s</b></big>\n\n%s" % ( _("The language support is not installed completely"), _("Some translations or writing aids available for your " "chosen languages are not installed yet. Do you want " "to install them now?")) text = text.replace("\n", "<br />") res = KMessageBox.questionYesNo(self, text, "", yes, no) if res == KMessageBox.Yes: self.setEnabled(False) self.commit(missing, []) self.updateLanguagesList() self.setEnabled(True) def update(self): self.run_pkg_manager_update() def commit(self, inst, rm): # unlock here to make sure that lock/unlock are always run # pair-wise (and don't explode on errors) if len(inst) == 0 and len(rm) == 0: return self.run_pkg_manager(inst,rm) def updateLanguagesList(self): self.ui.listViewLanguagesInst.clear() self.ui.listViewLanguagesUninst.clear() # get the language names and sort them alphabetically languageList = self._cache.getLanguageInformation() self._localeinfo.listviewStrToLangInfoMap = {} for lang in languageList: self._localeinfo.listviewStrToLangInfoMap[utf8(self._localeinfo.translate(lang.languageCode))] = lang languages = self._localeinfo.listviewStrToLangInfoMap.keys() languages.sort() for langName in languages: lang = self._localeinfo.listviewStrToLangInfoMap[langName] elmIn = QListWidgetItem(utf8(self._localeinfo.translate(lang.languageCode)), self.ui.listViewLanguagesInst) elmUn = QListWidgetItem(utf8(self._localeinfo.translate(lang.languageCode)), self.ui.listViewLanguagesUninst) if lang.fullInstalled: elmIn.setFlags(Qt.ItemIsDropEnabled) #not sure how to unset all flags, but this disables the item elmIn.setToolTip(_("Already installed")) elmUn.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) elif lang.inconsistent: elmIn.setToolTip(_("Partially Installed")) else: elmUn.setFlags(Qt.ItemIsDropEnabled) #not sure how to unset all flags, but this disables the item elmUn.setToolTip(_("Not installed")) elmUn.setHidden(True) elmIn.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) def onChanged(self, state = 1): if state: self.changed() else: for button in [ "checkBoxTr", "checkBoxIm", "checkBoxSpell", "checkBoxFonts" ]: if getattr(self.ui, button).isEnabled() and getattr(self.ui, button).isChecked(): return self.emit(SIGNAL("changed(bool)"), False) def onTabChangeRevertApply(self): for listView in [ "listViewLanguagesInst", "listViewLanguagesUninst", "listBoxDefaultLanguage" ]: getattr(self.ui, listView).clearSelection() for button in [ "checkBoxTr", "checkBoxIm", "checkBoxSpell", "checkBoxFonts" ]: getattr(self.ui, button).setChecked(False) getattr(self.ui, button).setEnabled(False) self.emit(SIGNAL("changed(bool)"), False) def checkInstallableComponents(self): """ check available components for the selected language and set/unset the corresponding checkbutton accordingly """ items = self.ui.listViewLanguagesInst.selectedItems() if len(items) == 1: li = self._localeinfo.listviewStrToLangInfoMap[unicode(items[0].text())] langPkg = li.languagePkgList["languagePack"] self.ui.checkBoxTr.setEnabled(langPkg.available) self.ui.checkBoxTr.setChecked(False) if langPkg.installed: self.ui.checkBoxTr.setChecked(True) self.ui.checkBoxTr.setEnabled(False) self.ui.checkBoxTr.setToolTip(_("Component already installed")) elif not langPkg.available: self.ui.checkBoxTr.setToolTip(_("Component not available")) else: self.ui.checkBoxTr.setToolTip(_("Component not installed")) def checkInputMethods(self): """ check if the selected language has input method support and set checkbutton_enable_input_methods accordingly """ if (not self.imSwitch.available()) or (not self.getSystemLanguage()): return self.changed() (lang, code) = self.getSystemLanguage() combo = self.ui.comboBoxInputMethod combo.clear() currentIM = self.imSwitch.getInputMethodForLocale(code) if currentIM == None: currentIM = 'none' for (i, IM) in enumerate(self.imSwitch.getAvailableInputMethods()): combo.insertItem(i,IM) if IM == currentIM: combo.setCurrentIndex(i) def run_pkg_manager_update(self): self.returncode = 0 self.returncode = subprocess.call(["qapt-batch", "--attach", str(self.winId()), "--update"]) def run_pkg_manager(self, to_inst, to_rm): self.returncode = 0 if len(to_inst) > 0: print str(["qapt-batch","--install"]+to_inst) self.returncode = subprocess.call(["qapt-batch", "--attach", str(self.winId()), "--install"]+to_inst) # then remove if len(to_rm) > 0: print str(["qapt-batch","--uninstall"]+to_rm) self.returncode = subprocess.call(["qapt-batch", "--attach", str(self.winId()), "--uninstall"]+to_rm) def onSystemLanguageApply(self): (lang, code) = self.getSystemLanguage() self.writeSysLanguageSetting(code) self.writeSysLangSetting(code) self.updateInputMethods(code) KMessageBox.information(self, _("Default system Language now set to %s.") % lang, _("Language Set")) def updateInputMethods(self,code): IM_choice = self.ui.comboBoxInputMethod.currentText() self.imSwitch.setInputMethodForLocale(IM_choice, code) def getSystemLanguage(self): """ returns tuple of (lang, code) strings """ items = self.ui.listBoxDefaultLanguage.selectedItems() if len(items) == 1: item = items[0] lang = item.text() new_locale = ("%s"%lang) try: code = self._localeinfo.localeToCodeMap[new_locale] return (lang, code) except KeyError: print "ERROR: can not find new_locale: '%s'"%new_locale def pkgChanges(self, mode): if mode == "install": items = self.ui.listViewLanguagesInst.selectedItems() else: items = self.ui.listViewLanguagesUninst.selectedItems() if len(items) == 1: elm = items[0] li = self._localeinfo.listviewStrToLangInfoMap[unicode(elm.text())] langPkg = li.languagePkgList["languagePack"] if langPkg.available: if (mode == "install") and (not langPkg.installed): langPkg.doChange = self.ui.checkBoxTr.isChecked() elif (mode == "uninstall") and langPkg.installed: langPkg.doChange = True try: self._cache.tryChangeDetails(li) for langPkg in li.languagePkgList.values(): langPkg.doChange = False except ExceptionPkgCacheBroken: s = _("Software database is broken") t = _("It is impossible to install or remove any software. " "Please use the package manager \"Adept\" or run " "\"sudo apt-get install -f\" in a terminal to fix " "this issue at first.") KMessageBox.error(self, t, s) sys.exit(1) (to_inst, to_rm) = self._cache.getChangesList() if len(to_inst) == len(to_rm) == 0: return # first install self.setCursor(Qt.WaitCursor) self.setEnabled(False) self.run_pkg_manager(to_inst,to_rm) self.setCursor(Qt.ArrowCursor) self.setEnabled(True) # kdmscript = "/etc/init.d/kdm" # if os.path.exists("/var/run/kdm.pid") and os.path.exists(kdmscript): # subprocess.call(["invoke-rc.d","kdm","reload"]) #self.run_pkg_manager(to_inst, to_rm) if self.returncode == 0: if (mode == "install"): KMessageBox.information( self, _("All selected components have now been installed for %s. Select them from Country/Region & Language.") % unicode(items[0].text()), _("Language Installed") ) elif (mode == "uninstall"): KMessageBox.information( self, _("Translations and support have now been uninstalled for %s.") % unicode(items[0].text()), _("Language Uninstalled") ) # Resync the cache to match packageManager changes, then update views self._cache.open(None) self.updateLanguagesList() self.updateSystemDefaultListbox() if mode == "install": self.checkInstallableComponents() else: KMessageBox.sorry(self, _("Failed to set system language."), _("Language Not Set")) self._cache.clear() # undo all selections