From 4658ab89274e2264ee15a0df29b4b22bfc57a9c4 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Wed, 4 Aug 2004 22:40:22 +0000 Subject: [PATCH] beginning of the group chat support do not create a new connexion in the core if it already exists --- common/plugin.py | 1 + core/core.py | 57 ++++-- plugins/gtkgui/config.py | 1 - plugins/gtkgui/gtkgui.glade | 366 ++++++++++++++++++++++++++++++++++-- plugins/gtkgui/gtkgui.py | 145 +++++++++++++- 5 files changed, 530 insertions(+), 40 deletions(-) diff --git a/common/plugin.py b/common/plugin.py index ff2e9e343..6fb16af3d 100644 --- a/common/plugin.py +++ b/common/plugin.py @@ -31,6 +31,7 @@ class GajimPlugin: def load(self): thr = common.thread.GajimThread(self.name, self.queueIn, self.queueOut) + thr.setDaemon(1) thr.start() # END load # END GajimPlugin diff --git a/core/core.py b/core/core.py index 3573b84e2..08699cbbf 100644 --- a/core/core.py +++ b/core/core.py @@ -176,10 +176,14 @@ class GajimCore: def messageCB(self, con, msg): """Called when we recieve a message""" - if msg.getType() == 'error': + typ = msg.getType() + if typ == 'error': self.hub.sendPlugin('MSGERROR', self.connexions[con], \ (str(msg.getFrom()), msg.getErrorCode(), msg.getError(), \ msg.getBody())) + elif typ == 'groupchat': + self.hub.sendPlugin('GC_MSG', self.connexions[con], \ + (str(msg.getFrom()), msg.getBody())) else: self.hub.sendPlugin('MSG', self.connexions[con], \ (str(msg.getFrom()), msg.getBody())) @@ -258,20 +262,31 @@ class GajimCore: name = self.cfgParser.tab[account]["name"] password = self.cfgParser.tab[account]["password"] ressource = self.cfgParser.tab[account]["ressource"] - if self.cfgParser.tab[account]["use_proxy"]: - proxy = {"host":self.cfgParser.tab[account]["proxyhost"]} - proxy["port"] = self.cfgParser.tab[account]["proxyport"] - else: - proxy = None - if self.log: - con = common.jabber.Client(host = hostname, debug = [], \ - log = sys.stderr, connection=common.xmlstream.TCP, port=5222, \ - proxy = proxy) - else: - con = common.jabber.Client(host = hostname, debug = [], log = None, \ - connection=common.xmlstream.TCP, port=5222, proxy = proxy) - #debug = [common.jabber.DBG_ALWAYS], log = sys.stderr, \ - #connection=common.xmlstream.TCP_SSL, port=5223, proxy = proxy) + + #create connexion if it doesn't already existe + con = None + for conn in self.connexions: + if self.connexions[conn] == account: + con = conn + if not con: + if self.cfgParser.tab[account]["use_proxy"]: + proxy = {"host":self.cfgParser.tab[account]["proxyhost"]} + proxy["port"] = self.cfgParser.tab[account]["proxyport"] + else: + proxy = None + if self.log: + con = common.jabber.Client(host = hostname, debug = [], \ + log = sys.stderr, connection=common.xmlstream.TCP, port=5222, \ + proxy = proxy) + else: + con = common.jabber.Client(host = hostname, debug = [], log = None,\ + connection=common.xmlstream.TCP, port=5222, proxy = proxy) + #debug = [common.jabber.DBG_ALWAYS], log = sys.stderr, \ + #connection=common.xmlstream.TCP_SSL, port=5223, proxy = proxy) + con.setDisconnectHandler(self.disconnectedCB) + con.registerHandler('message', self.messageCB) + con.registerHandler('presence', self.presenceCB) + con.registerHandler('iq',self.vCardCB,'result')#common.jabber.NS_VCARD) try: con.connect() except IOError, e: @@ -292,13 +307,12 @@ class GajimCore: self.hub.sendPlugin('WARNING', None, _("Couldn't connect to %s : %s") \ % (hostname, e)) return 0 + except: + sys.exc_info()[1][0] + sys.exc_info()[1][1] else: log.debug("Connected to server") - con.registerHandler('message', self.messageCB) - con.registerHandler('presence', self.presenceCB) - con.registerHandler('iq',self.vCardCB,'result')#common.jabber.NS_VCARD) - con.setDisconnectHandler(self.disconnectedCB) #BUG in jabberpy library : if hostname is wrong : "boucle" if con.auth(name, password, ressource): self.connexions[con] = account @@ -596,6 +610,11 @@ class GajimCore: self.hub.register(ev[1], msg) elif ev[0] == 'EXEC_PLUGIN': self.loadPlugins(ev[2]) + #('GC_JOIN', account, (nick, room, server, passwd)) + elif ev[0] == 'GC_JOIN': + p = common.jabber.Presence(to='%s@%s/%s' % (ev[2][1], ev[2][2], \ + ev[2][0])) + con.send(p) else: log.debug(_("Unknown Command %s") % ev[0]) if self.mode == 'server': diff --git a/plugins/gtkgui/config.py b/plugins/gtkgui/config.py index fd8b7e3a4..9fba4eec1 100644 --- a/plugins/gtkgui/config.py +++ b/plugins/gtkgui/config.py @@ -125,7 +125,6 @@ class vCard_Window: self.xml.signal_connect('on_retrieve_clicked', self.on_retrieve) self.xml.signal_connect('on_publish_clicked', self.on_publish) - class preference_Window: """Class for Preferences window""" def delete_event(self, widget): diff --git a/plugins/gtkgui/gtkgui.glade b/plugins/gtkgui/gtkgui.glade index cd72620eb..b87daa68d 100644 --- a/plugins/gtkgui/gtkgui.glade +++ b/plugins/gtkgui/gtkgui.glade @@ -44,7 +44,7 @@ True - + True gtk-convert 1 @@ -66,7 +66,7 @@ - + True gtk-preferences 1 @@ -87,7 +87,7 @@ - + True gtk-select-color 1 @@ -108,7 +108,7 @@ - + True gtk-find 1 @@ -122,7 +122,7 @@ - + True @@ -134,7 +134,7 @@ True - + True gtk-add 1 @@ -158,7 +158,16 @@ - + + True + _Join Groupchat + True + + + + + + True @@ -171,7 +180,7 @@ - + True gtk-help 1 @@ -193,7 +202,7 @@ - + True gtk-quit 1 @@ -7127,7 +7136,7 @@ when NOT online - + True Group chat GTK_WINDOW_TOPLEVEL @@ -7140,6 +7149,7 @@ when NOT online False GDK_WINDOW_TYPE_HINT_NORMAL GDK_GRAVITY_NORTH_WEST + @@ -7208,7 +7218,6 @@ when NOT online True True - 0 @@ -7236,7 +7245,7 @@ when NOT online GTK_CORNER_TOP_LEFT - + True True False @@ -7262,7 +7271,7 @@ when NOT online GTK_CORNER_TOP_LEFT - + True True True @@ -7328,7 +7337,7 @@ when NOT online GTK_CORNER_TOP_LEFT - + True True True @@ -7363,4 +7372,333 @@ when NOT online + + True + Join Groupchat + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + True + False + 0 + + + + True + 4 + 2 + False + 5 + 10 + + + + True + Nickname + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 0 + 1 + fill + + + + + + + True + Room + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 1 + 2 + fill + + + + + + + True + Server + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 2 + 3 + fill + + + + + + + True + Password + False + False + GTK_JUSTIFY_LEFT + False + False + 0 + 0.5 + 0 + 0 + + + 0 + 1 + 3 + 4 + fill + + + + + + + True + True + True + True + 0 + + True + * + False + + + 1 + 2 + 0 + 1 + + + + + + + True + True + True + True + 0 + + True + * + False + + + 1 + 2 + 1 + 2 + + + + + + + True + True + True + True + 0 + + True + * + False + + + 1 + 2 + 2 + 3 + + + + + + + True + True + True + True + 3 + + True + * + False + + + 1 + 2 + 3 + 4 + + + + + + 0 + True + True + + + + + + True + + + 0 + False + True + + + + + + 10 + True + GTK_BUTTONBOX_END + 20 + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + + + + + + + True + True + True + GTK_RELIEF_NORMAL + True + + + + + True + 0.5 + 0.5 + 0 + 0 + 0 + 0 + 0 + 0 + + + + True + False + 2 + + + + True + gtk-apply + 4 + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + True + _Join + True + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + + + 0 + False + False + + + + + + + + + + + 0 + False + True + + + + + + diff --git a/plugins/gtkgui/gtkgui.py b/plugins/gtkgui/gtkgui.py index c5d2a48c1..dc44c2e3e 100644 --- a/plugins/gtkgui/gtkgui.py +++ b/plugins/gtkgui/gtkgui.py @@ -298,6 +298,92 @@ class message_Window: if plugin.queues[account].has_key(user.jid): self.read_queue(plugin.queues[account][user.jid]) +class gc: + def delete_event(self, widget): + """close window""" + del self.plugin.windows[self.account]['chats'][self.jid] + + def on_close(self, widget): + """When Cancel button is clicked""" + widget.get_toplevel().destroy() + + def print_conversation(self, txt, contact = None, tim = None): + """Print a line in the conversation : + if contact is set : it's a message from someone + if contact is not set : it's a message from the server""" + conversation = self.xml.get_widget('conversation') + buffer = conversation.get_buffer() + if not txt: + txt = "" + end_iter = buffer.get_end_iter() + if not tim: + tim = time.strftime("[%H:%M:%S]") + buffer.insert(end_iter, tim) + if contact: + #TODO it a message from me + if contact == '': + buffer.insert_with_tags_by_name(end_iter, '<'+contact+'> ', 'outgoing') + else: + buffer.insert_with_tags_by_name(end_iter, '<' + \ + contact + '> ', 'incoming') + buffer.insert(end_iter, txt+'\n') + else: + buffer.insert_with_tags_by_name(end_iter, txt+'\n', \ + 'status') + #scroll to the end of the textview + conversation.scroll_to_mark(buffer.get_mark('end'), 0.1, 0, 0, 0) + + def __init__(self, jid, plugin, account): + self.jid = jid + self.plugin = plugin + self.account = account + self.xml = gtk.glade.XML(GTKGUI_GLADE, 'Gc', APP) + self.window = self.xml.get_widget('Gc') + conversation = self.xml.get_widget('conversation') + buffer = conversation.get_buffer() + end_iter = buffer.get_end_iter() + buffer.create_mark('end', end_iter, 0) + self.tagIn = buffer.create_tag("incoming") + color = self.plugin.config['inmsgcolor'] + self.tagIn.set_property("foreground", color) + self.tagOut = buffer.create_tag("outgoing") + color = self.plugin.config['outmsgcolor'] + self.tagOut.set_property("foreground", color) + self.tagStatus = buffer.create_tag("status") + color = self.plugin.config['statusmsgcolor'] + self.tagStatus.set_property("foreground", color) + self.xml.signal_connect('gtk_widget_destroy', self.delete_event) + +class join_gc: + def delete_event(self, widget): + """close window""" + del self.plugin.windows['join_gc'] + + def on_close(self, widget): + """When Cancel button is clicked""" + widget.get_toplevel().destroy() + + def on_join(self, widget): + """When Join button is clicked""" + nick = self.xml.get_widget('entry_nick').get_text() + room = self.xml.get_widget('entry_room').get_text() + server = self.xml.get_widget('entry_server').get_text() + passw = self.xml.get_widget('entry_pass').get_text() + jid = '%s@%s' % (room, server) + self.plugin.windows[self.account]['chats'][jid] = gc(jid, self.plugin,\ + self.account) + #TODO: verify entries + self.plugin.send('GC_JOIN', self.account, (nick, room, server, passw)) + widget.get_toplevel().destroy() + + def __init__(self, plugin, account): + self.plugin = plugin + self.account = account + self.xml = gtk.glade.XML(GTKGUI_GLADE, 'Join_gc', APP) + self.xml.signal_connect('gtk_widget_destroy', self.delete_event) + self.xml.signal_connect('on_cancel_clicked', self.on_close) + self.xml.signal_connect('on_join_clicked', self.on_join) + class log_Window: """Class for bowser agent window : to know the agents on the selected server""" @@ -581,13 +667,15 @@ class roster_Window: model.set_value(iter, 1, name) def mkmenu(self): - """create the browse agents and add sub menus""" + """create the browse agents, add and join groupchat sub menus""" if len(self.plugin.accounts.keys()) > 0: self.xml.get_widget('add').set_sensitive(True) self.xml.get_widget('browse_agents').set_sensitive(True) + self.xml.get_widget('join_gc').set_sensitive(True) else: self.xml.get_widget('add').set_sensitive(False) self.xml.get_widget('browse_agents').set_sensitive(False) + self.xml.get_widget('join_gc').set_sensitive(False) if len(self.plugin.accounts.keys()) > 1: #add menu_sub = gtk.Menu() @@ -605,6 +693,14 @@ class roster_Window: menu_sub.append(item) item.connect("activate", self.on_browse, a) menu_sub.show_all() + #join gc + menu_sub = gtk.Menu() + self.xml.get_widget('join_gc').set_submenu(menu_sub) + for a in self.plugin.accounts.keys(): + item = gtk.MenuItem(a) + menu_sub.append(item) + item.connect("activate", self.on_join_gc, a) + menu_sub.show_all() elif len(self.plugin.accounts.keys()) == 1: #add self.xml.get_widget('add').connect("activate", self.on_add, \ @@ -612,6 +708,9 @@ class roster_Window: #agents self.xml.get_widget('browse_agents').connect("activate", \ self.on_browse, self.plugin.accounts.keys()[0]) + #join_gc + self.xml.get_widget('join_gc').connect("activate", \ + self.on_join_gc, self.plugin.accounts.keys()[0]) def draw_roster(self): """Clear and draw roster""" @@ -1086,6 +1185,12 @@ class roster_Window: call the add class""" addContact_Window(self.plugin, account) + def on_join_gc(self, widget, account): + """When Join Groupchat is selected : + call the join_gc class""" + if not self.plugin.windows.has_key('join_gc'): + self.plugin.windows['join_gc'] = join_gc(self.plugin, account) + def on_about(self, widget): """When about is selected : call the about class""" @@ -1097,6 +1202,14 @@ class roster_Window: call the accounts class to modify accounts""" if not self.plugin.windows.has_key('accounts'): self.plugin.windows['accounts'] = accounts_Window(self.plugin) + + def close_all(self, dic): + """close all the windows in the given dictionary""" + for w in dic.values(): + if type(w) == type({}): + self.close_all(w) + else: + w.event(gtk.gdk.Event(gtk.gdk.DESTROY)) def on_quit(self, widget): """When we quit the gtk plugin : @@ -1105,8 +1218,10 @@ class roster_Window: self.plugin.send('CONFIG', None, ('GtkGui', self.plugin.config)) self.plugin.send('QUIT', None, ('gtkgui', 0)) print _("plugin gtkgui stopped") +# self.close_all(self.plugin.windows) self.plugin.systray.t.destroy() - gtk.mainquit() + gtk.main_quit() +# gtk.gdk.threads_leave() def on_row_activated(self, widget, path, col=0): """When an iter is dubble clicked : @@ -1798,6 +1913,23 @@ class plugin: if self.windows['logs'].has_key(array[0]): self.windows['logs'][array[0]].new_line(array[1:]) + def handle_event_gc_msg(self, account, array): + #('GC_MSG', account, (jid, msg)) + jids = string.split(array[0], '/') + jid = jids[0] + if not self.windows[account]['chats'].has_key(jid): + return + if len(jids) == 1: + #message from server + self.windows[account]['chats'][jid].print_conversation(array[1]) + else: + #message from someone + self.windows[account]['chats'][jid].print_conversation(array[1], \ + jids[1]) + if not self.windows[account]['chats'][jid].window.\ + get_property('is-active'): + self.systray.add_jid(jid, account) + def read_queue(self): """Read queue from the core and execute commands from it""" while self.queueIN.empty() == 0: @@ -1836,6 +1968,8 @@ class plugin: self.handle_event_log_nb_line(ev[1], ev[2]) elif ev[0] == 'LOG_LINE': self.handle_event_log_line(ev[1], ev[2]) + elif ev[0] == 'GC_MSG': + self.handle_event_gc_msg(ev[1], ev[2]) return 1 def read_sleepy(self): @@ -1868,14 +2002,14 @@ class plugin: return 1 def __init__(self, quIN, quOUT): - gtk.threads_init() - gtk.threads_enter() + gtk.gdk.threads_init() +# gtk.gdk.threads_enter() self.queueIN = quIN self.queueOUT = quOUT self.send('REG_MESSAGE', 'gtkgui', ['ROSTER', 'WARNING', 'STATUS', \ 'NOTIFY', 'MSG', 'MSGERROR', 'SUBSCRIBED', 'UNSUBSCRIBED', \ 'SUBSCRIBE', 'AGENTS', 'AGENT_INFO', 'QUIT', 'ACC_OK', 'CONFIG', \ - 'MYVCARD', 'VCARD', 'LOG_NB_LINE', 'LOG_LINE', 'VISUAL']) + 'MYVCARD', 'VCARD', 'LOG_NB_LINE', 'LOG_LINE', 'VISUAL', 'GC_MSG']) self.send('ASK_CONFIG', None, ('GtkGui', 'GtkGui', {'autopopup':1,\ 'autopopupaway':1,\ 'showoffline':0,\ @@ -1926,6 +2060,5 @@ class plugin: else: self.systray = systrayDummy() gtk.main() - gtk.threads_leave() print _("plugin gtkgui loaded")