1 # vim:set et sts=4 sw=4:
5 # Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this program; if not, write to the
19 # Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 # Boston, MA 02111-1307 USA
31 import keyboardshortcut
33 from xdg import BaseDirectory
37 _ = lambda a : gettext.dgettext("ibus", a)
62 def __flush_gtk_events(self):
63 while gtk.events_pending():
67 super(Setup, self).__init__()
68 locale.bind_textdomain_codeset("ibus", "UTF-8")
69 glade.textdomain("ibus")
70 glade_file = path.join(path.dirname(__file__), "./setup.glade")
71 self.__xml = glade.XML(glade_file)
77 # add icon search path
78 icon_theme = gtk.icon_theme_get_default()
79 dir = path.dirname(__file__)
80 icondir = path.join(dir, "..", "icons")
81 icon_theme.prepend_search_path(icondir)
84 self.__dialog = self.__xml.get_widget("dialog_setup")
87 self.__checkbutton_auto_start = self.__xml.get_widget("checkbutton_auto_start")
88 self.__checkbutton_auto_start.set_active(self.__is_auto_start())
89 self.__checkbutton_auto_start.connect("toggled", self.__checkbutton_auto_start_toggled_cb)
93 shortcuts = self.__bus.config_get_value(
94 "general", "keyboard_shortcut_trigger",
95 ibus.CONFIG_GENERAL_SHORTCUT_TRIGGER_DEFAULT)
96 button = self.__xml.get_widget("button_trigger")
97 entry = self.__xml.get_widget("entry_trigger")
98 entry.set_text("; ".join(shortcuts))
99 button.connect("clicked", self.__shortcut_button_clicked_cb,
100 N_("trigger"), "general", "keyboard_shortcut_trigger", entry)
103 shortcuts = self.__bus.config_get_value(
104 "general", "keyboard_shortcut_next_engine",
105 ibus.CONFIG_GENERAL_SHORTCUT_NEXT_ENGINE_DEFAULT)
106 button = self.__xml.get_widget("button_next_engine")
107 entry = self.__xml.get_widget("entry_next_engine")
108 entry.set_text("; ".join(shortcuts))
109 button.connect("clicked", self.__shortcut_button_clicked_cb,
110 N_("next engine"), "general", "keyboard_shortcut_next_engine", entry)
113 shortcuts = self.__bus.config_get_value(
114 "general", "keyboard_shortcut_prev_engine",
115 ibus.CONFIG_GENERAL_SHORTCUT_PREV_ENGINE_DEFAULT)
116 button = self.__xml.get_widget("button_prev_engine")
117 entry = self.__xml.get_widget("entry_prev_engine")
118 entry.set_text("; ".join(shortcuts))
119 button.connect("clicked", self.__shortcut_button_clicked_cb,
120 N_("prev engine"), "general", "keyboard_shortcut_prev_engine", entry)
124 # lookup table orientation
125 self.__combobox_lookup_table_orientation = self.__xml.get_widget("combobox_lookup_table_orientation")
126 self.__combobox_lookup_table_orientation.set_active(
127 self.__bus.config_get_value("panel", "lookup_table_orientation", 0))
128 self.__combobox_lookup_table_orientation.connect("changed",
129 self.__combobox_lookup_table_orientation_changed_cb)
132 self.__checkbutton_auto_hide = self.__xml.get_widget("checkbutton_auto_hide")
133 self.__checkbutton_auto_hide.set_active(
134 self.__bus.config_get_value("panel", "auto_hide", False))
135 self.__checkbutton_auto_hide.connect("toggled", self.__checkbutton_auto_hide_toggled_cb)
138 self.__checkbutton_custom_font = self.__xml.get_widget("checkbutton_custom_font")
139 self.__checkbutton_custom_font.set_active(
140 self.__bus.config_get_value("panel", "use_custom_font", False))
141 self.__checkbutton_custom_font.connect("toggled", self.__checkbutton_custom_font_toggled_cb)
143 self.__fontbutton_custom_font = self.__xml.get_widget("fontbutton_custom_font")
144 if self.__bus.config_get_value("panel", "use_custom_font", False):
145 self.__fontbutton_custom_font.set_sensitive(True)
147 self.__fontbutton_custom_font.set_sensitive(False)
148 font_name = gtk.settings_get_default().get_property("gtk-font-name")
149 font_name = unicode(font_name, "utf-8")
150 font_name = self.__bus.config_get_value("panel", "custom_font", font_name)
151 self.__fontbutton_custom_font.connect("notify::font-name", self.__fontbutton_custom_font_notify_cb)
152 self.__fontbutton_custom_font.set_font_name(font_name)
154 self.__init_engine_view()
156 def __init_bus(self):
158 self.__bus = ibus.Bus()
159 # self.__bus.connect("config-value-changed", self.__config_value_changed_cb)
160 self.__bus.connect("config-reloaded", self.__config_reloaded_cb)
161 self.__bus.config_add_watch("/general")
162 self.__bus.config_add_watch("/panel")
164 while self.__bus == None:
165 message = _("IBus daemon is not started. Do you want to start it now?")
166 dlg = gtk.MessageDialog(type = gtk.MESSAGE_QUESTION,
167 buttons = gtk.BUTTONS_YES_NO,
168 message_format = message)
171 self.__flush_gtk_events()
172 if id != gtk.RESPONSE_YES:
174 pid = os.spawnlp(os.P_NOWAIT, "ibus", "ibus")
177 self.__bus = ibus.Bus()
180 message = _("IBus has been started! "
181 "If you can not use IBus, please add below lines in $HOME/.bashrc, and relogin your desktop.\n"
182 " export GTK_IM_MODULE=ibus\n"
183 " export XMODIFIERS=@im=ibus\n"
184 " export QT_IM_MODULE=ibus"
186 dlg = gtk.MessageDialog(type = gtk.MESSAGE_INFO,
187 buttons = gtk.BUTTONS_OK,
188 message_format = message)
191 self.__flush_gtk_events()
193 def __init_engine_view(self):
195 self.__tree = self.__xml.get_widget("treeview_engines")
196 self.__preload_engines = set(self.__bus.config_get_value("general", "preload_engines", []))
197 model = self.__create_model()
198 self.__tree.set_model(model)
201 column = gtk.TreeViewColumn()
202 column.set_title(_("Engine"))
203 column.set_resizable(True)
204 column.set_min_width(120)
206 renderer = gtk.CellRendererPixbuf()
207 renderer.set_property("xalign", 0.5)
209 column.pack_start(renderer, False)
210 column.set_attributes(renderer, pixbuf = COLUMN_ICON, visible = COLUMN_VISIBLE)
212 renderer = gtk.CellRendererText()
213 renderer.set_property("xalign", 0.0)
214 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
216 # column.set_clickable(True)
217 column.pack_start(renderer)
218 column.set_attributes(renderer, text = COLUMN_NAME)
220 self.__tree.append_column(column)
223 renderer = gtk.CellRendererToggle()
224 renderer.set_data('column', COLUMN_ENABLE)
225 renderer.set_property("xalign", 0.5)
226 renderer.connect("toggled", self.__item_started_column_toggled_cb, model)
228 #col_offset = gtk.TreeViewColumn("Holiday", renderer, text=HOLIDAY_NAME)
229 column = gtk.TreeViewColumn(_("Started"), renderer, active = COLUMN_ENABLE, visible = COLUMN_VISIBLE)
230 column.set_resizable(True)
231 self.__tree.append_column(column)
234 renderer = gtk.CellRendererToggle()
235 renderer.set_data('column', COLUMN_PRELOAD)
236 renderer.set_property("xalign", 0.5)
237 renderer.connect("toggled", self.__item_preload_column_toggled_cb, model)
239 column = gtk.TreeViewColumn(_("Preload"), renderer, active = COLUMN_PRELOAD, visible = COLUMN_VISIBLE)
240 column.set_resizable(True)
241 self.__tree.append_column(column)
243 renderer = gtk.CellRendererText()
244 column = gtk.TreeViewColumn("", renderer)
245 self.__tree.append_column(column)
247 def __shortcut_button_clicked_cb(self, button, name, section, _name, entry):
248 buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)
249 title = _("Select keyboard shortcut for %s") % _(name)
250 dialog = keyboardshortcut.KeyboardShortcutSelectionDialog(buttons = buttons, title = title)
251 text = entry.get_text()
253 shortcuts = text.split("; ")
256 dialog.set_shortcuts(shortcuts)
258 shortcuts = list(set(dialog.get_shortcuts()))
260 if id != gtk.RESPONSE_OK:
262 self.__bus.config_set_value(section, _name, shortcuts)
263 entry.set_text("; ".join(shortcuts))
266 def __item_started_column_toggled_cb(self, cell, path_str, model):
269 iter = model.get_iter_from_string(path_str)
270 data = model.get_value(iter, COLUMN_DATA)
272 # do something with the value
273 if data[DATA_STARTED] == False:
275 self.__bus.register_start_engine(data[DATA_LANG], data[DATA_NAME])
277 dlg = gtk.MessageDialog(type = gtk.MESSAGE_ERROR,
278 buttons = gtk.BUTTONS_CLOSE,
279 message_format = str(e))
282 self.__flush_gtk_events()
286 self.__bus.register_stop_engine(data[DATA_LANG], data[DATA_NAME])
288 dlg = gtk.MessageDialog(type = gtk.MESSAGE_ERROR,
289 buttons = gtk.BUTTONS_CLOSE,
290 message_format = str(e))
293 self.__flush_gtk_events()
295 data[DATA_STARTED] = not data[DATA_STARTED]
298 model.set(iter, COLUMN_ENABLE, data[DATA_STARTED])
300 def __item_preload_column_toggled_cb(self, cell, path_str, model):
303 iter = model.get_iter_from_string(path_str)
304 data = model.get_value(iter, COLUMN_DATA)
306 data[DATA_PRELOAD] = not data[DATA_PRELOAD]
307 engine = "%s:%s" % (data[DATA_LANG], data[DATA_NAME])
309 if data[DATA_PRELOAD]:
310 if engine not in self.__preload_engines:
311 self.__preload_engines.add(engine)
312 self.__bus.config_set_list("general", "preload_engines", list(self.__preload_engines), "s")
314 if engine in self.__preload_engines:
315 self.__preload_engines.remove(engine)
316 self.__bus.config_set_list("general", "preload_engines", list(self.__preload_engines), "s")
319 model.set(iter, COLUMN_PRELOAD, data[DATA_PRELOAD])
321 def __load_icon(self, icon, icon_size):
324 pixbuf = gdk.pixbuf_new_from_file(icon)
325 w, h = pixbuf.get_width(), pixbuf.get_height()
326 rate = max(w, h) / float(icon_size)
329 pixbuf = pixbuf.scale_simple(w, h, gdk.INTERP_BILINEAR)
334 theme = gtk.icon_theme_get_default()
335 pixbuf = theme.load_icon(icon, icon_size, 0)
340 def __create_model(self):
342 model = gtk.TreeStore(
344 gobject.TYPE_BOOLEAN,
345 gobject.TYPE_BOOLEAN,
346 gobject.TYPE_BOOLEAN,
348 gobject.TYPE_PYOBJECT)
352 self.__bus.register_reload_engines()
353 for name, local_name, lang, icon, author, credits, _exec, started in self.__bus.register_list_engines():
354 _lang = ibus.get_language_name(lang)
355 if _lang not in langs:
356 langs[_lang] = list()
357 langs[_lang].append([name, local_name, lang, icon, author, credits, _exec, started])
361 if _("Other") in keys:
362 keys.remove(_("Other"))
363 keys.append(_("Other"))
365 icon_size = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR)[0]
366 pixbuf_missing = self.__load_icon("engine-default", icon_size)
367 if pixbuf_missing == None:
368 pixbuf_missing = self.__load_icon("gtk-missing-image", icon_size)
371 iter = model.append(None)
374 COLUMN_ENABLE, False,
375 COLUMN_PRELOAD, False,
376 COLUMN_VISIBLE, False,
381 for name, local_name, lang, icon, author, credits, _exec, started in langs[key]:
382 child_iter = model.append(iter)
383 is_preload = "%s:%s" % (lang, name) in self.__preload_engines
385 pixbuf = self.__load_icon(icon, icon_size)
387 pixbuf = pixbuf_missing
389 model.set(child_iter,
390 COLUMN_NAME, local_name,
391 COLUMN_ENABLE, started,
392 COLUMN_PRELOAD, is_preload,
393 COLUMN_VISIBLE, True,
396 [name, local_name, lang, icon, author, credits, _exec, started, is_preload])
400 def __is_auto_start(self):
401 link_file = path.join(BaseDirectory.xdg_config_home, "autostart/ibus.desktop")
402 ibus_desktop = path.join(os.getenv("IBUS_PREFIX"), "share/applications/ibus.desktop")
404 if not path.exists(link_file):
406 if not path.islink(link_file):
408 if path.realpath(link_file) != ibus_desktop:
412 def __checkbutton_auto_start_toggled_cb(self, button):
413 auto_start_dir = path.join(BaseDirectory.xdg_config_home, "autostart")
414 if not path.isdir(auto_start_dir):
415 os.makedirs(auto_start_dir)
417 link_file = path.join(BaseDirectory.xdg_config_home, "autostart/ibus.desktop")
418 ibus_desktop = path.join(os.getenv("IBUS_PREFIX"), "share/applications/ibus.desktop")
424 if self.__checkbutton_auto_start.get_active():
425 os.symlink(ibus_desktop, link_file)
427 def __combobox_lookup_table_orientation_changed_cb(self, combobox):
428 self.__bus.config_set_value(
429 "panel", "lookup_table_orientation",
430 self.__combobox_lookup_table_orientation.get_active())
432 def __checkbutton_auto_hide_toggled_cb(self, button):
433 self.__bus.config_set_value(
434 "panel", "auto_hide",
435 self.__checkbutton_auto_hide.get_active())
437 def __checkbutton_custom_font_toggled_cb(self, button):
438 if self.__checkbutton_custom_font.get_active():
439 self.__fontbutton_custom_font.set_sensitive(True)
440 self.__bus.config_set_value("panel", "use_custom_font", True)
442 self.__fontbutton_custom_font.set_sensitive(False)
443 self.__bus.config_set_value("panel", "use_custom_font", False)
445 def __fontbutton_custom_font_notify_cb(self, button, arg):
446 font_name = self.__fontbutton_custom_font.get_font_name()
447 font_name = unicode(font_name, "utf-8")
448 self.__bus.config_set_value("panel", "custom_font", font_name)
450 def __config_value_changed_cb(self, bus, section, name, value):
453 def __config_reloaded_cb(self, bus):
457 return self.__dialog.run()
459 if __name__ == "__main__":