Blame setup/enginedialog.py

Packit 3ff832
# vim:set et sts=4 sw=4:
Packit 3ff832
# -*- coding: utf-8 -*-
Packit 3ff832
#
Packit 3ff832
# ibus - The Input Bus
Packit 3ff832
#
Packit 3ff832
# Copyright (c) 2015 Peng Huang <shawn.p.huang@gmail.com>
Packit 3ff832
# Copyright (c) 2015 Takao Fujiwara <takao.fujiwara1@gmail.com>
Packit 3ff832
# Copyright (c) 2013-2015 Red Hat, Inc.
Packit 3ff832
#
Packit 3ff832
# This program is free software; you can redistribute it and/or
Packit 3ff832
# modify it under the terms of the GNU General Public License as
Packit 3ff832
# published by the Free Software Foundation; either version 2 of the
Packit 3ff832
# License, or (at your option) any later version.
Packit 3ff832
#
Packit 3ff832
# This program is distributed in the hope that it will be useful, but
Packit 3ff832
# WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 3ff832
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 3ff832
# General Public License for more details.
Packit 3ff832
#
Packit 3ff832
# You should have received a copy of the GNU General Public License
Packit 3ff832
# along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit 3ff832
Packit 3ff832
# This file is ported from
Packit 3ff832
# gnome-control-center/panels/region/cc-input-chooser.c
Packit 3ff832
Packit 3ff832
from gi.repository import Gtk
Packit 3ff832
from gi.repository import GLib
Packit 3ff832
from gi.repository import IBus
Packit 3ff832
Packit 3ff832
import functools
Packit 3ff832
import gettext
Packit 3ff832
import i18n
Packit 3ff832
import locale
Packit 3ff832
Packit 3ff832
from icon import load_icon
Packit 3ff832
from i18n import _, N_
Packit 3ff832
Packit 3ff832
ROW_TRAVEL_DIRECTION_NONE,      \
Packit 3ff832
ROW_TRAVEL_DIRECTION_FORWARD,   \
Packit 3ff832
ROW_TRAVEL_DIRECTION_BACKWARD = list(range(3))
Packit 3ff832
Packit 3ff832
class EngineDialog(Gtk.Dialog):
Packit 3ff832
    __gtype_name__ = 'EngineDialog'
Packit 3ff832
    __initial_languages = [ IBus.get_language_name('en_US'),
Packit 3ff832
                            IBus.get_language_name('en_GB'),
Packit 3ff832
                            IBus.get_language_name('de_DE'),
Packit 3ff832
                            IBus.get_language_name('fr_FR'),
Packit 3ff832
                            IBus.get_language_name('es_ES'),
Packit 3ff832
                            IBus.get_language_name('zh_CN'),
Packit 3ff832
                            IBus.get_language_name('ja_JP'),
Packit 3ff832
                            IBus.get_language_name('ru_RU'),
Packit 3ff832
                            IBus.get_language_name('ar_EG') ]
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __init__(self, transient_for = None):
Packit 3ff832
        super(EngineDialog, self).__init__(
Packit 3ff832
                title = _("Select an input method"),
Packit 3ff832
                transient_for = transient_for,
Packit 3ff832
                resizable = True)
Packit 3ff832
        buttons = (_("_Cancel"), Gtk.ResponseType.CANCEL,
Packit 3ff832
                   _("_Add"), Gtk.ResponseType.APPLY)
Packit 3ff832
        self.add_buttons(*buttons)
Packit 3ff832
        self.set_response_sensitive(Gtk.ResponseType.APPLY, False)
Packit 3ff832
Packit 3ff832
        self.__engines_for_lang = {}
Packit 3ff832
        self.__untrans_for_lang = {}
Packit 3ff832
        self.__langs = {}
Packit 3ff832
Packit 3ff832
        self.__scrolled = Gtk.ScrolledWindow(
Packit 3ff832
                hscrollbar_policy = Gtk.PolicyType.NEVER,
Packit 3ff832
                vscrollbar_policy = Gtk.PolicyType.NEVER,
Packit 3ff832
                shadow_type = Gtk.ShadowType.IN,
Packit 3ff832
                margin_left = 6,
Packit 3ff832
                margin_right = 6,
Packit 3ff832
                margin_top = 6,
Packit 3ff832
                margin_bottom = 6)
Packit 3ff832
        self.vbox.add(self.__scrolled)
Packit 3ff832
        viewport = Gtk.Viewport()
Packit 3ff832
        self.__scrolled.add(viewport)
Packit 3ff832
        self.__list = Gtk.ListBox(vexpand = True,
Packit 3ff832
                                  halign = Gtk.Align.FILL,
Packit 3ff832
                                  valign = Gtk.Align.FILL)
Packit 3ff832
        viewport.add(self.__list)
Packit 3ff832
Packit 3ff832
        self.__adjustment = self.__scrolled.get_vadjustment()
Packit 3ff832
        self.__list.set_adjustment(self.__adjustment)
Packit 3ff832
        self.__list.set_filter_func(self.__list_filter, None)
Packit 3ff832
        self.__list.connect('row-activated', self.__row_activated)
Packit 3ff832
        self.__list.connect('row-selected', self.__row_selected)
Packit 3ff832
Packit 3ff832
        self.__showing_extra = False
Packit 3ff832
        self.__more_row = self.__more_row_new()
Packit 3ff832
Packit 3ff832
        self.__filter_timeout_id = 0
Packit 3ff832
        self.__filter_word = None
Packit 3ff832
        self.__filter_entry = Gtk.SearchEntry(hexpand = True,
Packit 3ff832
                                              margin_left = 6,
Packit 3ff832
                                              margin_right = 6,
Packit 3ff832
                                              margin_top = 6,
Packit 3ff832
                                              margin_bottom = 6)
Packit 3ff832
        self.__filter_entry.set_no_show_all(True)
Packit 3ff832
        self.__filter_entry.connect('search-changed', self.__filter_changed)
Packit 3ff832
        self.vbox.add(self.__filter_entry)
Packit 3ff832
Packit 3ff832
        self.show_all()
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __list_filter(self, row, data):
Packit 3ff832
        if row == self.__more_row:
Packit 3ff832
            return not self.__showing_extra
Packit 3ff832
        if not self.__showing_extra and row.is_extra:
Packit 3ff832
            return False
Packit 3ff832
        if self.__filter_word == None:
Packit 3ff832
            return True
Packit 3ff832
Packit 3ff832
        name = row.name.lower()
Packit 3ff832
        untrans = row.untrans.lower()
Packit 3ff832
        if self.__filter_word != None:
Packit 3ff832
            word = self.__filter_word.lower()
Packit 3ff832
            if name.startswith(word):
Packit 3ff832
                return True
Packit 3ff832
            if untrans.startswith(word):
Packit 3ff832
                return True
Packit 3ff832
        return False
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __row_activated(self, box, row):
Packit 3ff832
        if row == self.__more_row:
Packit 3ff832
            self.__show_more()
Packit 3ff832
            return
Packit 3ff832
        if row.back:
Packit 3ff832
            self.__filter_entry.set_text('')
Packit 3ff832
            self.__show_lang_rows()
Packit 3ff832
            return
Packit 3ff832
        if row.lang_info:
Packit 3ff832
            self.__filter_entry.set_text('')
Packit 3ff832
            self.__show_engines_for_lang(row)
Packit 3ff832
            return
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __row_selected(self, box, row):
Packit 3ff832
        self.set_response_sensitive(Gtk.ResponseType.APPLY, row != None)
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __padded_label_new(self, text, icon, alignment, direction):
Packit 3ff832
        hbox = Gtk.Box(orientation = Gtk.Orientation.HORIZONTAL)
Packit 3ff832
Packit 3ff832
        if direction == ROW_TRAVEL_DIRECTION_BACKWARD:
Packit 3ff832
            rtl = (Gtk.Widget.get_default_direction() == \
Packit 3ff832
                   Gtk.TextDirection.RTL)
Packit 3ff832
            if rtl:
Packit 3ff832
                arrow = Gtk.Image.new_from_icon_name(
Packit 3ff832
                    'go-previous-rtl-symbolic', Gtk.IconSize.MENU)
Packit 3ff832
            else:
Packit 3ff832
                arrow = Gtk.Image.new_from_icon_name(
Packit 3ff832
                    'go-previous-symbolic', Gtk.IconSize.MENU)
Packit 3ff832
            hbox.pack_start(arrow, False, True, 0)
Packit 3ff832
Packit 3ff832
        if icon != None:
Packit 3ff832
            pixbuf = load_icon(icon, Gtk.IconSize.LARGE_TOOLBAR)
Packit 3ff832
            image = Gtk.Image(pixbuf = pixbuf)
Packit 3ff832
            hbox.pack_start(image, False, True, 0)
Packit 3ff832
Packit 3ff832
        label = Gtk.Label(label = text)
Packit 3ff832
        label.set_halign(alignment)
Packit 3ff832
        label.set_valign(Gtk.Align.CENTER)
Packit 3ff832
        label.set_margin_left(20)
Packit 3ff832
        label.set_margin_right(20)
Packit 3ff832
        label.set_margin_top(6)
Packit 3ff832
        label.set_margin_bottom(6)
Packit 3ff832
        hbox.pack_start(label, True, True, 0)
Packit 3ff832
        return hbox
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __list_box_row_new(self, text):
Packit 3ff832
        row = Gtk.ListBoxRow()
Packit 3ff832
        row.name = text
Packit 3ff832
        row.is_extra = False
Packit 3ff832
        row.lang_info = False
Packit 3ff832
        row.back = False
Packit 3ff832
        row.untrans = ''
Packit 3ff832
        row.engine = None
Packit 3ff832
        return row
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __lang_row_new(self, text):
Packit 3ff832
        row = self.__list_box_row_new(text)
Packit 3ff832
        row.lang_info = True
Packit 3ff832
        if len(self.__untrans_for_lang) != 0:
Packit 3ff832
            row.untrans = self.__untrans_for_lang[text]
Packit 3ff832
        if not self.__showing_extra and text not in self.__initial_languages:
Packit 3ff832
            row.is_extra = True
Packit 3ff832
        widget = self.__padded_label_new(text,
Packit 3ff832
                                         None,
Packit 3ff832
                                         Gtk.Align.CENTER,
Packit 3ff832
                                         ROW_TRAVEL_DIRECTION_NONE)
Packit 3ff832
        row.add(widget)
Packit 3ff832
        return row
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __more_row_new(self):
Packit 3ff832
        row = Gtk.ListBoxRow()
Packit 3ff832
        hbox = Gtk.Box(orientation = Gtk.Orientation.HORIZONTAL)
Packit 3ff832
        row.add(hbox)
Packit 3ff832
        row.set_tooltip_text(_("Moreā€¦"))
Packit 3ff832
        arrow = Gtk.Image.new_from_icon_name('view-more-symbolic',
Packit 3ff832
                                             Gtk.IconSize.MENU)
Packit 3ff832
        arrow.set_margin_left(20)
Packit 3ff832
        arrow.set_margin_right(20)
Packit 3ff832
        arrow.set_margin_top(6)
Packit 3ff832
        arrow.set_margin_bottom(6)
Packit 3ff832
        arrow.set_halign(Gtk.Align.CENTER)
Packit 3ff832
        arrow.set_valign(Gtk.Align.CENTER)
Packit 3ff832
        hbox.pack_start(arrow, True, True, 0)
Packit 3ff832
        return row
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __back_row_new(self, text):
Packit 3ff832
        row = self.__list_box_row_new(text)
Packit 3ff832
        row.lang_info = True
Packit 3ff832
        row.back = True
Packit 3ff832
        widget = self.__padded_label_new(text,
Packit 3ff832
                                         None,
Packit 3ff832
                                         Gtk.Align.CENTER,
Packit 3ff832
                                         ROW_TRAVEL_DIRECTION_BACKWARD)
Packit 3ff832
        row.add(widget)
Packit 3ff832
        return row
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __engine_row_new(self, engine):
Packit 3ff832
        longname = i18n.gettext_engine_longname(engine)
Packit 3ff832
        description = i18n.gettext_engine_description(engine)
Packit 3ff832
        row = self.__list_box_row_new(longname)
Packit 3ff832
        row.untrans = engine.get_longname()
Packit 3ff832
        row.set_tooltip_text(description)
Packit 3ff832
        row.engine = engine
Packit 3ff832
        widget = self.__padded_label_new(longname,
Packit 3ff832
                                         engine.get_icon(),
Packit 3ff832
                                         Gtk.Align.START,
Packit 3ff832
                                         ROW_TRAVEL_DIRECTION_NONE)
Packit 3ff832
        row.add(widget)
Packit 3ff832
        return row
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __set_fixed_size(self):
Packit 3ff832
        if self.__scrolled.get_policy()[0] == Gtk.PolicyType.AUTOMATIC:
Packit 3ff832
            return
Packit 3ff832
        (width, height) = self.get_size()
Packit 3ff832
        self.set_size_request(width, height)
Packit 3ff832
        self.__scrolled.set_policy(Gtk.PolicyType.AUTOMATIC,
Packit 3ff832
                                   Gtk.PolicyType.AUTOMATIC)
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __remove_all_children(self):
Packit 3ff832
        for l in self.__list.get_children():
Packit 3ff832
            self.__list.remove(l)
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __add_engine_rows_for_lang(self, row):
Packit 3ff832
        lang = row.name
Packit 3ff832
Packit 3ff832
        def cmp_engine(a, b):
Packit 3ff832
            if a.get_rank() == b.get_rank():
Packit 3ff832
                a_longname = i18n.gettext_engine_longname(a)
Packit 3ff832
                b_longname = i18n.gettext_engine_longname(b)
Packit 3ff832
                return locale.strcoll(a_longname, b_longname)
Packit 3ff832
            return int(b.get_rank() - a.get_rank())
Packit 3ff832
Packit 3ff832
        self.__engines_for_lang[lang].sort(
Packit 3ff832
                key = functools.cmp_to_key(cmp_engine))
Packit 3ff832
        for e in self.__engines_for_lang[lang]:
Packit 3ff832
            row = self.__engine_row_new(e)
Packit 3ff832
            self.__list.add(row)
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __show_lang_rows(self):
Packit 3ff832
        self.__remove_all_children()
Packit 3ff832
        for lang in self.__langs:
Packit 3ff832
            row = self.__lang_row_new(lang)
Packit 3ff832
            self.__list.add(row)
Packit 3ff832
        self.__list.add(self.__more_row)
Packit 3ff832
        self.__list.show_all()
Packit 3ff832
        self.__adjustment.set_value(self.__adjustment.get_lower())
Packit 3ff832
        self.__list.invalidate_filter()
Packit 3ff832
        self.__list.set_selection_mode(Gtk.SelectionMode.SINGLE)
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __show_more(self):
Packit 3ff832
        self.__set_fixed_size()
Packit 3ff832
        self.__filter_entry.show()
Packit 3ff832
        self.__showing_extra = True
Packit 3ff832
        self.__list.invalidate_filter()
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __show_engines_for_lang(self, row):
Packit 3ff832
        text = row.name
Packit 3ff832
        self.__set_fixed_size()
Packit 3ff832
        self.__remove_all_children()
Packit 3ff832
        row = self.__back_row_new(text)
Packit 3ff832
        self.__list.add(row)
Packit 3ff832
        self.__add_engine_rows_for_lang(row)
Packit 3ff832
        self.__list.show_all()
Packit 3ff832
        self.__adjustment.set_value(self.__adjustment.get_lower())
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __do_filter(self):
Packit 3ff832
        text = self.__filter_entry.get_text()
Packit 3ff832
        if text == '':
Packit 3ff832
            self.__filter_word = None
Packit 3ff832
        else:
Packit 3ff832
            self.__filter_word = text
Packit 3ff832
        self.__list.invalidate_filter()
Packit 3ff832
        self.__filter_timeout_id = 0
Packit 3ff832
        return False
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __filter_changed(self, entry):
Packit 3ff832
        if self.__filter_timeout_id == 0:
Packit 3ff832
            self.__filter_timeout_id = GLib.timeout_add(150, self.__do_filter)
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def set_engines(self, engines):
Packit 3ff832
        self.__engines_for_lang = {}
Packit 3ff832
        self.__untrans_for_lang = {}
Packit 3ff832
        for e in engines:
Packit 3ff832
            l = IBus.get_language_name(e.get_language())
Packit 3ff832
            if l == None:
Packit 3ff832
                l = ''
Packit 3ff832
            if l not in self.__engines_for_lang:
Packit 3ff832
                self.__engines_for_lang[l] = []
Packit 3ff832
            i18n.init_textdomain(e.get_textdomain())
Packit 3ff832
            self.__engines_for_lang[l].append(e)
Packit 3ff832
Packit 3ff832
            # Retrieve Untranslated language names.
Packit 3ff832
            untrans = IBus.get_untranslated_language_name(e.get_language())
Packit 3ff832
            if untrans == None:
Packit 3ff832
                untrans = ''
Packit 3ff832
            self.__untrans_for_lang[l] = untrans
Packit 3ff832
Packit 3ff832
        keys = list(self.__engines_for_lang.keys())
Packit 3ff832
        keys.sort(key=functools.cmp_to_key(locale.strcoll))
Packit 3ff832
        loc = locale.getlocale()[0]
Packit 3ff832
        # None on C locale
Packit 3ff832
        if loc == None or loc == 'C':
Packit 3ff832
            loc = 'en_US'
Packit 3ff832
        current_lang = IBus.get_language_name(loc)
Packit 3ff832
        # move current language to the first place
Packit 3ff832
        if current_lang in keys:
Packit 3ff832
            keys.remove(current_lang)
Packit 3ff832
            keys.insert(0, current_lang)
Packit 3ff832
Packit 3ff832
        # move English to the second place
Packit 3ff832
        en_lang = IBus.get_language_name('en_US')
Packit 3ff832
        if en_lang != current_lang and en_lang in keys:
Packit 3ff832
            keys.remove(en_lang)
Packit 3ff832
            keys.insert(1, en_lang)
Packit 3ff832
Packit 3ff832
        #add 'Others' to the end of the combo box
Packit 3ff832
        if IBus.get_language_name('Other') in keys:
Packit 3ff832
            keys.remove(IBus.get_language_name('Other'))
Packit 3ff832
            keys += [IBus.get_language_name('Other')]
Packit 3ff832
Packit 3ff832
        self.__langs = keys
Packit 3ff832
        self.__show_lang_rows()
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def get_selected_engine(self):
Packit 3ff832
        row = self.__list.get_selected_row()
Packit 3ff832
        if row == None:
Packit 3ff832
            return None
Packit 3ff832
        return row.engine