panel.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #! /usr/bin/env python
  2. # vim:set et sts=4 sw=4:
  3. #
  4. # ibus-panel-dbus - Another panel for ibus
  5. #
  6. # Copyright (c) 2009 Wang Hoi <zealot.hoi@gmail.com>
  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 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
  16. # GNU 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 program; if not, write to the
  20. # Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  21. # Boston, MA 02111-1307 USA
  22. #IBUS_SERVICE_KIMPANEL = "org.freedesktop.IBus.Panel.KIM"
  23. #IBUS_PATH_KIMPANEL = "/org/freedesktop/IBus/Panel/KIM"
  24. from ibus import *
  25. from ibus.panel import *
  26. from ibus.bus import Bus
  27. from ibus.inputcontext import InputContext
  28. from ibus import keysyms
  29. #import ibus.interface
  30. import gtk
  31. import dbus
  32. IBUS_ICON_DIR = '/usr/share/ibus/icons/'
  33. from gettext import dgettext
  34. _ = lambda a : dgettext("ibus", a)
  35. N_ = lambda a : a
  36. def prop2string(prop):
  37. __prop_key = '/IBus/'+prop.get_key()
  38. __prop_label = prop.get_label().get_text()
  39. __prop_icon = prop.get_icon()
  40. __prop_tip = prop.get_tooltip().get_text()
  41. # workaround
  42. if len(__prop_icon)==0:
  43. # the setup icon
  44. if (prop.get_key()=='setup'):
  45. __prop_icon = 'configure'
  46. __prop = __prop_key + ':' + __prop_label + ':' + __prop_icon + ':' + __prop_tip
  47. return __prop
  48. class KIMIbusClient(dbus.service.Object):
  49. def __init__(self, object_path):
  50. dbus.service.Object.__init__(self, dbus.SessionBus(), object_path)
  51. @dbus.service.signal(dbus_interface='org.ibus.panel',
  52. signature='s')
  53. def ExecDialog(self, prop):
  54. pass
  55. @dbus.service.signal(dbus_interface='org.ibus.panel',
  56. signature='as')
  57. def ExecMenu(self, props):
  58. pass
  59. @dbus.service.signal(dbus_interface='org.ibus.panel',
  60. signature='as')
  61. def RegisterProperties(self, props):
  62. pass
  63. @dbus.service.signal(dbus_interface='org.ibus.panel',
  64. signature='s')
  65. def UpdateProperty(self, prop):
  66. pass
  67. @dbus.service.signal(dbus_interface='org.ibus.panel',
  68. signature='s')
  69. def RemoveProperty(self, prop):
  70. pass
  71. @dbus.service.signal(dbus_interface='org.ibus.panel',
  72. signature='b')
  73. def Enable(self, b):
  74. pass
  75. @dbus.service.signal(dbus_interface='org.ibus.panel',
  76. signature='b')
  77. def ShowAux(self, b):
  78. pass
  79. @dbus.service.signal(dbus_interface='org.ibus.panel',
  80. signature='b')
  81. def ShowPreedit(self, b):
  82. pass
  83. @dbus.service.signal(dbus_interface='org.ibus.panel',
  84. signature='b')
  85. def ShowLookupTable(self, b):
  86. pass
  87. @dbus.service.signal(dbus_interface='org.ibus.panel',
  88. signature='asasasbb')
  89. def UpdateLookupTable(self, labels,items,xs,bool1,bool2):
  90. pass
  91. @dbus.service.signal(dbus_interface='org.ibus.panel',
  92. signature='i')
  93. def UpdatePreeditCaret(self, pos):
  94. pass
  95. @dbus.service.signal(dbus_interface='org.ibus.panel',
  96. signature='ss')
  97. def UpdatePreeditText(self, test, attr):
  98. pass
  99. @dbus.service.signal(dbus_interface='org.ibus.panel',
  100. signature='ss')
  101. def UpdateAux(self, test, attr):
  102. pass
  103. @dbus.service.signal(dbus_interface='org.ibus.panel',
  104. signature='ii')
  105. def UpdateSpotLocation(self, x, y):
  106. pass
  107. @dbus.service.signal(dbus_interface='org.ibus.panel',
  108. signature='i')
  109. def UpdateScreen(self, id):
  110. pass
  111. class KIMPanel(PanelBase):
  112. def __init__(self):
  113. self.__bus = Bus()
  114. self.__bus.connect("disconnected", gtk.main_quit)
  115. super(KIMPanel, self).__init__(self.__bus)
  116. self.__bus.request_name(IBUS_SERVICE_PANEL, 0)
  117. self.__session_bus = dbus.SessionBus()
  118. #self.__kimproxy = self.__session_bus.get_object('org.kde.impanel',
  119. # '/org/kde/impanel')
  120. #self.__kimifce = dbus.Interface(self.__kimproxy,
  121. # 'org.kde.impanel')
  122. self.__session_bus.add_signal_receiver(self.kim_trigger_property,
  123. signal_name='TriggerProperty',
  124. dbus_interface='org.kde.impanel')
  125. self.__session_bus.add_signal_receiver(self.kim_panel_created,
  126. signal_name='PanelCreated',
  127. dbus_interface='org.kde.impanel')
  128. self.__session_bus.add_signal_receiver(self.kim_reload_config,
  129. signal_name='ReloadConfig',
  130. dbus_interface='org.kde.impanel')
  131. self.__session_bus.add_signal_receiver(gtk.main_quit,
  132. signal_name='Exit',
  133. dbus_interface='org.kde.impanel')
  134. self.__session_bus.add_signal_receiver(self.page_up,
  135. signal_name='LookupTablePageUp',
  136. dbus_interface='org.kde.impanel')
  137. self.__session_bus.add_signal_receiver(self.page_down,
  138. signal_name='LookupTablePageDown',
  139. dbus_interface='org.kde.impanel')
  140. self.__session_bus.add_signal_receiver(self.kim_select_candidate,
  141. signal_name='SelectCandidate',
  142. dbus_interface='org.kde.impanel')
  143. self.__kimclient = KIMIbusClient('/org/ibus/panel')
  144. self.__focus_ic = None
  145. self.__logo_prop = Property(key='Logo', label='IBus', icon=IBUS_ICON_DIR + '/ibus.svg', tooltip='IBus input method')
  146. self.__about_prop = Property(key='About', label=_('IBus intelligent input bus'), icon='help-about')
  147. self.__about_prop.set_tooltip(_("IBus is an intelligent input bus for Linux/Unix.\n\nHuang Peng <shawn.p.huang@gmail.com>"))
  148. self.__prop_map = {}
  149. self.__im_menu = []
  150. def focus_in(self,ic):
  151. self.__focus_ic = InputContext(self.__bus, ic)
  152. enabled = self.__focus_ic.is_enabled()
  153. if not enabled:
  154. self.__logo_prop.icon = IBUS_ICON_DIR + '/ibus.svg'
  155. else:
  156. engine = self.__focus_ic.get_engine()
  157. if engine:
  158. self.__logo_prop.icon = engine.icon
  159. else:
  160. self.__logo_prop.icon = IBUS_ICON_DIR + '/ibus.svg'
  161. self.__kimclient.UpdateProperty(prop2string(self.__logo_prop))
  162. def state_changed(self):
  163. print 'state_changed'
  164. if not self.__focus_ic:
  165. return
  166. enabled = self.__focus_ic.is_enabled()
  167. if enabled == False:
  168. self.__reset()
  169. self.__logo_prop.set_icon(IBUS_ICON_DIR + 'ibus.svg')
  170. else:
  171. engine = self.__focus_ic.get_engine()
  172. if engine:
  173. self.__logo_prop.set_icon(engine.icon)
  174. else:
  175. self.__logo_prop.set_icon(IBUS_ICON_DIR + 'ibus.svg')
  176. self.__kimclient.UpdateProperty(prop2string(self.__logo_prop))
  177. def focus_out(self,ic):
  178. #self.__focus_ic = None
  179. self.__logo_prop.icon = IBUS_ICON_DIR + '/ibus.svg'
  180. self.__kimclient.UpdateProperty(prop2string(self.__logo_prop))
  181. def set_cursor_location(self, x, y, w, h):
  182. #print 'set_cursor_location',x,y,w,h
  183. self.__kimclient.UpdateSpotLocation(x+w,y+h)
  184. def update_preedit_text(self, text, cursor_pos, visible):
  185. print 'update_preedit_text',cursor_pos,visible
  186. self.__kimclient.UpdatePreeditText(text.get_text(),'')
  187. self.__kimclient.UpdatePreeditCaret(cursor_pos)
  188. if visible:
  189. self.show_preedit_text()
  190. else:
  191. self.hide_preedit_text()
  192. def show_preedit_text(self):
  193. print 'show_preedit_text'
  194. self.__kimclient.ShowPreedit(1)
  195. def hide_preedit_text(self):
  196. print 'hide_preedit_text'
  197. self.__kimclient.ShowPreedit(0)
  198. def update_auxiliary_text(self, text, visible):
  199. #print 'update_auxiliary_text',visible
  200. self.__kimclient.UpdateAux(text.get_text(),'')
  201. if visible:
  202. self.show_auxiliary_text()
  203. else:
  204. self.hide_auxiliary_text()
  205. def show_auxiliary_text(self):
  206. print 'show_auxiliary_text'
  207. self.__kimclient.ShowAux(1)
  208. def hide_auxiliary_text(self):
  209. print 'hide_auxiliary_text'
  210. self.__kimclient.ShowAux(0)
  211. def update_lookup_table(self, lookup_table, visible):
  212. if lookup_table == None:
  213. lookup_table = LookupTable()
  214. self.__lookup_table = lookup_table
  215. self.__labels = []
  216. self.__candis = []
  217. self.__attrs = []
  218. i = 0
  219. for text_obj in lookup_table.get_candidates_in_current_page():
  220. i=i+1
  221. if i==10:
  222. i=0
  223. self.__labels.append(str(i))
  224. self.__candis.append(text_obj.get_text())
  225. self.__attrs.append('')
  226. self.__kimclient.UpdateLookupTable(self.__labels,
  227. self.__candis,self.__attrs,dbus.Boolean(1),dbus.Boolean(lookup_table.get_current_page_size() <= lookup_table.get_page_size()))
  228. if visible:
  229. self.show_lookup_table()
  230. else:
  231. self.hide_lookup_table()
  232. def show_lookup_table(self):
  233. print 'show_lookup_table'
  234. self.__kimclient.ShowLookupTable(1)
  235. def hide_lookup_table(self):
  236. print 'hide_lookup_table'
  237. self.__kimclient.ShowLookupTable(0)
  238. def cursor_up_lookup_table(self):
  239. print 'cursor_up_lookup_table'
  240. def cursor_down_lookup_table(self):
  241. print 'cursor_down_lookup_table'
  242. def show_candidate_window(self):
  243. print 'show_candidate_window'
  244. def hide_candidate_window(self):
  245. print 'hide_candidate_window'
  246. def show_language_bar(self):
  247. print 'show_language_bar'
  248. def hide_language_bar(self):
  249. print 'hide_language_bar'
  250. def register_properties(self, props):
  251. print 'register_properties'
  252. __props = []
  253. __props.append(prop2string(self.__logo_prop))
  254. for prop in props.get_properties():
  255. __props.append(prop2string(prop))
  256. __prop_key = '/IBus/'+prop.get_key()
  257. #self.__prop
  258. __props.append(prop2string(self.__about_prop))
  259. self.__kimclient.RegisterProperties(__props)
  260. def update_property(self, prop):
  261. print 'update_property'
  262. self.__kimclient.UpdateProperty(prop2string(prop))
  263. def get_status_icon(self):
  264. print 'get_status_icon'
  265. # begin of signal handler
  266. def kim_panel_created(self):
  267. print 'KIM: panel created'
  268. def kim_reload_config(self):
  269. print 'KIM: reload config'
  270. def kim_trigger_property(self,prop):
  271. print 'KIM: trigger property'
  272. if prop.startswith('/IBus/'):
  273. __prop_key = prop[6:]
  274. if __prop_key == 'Logo':
  275. self.__im_menu = self.__create_im_menu()
  276. self.__kimclient.ExecMenu(map(prop2string,self.__im_menu))
  277. elif __prop_key == 'About':
  278. self.__kimclient.ExecDialog(prop2string(self.__about_prop))
  279. elif __prop_key.startswith('Engine/'):
  280. self.__reset()
  281. __prop_key = __prop_key[7:]
  282. if __prop_key == 'None':
  283. self.__focus_ic.disable()
  284. else:
  285. engines = self.__bus.list_active_engines()
  286. for engine in engines:
  287. print engine.name
  288. if engine.name == __prop_key:
  289. print 'matched engine'
  290. self.__focus_ic.set_engine(engine)
  291. else:
  292. self.property_activate(__prop_key,PROP_STATE_CHECKED)
  293. def kim_select_candidate(self,index):
  294. print 'select_candidate:Implement me!'
  295. # dirty hack
  296. #if self.__focus_ic:
  297. # #engine = self.__focus_ic.get_engine()
  298. # #if engine:
  299. # # print 'select_candidate',index
  300. # self.__focus_ic.process_key_event(keysyms._1,0)
  301. pass
  302. def __reset(self):
  303. self.hide_auxiliary_text()
  304. self.hide_preedit_text()
  305. self.hide_lookup_table()
  306. def __create_im_menu(self):
  307. engines = self.__bus.list_active_engines()
  308. tmp = {}
  309. for engine in engines:
  310. lang = get_language_name(engine.language)
  311. if lang not in tmp:
  312. tmp[lang] = []
  313. tmp[lang].append(engine)
  314. langs = tmp.keys()
  315. other = tmp.get(_("Other"), [])
  316. if _("Other") in tmp:
  317. langs.remove(_("Other"))
  318. langs.append(_("Other"))
  319. im_menu = []
  320. for lang in langs:
  321. if len(tmp[lang]) == 1:
  322. engine = tmp[lang][0]
  323. item = Property(key='Engine/'+engine.name)
  324. item.set_label("%s - %s" % (lang, engine.longname))
  325. if engine.icon:
  326. item.set_icon(engine.icon)
  327. else:
  328. item.set_icon("engine-default")
  329. print prop2string(item)
  330. im_menu.append(item)
  331. else:
  332. pass
  333. item = Property(key='Engine/None',label=_('Disable'),icon=IBUS_ICON_DIR+'/ibus.svg')
  334. im_menu.append(item)
  335. return im_menu
  336. def launch_panel():
  337. panel = KIMPanel()
  338. gtk.main()
  339. if __name__ == "__main__":
  340. launch_panel()