diff --git a/src/chat_control.py b/src/chat_control.py index 2c1a51a01..002f7cb8c 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -916,7 +916,7 @@ class ChatControlBase(MessageControl): # TODO : get the contact and check notify.get_show_in_roster() if self.type_id == message_control.TYPE_PM: room_jid, nick = gajim.get_room_and_nick_from_fjid(jid) - groupchat_control = gajim.interface.msg_win_mgr.get_control( + groupchat_control = gajim.interface.msg_win_mgr.get_gc_control( room_jid, self.account) if room_jid in gajim.interface.minimized_controls[self.account]: groupchat_control = \ @@ -927,7 +927,7 @@ class ChatControlBase(MessageControl): if contact: gajim.interface.roster.draw_contact(room_jid, self.account) groupchat_control.draw_contact(nick) - mw = gajim.interface.msg_win_mgr.get_window(room_jid, self.account) + mw = gajim.interface.msg_win_mgr.get_gc_window(room_jid, self.account) if mw: mw.redraw_tab(groupchat_control) else: diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 29b27e479..3e9fece19 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -1298,7 +1298,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, reply.addChild(node=common.xmpp.ErrorNode('service-unavailable', typ='cancel')) con.send(reply) - + raise common.xmpp.NodeProcessed def _InitE2ECB(self, con, stanza, session): @@ -1328,7 +1328,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, errmsg = iq_obj.getErrorMsg() errcode = iq_obj.getErrorCode() self.dispatch('ERROR_ANSWER', (id, jid_from, errmsg, errcode)) - + def _PrivateCB(self, con, iq_obj): ''' Private Data (XEP 048 and 049) @@ -1590,7 +1590,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, try: msg = session.decrypt_stanza(msg) except: - self.dispatch('FAILED_DECRYPT', (frm, tim)) + self.dispatch('FAILED_DECRYPT', (frm, tim, session)) msgtxt = msg.getBody() subject = msg.getSubject() # if not there, it's None diff --git a/src/gajim.py b/src/gajim.py index 3c84e56c7..09bab6b89 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -446,7 +446,7 @@ class Interface: title = data[1] prompt = data[2] proposed_nick = data[3] - gc_control = self.msg_win_mgr.get_control(room_jid, account) + gc_control = self.msg_win_mgr.get_gc_control(room_jid, account) if not gc_control and \ room_jid in self.minimized_controls[account]: gc_control = self.minimized_controls[account][room_jid] @@ -500,9 +500,10 @@ class Interface: (jid_from, file_props)) conn.disconnect_transfer(file_props) return - ctrl = self.msg_win_mgr.get_control(jid_from, account) - if ctrl and ctrl.type_id == message_control.TYPE_GC: - ctrl.print_conversation('Error %s: %s' % (array[2], array[1])) + + for ctrl in self.msg_win_mgr.get_chat_controls(jid_from, account): + if ctrl.type_id == message_control.TYPE_GC: + ctrl.print_conversation('Error %s: %s' % (array[2], array[1])) def handle_event_con_type(self, account, con_type): # ('CON_TYPE', account, con_type) which can be 'ssl', 'tls', 'tcp' @@ -956,21 +957,22 @@ class Interface: win.set_values(vcard) # show avatar in chat - win = None - ctrl = None + ctrls = [] if resource and self.msg_win_mgr.has_window( jid + '/' + resource, account): win = self.msg_win_mgr.get_window(jid + '/' + resource, account) - ctrl = win.get_control(jid + '/' + resource, account) + ctrls = win.get_controls(jid + '/' + resource, account) elif self.msg_win_mgr.has_window(jid, account): win = self.msg_win_mgr.get_window(jid, account) - ctrl = win.get_control(jid, account) - if win and ctrl.type_id != message_control.TYPE_GC: - ctrl.show_avatar() + ctrls = win.get_controls(jid, account) + + for ctrl in ctrls: + if ctrl.type_id != message_control.TYPE_GC: + ctrl.show_avatar() # Show avatar in roster or gc_roster - gc_ctrl = self.msg_win_mgr.get_control(jid, account) + gc_ctrl = self.msg_win_mgr.get_gc_control(jid, account) if not gc_ctrl and \ jid in self.minimized_controls[account]: gc_ctrl = self.minimized_controls[account][jid] @@ -1027,26 +1029,25 @@ class Interface: # Get the window and control for the updated status, this may be a # PrivateChatControl - control = self.msg_win_mgr.get_control(room_jid, account) + control = self.msg_win_mgr.get_gc_control(room_jid, account) + if not control and \ room_jid in self.minimized_controls[account]: control = self.minimized_controls[account][room_jid] - if control and control.type_id != message_control.TYPE_GC: + if not control or (control and control.type_id != message_control.TYPE_GC): return - if control: - control.chg_contact_status(nick, show, status, array[4], array[5], - array[6], array[7], array[8], array[9], array[10], array[11]) + + control.chg_contact_status(nick, show, status, array[4], array[5], + array[6], array[7], array[8], array[9], array[10], array[11]) contact = gajim.contacts.\ get_contact_with_highest_priority(account, room_jid) if contact: self.roster.draw_contact(room_jid, account) - ctrl = self.msg_win_mgr.get_control(fjid, account) - - # print status in chat window and update status/GPG image - if ctrl: + # print status in chat windows and update status/GPG image + for ctrl in self.msg_win_mgr.get_chat_controls(fjid, account): statusCode = array[9] if '303' in statusCode: new_nick = array[10] @@ -1082,7 +1083,7 @@ class Interface: jids = array[0].split('/', 1) room_jid = jids[0] - gc_control = self.msg_win_mgr.get_control(room_jid, account) + gc_control = self.msg_win_mgr.get_gc_control(room_jid, account) if not gc_control and \ room_jid in self.minimized_controls[account]: gc_control = self.minimized_controls[account][room_jid] @@ -1115,7 +1116,7 @@ class Interface: jids = array[0].split('/', 1) jid = jids[0] - gc_control = self.msg_win_mgr.get_control(jid, account) + gc_control = self.msg_win_mgr.get_gc_control(jid, account) if not gc_control and \ jid in self.minimized_controls[account]: @@ -1180,7 +1181,7 @@ class Interface: jid = array[0] statusCode = array[1] - gc_control = self.msg_win_mgr.get_control(jid, account) + gc_control = self.msg_win_mgr.get_gc_control(jid, account) if not gc_control and \ jid in self.minimized_controls[account]: gc_control = self.minimized_controls[account][jid] @@ -1239,7 +1240,7 @@ class Interface: self.roster.on_disconnect(None, room_jid, account) else: win = self.msg_win_mgr.get_window(room_jid, account) - ctrl = win.get_control(room_jid, account) + ctrl = win.get_gc_control(room_jid, account) win.remove_tab(ctrl, 3) dlg = dialogs.InputDialog(_('Password Required'), @@ -1782,9 +1783,9 @@ class Interface: AtomWindow.newAtomEntry(atom_entry) def handle_event_failed_decrypt(self, account, data): - jid, tim = data + jid, tim, session = data - ctrl = self.msg_win_mgr.get_control(jid, account) + ctrl = self.msg_win_mgr.get_control(jid, account, session.thread_id) if ctrl: ctrl.print_conversation_line('Unable to decrypt message from %s\nIt may have been tampered with.' % (jid), 'status', '', tim) else: @@ -2583,6 +2584,7 @@ class Interface: data[1], data[3]) gajim.events.remove_events(account, jid, event) self.roster.draw_contact(jid, account) + if w: w.set_active_tab(fjid, account) w.window.present() diff --git a/src/groupchat_control.py b/src/groupchat_control.py index 0234ce5a1..61def8345 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -43,6 +43,7 @@ import cell_renderer_image from common import gajim from common import helpers +from common.stanza_session import StanzaSession from chat_control import ChatControl from chat_control import ChatControlBase @@ -57,7 +58,7 @@ C_TYPE, # type of the row ('contact' or 'role') C_TEXT, # text shown in the cellrenderer C_AVATAR, # avatar of the contact ) = range(5) - + def set_renderer_color(treeview, renderer, set_background = True): '''set style for group row, using PRELIGHT system color''' if set_background: @@ -210,6 +211,9 @@ class GroupchatControl(ChatControlBase): self.new_nick = '' self.name = self.room_jid.split('@')[0] + self.session = StanzaSession(gajim.connections[self.account], + self.room_jid, 'gc', 'gc') + compact_view = gajim.config.get('compact_view') self.chat_buttons_set_visible(compact_view) self.widget_set_visible(self.xml.get_widget('banner_eventbox'), @@ -852,10 +856,9 @@ class GroupchatControl(ChatControlBase): for nick in nick_list: # Update pm chat window fjid = self.room_jid + '/' + nick - ctrl = gajim.interface.msg_win_mgr.get_control(fjid, self.account) gc_contact = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) - if ctrl: + for ctrl in gajim.interface.msg_win_mgr.get_chat_controls(fjid, self.account): gc_contact.show = 'offline' gc_contact.status = '' ctrl.update_ui() @@ -2022,7 +2025,7 @@ class GroupchatControl(ChatControlBase): menu.show_all() menu.popup(None, None, None, event.button, event.time) - def _start_private_message(self, nick, session = None): + def _start_private_message(self, nick): gc_c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) nick_jid = gc_c.get_full_jid() diff --git a/src/message_window.py b/src/message_window.py index 5f857d841..74aa6f16a 100644 --- a/src/message_window.py +++ b/src/message_window.py @@ -396,8 +396,7 @@ class MessageWindow(object): else: gtkgui_helpers.set_unset_urgency_hint(self.window, False) - def set_active_tab(self, session): - ctrl = self._controls[session.conn.name][session.jid][session.thread_id] + def set_active_tab(self, ctrl): ctrl_page = self.notebook.page_num(ctrl.widget) self.notebook.set_current_page(ctrl_page) @@ -538,16 +537,16 @@ class MessageWindow(object): for ctrl in self.controls(): ctrl.update_tags() - def get_control(self, key, acct): + def get_control(self, key, acct, thread_id): '''Return the MessageControl for jid or n, where n is a notebook page index. - When key is an int index acct may be None''' + When key is an int index acct and thread_id may be None''' if isinstance(key, str): key = unicode(key, 'utf-8') if isinstance(key, unicode): jid = key try: - return self._controls[acct][jid] + return self._controls[acct][jid][thread_id] except: return None else: @@ -558,6 +557,15 @@ class MessageWindow(object): nth_child = notebook.get_nth_page(page_num) return self._widget_to_control(nth_child) + def get_gc_control(self, jid, acct): + return self.get_control(jid, acct, 'gc') + + def get_controls(self, jid, acct): + try: + return self._controls[acct][jid].values() + except KeyError: + return [] + def change_key(self, old_jid, new_jid, acct): '''Change the key of a control''' try: @@ -594,7 +602,7 @@ class MessageWindow(object): ind = ind - 1 if ind < 0: ind = self.notebook.get_n_pages() - 1 - ctrl = self.get_control(ind, None) + ctrl = self.get_control(ind, None, None) if ctrl.get_nb_unread() > 0: found = True break # found @@ -786,8 +794,19 @@ class MessageWindowMgr(gobject.GObject): def get_window(self, jid, acct): for win in self.windows(): - if win.get_control(jid, acct): - return win + try: + if win._controls[acct][jid]: + return win + except KeyError: + pass + return None + + def get_gc_control(self, jid, acct): + win = self.get_window(jid, acct) + + if win: + return win.get_gc_control(jid, acct) + return None def has_window(self, jid, acct): @@ -914,11 +933,11 @@ class MessageWindowMgr(gobject.GObject): del self._windows[k] return - def get_control(self, jid, acct): + def get_control(self, jid, acct, session): '''Amongst all windows, return the MessageControl for jid''' win = self.get_window(jid, acct) if win: - return win.get_control(jid, acct) + return win.get_control(jid, acct, session) return None def get_controls(self, type = None, acct = None): @@ -930,6 +949,14 @@ class MessageWindowMgr(gobject.GObject): ctrls.append(c) return ctrls + def get_chat_controls(self, jid, acct): + win = self.get_window(jid, acct) + + if win: + return win.get_controls(jid, acct) + else: + return [] + def windows(self): for w in self._windows.values(): yield w diff --git a/src/roster_window.py b/src/roster_window.py index c5145868a..315683761 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -777,12 +777,13 @@ class RosterWindow: def join_gc_room(self, account, room_jid, nick, password, minimize=False, is_continued=False): - '''joins the room immediatelly''' + '''joins the room immediately''' if gajim.interface.msg_win_mgr.has_window(room_jid, account) and \ gajim.gc_connected[account][room_jid]: win = gajim.interface.msg_win_mgr.get_window(room_jid, account) + ctrl = gajim.interface.msg_win_mgr.get_gc_control(room_jid, account) win.window.present() - win.set_active_tab(room_jid, account) + win.set_active_tab(ctrl) dialogs.ErrorDialog(_('You are already in group chat %s') % room_jid) return minimized_control_exists = False @@ -808,7 +809,8 @@ class RosterWindow: self.new_room(room_jid, nick, account, is_continued=is_continued) if not minimized_control_exists: gc_win = gajim.interface.msg_win_mgr.get_window(room_jid, account) - gc_win.set_active_tab(room_jid, account) + gc_control = gc_win.get_gc_control(room_jid, account) + gc_win.set_active_tab(gc_control) gc_win.window.present() gajim.connections[account].join_gc(nick, room_jid, password) if password: @@ -1361,10 +1363,10 @@ class RosterWindow: gajim.transport_avatar[account][host] = [contact1.jid] else: gajim.transport_avatar[account][host].append(contact1.jid) - # If we already have a chat window opened, update it with new contact + + # If we already have chat windows opened, update them with new contact # instance - chat_control = gajim.interface.msg_win_mgr.get_control(ji, account) - if chat_control: + for chat_control in gajim.interface.msg_win_mgr.get_chat_controls(ji, account): chat_control.contact = contact1 def chg_contact_status(self, contact, show, status, account): @@ -1385,28 +1387,30 @@ class RosterWindow: account): win = gajim.interface.msg_win_mgr.get_window(jid_with_resource, account) - ctrl = win.get_control(jid_with_resource, account) - ctrl.update_ui() - win.redraw_tab(ctrl) + for ctrl in win.get_controls(jid_with_resource, account): + ctrl.update_ui() + win.redraw_tab(ctrl) + gajim.contacts.remove_contact(account, contact) self.remove_contact(contact, account) self.add_contact_to_roster(contact.jid, account) # print status in chat window and update status/GPG image if gajim.interface.msg_win_mgr.has_window(contact.jid, account): win = gajim.interface.msg_win_mgr.get_window(contact.jid, account) - ctrl = win.get_control(contact.jid, account) - ctrl.contact = gajim.contacts.get_contact_with_highest_priority( - account, contact.jid) - ctrl.update_ui() - win.redraw_tab(ctrl) - uf_show = helpers.get_uf_show(show) - if status: - ctrl.print_conversation(_('%s is now %s (%s)') % (name, uf_show, - status), 'status') - else: # No status message - ctrl.print_conversation(_('%s is now %s') % (name, uf_show), - 'status') + + for ctrl in win.get_controls(contact.jid, account): + ctrl.contact = gajim.contacts.get_contact_with_highest_priority( + account, contact.jid) + ctrl.update_ui() + win.redraw_tab(ctrl) + + if status: + ctrl.print_conversation(_('%s is now %s (%s)') % (name, uf_show, + status), 'status') + else: # No status message + ctrl.print_conversation(_('%s is now %s') % (name, uf_show), + 'status') # unset custom status if gajim.interface.status_sent_to_users.has_key(account) and \ @@ -1808,9 +1812,8 @@ class RosterWindow: u.name = new_text gajim.connections[account].update_contact(jid, new_text, u.groups) self.draw_contact(jid, account) - # Update opened chat - ctrl = gajim.interface.msg_win_mgr.get_control(jid, account) - if ctrl: + # Update opened chats + for ctrl in gajim.interface.msg_win_mgr.get_controls(jid, account): ctrl.update_ui() win = gajim.interface.msg_win_mgr.get_window(jid, account) win.redraw_tab(ctrl) @@ -1858,8 +1861,9 @@ class RosterWindow: # Close chat window msg_win = gajim.interface.msg_win_mgr.get_window(contact.jid, account) - ctrl = gajim.interface.msg_win_mgr.get_control(contact.jid, account) - msg_win.remove_tab(ctrl, msg_win.CLOSE_CLOSE_BUTTON) + for ctrl in gajim.interface.msg_win_mgr.get_controls(contact.jid, + account): + msg_win.remove_tab(ctrl, msg_win.CLOSE_CLOSE_BUTTON) else: need_readd = True if need_readd: @@ -1918,8 +1922,7 @@ class RosterWindow: keyID = keyID[0] keys[contact.jid] = keyID - if gajim.interface.msg_win_mgr.has_window(contact.jid, account): - ctrl = gajim.interface.msg_win_mgr.get_control(contact.jid, account) + for ctrl in gajim.interface.msg_win_mgr.get_chat_controls(contact.jid, account): ctrl.update_ui() keys_str = '' for jid in keys: @@ -1934,10 +1937,9 @@ class RosterWindow: self.draw_avatar(jid, account) # Update chat window if gajim.interface.msg_win_mgr.has_window(jid, account): - win = gajim.interface.msg_win_mgr.get_window(jid, account) - ctrl = win.get_control(jid, account) - if win and ctrl.type_id != message_control.TYPE_GC: - ctrl.show_avatar() + for ctrl in gajim.interface.msg_win_mgr.get_chat_controls(jid, account): + if ctrl.type_id != message_control.TYPE_GC: + ctrl.show_avatar() def on_set_custom_avatar_activate(self, widget, contact, account): def on_ok(widget, path_to_file): @@ -2654,7 +2656,7 @@ class RosterWindow: ctrl.account, ctrl.type_id) ctrl.parent_win = mw mw.new_tab(ctrl) - mw.set_active_tab(jid, account) + mw.set_active_tab(ctrl) mw.window.present() del gajim.interface.minimized_controls[account][jid] @@ -3971,12 +3973,12 @@ class RosterWindow: session.control.read_queue() mw = gajim.interface.msg_win_mgr.get_window(fjid, account) - mw.set_active_tab(fjid, account) + mw.set_active_tab(session.control) mw.window.present() # For JEP-0172 if added_to_roster: - mc = mw.get_control(fjid, account) - mc.user_nick = gajim.nicks[account] + for mc in mw.get_controls(fjid, account): + mc.user_nick = gajim.nicks[account] def new_room(self, room_jid, nick, account, is_continued=False): # Get target window, create a control, and associate it with the window @@ -4322,10 +4324,11 @@ class RosterWindow: gajim.last_message_time[account][session.control.get_full_jid()] = 0 win = session.control.parent_win - win.set_active_tab(session) + win.set_active_tab(session.control) if conn.is_zeroconf and conn.status in ('offline', 'invisible'): - win.get_control(fjid, account).got_disconnected() + for ctrl in win.get_controls(fjid, account): + ctrl.got_disconnected() win.window.present() diff --git a/src/session.py b/src/session.py index f77569c16..1f11450b3 100644 --- a/src/session.py +++ b/src/session.py @@ -107,7 +107,7 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): if gajim.jid_is_transport(jid): jid = jid.replace('@', '') - groupchat_control = gajim.interface.msg_win_mgr.get_control(jid, self.conn.name) + #groupchat_control = gajim.interface.msg_win_mgr.get_control(jid, self.conn.name) # XXX fixme # if not groupchat_control and \ diff --git a/src/vcard.py b/src/vcard.py index b6fcc3695..d1b974198 100644 --- a/src/vcard.py +++ b/src/vcard.py @@ -123,11 +123,9 @@ class VcardWindow: jid = self.contact.jid # Update roster gajim.interface.roster.draw_avatar(jid, self.account) - # Update chat window - if gajim.interface.msg_win_mgr.has_window(jid, self.account): - win = gajim.interface.msg_win_mgr.get_window(jid, self.account) - ctrl = win.get_control(jid, self.account) - if win and ctrl.type_id != message_control.TYPE_GC: + # Update chat windows + for ctrl in gajim.interface.msg_win_mgr.get_chat_controls(jid, self.account): + if ctrl.type_id != message_control.TYPE_GC: ctrl.show_avatar() def on_vcard_information_window_destroy(self, widget):