list2form : gestion des erreurs et des petits fichiers (merci cgi.py…)
[progfou.git] / pygtranslator / pygtranslator.py
CommitLineData
4c412ef3 1#!/usr/bin/env python
e603e417
P
2# -*- coding: utf-8 -*-
3"""
4PygTranslator - pas de doc cette fois-ci... :-P
5
6Copyright : Agence universitaire de la Francophonie
7Licence : GNU General Public Licence, version 2
8Auteur : Jean Christophe André
9Date de création : 28 septembre 2009
10"""
f682a3c3 11import sys
ed507d05 12from getpass import getpass
e603e417
P
13from threading import Thread
14from Queue import Queue
f682a3c3
P
15try:
16 import xmpp
17 import pygtk
18 pygtk.require('2.0')
19 import gtk
20 import gobject
21except ImportError:
4c412ef3 22 modules = ['python-xmpp','python-gtk2','python-gobject']
f682a3c3 23 print u"Ce programme requiert l'installation des paquets Debian suivants :"
4c412ef3
P
24 print u" " + u" ".join(modules)
25 print u"Essayez ceci : sudo apt-get install " + u" ".join(modules)
f682a3c3
P
26 sys.exit(-1)
27
28debug = False
e603e417 29def DEBUG(message):
f682a3c3
P
30 if debug:
31 print "\x1b[31;1mDEBUG\x1b[m:", message
e603e417
P
32 return
33
34class XmppTranslator(Thread):
35
36 def __init__(self, jid, password):
37 Thread.__init__(self)
38 self.setDaemon(True)
69eefce0
P
39 self._quit = False
40
e603e417
P
41 self._input_queue = Queue(0)
42 self._output_queue = Queue(0)
69eefce0 43 self._last_text_to_translate = {}
e603e417
P
44
45 self._jid = xmpp.JID(jid)
46 self._password = password
47 if self._jid.getResource() == '':
48 self._jid.setResource('translator')
49
50 self._client = xmpp.Client(self._jid.getDomain(), debug=[])
51
52 def __del__(self):
53 if self._client and not self._client.isConnected():
54 return
55 self._client.sendPresence(typ='unavailable')
56 self._client.disconnect()
57
58 def _connect(self):
59 try:
60 if not self._client.connect():
61 raise IOError
62 except IOError:
63 raise IOError, "can't connect to '%s'" % self._jid.getDomain()
64 self._client.RegisterHandler('message', self._messageHandler)
65
66 auth = self._client.auth(self._jid.getNode(), self._password,
67 self._jid.getResource())
68 if not auth:
69 raise IOError, "unable to authenticate '%s'" % self._jid.getNode()
70 self._client.sendInitPresence(requestRoster=0)
71
72 def _messageHandler(self, client, message):
73 if message.getType() == 'error':
74 return
75 translation_path = message.getFrom().getNode()
76 text = message.getBody()
77 self._output_queue.put( (translation_path, text) )
78 raise xmpp.NodeProcessed
79
80 def _process_input_queue(self):
81 if self._input_queue.empty():
82 return
83 # process pending translation job
84 translation_path, text = self._input_queue.get()
85 jid = '%s@bot.talk.google.com' % translation_path
86 message = xmpp.Message(to=jid, typ='chat', body=text)
87 self._client.send(message)
88 DEBUG("sent [%s] to '%s'." % (text, jid))
89 self._input_queue.task_done()
90
91 def run(self):
92 self._connect()
93 self._client.Process(1)
94 while not self._quit:
95 self._process_input_queue()
96 self._client.Process(1)
97
98 def request_translation(self, translation_path, text):
69eefce0
P
99 text = text.strip().replace('\r\n','\n')
100 # skip consecutive identical requests
101 if text == self._last_text_to_translate.get(translation_path):
102 return
103 self._last_text_to_translate[translation_path] = text
e603e417
P
104 # remove any pending translation job
105 while not self._input_queue.empty():
106 self._input_queue.get()
107 DEBUG("removed a pending translation job")
108 self._input_queue.task_done()
109 # put a new translation job
110 self._input_queue.put( (translation_path, text) )
111
112 def translation_result(self):
113 if self._output_queue.empty():
114 return None
115 translation_path, text = self._output_queue.get()
116 return translation_path, text
117
118 def translation_done(self):
119 self._output_queue.task_done()
120
121class GtkTranslator(object):
122
123 def __init__(self, translator):
124 self._translator = translator
125
126 self._textbuf = {}
127
128 self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
129 self.window.set_title(u"PygTranslator")
130 self.window.set_border_width(0)
131 self.window.connect("destroy", lambda w: gtk.main_quit())
69eefce0 132 self.window.connect("delete_event", self._delete_event)
e603e417
P
133
134 vbox = gtk.VBox(True, 0)
135 vbox.show()
136
137 textview = gtk.TextView()
138 textview.set_size_request(400, 100)
139 textview.set_wrap_mode(gtk.WRAP_WORD)
140 textview.show()
141 scroll = gtk.ScrolledWindow()
142 scroll.add(textview)
143 scroll.show()
144 frame = gtk.Frame(u"Texte en français")
69eefce0
P
145 frame.connect("key_release_event", self._text_change, 'fr')
146 frame.connect("button_release_event", self._text_change, 'fr')
e603e417
P
147 frame.add(scroll)
148 frame.show()
149 vbox.pack_start(frame, True, True, 0)
150 self._textbuf['fr'] = textview.get_buffer()
151
152 textview = gtk.TextView()
153 textview.set_size_request(400, 100)
154 textview.set_wrap_mode(gtk.WRAP_WORD)
155 textview.show()
156 scroll = gtk.ScrolledWindow()
157 scroll.add(textview)
158 scroll.show()
159 frame = gtk.Frame(u"Text in English")
69eefce0
P
160 frame.connect("key_release_event", self._text_change, 'en')
161 frame.connect("button_release_event", self._text_change, 'en')
e603e417
P
162 frame.add(scroll)
163 frame.show()
164 vbox.pack_start(frame, True, True, 0)
165 self._textbuf['en'] = textview.get_buffer()
166
167 self.window.add(vbox)
168 self.window.show()
169
69eefce0 170 def _delete_event(self, widget, event, data=None):
e603e417
P
171 DEBUG("caught delete event")
172 gtk.main_quit()
173 return False
174
69eefce0 175 def _text_change(self, widget, event, lang):
e603e417
P
176 start, end = self._textbuf[lang].get_bounds()
177 text = self._textbuf[lang].get_text(start, end)
178 other_lang = (set(self._textbuf.keys()) - set((lang,))).pop()
179 translation_path = lang + '2' + other_lang
180 self._translator.request_translation(translation_path, text)
181
69eefce0 182 def _process_translation_result(self):
e603e417
P
183 result = {}
184 # FIXME: to transform into an iterator...
185 while True:
186 r = self._translator.translation_result()
187 if r is None:
188 break
189 translation_path, text = r
190 lang = translation_path[3:]
191 if lang in self._textbuf:
192 result[lang] = text
193 else:
194 DEBUG("unknown destination language '%s'" % lang)
195 self._translator.translation_done()
196 for lang, text in result.items():
197 self._textbuf[lang].set_text(text)
69eefce0
P
198 gobject.timeout_add(300, self._process_translation_result)
199
200 def run(self):
201 DEBUG("running graphic interface")
202 gobject.timeout_add(300, self._process_translation_result)
203 gtk.gdk.threads_init()
204 gtk.main()
e603e417
P
205
206if __name__ == "__main__":
f682a3c3
P
207 if len(sys.argv) > 1 and sys.argv[1] == '-d':
208 debug = True
209 del(sys.argv[1])
ed507d05
P
210 if len(sys.argv) > 1:
211 jid = sys.argv[1]
212 del(sys.argv[1])
213 if len(sys.argv) > 1:
214 password = sys.argv[1]
215 del(sys.argv[1])
216 else:
217 password = getpass()
218 if len(sys.argv) != 1:
219 print "Usage: %s [-d] <jid> [<password>]" % sys.argv[0]
e603e417
P
220 sys.exit(1)
221
ed507d05 222 translator = XmppTranslator(jid, password)
e603e417
P
223 translator.start()
224
225 pygtranslator = GtkTranslator(translator)
226 try:
227 pygtranslator.run()
228 except KeyboardInterrupt:
229 pass
230
231 translator._quit = True
232 translator.join()
233
234 sys.exit(0)
235