tweak_group_xkb.py 6.58 KB
Newer Older
1
2
3
# Copyright (c) 2012 Red Hat, Inc.
# Authors:
#       Rui Matos
4
5
# SPDX-License-Identifier: GPL-3.0+
# License-Filename: LICENSES/GPL-3.0
6
7
8

import logging

9
10
import gi
gi.require_version("GnomeDesktop", "3.0")
11
from gi.repository import Gtk, GnomeDesktop
John Stowers's avatar
John Stowers committed
12
from gtweak.tweakmodel import Tweak, TweakGroup
13
14
from gtweak.widgets import GSettingsSwitchTweak, build_label_beside_widget, GSettingsComboEnumTweak, GSettingsComboTweak, build_horizontal_sizegroup, ListBoxTweakGroup
from gtweak.gsettings import GSettingsSetting, GSettingsMissingError
15
16


17
class _XkbOption(Gtk.Expander, Tweak):
18
19
20
21
22
    def __init__(self, group_id, parent_settings, xkb_info, **options):
        try:
            desc = xkb_info.description_for_group(group_id)
        except AttributeError:
            desc = group_id
23
        Gtk.Expander.__init__(self)
24
25
        Tweak.__init__(self, desc, desc, **options)

26
27
28
29
30
        self.set_label(self.name)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=3)
        vbox.set_margin_start(15)
        self.add(vbox)

31
        self._multiple_selection = not group_id in { 'keypad', 'kpdl', 'caps', 'altwin', 'nbsp', 'esperanto' }
32
33
34
35
36
        self._group_id = group_id
        self._parent_settings = parent_settings
        self._xkb_info = xkb_info
        self._possible_values = []

37
        model_values = []
38
39
40
        if not self._multiple_selection:
            model_values.append((None, _("Disabled")))

41
42
43
44
45
        for option_id in self._xkb_info.get_options_for_group(group_id):
            desc = self._xkb_info.description_for_option(group_id, option_id)
            model_values.append((option_id, desc))
            self._possible_values.append(option_id)

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
        def values_cmp_py3_wrap(f):
            ''' https://docs.python.org/3/howto/sorting.html#the-old-way-using-the-cmp-parameter '''
            class C:
                def __init__(self, obj, *args):
                    self.obj = obj
                def __lt__(self, other):
                    return f(self.obj, other.obj) < 0
                def __gt__(self, other):
                    return f(self.obj, other.obj) > 0
                def __eq__(self, other):
                    return f(self.obj, other.obj) == 0
                def __le__(self, other):
                    return f(self.obj, other.obj) <= 0
                def __ge__(self, other):
                    return f(self.obj, other.obj) >= 0
                def __ne__(self, other):
                    return f(self.obj, other.obj) != 0
            return C

        def values_cmp(xxx_todo_changeme, xxx_todo_changeme1):
            (av, ad) = xxx_todo_changeme
            (bv, bd) = xxx_todo_changeme1
68
69
70
71
72
            if not av:
                return -1
            elif not bv:
                return 1
            else:
73
74
                return (ad > bd) - (ad < bd)
        model_values.sort(key=values_cmp_py3_wrap(values_cmp))
75

76
        self._widgets = dict()
77
        for (val, name) in model_values:
78
79
80
81
82
83
84
            w = None
            if self._multiple_selection:
                w = Gtk.CheckButton.new()
            else:
                w = Gtk.RadioButton.new_from_widget(self._widgets.get(None))
            self._widgets[val] = w;
            vbox.add(w)
85
            l = Gtk.Label(label=name)
86
            l.set_line_wrap(True)
87
88
89
            w.add(l)
            w._changed_id = w.connect('toggled', self._on_toggled)
            w._val = val
90

John Stowers's avatar
John Stowers committed
91
        self.widget_for_size_group = None
92
93
94
        self.reload()

    def reload(self):
95
        self._values = []
96
97
        for v in self._parent_settings.get_strv(TypingTweakGroup.XKB_GSETTINGS_NAME):
            if (v in self._possible_values):
98
                self._values.append(v)
99

100
        self._update_checks()
101

102
103
    def _update_checks(self):
        if len(self._values) > 0:
104
105
106
107
            self.set_label('<b>'+self.name+'</b>')
            self.set_use_markup(True)
        else:
            self.set_label(self.name)
108

109
110
111
112
        def _set_active(w, active):
            w.disconnect(w._changed_id)
            w.set_active(active)
            w._changed_id = w.connect('toggled', self._on_toggled)
113

114
115
116
117
118
119
        if not self._multiple_selection:
            if len(self._values) > 0:
                w = self._widgets.get(self._values[0])
                if w:
                    _set_active(w, True)
        else:
120
            for w in list(self._widgets.values()):
121
122
123
124
125
126
127
                if w._val in self._values:
                    _set_active(w, True)
                else:
                    _set_active(w, False)

    def _on_toggled(self, w):
        active = w.get_active()
128
129
130
131
        if not self._multiple_selection and active:
            for v in self._values:
                self._parent_settings.setting_remove_from_list(TypingTweakGroup.XKB_GSETTINGS_NAME, v)

132
133
134
135
        if w._val in self._values and not active:
            self._parent_settings.setting_remove_from_list(TypingTweakGroup.XKB_GSETTINGS_NAME, w._val)
        elif active and not w._val in self._values and w._val:
            self._parent_settings.setting_add_to_list(TypingTweakGroup.XKB_GSETTINGS_NAME, w._val)
136

137
class TypingTweakGroup(Gtk.Box):
138
139
140

    XKB_GSETTINGS_SCHEMA = "org.gnome.desktop.input-sources"
    XKB_GSETTINGS_NAME = "xkb-options"
141
    # grp_led is unsupported
142
    XKB_OPTIONS_BLACKLIST = {"grp_led", "Compose key"}
143
144

    def __init__(self):
John Stowers's avatar
John Stowers committed
145
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=3)
146
147
148
149
        self._option_objects = []
        ok = False
        try:
            self._kbdsettings = GSettingsSetting(self.XKB_GSETTINGS_SCHEMA)
150
            self._kdb_settings_id = self._kbdsettings.connect("changed::"+self.XKB_GSETTINGS_NAME, self._on_changed)
151
152
            self._xkb_info = GnomeDesktop.XkbInfo()
            ok = True
153
            self.loaded = True
154
155
        except GSettingsMissingError:
            logging.info("Typing missing schema %s" % self.XKB_GSETTINGS_SCHEMA)
Jeremy Bicha's avatar
Jeremy Bicha committed
156
            self.loaded = False
157
158
        except AttributeError:
            logging.warning("Typing missing GnomeDesktop.gir with Xkb support")
159
            self.loaded = False
160
161
162
        finally:
            if ok:
                for opt in set(self._xkb_info.get_all_option_groups()) - self.XKB_OPTIONS_BLACKLIST:
163
164
165
                    obj = _XkbOption(opt, self._kbdsettings, self._xkb_info)
                    self._option_objects.append(obj)
                    self.pack_start(obj, False, False, 0)
John Stowers's avatar
John Stowers committed
166
        TweakGroup.__init__(self, _("Typing"), *self._option_objects)
167

168
169
        self.connect("destroy", self._on_destroy)

170
171
172
    def _on_changed(self, *args):
        for obj in self._option_objects:
            obj.reload()
173
174
175
176

    def _on_destroy(self, event):
        if (self._kdb_settings_id):
            self._kbdsettings.disconnect(self._kdb_settings_id)