Blame setup/enginetreeview.py

Packit 3ff832
# vim:set et sts=4 sw=4:
Packit 3ff832
#
Packit 3ff832
# ibus - The Input Bus
Packit 3ff832
#
Packit 3ff832
# Copyright (c) 2007-2015 Peng Huang <shawn.p.huang@gmail.com>
Packit 3ff832
# Copyright (c) 2014-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
Packit 3ff832
# Copyright (c) 2007-2018 Red Hat, Inc.
Packit 3ff832
#
Packit 3ff832
# This library is free software; you can redistribute it and/or
Packit 3ff832
# modify it under the terms of the GNU Lesser General Public
Packit 3ff832
# License as published by the Free Software Foundation; either
Packit 3ff832
# version 2.1 of the License, or (at your option) any later version.
Packit 3ff832
#
Packit 3ff832
# This library is distributed in the hope that it will be useful,
Packit 3ff832
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 3ff832
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 3ff832
# Lesser General Public License for more details.
Packit 3ff832
#
Packit 3ff832
# You should have received a copy of the GNU Lesser General Public
Packit 3ff832
# License along with this library; if not, write to the Free Software
Packit 3ff832
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
Packit 3ff832
# USA
Packit 3ff832
Packit 3ff832
from gi.repository import GLib
Packit 3ff832
from gi.repository import GObject
Packit 3ff832
from gi.repository import Gtk
Packit 3ff832
from gi.repository import IBus
Packit 3ff832
from gi.repository import Pango
Packit 3ff832
Packit 3ff832
import i18n
Packit 3ff832
Packit 3ff832
from icon import load_icon
Packit 3ff832
from i18n import _, N_
Packit 3ff832
Packit 3ff832
class EngineTreeView(Gtk.TreeView):
Packit 3ff832
    __gtype_name__ = 'EngineTreeView'
Packit 3ff832
    __gproperties__ = {
Packit 3ff832
        'active-engine' : (
Packit 3ff832
            object,
Packit 3ff832
            'selected engine',
Packit 3ff832
            'selected engine',
Packit 3ff832
            GObject.ParamFlags.READABLE),
Packit 3ff832
        'engines' : (
Packit 3ff832
            object,
Packit 3ff832
            'engines',
Packit 3ff832
            'engines',
Packit 3ff832
            GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE)
Packit 3ff832
    }
Packit 3ff832
Packit 3ff832
    def __init__(self):
Packit 3ff832
        super(EngineTreeView, self).__init__()
Packit 3ff832
Packit 3ff832
        self.__engines = []
Packit 3ff832
        self.__changed = False
Packit 3ff832
Packit 3ff832
        # self.set_headers_visible(True)
Packit 3ff832
        self.set_reorderable(True)
Packit 3ff832
Packit 3ff832
        self.__model = Gtk.ListStore(GObject.TYPE_PYOBJECT, GObject.TYPE_STRING)
Packit 3ff832
        self.set_model(self.__model)
Packit 3ff832
        self.__model.connect("row-changed", self.__emit_changed_delay_cb, "row-changed")
Packit 3ff832
        self.__model.connect("row-deleted", self.__emit_changed_delay_cb, "row-deleted")
Packit 3ff832
        self.__model.connect("row-inserted", self.__emit_changed_delay_cb, "row-inserted")
Packit 3ff832
        self.__model.connect("rows-reordered", self.__emit_changed_delay_cb, "rows-reordered")
Packit 3ff832
        self.__model.set_default_sort_func(self.__sort_engines, None)
Packit 3ff832
        self.__model.set_sort_column_id(-1, Gtk.SortType.ASCENDING)
Packit 3ff832
Packit 3ff832
        # create im name & icon column
Packit 3ff832
        column = Gtk.TreeViewColumn(_("Input Method"))
Packit 3ff832
        column.set_min_width(220)
Packit 3ff832
Packit 3ff832
        renderer = Gtk.CellRendererPixbuf()
Packit 3ff832
        renderer.set_property("xalign", 0)
Packit 3ff832
        column.pack_start(renderer, False)
Packit 3ff832
        column.set_cell_data_func(renderer, self.__icon_cell_data_cb)
Packit 3ff832
Packit 3ff832
        renderer = Gtk.CellRendererText()
Packit 3ff832
        renderer.set_property("xalign", 0)
Packit 3ff832
        renderer.set_property("ellipsize", Pango.EllipsizeMode.END)
Packit 3ff832
        column.pack_start(renderer, True)
Packit 3ff832
        column.set_cell_data_func(renderer, self.__name_cell_data_cb)
Packit 3ff832
        self.append_column(column)
Packit 3ff832
Packit 3ff832
        # create im keyboard layout column
Packit 3ff832
        renderer = Gtk.CellRendererCombo()
Packit 3ff832
        model = Gtk.ListStore(GObject.TYPE_STRING)
Packit 3ff832
        model.append(("us",))
Packit 3ff832
        model.append(("jp",))
Packit 3ff832
        model.append(("xkb",))
Packit 3ff832
        renderer.set_property("xalign", 0)
Packit 3ff832
        renderer.set_property("model", model)
Packit 3ff832
        renderer.set_property("text-column", 0)
Packit 3ff832
        renderer.set_property("has-entry", False)
Packit 3ff832
        renderer.set_property("editable", True)
Packit 3ff832
Packit 3ff832
        column = Gtk.TreeViewColumn(_("Kbd"))
Packit 3ff832
        column.set_expand(False)
Packit 3ff832
        column.set_fixed_width(32)
Packit 3ff832
        column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
Packit 3ff832
        column.pack_start(renderer, False)
Packit 3ff832
        column.set_cell_data_func(renderer, self.__layout_cell_data_cb)
Packit 3ff832
        # self.append_column(column)
Packit 3ff832
Packit 3ff832
        self.get_selection().connect("changed", self.__selection_changed_cb)
Packit 3ff832
Packit 3ff832
    def __sort_engines(self, model, a, b, data):
Packit 3ff832
        engine_a = model[a][0]
Packit 3ff832
        engine_b = model[b][0]
Packit 3ff832
        language_a = IBus.get_language_name(engine_a.get_language())
Packit 3ff832
        language_b = IBus.get_language_name(engine_b.get_language())
Packit 3ff832
        longname_a = i18n.gettext_engine_longname(engine_a)
Packit 3ff832
        longname_b = i18n.gettext_engine_longname(engine_b)
Packit 3ff832
        label_a = "%s - %s" % (language_a, longname_a)
Packit 3ff832
        label_b = "%s - %s" % (language_b, longname_b)
Packit 3ff832
        # http://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons
Packit 3ff832
        return (label_a > label_b) - (label_a < label_b)
Packit 3ff832
Packit 3ff832
    def __selection_changed_cb(self, *args):
Packit 3ff832
        self.notify("active-engine");
Packit 3ff832
Packit 3ff832
    def __emit_changed(self, *args):
Packit 3ff832
        if self.__changed:
Packit 3ff832
            self.__changed = False
Packit 3ff832
            self.notify("engines")
Packit 3ff832
Packit 3ff832
    def __emit_changed_delay_cb(self, *args):
Packit 3ff832
        if not self.__changed:
Packit 3ff832
            self.__changed = True
Packit 3ff832
            GLib.idle_add(self.__emit_changed)
Packit 3ff832
Packit 3ff832
Packit 3ff832
    def __icon_cell_data_cb(self, celllayout, renderer, model, it, data):
Packit 3ff832
        engine = self.__model.get_value(it, 0)
Packit 3ff832
Packit 3ff832
        # When append_engine() is called, self.__model.append(None)
Packit 3ff832
        # is called internally and engine == None could happen in
Packit 3ff832
        # a slow system.
Packit 3ff832
        if engine == None:
Packit 3ff832
            return
Packit 3ff832
Packit 3ff832
        icon_size = Gtk.icon_size_lookup(Gtk.IconSize.LARGE_TOOLBAR)[0]
Packit 3ff832
        pixbuf = load_icon(engine.get_icon(), Gtk.IconSize.LARGE_TOOLBAR)
Packit 3ff832
        renderer.set_property("pixbuf", pixbuf)
Packit 3ff832
Packit 3ff832
    def __name_cell_data_cb(self, celllayout, renderer, model, it, data):
Packit 3ff832
        engine = self.__model.get_value(it, 0)
Packit 3ff832
Packit 3ff832
        # When append_engine() is called, self.__model.append(None)
Packit 3ff832
        # is called internally and engine == None could happen in
Packit 3ff832
        # a slow system.
Packit 3ff832
        if engine == None:
Packit 3ff832
            return
Packit 3ff832
Packit 3ff832
        renderer.set_property("sensitive", True)
Packit 3ff832
        language = IBus.get_language_name(engine.get_language())
Packit 3ff832
        longname = i18n.gettext_engine_longname(engine)
Packit 3ff832
        renderer.set_property("text",
Packit 3ff832
                "%s - %s" % (language, longname))
Packit 3ff832
        renderer.set_property("weight", Pango.Weight.NORMAL)
Packit 3ff832
Packit 3ff832
    def __layout_cell_data_cb(self, celllayout, renderer, model, it, data):
Packit 3ff832
        engine = self.__model.get_value(it, 0)
Packit 3ff832
        layout = self.__model.get_value(it, 1)
Packit 3ff832
        renderer.set_property("sensitive", True)
Packit 3ff832
        if not layout:
Packit 3ff832
            layout = engine.layout
Packit 3ff832
        renderer.set_property("text", layout)
Packit 3ff832
        renderer.set_property("weight", Pango.Weight.NORMAL)
Packit 3ff832
Packit 3ff832
    def do_get_property(self, prop):
Packit 3ff832
        if prop.name == "active-engine":
Packit 3ff832
            it = self.get_selected_iter()
Packit 3ff832
            if it == None:
Packit 3ff832
                return None
Packit 3ff832
            row = self.__model.get(it, 0)
Packit 3ff832
            return row[0]
Packit 3ff832
        elif prop.name == "engines":
Packit 3ff832
            engines = [ r[0] for r in self.__model if r[0] != None]
Packit 3ff832
            return engines
Packit 3ff832
        else:
Packit 3ff832
            raise AttributeError('unknown property %s' % prop.name)
Packit 3ff832
Packit 3ff832
    def do_set_property(self, prop, value):
Packit 3ff832
        if prop.name == "active-engine":
Packit 3ff832
            raise AttributeError("active-engine is readonly")
Packit 3ff832
        elif prop.name == "engines":
Packit 3ff832
            set_engines(value)
Packit 3ff832
        else:
Packit 3ff832
            raise AttributeError('unknown property %s' % prop.name)
Packit 3ff832
Packit 3ff832
    def set_engines(self, engines):
Packit 3ff832
        self.__model.clear()
Packit 3ff832
        self.__engines = []
Packit 3ff832
        for e in engines:
Packit 3ff832
            if e in self.__engines:
Packit 3ff832
                continue
Packit 3ff832
            it = self.__model.append(None)
Packit 3ff832
            i18n.init_textdomain(e.get_textdomain())
Packit 3ff832
            self.__model.set(it, 0, e)
Packit 3ff832
            self.__engines.append(e)
Packit 3ff832
        self.__emit_changed()
Packit 3ff832
Packit 3ff832
    def get_selected_iter(self):
Packit 3ff832
        selection = self.get_selection()
Packit 3ff832
        if selection:
Packit 3ff832
            return selection.get_selected()[1]
Packit 3ff832
Packit 3ff832
    def get_engines(self):
Packit 3ff832
        return self.__engines
Packit 3ff832
Packit 3ff832
    def get_sorted_engines(self):
Packit 3ff832
        return self.get_property("engines")
Packit 3ff832
Packit 3ff832
    def get_active_engine(self):
Packit 3ff832
        return self.get_property("active-engine")
Packit 3ff832
Packit 3ff832
    def prepend_engine(self, engine):
Packit 3ff832
        if engine == None or engine in self.__engines:
Packit 3ff832
            return
Packit 3ff832
        it = self.__model.prepend(None)
Packit 3ff832
        self.__model.set(it, 0, engine)
Packit 3ff832
        self.__engines = [engine] + self.__engines
Packit 3ff832
Packit 3ff832
    def append_engine(self, engine):
Packit 3ff832
        if engine == None or engine in self.__engines:
Packit 3ff832
            return
Packit 3ff832
        it = self.__model.append(None)
Packit 3ff832
        self.__model.set(it, 0, engine)
Packit 3ff832
        self.__engines.append(engine)
Packit 3ff832
Packit 3ff832
    def remove_engine(self):
Packit 3ff832
        it = self.get_selected_iter()
Packit 3ff832
        if it == None:
Packit 3ff832
            return
Packit 3ff832
        row = self.__model[it]
Packit 3ff832
        engine = row[0]
Packit 3ff832
        self.__engines.remove(engine)
Packit 3ff832
        index = row.path.get_indices()[0]
Packit 3ff832
        self.__model.remove(it)
Packit 3ff832
        try:
Packit 3ff832
            row = self.__model[index]
Packit 3ff832
            selection = self.get_selection()
Packit 3ff832
            selection.select_path(row.path)
Packit 3ff832
        except:
Packit 3ff832
            pass
Packit 3ff832
Packit 3ff832
    def move_up_engine(self):
Packit 3ff832
        it = self.get_selected_iter()
Packit 3ff832
        if it == None:
Packit 3ff832
            return
Packit 3ff832
        row = self.__model[it]
Packit 3ff832
        index = row.path.get_indices()[0]
Packit 3ff832
        if index == 0:
Packit 3ff832
            return
Packit 3ff832
        self.__model.swap(it, self.__model[index - 1].iter)
Packit 3ff832
        self.scroll_to_cell(row.path, None)
Packit 3ff832
Packit 3ff832
    def move_down_engine(self):
Packit 3ff832
        it = self.get_selected_iter()
Packit 3ff832
        if it == None:
Packit 3ff832
            return
Packit 3ff832
        row = self.__model[it]
Packit 3ff832
        index = row.path.get_indices()[0]
Packit 3ff832
        last_row = self.__model[-1]
Packit 3ff832
        last_index = last_row.path.get_indices()[0]
Packit 3ff832
        if index == last_index:
Packit 3ff832
            return
Packit 3ff832
        self.__model.swap(it, self.__model[index + 1].iter)
Packit 3ff832
        self.scroll_to_cell(row.path, None)
Packit 3ff832
Packit 3ff832
GObject.type_register(EngineTreeView)
Packit 3ff832
Packit 3ff832
if __name__ == "__main__":
Packit 3ff832
    tree = EngineTreeView()
Packit 3ff832
    tree.set_engines([IBus.EngineDesc(language="zh")])
Packit 3ff832
    w = Gtk.Window()
Packit 3ff832
    w.add(tree)
Packit 3ff832
    w.show_all()
Packit 3ff832
    Gtk.main()