From e603e4177c425ea746defc5ffad58d3a1f7c5fd2 Mon Sep 17 00:00:00 2001 From: Progfou Date: Mon, 28 Sep 2009 05:31:02 +0700 Subject: [PATCH] Ajout d'un exercice de programmation Python+Gtk+Thread+Xmpp. --- pygtranslator/pygtranslator.py | 206 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 206 insertions(+) create mode 100755 pygtranslator/pygtranslator.py diff --git a/pygtranslator/pygtranslator.py b/pygtranslator/pygtranslator.py new file mode 100755 index 0000000..ae77618 --- /dev/null +++ b/pygtranslator/pygtranslator.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python2.5 +# -*- coding: utf-8 -*- +""" +PygTranslator - pas de doc cette fois-ci... :-P + +Copyright : Agence universitaire de la Francophonie +Licence : GNU General Public Licence, version 2 +Auteur : Jean Christophe André +Date de création : 28 septembre 2009 +""" + +from threading import Thread +from Queue import Queue +import xmpp + +import pygtk +pygtk.require('2.0') +import gtk, gobject + +def DEBUG(message): + #print "\x1b[31;1mDEBUG\x1b[m:", message + return + +class XmppTranslator(Thread): + + def __init__(self, jid, password): + Thread.__init__(self) + self.setDaemon(True) + self._input_queue = Queue(0) + self._output_queue = Queue(0) + self._quit = False + + self._jid = xmpp.JID(jid) + self._password = password + if self._jid.getResource() == '': + self._jid.setResource('translator') + + self._client = xmpp.Client(self._jid.getDomain(), debug=[]) + + def __del__(self): + if self._client and not self._client.isConnected(): + return + self._client.sendPresence(typ='unavailable') + self._client.disconnect() + + def _connect(self): + try: + if not self._client.connect(): + raise IOError + except IOError: + raise IOError, "can't connect to '%s'" % self._jid.getDomain() + self._client.RegisterHandler('message', self._messageHandler) + + auth = self._client.auth(self._jid.getNode(), self._password, + self._jid.getResource()) + if not auth: + raise IOError, "unable to authenticate '%s'" % self._jid.getNode() + self._client.sendInitPresence(requestRoster=0) + + def _messageHandler(self, client, message): + if message.getType() == 'error': + return + translation_path = message.getFrom().getNode() + text = message.getBody() + self._output_queue.put( (translation_path, text) ) + raise xmpp.NodeProcessed + + def _process_input_queue(self): + if self._input_queue.empty(): + return + # process pending translation job + translation_path, text = self._input_queue.get() + jid = '%s@bot.talk.google.com' % translation_path + message = xmpp.Message(to=jid, typ='chat', body=text) + self._client.send(message) + DEBUG("sent [%s] to '%s'." % (text, jid)) + self._input_queue.task_done() + + def run(self): + self._connect() + self._client.Process(1) + while not self._quit: + self._process_input_queue() + self._client.Process(1) + + def request_translation(self, translation_path, text): + # remove any pending translation job + while not self._input_queue.empty(): + self._input_queue.get() + DEBUG("removed a pending translation job") + self._input_queue.task_done() + # put a new translation job + self._input_queue.put( (translation_path, text) ) + + def translation_result(self): + if self._output_queue.empty(): + return None + translation_path, text = self._output_queue.get() + return translation_path, text + + def translation_done(self): + self._output_queue.task_done() + +class GtkTranslator(object): + + def __init__(self, translator): + self._translator = translator + + self._textbuf = {} + + self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) + self.window.set_title(u"PygTranslator") + self.window.set_border_width(0) + self.window.connect("destroy", lambda w: gtk.main_quit()) + self.window.connect("delete_event", self.delete_event) + + vbox = gtk.VBox(True, 0) + vbox.show() + + textview = gtk.TextView() + textview.set_size_request(400, 100) + textview.set_wrap_mode(gtk.WRAP_WORD) + textview.show() + scroll = gtk.ScrolledWindow() + scroll.add(textview) + scroll.show() + frame = gtk.Frame(u"Texte en français") + frame.connect("key_release_event", self.key_release_event, 'fr') + frame.add(scroll) + frame.show() + vbox.pack_start(frame, True, True, 0) + self._textbuf['fr'] = textview.get_buffer() + + textview = gtk.TextView() + textview.set_size_request(400, 100) + textview.set_wrap_mode(gtk.WRAP_WORD) + textview.show() + scroll = gtk.ScrolledWindow() + scroll.add(textview) + scroll.show() + frame = gtk.Frame(u"Text in English") + frame.connect("key_release_event", self.key_release_event, 'en') + frame.add(scroll) + frame.show() + vbox.pack_start(frame, True, True, 0) + self._textbuf['en'] = textview.get_buffer() + + self.window.add(vbox) + self.window.show() + + def run(self): + DEBUG("running graphic interface") + gobject.timeout_add(100, self.process_translation_result) + gtk.gdk.threads_init() + gtk.main() + + def delete_event(self, widget, event, data=None): + DEBUG("caught delete event") + gtk.main_quit() + return False + + def key_release_event(self, widget, event, lang): + start, end = self._textbuf[lang].get_bounds() + text = self._textbuf[lang].get_text(start, end) + other_lang = (set(self._textbuf.keys()) - set((lang,))).pop() + translation_path = lang + '2' + other_lang + self._translator.request_translation(translation_path, text) + + def process_translation_result(self): + result = {} + # FIXME: to transform into an iterator... + while True: + r = self._translator.translation_result() + if r is None: + break + translation_path, text = r + lang = translation_path[3:] + if lang in self._textbuf: + result[lang] = text + else: + DEBUG("unknown destination language '%s'" % lang) + self._translator.translation_done() + for lang, text in result.items(): + self._textbuf[lang].set_text(text) + gobject.timeout_add(100, self.process_translation_result) + +if __name__ == "__main__": + import sys + if len(sys.argv) != 3: + print "Usage: %s " % sys.argv[0] + sys.exit(1) + + translator = XmppTranslator(sys.argv[1], sys.argv[2]) + translator.start() + + pygtranslator = GtkTranslator(translator) + try: + pygtranslator.run() + except KeyboardInterrupt: + pass + + translator._quit = True + translator.join() + + sys.exit(0) + -- 1.7.10.4