diff --git a/src/chat_control.py b/src/chat_control.py index 7d80a410e..a9a816c1c 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -577,7 +577,7 @@ class ChatControlBase(MessageControl): type_ = 'printed_' + self.type_id event = 'message_received' show_in_roster = notify.get_show_in_roster(event, - self.account, self.contact, self.session) + self.account, self.contact) show_in_systray = notify.get_show_in_systray(event, self.account, self.contact) if gc_message: @@ -606,7 +606,7 @@ class ChatControlBase(MessageControl): not self.parent_win.is_active() or not end) and \ kind in ('incoming', 'incoming_queue'): self.parent_win.redraw_tab(self) - ctrl = gajim.interface.msg_win_mgr.get_control(full_jid, self.account, self.session.thread_id) + ctrl = gajim.interface.msg_win_mgr.get_control(full_jid, self.account) if not self.parent_win.is_active(): self.parent_win.show_title(True, ctrl) # Enabled Urgent hint else: @@ -904,7 +904,7 @@ class ChatControl(ChatControlBase): TYPE_ID = message_control.TYPE_CHAT old_msg_kind = None # last kind of the printed message CHAT_CMDS = ['clear', 'compact', 'help', 'ping'] - + def __init__(self, parent_win, contact, acct, session, resource = None): ChatControlBase.__init__(self, self.TYPE_ID, parent_win, 'chat_child_vbox', contact, acct, resource) @@ -935,7 +935,7 @@ class ChatControl(ChatControlBase): # it is on enter-notify and leave-notify so no need to be per jid self.show_bigger_avatar_timeout_id = None self.bigger_avatar_window = None - self.show_avatar(self.contact.resource) + self.show_avatar(self.contact.resource) # chatstate timers and state self.reset_kbd_mouse_timeout_vars() @@ -1799,7 +1799,7 @@ class ChatControl(ChatControlBase): # Is it a pm ? is_pm = False room_jid, nick = gajim.get_room_and_nick_from_fjid(jid) - control = gajim.interface.msg_win_mgr.get_control(room_jid, self.account, self.session.thread_id) + control = gajim.interface.msg_win_mgr.get_control(room_jid, self.account) if control and control.type_id == message_control.TYPE_GC: is_pm = True # list of message ids which should be marked as read @@ -1817,6 +1817,9 @@ class ChatControl(ChatControlBase): encrypted = data[4], subject = data[1], xhtml = data[7]) if len(data) > 6 and isinstance(data[6], int): message_ids.append(data[6]) + + if len(data) > 8: + self.set_session(data[8]) if message_ids: gajim.logger.set_read_messages(message_ids) gajim.events.remove_events(self.account, jid_with_resource, diff --git a/src/common/connection.py b/src/common/connection.py index 6deee84a6..047e19d67 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -21,6 +21,8 @@ import os import random import socket +import time + try: randomsource = random.SystemRandom() except: @@ -48,8 +50,6 @@ log = logging.getLogger('gajim.c.connection') import gtkgui_helpers -import time - class Connection(ConnectionHandlers): '''Connection class''' def __init__(self, name): @@ -888,8 +888,7 @@ class Connection(ConnectionHandlers): # XEP-0201 if session: session.last_send = time.time() - if session.thread_id: - msg_iq.setThread(session.thread_id) + msg_iq.setThread(session.thread_id) # JEP-0172: user_nickname if user_nick: diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index ab7cb8042..f4f6306ff 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -37,6 +37,8 @@ from common import atom from common.commands import ConnectionCommands from common.pubsub import ConnectionPubSub +from common.stanza_session import StanzaSession + STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd', 'invisible', 'error'] # kind of events we can wait for an answer @@ -55,7 +57,7 @@ except: class ConnectionBytestream: def __init__(self): self.files_props = {} - + def is_transfer_stoped(self, file_props): if file_props.has_key('error') and file_props['error'] != 0: return True @@ -1168,14 +1170,17 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, # keep the jids we auto added (transports contacts) to not send the # SUBSCRIBED event to gui self.automatically_added = [] - # keep the latest subscribed event for each jid to prevent loop when we + # keep the latest subscribed event for each jid to prevent loop when we # acknoledge presences self.subscribed_events = {} + + # keep track of sessions this connection has with other JIDs + self.sessions = {} try: idle.init() except: HAS_IDLE = False - + def build_http_auth_answer(self, iq_obj, answer): if answer == 'yes': self.connection.send(iq_obj.buildReply('result')) @@ -1197,13 +1202,13 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.dispatch('HTTP_AUTH', (method, url, id, iq_obj, msg)); raise common.xmpp.NodeProcessed - def _FeatureNegCB(self, con, stanza): + def _FeatureNegCB(self, con, stanza, session): gajim.log.debug('FeatureNegCB') feature = stanza.getTag('feature') form = common.xmpp.DataForm(node=feature.getTag('x')) if form['FORM_TYPE'] == 'urn:xmpp:ssn': - self.dispatch('SESSION_NEG', (stanza.getFrom(), stanza.getThread(), form)) + self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form)) else: reply = stanza.buildReply() reply.setType('error') @@ -1410,6 +1415,18 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, def _messageCB(self, con, msg): '''Called when we receive a message''' + frm = helpers.get_full_jid_from_iq(msg) + mtype = msg.getType() + thread_id = msg.getThread() + + if not mtype: + mtype = 'normal' + + session = self.get_session(frm, thread_id, mtype) + + if thread_id and not session.received_thread_id: + session.received_thread_id = True + # check if the message is pubsub#event if msg.getTag('event') is not None: self._pubsubEventCB(con, msg) @@ -1421,18 +1438,15 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, return if msg.getTag('feature') and msg.getTag('feature').namespace == \ common.xmpp.NS_FEATURE: - self._FeatureNegCB(con, msg) + self._FeatureNegCB(con, msg, session) return msgtxt = msg.getBody() msghtml = msg.getXHTML() - mtype = msg.getType() subject = msg.getSubject() # if not there, it's None - thread = msg.getThread() tim = msg.getTimestamp() tim = time.strptime(tim, '%Y%m%dT%H:%M:%S') tim = time.localtime(timegm(tim)) - frm = helpers.get_full_jid_from_iq(msg) jid = helpers.get_jid_from_iq(msg) no_log_for = gajim.config.get_per('accounts', self.name, 'no_log_for') @@ -1486,7 +1500,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, if encTag and GnuPG.USE_GPG: #decrypt encmsg = encTag.getData() - + keyID = gajim.config.get_per('accounts', self.name, 'keyid') if keyID: decmsg = self.gpg.decrypt(encmsg, keyID) @@ -1545,7 +1559,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, if treat_as: mtype = treat_as self.dispatch('MSG', (frm, msgtxt, tim, encrypted, mtype, - subject, chatstate, msg_id, composing_jep, user_nick, msghtml, thread)) + subject, chatstate, msg_id, composing_jep, user_nick, msghtml, session)) # END messageCB def get_session(self, jid, thread_id, type): @@ -1557,7 +1571,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, else: # it's possible we initiated a session with a bare JID and this is the # first time we've seen a resource - bare_jid = gajim.get_jid_without_resource(original_jid) + bare_jid = gajim.get_jid_without_resource(jid) if bare_jid != jid: session = self.find_session(bare_jid, thread_id, type) if session: @@ -1576,9 +1590,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, return None def move_session(self, original_jid, thread_id, to_resource): - session = self.sessions[jid][thread_id] + session = self.sessions[original_jid][thread_id] - del self.sessions[jid][thread_id] + del self.sessions[original_jid][thread_id] new_jid = gajim.get_jid_without_resource(original_jid) + '/' + to_resource session.jid = new_jid diff --git a/src/common/contacts.py b/src/common/contacts.py index 68db5b766..b309981d4 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -16,8 +16,6 @@ import common.gajim -#import random, string - class Contact: '''Information concerning each contact''' def __init__(self, jid='', name='', groups=[], show='', status='', sub='', @@ -52,20 +50,6 @@ class Contact: self.chatstate = chatstate self.last_status_time = last_status_time - # XEP-0201 -# self.sessions = {} - -# def new_session(self): -# thread_id = "".join([random.choice(string.letters) for x in xrange(0,32)]) -# self.sessions[self.get_full_jid()] = thread_id -# return thread_id - -# def get_session(self): -# try: -# return self.sessions[self.get_full_jid()] -# except KeyError: -# return None - def get_full_jid(self): if self.resource: return self.jid + '/' + self.resource @@ -169,7 +153,7 @@ class Contacts: return Contact(jid, name, groups, show, status, sub, ask, resource, priority, keyID, our_chatstate, chatstate, last_status_time, composing_jep) - + def copy_contact(self, contact): return self.create_contact(jid = contact.jid, name = contact.name, groups = contact.groups, show = contact.show, status = contact.status, diff --git a/src/common/helpers.py b/src/common/helpers.py index 60252e6bf..12388bf81 100644 --- a/src/common/helpers.py +++ b/src/common/helpers.py @@ -820,7 +820,7 @@ def allow_sound_notification(sound_event, advanced_notif_num = None): return True return False -def get_chat_control(account, contact, session): +def get_chat_control(account, contact): full_jid_with_resource = contact.jid if contact.resource: full_jid_with_resource += '/' + contact.resource @@ -829,16 +829,16 @@ def get_chat_control(account, contact, session): # Look for a chat control that has the given resource, or default to # one without resource ctrl = gajim.interface.msg_win_mgr.get_control(full_jid_with_resource, - account, session.thread_id) + account) if ctrl: return ctrl elif not highest_contact or not highest_contact.resource: # unknow contact or offline message - return gajim.interface.msg_win_mgr.get_control(contact.jid, account, session.thread_id) + return gajim.interface.msg_win_mgr.get_control(contact.jid, account) elif highest_contact and contact.resource != \ highest_contact.resource: return None - return gajim.interface.msg_win_mgr.get_control(contact.jid, account, session.thread_id) + return gajim.interface.msg_win_mgr.get_control(contact.jid, account) def reduce_chars_newlines(text, max_chars = 0, max_lines = 0): '''Cut the chars after 'max_chars' on each line diff --git a/src/dialogs.py b/src/dialogs.py index 526e6b95b..e76ac7dda 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -196,7 +196,7 @@ class EditGroupsDialog: for group in groups: if group not in helpers.special_groups or groups[group] > 0: group_list.append(group) - group_list.sort() + group_list.sort() for group in group_list: iter = store.append() store.set(iter, 0, group) # Group name @@ -2099,7 +2099,7 @@ class PrivacyListWindow: jid_entry_completion.set_text_column(0) jid_entry_completion.set_model(jids_list_store) jid_entry_completion.set_popup_completion(True) - self.edit_type_jabberid_entry.set_completion(jid_entry_completion) + self.edit_type_jabberid_entry.set_completion(jid_entry_completion) if action == 'EDIT': self.refresh_rules() diff --git a/src/gajim.py b/src/gajim.py index 5c13131e1..5309be946 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -443,9 +443,9 @@ class Interface: (jid_from, file_props)) conn.disconnect_transfer(file_props) return - for ctrl in self.msg_win_mgr.get_controls(jid=jid_from, acct=account): - if ctrl and ctrl.type_id == message_control.TYPE_GC: - ctrl.print_conversation('Error %s: %s' % (array[2], array[1])) + 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])) def handle_event_con_type(self, account, con_type): # ('CON_TYPE', account, con_type) which can be 'ssl', 'tls', 'tcp' @@ -663,7 +663,7 @@ class Interface: # It's maybe a GC_NOTIFY (specialy for MSN gc) self.handle_event_gc_notify(account, (jid, array[1], status_message, array[3], None, None, None, None, None, None, None, None)) - + def handle_event_msg(self, account, array): # 'MSG' (account, (jid, msg, time, encrypted, msg_type, subject, @@ -688,7 +688,7 @@ class Interface: if gajim.jid_is_transport(jid): jid = jid.replace('@', '') - groupchat_control = self.msg_win_mgr.get_control(jid, account, session.thread_id) + groupchat_control = self.msg_win_mgr.get_control(jid, account) if not groupchat_control and \ gajim.interface.minimized_controls.has_key(account) and \ jid in gajim.interface.minimized_controls[account]: @@ -700,29 +700,28 @@ class Interface: pm = True msg_type = 'pm' -# chat_control = None -# jid_of_control = full_jid_with_resource + chat_control = None + jid_of_control = full_jid_with_resource highest_contact = gajim.contacts.get_contact_with_highest_priority( account, jid) # Look for a chat control that has the given resource, or default to one # without resource - chat_control = session.get_control() -# ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account, session.thread_id) -# if ctrl: -# chat_control = ctrl -# elif not pm and (not highest_contact or not highest_contact.resource): + ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account) + if ctrl: + chat_control = ctrl + elif not pm and (not highest_contact or not highest_contact.resource): # unknow contact or offline message -# jid_of_control = jid -# chat_control = self.msg_win_mgr.get_control(jid, account, session.thread_id) -# elif highest_contact and resource != highest_contact.resource and \ -# highest_contact.show != 'offline': -# jid_of_control = full_jid_with_resource -# chat_control = None -# elif not pm: -# jid_of_control = jid -# chat_control = self.msg_win_mgr.get_control(jid, account, session.thread_id) + jid_of_control = jid + chat_control = self.msg_win_mgr.get_control(jid, account) + elif highest_contact and resource != highest_contact.resource and \ + highest_contact.show != 'offline': + jid_of_control = full_jid_with_resource + chat_control = None + elif not pm: + jid_of_control = jid + chat_control = self.msg_win_mgr.get_control(jid, account) - # Handle chat states + # Handle chat states contact = gajim.contacts.get_contact(account, jid, resource) if contact and isinstance(contact, list): contact = contact[0] @@ -740,7 +739,7 @@ class Interface: # got no valid jep85 answer, peer does not support it contact.chatstate = False elif chatstate == 'active': - # Brand new message, incoming. + # Brand new message, incoming. contact.our_chatstate = chatstate contact.chatstate = chatstate if msg_id: # Do not overwrite an existing msg_id with None @@ -754,12 +753,10 @@ class Interface: if gajim.config.get('ignore_unknown_contacts') and \ not gajim.contacts.get_contact(account, jid) and not pm: return - if not contact: # contact is not in the roster, create a fake one to display # notification - contact = common.contacts.Contact(jid = jid, resource = resource) - + contact = common.contacts.Contact(jid = jid, resource = resource) advanced_notif_num = notify.get_advanced_notification('message_received', account, contact) @@ -768,8 +765,8 @@ class Interface: if msg_type == 'normal': if not gajim.events.get_events(account, jid, ['normal']): first = True - elif not chat_control and not gajim.events.get_events(account, - full_jid_with_resource, [msg_type]): # msg_type can be chat or pm + elif not chat_control and not gajim.events.get_events(account, + jid_of_control, [msg_type]): # msg_type can be chat or pm first = True if pm: @@ -788,12 +785,11 @@ class Interface: msg_type, subject, resource, msg_id, array[9], advanced_notif_num, xhtml = xhtml, session = session) nickname = gajim.get_name_from_jid(account, jid) - # Check and do wanted notifications msg = message if subject: msg = _('Subject: %s') % subject + '\n' + msg - notify.notify('new_message', full_jid_with_resource, account, [msg_type, + notify.notify('new_message', jid_of_control, account, [msg_type, first, nickname, msg], advanced_notif_num) if self.remote_ctrl: @@ -990,7 +986,7 @@ class Interface: resource = '' if vcard.has_key('resource'): resource = vcard['resource'] - + # vcard window win = None if self.instances[account]['infos'].has_key(jid): @@ -1012,14 +1008,11 @@ class Interface: elif self.msg_win_mgr.has_window(jid, account): win = self.msg_win_mgr.get_window(jid, account) ctrl = win.get_control(jid, account) - - for ctrl in self.msg_win_mgr.get_controls(jid=jid, acct=account): - if ctrl.type_id != message_control.TYPE_GC: - ctrl.show_avatar() + if win and 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) - # XXX get_gc_control? if gc_ctrl and gc_ctrl.type_id == message_control.TYPE_GC: gc_ctrl.draw_avatar(resource) else: @@ -1668,17 +1661,18 @@ class Interface: # XXX check if we can autoaccept if form.getType() == 'form': - ctrl = session.get_control() -# ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account) -# if not ctrl: -# resource = jid.getResource() -# contact = gajim.contacts.get_contact(account, str(jid), resource) -# if not contact: -# connection = gajim.connections[account] -# contact = gajim.contacts.create_contact(jid = jid.getStripped(), resource = resource, show = connection.get_status()) -# self.roster.new_chat(contact, account, resource = resource) + ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account) + if not ctrl: + resource = jid.getResource() + contact = gajim.contacts.get_contact(account, str(jid), resource) + if not contact: + connection = gajim.connections[account] + contact = gajim.contacts.create_contact(jid = jid.getStripped(), resource = resource, show = connection.get_status()) + self.roster.new_chat(contact, account, resource = resource) -# ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account) + ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account) + + ctrl.set_session(session) negotiation.FeatureNegotiationWindow(account, jid, session, form) diff --git a/src/message_control.py b/src/message_control.py index c0b409b11..6835ddb32 100644 --- a/src/message_control.py +++ b/src/message_control.py @@ -110,6 +110,13 @@ class MessageControl: def get_specific_unread(self): return len(gajim.events.get_events(self.account, self.contact.jid)) + def set_session(self, session): + if session == self.session: + return + if self.session: + print "starting a new session, forgetting about the old one!" + self.session = session + def send_message(self, message, keyID = '', type = 'chat', chatstate = None, msg_id = None, composing_jep = None, resource = None, user_nick = None): diff --git a/src/message_window.py b/src/message_window.py index 87e9a204f..6445495be 100644 --- a/src/message_window.py +++ b/src/message_window.py @@ -123,9 +123,8 @@ class MessageWindow: def get_num_controls(self): n = 0 - for sess_dict in self._controls.values(): - for dict in sess_dict.values(): - n += len(dict) + for dict in self._controls.values(): + n += len(dict) return n def _on_window_focus(self, widget, event): @@ -166,9 +165,7 @@ class MessageWindow: if not self._controls.has_key(control.account): self._controls[control.account] = {} fjid = control.get_full_jid() - if not self._controls.has_key(fjid): - self._controls[control.account][fjid] = {} - self._controls[control.account][fjid][control.session.thread_id] = control + self._controls[control.account][fjid] = control if self.get_num_controls() == 2: # is first conversation_textview scrolled down ? @@ -295,11 +292,11 @@ class MessageWindow: else: gtkgui_helpers.set_unset_urgency_hint(self.window, False) - def set_active_tab(self, jid, acct, thread_id): - ctrl = self._controls[acct][jid][thread_id] + def set_active_tab(self, jid, acct): + ctrl = self._controls[acct][jid] ctrl_page = self.notebook.page_num(ctrl.widget) self.notebook.set_current_page(ctrl_page) - + def remove_tab(self, ctrl, method, reason = None, force = False): '''reason is only for gc (offline status message) if force is True, do not ask any confirmation''' @@ -320,9 +317,7 @@ class MessageWindow: self.notebook.remove_page(self.notebook.page_num(ctrl.widget)) fjid = ctrl.get_full_jid() - del self._controls[ctrl.account][fjid][ctrl.session.thread_id] - if len(self._controls[ctrl.account][fjid]) == 0: - del self._controls[ctrl.account][fjid] + del self._controls[ctrl.account][fjid] if len(self._controls[ctrl.account]) == 0: del self._controls[ctrl.account] @@ -420,19 +415,7 @@ class MessageWindow: for ctrl in self.controls(): ctrl.update_tags() - def has_control(self, jid, acct, thread_id = None): - try: - if thread_id: - return (thread_id in self._controls[acct][jid]) - else: - return (jid in self._controls[acct]) - except KeyError: - return False - - def get_controls(self, jid, acct): - return self._controls[acct][jid].values() - - def get_control(self, key, acct, thread_id): + def get_control(self, key, acct): '''Return the MessageControl for jid or n, where n is a notebook page index. When key is an int index acct may be None''' if isinstance(key, str): @@ -441,7 +424,7 @@ class MessageWindow: if isinstance(key, unicode): jid = key try: - return self._controls[acct][jid][thread_id] + return self._controls[acct][jid] except: return None else: @@ -453,10 +436,9 @@ class MessageWindow: return self._widget_to_control(nth_child) def controls(self): - for jid_dict in self._controls.values(): - for sess_dict in jid_dict.values(): - for ctrl in sess_dict.values(): - yield ctrl + for ctrl_dict in self._controls.values(): + for ctrl in ctrl_dict.values(): + yield ctrl def move_to_next_unread_tab(self, forward): ind = self.notebook.get_current_page() @@ -513,7 +495,7 @@ class MessageWindow: if old_no >= 0: old_ctrl = self._widget_to_control(notebook.get_nth_page(old_no)) old_ctrl.set_control_active(False) - + new_ctrl = self._widget_to_control(notebook.get_nth_page(page_num)) new_ctrl.set_control_active(True) self.show_title(control = new_ctrl) @@ -587,11 +569,11 @@ class MessageWindow: source_child = self.notebook.get_nth_page(source_page_num) if dest_page_num != source_page_num: self.notebook.reorder_child(source_child, dest_page_num) - + def get_tab_at_xy(self, x, y): '''Thanks to Gaim Return the tab under xy and - if its nearer from left or right side of the tab + if its nearer from left or right side of the tab ''' page_num = -1 to_right = False @@ -612,7 +594,7 @@ class MessageWindow: if (y >= tab_alloc.y) and \ (y <= (tab_alloc.y + tab_alloc.height)): page_num = i - + if y > tab_alloc.y + (tab_alloc.height / 2.0): to_right = True break @@ -677,22 +659,14 @@ class MessageWindowMgr: return w return None - def get_window(self, jid, acct, thread_id): + def get_window(self, jid, acct): for win in self.windows(): - if win.has_control(jid, acct, thread_id): + if win.get_control(jid, acct): return win return None - def get_windows(self, jid, acct): - for win in self.windows(): - if win.has_control(jid, acct): - yield win - - def has_window(self, jid, acct, thread_id = None): - for win in self.windows(): - if win.has_control(jid, acct, thread_id): - return True - return False + def has_window(self, jid, acct): + return self.get_window(jid, acct) != None def one_window_opened(self, contact, acct, type): try: @@ -704,7 +678,7 @@ class MessageWindowMgr: '''Resizes window according to config settings''' if not gajim.config.get('saveposition'): return - + if self.mode == self.ONE_MSG_WINDOW_ALWAYS: size = (gajim.config.get('msgwin-width'), gajim.config.get('msgwin-height')) @@ -721,7 +695,7 @@ class MessageWindowMgr: return gtkgui_helpers.resize_window(win.window, size[0], size[1]) - + def _position_window(self, win, acct, type): '''Moves window according to config settings''' if not gajim.config.get('saveposition') or\ @@ -799,20 +773,18 @@ class MessageWindowMgr: del self._windows[k] return - def get_control(self, jid, acct, thread_id): + def get_control(self, jid, acct): '''Amongst all windows, return the MessageControl for jid''' - win = self.get_window(jid, acct, thread_id) + win = self.get_window(jid, acct) if win: - return win.get_control(jid, acct, thread_id) + return win.get_control(jid, acct) return None - def get_controls(self, type = None, acct = None, jid = None): + def get_controls(self, type = None, acct = None): ctrls = [] for c in self.controls(): if acct and c.account != acct: continue - if jid and c.get_full_jid() != jid: - continue if not type or c.type_id == type: ctrls.append(c) return ctrls @@ -836,7 +808,7 @@ class MessageWindowMgr: def save_state(self, msg_win): if not gajim.config.get('saveposition'): return - + # Save window size and position pos_x_key = 'msgwin-x-position' pos_y_key = 'msgwin-y-position' @@ -871,11 +843,11 @@ class MessageWindowMgr: if self.mode != self.ONE_MSG_WINDOW_NEVER: gajim.config.set_per('accounts', acct, pos_x_key, x) gajim.config.set_per('accounts', acct, pos_y_key, y) - + else: gajim.config.set(size_width_key, width) gajim.config.set(size_height_key, height) - + if self.mode != self.ONE_MSG_WINDOW_NEVER: gajim.config.set(pos_x_key, x) gajim.config.set(pos_y_key, y) diff --git a/src/notify.py b/src/notify.py index 8dda70f69..66b130791 100644 --- a/src/notify.py +++ b/src/notify.py @@ -40,7 +40,7 @@ try: except ImportError: USER_HAS_PYNOTIFY = False -def get_show_in_roster(event, account, contact, session): +def get_show_in_roster(event, account, contact): '''Return True if this event must be shown in roster, else False''' if event == 'gc_message_received': return True @@ -51,7 +51,7 @@ def get_show_in_roster(event, account, contact, session): if gajim.config.get_per('notifications', str(num), 'roster') == 'no': return False if event == 'message_received': - chat_control = helpers.get_chat_control(account, contact, session) + chat_control = helpers.get_chat_control(account, contact) if chat_control: return False return True diff --git a/src/roster_window.py b/src/roster_window.py index 139facee8..f9e85debc 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -1191,9 +1191,8 @@ class RosterWindow: for jid in gajim.contacts.get_jid_list(account): results = gajim.logger.get_unread_msgs_for_jid(jid) - # XXX results should contain sessions anyways + # XXX unread messages should probably have their session with them session = gajim.connections[account].make_new_session(jid) - for result in results: tim = time.localtime(float(result[2])) self.on_message(jid, result[1], tim, account, msg_type = 'chat', @@ -1259,8 +1258,8 @@ class RosterWindow: gajim.transport_avatar[account][host].append(contact1.jid) # If we already have a chat window opened, update it with new contact # instance - chat_controls = gajim.interface.msg_win_mgr.get_controls(jid=ji, acct=account) - for chat_control in chat_controls: + chat_control = gajim.interface.msg_win_mgr.get_control(ji, account) + if chat_control: chat_control.contact = contact1 def chg_contact_status(self, contact, show, status, account): @@ -1287,14 +1286,14 @@ class RosterWindow: jid_list = [contact.jid] for jid in jid_list: if gajim.interface.msg_win_mgr.has_window(jid, account): - for win in gajim.interface.msg_win_mgr.get_windows(jid, account): - for ctrl in win.get_controls(jid=jid, acct=account): - ctrl.contact = gajim.contacts.get_contact_with_highest_priority( - account, contact.jid) - ctrl.update_ui() - win.redraw_tab(ctrl) + win = gajim.interface.msg_win_mgr.get_window(jid, account) + ctrl = win.get_control(jid, account) + ctrl.contact = gajim.contacts.get_contact_with_highest_priority( + account, contact.jid) + ctrl.update_ui() + win.redraw_tab(ctrl) - name = contact.get_shown_name() + name = contact.get_shown_name() # if multiple resources (or second one disconnecting) if (len(contact_instances) > 1 or (len(contact_instances) == 1 and \ @@ -3492,7 +3491,7 @@ class RosterWindow: if not session: session = gajim.connections[account].make_new_session(fjid) - mw = gajim.interface.msg_win_mgr.get_window(fjid, account, session.thread_id) + mw = gajim.interface.msg_win_mgr.get_window(fjid, account) if not mw: mw = gajim.interface.msg_win_mgr.create_window(contact, account, type_) @@ -3504,8 +3503,6 @@ class RosterWindow: # We call this here to avoid race conditions with widget validation chat_control.read_queue() - return session - def new_chat_from_jid(self, account, fjid): jid, resource = gajim.get_room_and_nick_from_fjid(fjid) if resource: @@ -3579,18 +3576,16 @@ class RosterWindow: path = self.get_path(jid, account) # Try to get line of contact in roster - ctrl = session.get_control(advanced_notif_num) - # Look for a chat control that has the given resource -# ctrl = gajim.interface.msg_win_mgr.get_control(fjid, account) -# if not ctrl: + ctrl = gajim.interface.msg_win_mgr.get_control(fjid, account) + if not ctrl: # if not, if message comes from highest prio, get control or open one # without resource -# if highest_contact and contact.resource == highest_contact.resource \ -# and not jid == gajim.get_jid_from_account(account): -# ctrl = gajim.interface.msg_win_mgr.get_control(jid, account) -# fjid = jid -# resource_for_chat = None + if highest_contact and contact.resource == highest_contact.resource \ + and not jid == gajim.get_jid_from_account(account): + ctrl = gajim.interface.msg_win_mgr.get_control(jid, account) + fjid = jid + resource_for_chat = None # Do we have a queue? no_queue = len(gajim.events.get_events(account, fjid)) == 0 @@ -3608,6 +3603,8 @@ class RosterWindow: typ = '' if msg_type == 'error': typ = 'status' + if session: + ctrl.set_session(session) ctrl.print_conversation(msg, typ, tim = tim, encrypted = encrypted, subject = subject, xhtml = xhtml) if msg_id: @@ -3620,26 +3617,26 @@ class RosterWindow: if msg_type == 'normal': type_ = 'normal' event_type = 'single_message_received' - show_in_roster = notify.get_show_in_roster(event_type, account, contact, session) + show_in_roster = notify.get_show_in_roster(event_type, account, contact) show_in_systray = notify.get_show_in_systray(event_type, account, contact) event = gajim.events.create_event(type_, (msg, subject, msg_type, tim, encrypted, resource, msg_id, xhtml, session), show_in_roster = show_in_roster, show_in_systray = show_in_systray) gajim.events.add_event(account, fjid, event) -# if popup: -# if not ctrl: -# self.new_chat(contact, account, resource = resource_for_chat) -# if path and not self.dragging and gajim.config.get( -# 'scroll_roster_to_last_message'): -# # we curently see contact in our roster OR he -# # is not in the roster at all. + if popup: + if not ctrl: + self.new_chat(contact, account, resource = resource_for_chat) + if path and not self.dragging and gajim.config.get( + 'scroll_roster_to_last_message'): + # we curently see contact in our roster OR he + # is not in the roster at all. # show and select his line in roster # do not change selection while DND'ing -# self.tree.expand_row(path[0:1], False) -# self.tree.expand_row(path[0:2], False) -# self.tree.scroll_to_cell(path) -# self.tree.set_cursor(path) - if not popup: + self.tree.expand_row(path[0:1], False) + self.tree.expand_row(path[0:2], False) + self.tree.scroll_to_cell(path) + self.tree.set_cursor(path) + else: if no_queue: # We didn't have a queue: we change icons self.draw_contact(jid, account) self.show_title() # we show the * or [n] @@ -3927,17 +3924,17 @@ class RosterWindow: fjid = contact.jid if resource: fjid += '/' + resource - - session = self.new_chat(contact, account, resource=resource, session=session) - win = gajim.interface.msg_win_mgr.get_window(fjid, account, session.thread_id) - ctrl = win.get_control(fjid, account, session.thread_id) - # last message is long time ago - gajim.last_message_time[account][ctrl.get_full_jid()] = 0 - - win.set_active_tab(fjid, account, session.thread_id) + win = gajim.interface.msg_win_mgr.get_window(fjid, account) + if not win: + self.new_chat(contact, account, resource = resource, session = session) + win = gajim.interface.msg_win_mgr.get_window(fjid, account) + ctrl = win.get_control(fjid, account) + # last message is long time ago + gajim.last_message_time[account][ctrl.get_full_jid()] = 0 + win.set_active_tab(fjid, account) if gajim.connections[account].is_zeroconf and \ gajim.connections[account].status in ('offline', 'invisible'): - win.get_control(fjid, account, session.thread_id).got_disconnected() + win.get_control(fjid, account).got_disconnected() win.window.present() @@ -3977,7 +3974,6 @@ class RosterWindow: jid = child_jid else: child_iter = model.iter_next(child_iter) - session = None if first_ev: session = first_ev.parameters[8] @@ -3991,7 +3987,7 @@ class RosterWindow: c = gajim.contacts.get_contact_with_highest_priority(account, jid) if jid == gajim.get_jid_from_account(account): resource = c.resource - self.on_open_chat_window(widget, c, account, resource = resource, session=session) + self.on_open_chat_window(widget, c, account, resource = resource, session = session) def on_roster_treeview_row_activated(self, widget, path, col = 0): '''When an iter is double clicked: open the first event window'''