~ubuntu-branches/debian/sid/ibus/sid

« back to all changes in this revision

Viewing changes to .pc/ibus-530711-preload-sys.patch/setup/main.py

  • Committer: Package Import Robot
  • Author(s): Osamu Aoki, Aron Xu, Osamu Aoki
  • Date: 2014-08-04 22:42:19 UTC
  • mfrom: (1.5.7)
  • Revision ID: package-import@ubuntu.com-20140804224219-mjprlql1jdwi5sxm
Tags: 1.5.8-1
[ Aron Xu ]
* Allow parallel building

[ Osamu Aoki ]
* Update ibus document with Qt5 support

[ Aron Xu ]
* Imported Upstream version 1.5.8
* Remove patch for chasing HEAD, imported new upstream release
* Remove the patch for updating IBusKeymap jp, applied upstream
* Drop gtk2 version of the password patch because it's never executed
* Drop ibus-541492-xkb.patch
* Drop ibus-530711-preload-sys.patch
* Drop ibus-810211-no-switch-by-no-trigger.patch
* Drop 999-update-po.patch

[ Osamu Aoki ]
* linux-any for ibus-wayland
* Remove some symbols matching ibus-541492-xkb.patch
* Remove old patch for GTK+ 3.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# vim:set et sts=4 sw=4:
2
 
#
3
 
# ibus - The Input Bus
4
 
#
5
 
# Copyright (c) 2007-2014 Peng Huang <shawn.p.huang@gmail.com>
6
 
# Copyright (c) 2007-2014 Red Hat, Inc.
7
 
#
8
 
# This library is free software; you can redistribute it and/or
9
 
# modify it under the terms of the GNU Lesser General Public
10
 
# License as published by the Free Software Foundation; either
11
 
# version 2.1 of the License, or (at your option) any later version.
12
 
#
13
 
# This library is distributed in the hope that it will be useful,
14
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 
# Lesser General Public License for more details.
17
 
#
18
 
# You should have received a copy of the GNU Lesser General Public
19
 
# License along with this library; if not, write to the Free Software
20
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
21
 
# USA
22
 
 
23
 
# for python2
24
 
from __future__ import print_function
25
 
 
26
 
import os
27
 
import signal
28
 
import sys
29
 
import time
30
 
 
31
 
from gi.repository import Gio
32
 
from gi.repository import GLib
33
 
from gi.repository import Gtk
34
 
from gi.repository import IBus
35
 
from os import path
36
 
 
37
 
import keyboardshortcut
38
 
import locale
39
 
from enginecombobox import EngineComboBox
40
 
from enginetreeview import EngineTreeView
41
 
from engineabout import EngineAbout
42
 
from i18n import DOMAINNAME, _, N_, init as i18n_init
43
 
 
44
 
(
45
 
    COLUMN_NAME,
46
 
    COLUMN_ENABLE,
47
 
    COLUMN_PRELOAD,
48
 
    COLUMN_VISIBLE,
49
 
    COLUMN_ICON,
50
 
    COLUMN_DATA,
51
 
) = list(range(6))
52
 
 
53
 
(
54
 
    DATA_NAME,
55
 
    DATA_LOCAL_NAME,
56
 
    DATA_LANG,
57
 
    DATA_ICON,
58
 
    DATA_AUTHOR,
59
 
    DATA_CREDITS,
60
 
    DATA_EXEC,
61
 
    DATA_STARTED,
62
 
    DATA_PRELOAD
63
 
) = list(range(9))
64
 
 
65
 
class Setup(object):
66
 
    def __flush_gtk_events(self):
67
 
        while Gtk.events_pending():
68
 
            Gtk.main_iteration()
69
 
 
70
 
    def __init__(self):
71
 
        super(Setup, self).__init__()
72
 
 
73
 
        self.__settings_general = Gio.Settings("org.freedesktop.ibus.general");
74
 
        self.__settings_hotkey = Gio.Settings(
75
 
                "org.freedesktop.ibus.general.hotkey");
76
 
        self.__settings_panel = Gio.Settings("org.freedesktop.ibus.panel");
77
 
 
78
 
        # IBus.Bus() calls ibus_bus_new().
79
 
        # Gtk.Builder().add_from_file() also calls ibus_bus_new_async()
80
 
        # via ibus_im_context_new().
81
 
        # Then if IBus.Bus() is called after Gtk.Builder().add_from_file(),
82
 
        # the connection delay would be happened without an async
83
 
        # finish function.
84
 
        self.__bus = None
85
 
        self.__init_bus()
86
 
 
87
 
        gtk_builder_file = path.join(path.dirname(__file__), "./setup.ui")
88
 
        self.__builder = Gtk.Builder()
89
 
        self.__builder.set_translation_domain(DOMAINNAME)
90
 
        self.__builder.add_from_file(gtk_builder_file);
91
 
        self.__init_ui()
92
 
 
93
 
    def __init_hotkey(self):
94
 
        name = 'triggers'
95
 
        label = 'switch_engine'
96
 
        shortcuts = self.__settings_hotkey.get_strv(name)
97
 
        button = self.__builder.get_object("button_%s" % label)
98
 
        entry = self.__builder.get_object("entry_%s" % label)
99
 
        entry.set_text("; ".join(shortcuts))
100
 
        tooltip = "\n".join(shortcuts)
101
 
        tooltip += "\n" + \
102
 
            _("Use shortcut with shift to switch to the previous input method") 
103
 
        entry.set_tooltip_text(tooltip)
104
 
        button.connect("clicked", self.__shortcut_button_clicked_cb,
105
 
                name, "general/hotkey", label, entry)
106
 
 
107
 
    def __init_panel(self):
108
 
        # lookup table orientation
109
 
        self.__combobox_lookup_table_orientation = self.__builder.get_object(
110
 
                "combobox_lookup_table_orientation")
111
 
        self.__settings_panel.bind('lookup-table-orientation',
112
 
                                   self.__combobox_lookup_table_orientation,
113
 
                                   'active',
114
 
                                   Gio.SettingsBindFlags.DEFAULT)
115
 
 
116
 
        # auto hide
117
 
        self.__combobox_panel_show = self.__builder.get_object(
118
 
                "combobox_panel_show")
119
 
        self.__settings_panel.bind('show',
120
 
                                   self.__combobox_panel_show,
121
 
                                   'active',
122
 
                                   Gio.SettingsBindFlags.DEFAULT)
123
 
 
124
 
        # panel position
125
 
        self.__combobox_panel_position = self.__builder.get_object(
126
 
                "combobox_panel_position")
127
 
        self.__combobox_panel_position.set_active(3)
128
 
        #self.__settings_panel.bind('position',
129
 
        #                           self.__combobox_panel_position,
130
 
        #                           'active',
131
 
        #                           Gio.SettingsBindFlags.DEFAULT)
132
 
 
133
 
        # custom font
134
 
        self.__checkbutton_custom_font = self.__builder.get_object(
135
 
                "checkbutton_custom_font")
136
 
        self.__settings_panel.bind('use-custom-font',
137
 
                                   self.__checkbutton_custom_font,
138
 
                                   'active',
139
 
                                   Gio.SettingsBindFlags.DEFAULT)
140
 
 
141
 
        self.__fontbutton_custom_font = self.__builder.get_object(
142
 
                "fontbutton_custom_font")
143
 
        self.__settings_panel.bind('custom-font',
144
 
                                    self.__fontbutton_custom_font,
145
 
                                   'font-name',
146
 
                                   Gio.SettingsBindFlags.DEFAULT)
147
 
        self.__settings_panel.bind('use-custom-font',
148
 
                                    self.__fontbutton_custom_font,
149
 
                                   'sensitive',
150
 
                                   Gio.SettingsBindFlags.GET)
151
 
 
152
 
        # show icon on system tray
153
 
        self.__checkbutton_show_icon_on_systray = self.__builder.get_object(
154
 
                "checkbutton_show_icon_on_systray")
155
 
        self.__settings_panel.bind('show-icon-on-systray',
156
 
                                   self.__checkbutton_show_icon_on_systray,
157
 
                                   'active',
158
 
                                   Gio.SettingsBindFlags.DEFAULT)
159
 
 
160
 
        # show ime name
161
 
        self.__checkbutton_show_im_name = self.__builder.get_object(
162
 
                "checkbutton_show_im_name")
163
 
        self.__settings_panel.bind('show-im-name',
164
 
                                   self.__checkbutton_show_im_name,
165
 
                                   'active',
166
 
                                   Gio.SettingsBindFlags.DEFAULT)
167
 
 
168
 
    def __init_general(self):
169
 
        # embed preedit text
170
 
        self.__checkbutton_embed_preedit_text = self.__builder.get_object(
171
 
                "checkbutton_embed_preedit_text")
172
 
        self.__settings_general.bind('embed-preedit-text',
173
 
                                    self.__checkbutton_embed_preedit_text,
174
 
                                    'active',
175
 
                                    Gio.SettingsBindFlags.DEFAULT)
176
 
 
177
 
        # use system keyboard layout setting
178
 
        self.__checkbutton_use_sys_layout = self.__builder.get_object(
179
 
                "checkbutton_use_sys_layout")
180
 
        self.__settings_general.bind('use-system-keyboard-layout',
181
 
                                    self.__checkbutton_use_sys_layout,
182
 
                                    'active',
183
 
                                    Gio.SettingsBindFlags.DEFAULT)
184
 
 
185
 
        # use global ime setting
186
 
        self.__checkbutton_use_global_engine = self.__builder.get_object(
187
 
                "checkbutton_use_global_engine")
188
 
        self.__settings_general.bind('use-global-engine',
189
 
                                    self.__checkbutton_use_global_engine,
190
 
                                    'active',
191
 
                                    Gio.SettingsBindFlags.DEFAULT)
192
 
 
193
 
        # init engine page
194
 
        self.__engines = self.__bus.list_engines()
195
 
        self.__combobox = self.__builder.get_object("combobox_engines")
196
 
        self.__combobox.set_engines(self.__engines)
197
 
 
198
 
        tmp_dict = {}
199
 
        for e in self.__engines:
200
 
            tmp_dict[e.get_name()] = e
201
 
        engine_names = self.__settings_general.get_strv('preload-engines')
202
 
        engines = [tmp_dict[name] for name in engine_names if name in tmp_dict]
203
 
 
204
 
        self.__treeview = self.__builder.get_object("treeview_engines")
205
 
        self.__treeview.set_engines(engines)
206
 
 
207
 
        button = self.__builder.get_object("button_engine_add")
208
 
        button.connect("clicked", self.__button_engine_add_cb)
209
 
        button = self.__builder.get_object("button_engine_remove")
210
 
        button.connect("clicked", lambda *args:self.__treeview.remove_engine())
211
 
        button = self.__builder.get_object("button_engine_up")
212
 
        button.connect("clicked", lambda *args:self.__treeview.move_up_engine())
213
 
 
214
 
        button = self.__builder.get_object("button_engine_down")
215
 
        button.connect("clicked",
216
 
                lambda *args:self.__treeview.move_down_engine())
217
 
 
218
 
        button = self.__builder.get_object("button_engine_about")
219
 
        button.connect("clicked", self.__button_engine_about_cb)
220
 
 
221
 
        self.__engine_setup_exec_list = {}
222
 
        button = self.__builder.get_object("button_engine_preferences")
223
 
        button.connect("clicked", self.__button_engine_preferences_cb)
224
 
 
225
 
        self.__combobox.connect("notify::active-engine",
226
 
                self.__combobox_notify_active_engine_cb)
227
 
        self.__treeview.connect("notify::active-engine", self.__treeview_notify_cb)
228
 
        self.__treeview.connect("notify::engines", self.__treeview_notify_cb)
229
 
 
230
 
    def __init_ui(self):
231
 
        # add icon search path
232
 
        self.__window = self.__builder.get_object("window_preferences")
233
 
        self.__window.connect("delete-event", Gtk.main_quit)
234
 
 
235
 
        self.__button_close = self.__builder.get_object("button_close")
236
 
        self.__button_close.connect("clicked", Gtk.main_quit)
237
 
 
238
 
        # auto start ibus
239
 
        self.__checkbutton_auto_start = self.__builder.get_object(
240
 
                "checkbutton_auto_start")
241
 
        self.__checkbutton_auto_start.set_active(self.__is_auto_start())
242
 
        self.__checkbutton_auto_start.connect("toggled",
243
 
                self.__checkbutton_auto_start_toggled_cb)
244
 
 
245
 
        self.__init_hotkey()
246
 
        self.__init_panel()
247
 
        self.__init_general()
248
 
 
249
 
    def __combobox_notify_active_engine_cb(self, combobox, property):
250
 
        engine = self.__combobox.get_active_engine()
251
 
        button = self.__builder.get_object("button_engine_add")
252
 
        button.set_sensitive(
253
 
                engine != None and engine not in self.__treeview.get_engines())
254
 
 
255
 
    def __get_engine_setup_exec_args(self, engine):
256
 
        args = []
257
 
        if engine == None:
258
 
           return args
259
 
        setup = str(engine.get_setup())
260
 
        if len(setup) != 0:
261
 
            args = setup.split()
262
 
            args.insert(1, path.basename(args[0]))
263
 
            return args
264
 
        name = str(engine.get_name())
265
 
        libexecdir = os.environ['IBUS_LIBEXECDIR']
266
 
        setup_path = (libexecdir + '/' + 'ibus-setup-' if libexecdir != None \
267
 
            else 'ibus-setup-') + name.split(':')[0]
268
 
        if path.exists(setup_path):
269
 
            args.append(setup_path)
270
 
            args.append(path.basename(setup_path))
271
 
        return args
272
 
 
273
 
    def __treeview_notify_cb(self, treeview, prop):
274
 
        if prop.name not in ("active-engine", "engines"):
275
 
            return
276
 
 
277
 
        engines = self.__treeview.get_engines()
278
 
        engine = self.__treeview.get_active_engine()
279
 
 
280
 
        self.__builder.get_object("button_engine_remove").set_sensitive(engine != None)
281
 
        self.__builder.get_object("button_engine_about").set_sensitive(engine != None)
282
 
        self.__builder.get_object("button_engine_up").set_sensitive(engine not in engines[:1])
283
 
        self.__builder.get_object("button_engine_down").set_sensitive(engine not in engines[-1:])
284
 
 
285
 
        obj = self.__builder.get_object("button_engine_preferences")
286
 
        if len(self.__get_engine_setup_exec_args(engine)) != 0:
287
 
            obj.set_sensitive(True)
288
 
        else:
289
 
            obj.set_sensitive(False)
290
 
 
291
 
        if prop.name == "engines":
292
 
            engine_names = [e.get_name() for e in engines]
293
 
            self.__settings_general.set_strv('preload-engines', engine_names)
294
 
 
295
 
    def __button_engine_add_cb(self, button):
296
 
        engine = self.__combobox.get_active_engine()
297
 
        self.__treeview.append_engine(engine)
298
 
 
299
 
    def __button_engine_about_cb(self, button):
300
 
        engine = self.__treeview.get_active_engine()
301
 
        if engine:
302
 
            about = EngineAbout(engine)
303
 
            about.run()
304
 
            about.destroy()
305
 
 
306
 
    def __button_engine_preferences_cb(self, button):
307
 
        engine = self.__treeview.get_active_engine()
308
 
        args = self.__get_engine_setup_exec_args(engine)
309
 
        if len(args) == 0:
310
 
            return
311
 
        name = engine.get_name()
312
 
        if name in list(self.__engine_setup_exec_list.keys()):
313
 
            try:
314
 
                wpid, sts = os.waitpid(self.__engine_setup_exec_list[name],
315
 
                                       os.WNOHANG)
316
 
                # the setup is still running.
317
 
                if wpid == 0:
318
 
                    return
319
 
            except OSError:
320
 
                pass
321
 
            del self.__engine_setup_exec_list[name]
322
 
        self.__engine_setup_exec_list[name] = os.spawnl(os.P_NOWAIT, *args)
323
 
 
324
 
    def __init_bus(self):
325
 
        self.__bus = IBus.Bus()
326
 
        if self.__bus.is_connected():
327
 
            return
328
 
 
329
 
        message = _("The IBus daemon is not running. Do you wish to start it?")
330
 
        dlg = Gtk.MessageDialog(type = Gtk.MessageType.QUESTION,
331
 
                                buttons = Gtk.ButtonsType.YES_NO,
332
 
                                text = message)
333
 
        id = dlg.run()
334
 
        dlg.destroy()
335
 
        self.__flush_gtk_events()
336
 
        if id != Gtk.ResponseType.YES:
337
 
            sys.exit(0)
338
 
 
339
 
        main_loop = GLib.MainLoop()
340
 
 
341
 
        timeout = 5
342
 
        GLib.timeout_add_seconds(timeout, lambda *args: main_loop.quit())
343
 
        self.__bus.connect("connected", lambda *args: main_loop.quit())
344
 
 
345
 
        os.spawnlp(os.P_NOWAIT, "ibus-daemon", "ibus-daemon", "--xim")
346
 
 
347
 
        main_loop.run()
348
 
 
349
 
        if self.__bus.is_connected():
350
 
            message = _("IBus has been started! "
351
 
                "If you cannot use IBus, add the following lines to your $HOME/.bashrc; then relog into your desktop.\n"
352
 
                "  export GTK_IM_MODULE=ibus\n"
353
 
                "  export XMODIFIERS=@im=ibus\n"
354
 
                "  export QT_IM_MODULE=ibus"
355
 
                )
356
 
            dlg = Gtk.MessageDialog(type = Gtk.MessageType.INFO,
357
 
                                    buttons = Gtk.ButtonsType.OK,
358
 
                                    text = message)
359
 
            id = dlg.run()
360
 
            dlg.destroy()
361
 
            self.__flush_gtk_events()
362
 
        else:
363
 
            # Translators: %d == 5 currently
364
 
            message = _("IBus daemon could not be started in %d seconds")
365
 
            dlg = Gtk.MessageDialog(type = Gtk.MessageType.INFO,
366
 
                                    buttons = Gtk.ButtonsType.OK,
367
 
                                    text = message % timeout)
368
 
            id = dlg.run()
369
 
            dlg.destroy()
370
 
            self.__flush_gtk_events()
371
 
            sys.exit(0)
372
 
 
373
 
    def __shortcut_button_clicked_cb(self, button, name, section, _name, entry):
374
 
        buttons = (_("_Cancel"), Gtk.ResponseType.CANCEL,
375
 
                   _("_OK"), Gtk.ResponseType.OK)
376
 
        title1 = _("Select keyboard shortcut for %s")
377
 
        # Translators: Title of the window
378
 
        title2 = _("switching input methods")
379
 
        title = title1 % title2
380
 
        dialog = keyboardshortcut.KeyboardShortcutSelectionDialog(buttons = buttons, title = title)
381
 
        text = entry.get_text()
382
 
        if text:
383
 
            shortcuts = text.split("; ")
384
 
        else:
385
 
            shortcuts = None
386
 
        dialog.set_shortcuts(shortcuts)
387
 
        id = dialog.run()
388
 
        shortcuts = dialog.get_shortcuts()
389
 
        dialog.destroy()
390
 
        if id != Gtk.ResponseType.OK:
391
 
            return
392
 
        self.__settings_hotkey.set_strv(name, shortcuts)
393
 
        text = "; ".join(shortcuts)
394
 
        entry.set_text(text)
395
 
        tooltip = "\n".join(shortcuts)
396
 
        tooltip += "\n" + \
397
 
            _("Use shortcut with shift to switch to the previous input method") 
398
 
        entry.set_tooltip_text(tooltip)
399
 
 
400
 
    def __item_started_column_toggled_cb(self, cell, path_str, model):
401
 
 
402
 
        # get toggled iter
403
 
        iter = model.get_iter_from_string(path_str)
404
 
        data = model.get_value(iter, COLUMN_DATA)
405
 
 
406
 
        # do something with the value
407
 
        if data[DATA_STARTED] == False:
408
 
            try:
409
 
                self.__bus.register_start_engine(data[DATA_LANG], data[DATA_NAME])
410
 
            except Exception as e:
411
 
                dlg = Gtk.MessageDialog(type = Gtk.MessageType.ERROR,
412
 
                        buttons = Gtk.ButtonsType.CLOSE,
413
 
                        message_format = str(e))
414
 
                dlg.run()
415
 
                dlg.destroy()
416
 
                self.__flush_gtk_events()
417
 
                return
418
 
        else:
419
 
            try:
420
 
                self.__bus.register_stop_engine(data[DATA_LANG], data[DATA_NAME])
421
 
            except Exception as e:
422
 
                dlg = Gtk.MessageDialog(type = Gtk.MessageType.ERROR,
423
 
                        buttons = Gtk.ButtonsType.CLOSE,
424
 
                        message_format = str(e))
425
 
                dlg.run()
426
 
                dlg.destroy()
427
 
                self.__flush_gtk_events()
428
 
                return
429
 
        data[DATA_STARTED] = not data[DATA_STARTED]
430
 
 
431
 
        # set new value
432
 
        model.set(iter, COLUMN_ENABLE, data[DATA_STARTED])
433
 
 
434
 
    def __item_preload_column_toggled_cb(self, cell, path_str, model):
435
 
 
436
 
        # get toggled iter
437
 
        iter = model.get_iter_from_string(path_str)
438
 
        data = model.get_value(iter, COLUMN_DATA)
439
 
 
440
 
        data[DATA_PRELOAD] = not data[DATA_PRELOAD]
441
 
        engine = "%s:%s" % (data[DATA_LANG], data[DATA_NAME])
442
 
 
443
 
        if data[DATA_PRELOAD]:
444
 
            if engine not in self.__preload_engines:
445
 
                self.__preload_engines.add(engine)
446
 
                self.__settings_general.set_strv('preload-engines',
447
 
                                                 list(self.__preload_engines))
448
 
        else:
449
 
            if engine in self.__preload_engines:
450
 
                self.__preload_engines.remove(engine)
451
 
                self.__settings_general.set_strv('preload-engines',
452
 
                                                 list(self.__preload_engines))
453
 
 
454
 
        # set new value
455
 
        model.set(iter, COLUMN_PRELOAD, data[DATA_PRELOAD])
456
 
 
457
 
    def __is_auto_start(self):
458
 
        link_file = path.join(GLib.get_user_config_dir(),
459
 
                              "autostart/ibus.desktop")
460
 
        ibus_desktop = path.join(os.getenv("IBUS_PREFIX"),
461
 
                                 "share/applications/ibus.desktop")
462
 
 
463
 
        if not path.exists(link_file):
464
 
            return False
465
 
        if not path.islink(link_file):
466
 
            return False
467
 
        if path.realpath(link_file) != ibus_desktop:
468
 
            return False
469
 
        return True
470
 
 
471
 
    def __checkbutton_auto_start_toggled_cb(self, button):
472
 
        auto_start_dir = path.join(GLib.get_user_config_dir(), "autostart")
473
 
        if not path.isdir(auto_start_dir):
474
 
            os.makedirs(auto_start_dir)
475
 
 
476
 
        link_file = path.join(GLib.get_user_config_dir(),
477
 
                              "autostart/ibus.desktop")
478
 
        ibus_desktop = path.join(os.getenv("IBUS_PREFIX"),
479
 
                                 "share/applications/ibus.desktop")
480
 
        # unlink file
481
 
        try:
482
 
            os.unlink(link_file)
483
 
        except:
484
 
            pass
485
 
        if self.__checkbutton_auto_start.get_active():
486
 
            os.symlink(ibus_desktop, link_file)
487
 
 
488
 
    def __sigusr1_cb(self, *args):
489
 
        self.__window.present()
490
 
 
491
 
    def run(self):
492
 
        self.__window.show_all()
493
 
        signal.signal(signal.SIGUSR1, self.__sigusr1_cb)
494
 
        Gtk.main()
495
 
 
496
 
if __name__ == "__main__":
497
 
    try:
498
 
        locale.setlocale(locale.LC_ALL, '')
499
 
    except locale.Error:
500
 
        print("Using the fallback 'C' locale", file=sys.stderr)
501
 
        locale.setlocale(locale.LC_ALL, 'C')
502
 
 
503
 
    i18n_init()
504
 
    setup = Setup()
505
 
    setup.run()