massive everything-breaking overhaul for per-session windows

This commit is contained in:
Brendan Taylor 2007-06-05 21:26:45 +00:00
parent d696f79c55
commit 17c5bf5e52
13 changed files with 319 additions and 188 deletions

View file

@ -577,7 +577,7 @@ class ChatControlBase(MessageControl):
type_ = 'printed_' + self.type_id type_ = 'printed_' + self.type_id
event = 'message_received' event = 'message_received'
show_in_roster = notify.get_show_in_roster(event, show_in_roster = notify.get_show_in_roster(event,
self.account, self.contact) self.account, self.contact, self.session)
show_in_systray = notify.get_show_in_systray(event, show_in_systray = notify.get_show_in_systray(event,
self.account, self.contact) self.account, self.contact)
if gc_message: if gc_message:
@ -606,7 +606,7 @@ class ChatControlBase(MessageControl):
not self.parent_win.is_active() or not end) and \ not self.parent_win.is_active() or not end) and \
kind in ('incoming', 'incoming_queue'): kind in ('incoming', 'incoming_queue'):
self.parent_win.redraw_tab(self) self.parent_win.redraw_tab(self)
ctrl = gajim.interface.msg_win_mgr.get_control(full_jid, self.account) ctrl = gajim.interface.msg_win_mgr.get_control(full_jid, self.account, self.session.thread_id)
if not self.parent_win.is_active(): if not self.parent_win.is_active():
self.parent_win.show_title(True, ctrl) # Enabled Urgent hint self.parent_win.show_title(True, ctrl) # Enabled Urgent hint
else: else:
@ -905,7 +905,7 @@ class ChatControl(ChatControlBase):
old_msg_kind = None # last kind of the printed message old_msg_kind = None # last kind of the printed message
CHAT_CMDS = ['clear', 'compact', 'help', 'ping'] CHAT_CMDS = ['clear', 'compact', 'help', 'ping']
def __init__(self, parent_win, contact, acct, resource = None): def __init__(self, parent_win, contact, acct, session, resource = None):
ChatControlBase.__init__(self, self.TYPE_ID, parent_win, ChatControlBase.__init__(self, self.TYPE_ID, parent_win,
'chat_child_vbox', contact, acct, resource) 'chat_child_vbox', contact, acct, resource)
@ -970,6 +970,8 @@ class ChatControl(ChatControlBase):
if self.contact.jid in gajim.encrypted_chats[self.account]: if self.contact.jid in gajim.encrypted_chats[self.account]:
self.xml.get_widget('gpg_togglebutton').set_active(True) self.xml.get_widget('gpg_togglebutton').set_active(True)
self.session = session
self.status_tooltip = gtk.Tooltips() self.status_tooltip = gtk.Tooltips()
self.update_ui() self.update_ui()
# restore previous conversation # restore previous conversation
@ -1797,7 +1799,7 @@ class ChatControl(ChatControlBase):
# Is it a pm ? # Is it a pm ?
is_pm = False is_pm = False
room_jid, nick = gajim.get_room_and_nick_from_fjid(jid) room_jid, nick = gajim.get_room_and_nick_from_fjid(jid)
control = gajim.interface.msg_win_mgr.get_control(room_jid, self.account) control = gajim.interface.msg_win_mgr.get_control(room_jid, self.account, self.session.thread_id)
if control and control.type_id == message_control.TYPE_GC: if control and control.type_id == message_control.TYPE_GC:
is_pm = True is_pm = True
# list of message ids which should be marked as read # list of message ids which should be marked as read
@ -1815,9 +1817,6 @@ class ChatControl(ChatControlBase):
encrypted = data[4], subject = data[1], xhtml = data[7]) encrypted = data[4], subject = data[1], xhtml = data[7])
if len(data) > 6 and isinstance(data[6], int): if len(data) > 6 and isinstance(data[6], int):
message_ids.append(data[6]) message_ids.append(data[6])
if len(data) > 8:
self.set_thread_id(data[8])
if message_ids: if message_ids:
gajim.logger.set_read_messages(message_ids) gajim.logger.set_read_messages(message_ids)
gajim.events.remove_events(self.account, jid_with_resource, gajim.events.remove_events(self.account, jid_with_resource,

View file

@ -48,6 +48,8 @@ log = logging.getLogger('gajim.c.connection')
import gtkgui_helpers import gtkgui_helpers
import time
class Connection(ConnectionHandlers): class Connection(ConnectionHandlers):
'''Connection class''' '''Connection class'''
def __init__(self, name): def __init__(self, name):
@ -839,7 +841,7 @@ class Connection(ConnectionHandlers):
def send_message(self, jid, msg, keyID, type = 'chat', subject='', def send_message(self, jid, msg, keyID, type = 'chat', subject='',
chatstate = None, msg_id = None, composing_jep = None, resource = None, chatstate = None, msg_id = None, composing_jep = None, resource = None,
user_nick = None, xhtml = None, thread = None): user_nick = None, xhtml = None, session = None):
if not self.connection: if not self.connection:
return 1 return 1
if msg and not xhtml and gajim.config.get('rst_formatting_outgoing_messages'): if msg and not xhtml and gajim.config.get('rst_formatting_outgoing_messages'):
@ -884,8 +886,10 @@ class Connection(ConnectionHandlers):
msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc) msg_iq.setTag(common.xmpp.NS_ENCRYPTED + ' x').setData(msgenc)
# XEP-0201 # XEP-0201
if thread: if session:
msg_iq.setTag("thread").setData(thread) session.last_send = time.time()
if session.thread_id:
msg_iq.setThread(session.thread_id)
# JEP-0172: user_nickname # JEP-0172: user_nickname
if user_nick: if user_nick:

View file

@ -37,6 +37,8 @@ from common import atom
from common.commands import ConnectionCommands from common.commands import ConnectionCommands
from common.pubsub import ConnectionPubSub from common.pubsub import ConnectionPubSub
from common.stanza_session import StanzaSession
STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd', STATUS_LIST = ['offline', 'connecting', 'online', 'chat', 'away', 'xa', 'dnd',
'invisible', 'error'] 'invisible', 'error']
# kind of events we can wait for an answer # kind of events we can wait for an answer
@ -1171,6 +1173,10 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
# 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 # acknoledge presences
self.subscribed_events = {} self.subscribed_events = {}
# keep track of sessions this connection has with other JIDs
self.sessions = {}
try: try:
idle.init() idle.init()
except: except:
@ -1197,13 +1203,13 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
self.dispatch('HTTP_AUTH', (method, url, id, iq_obj, msg)); self.dispatch('HTTP_AUTH', (method, url, id, iq_obj, msg));
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
def _FeatureNegCB(self, con, stanza): def _FeatureNegCB(self, con, stanza, session):
gajim.log.debug('FeatureNegCB') gajim.log.debug('FeatureNegCB')
feature = stanza.getTag('feature') feature = stanza.getTag('feature')
form = common.xmpp.DataForm(node=feature.getTag('x')) form = common.xmpp.DataForm(node=feature.getTag('x'))
if form['FORM_TYPE'] == 'urn:xmpp:ssn': 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: else:
reply = stanza.buildReply() reply = stanza.buildReply()
reply.setType('error') reply.setType('error')
@ -1410,6 +1416,17 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
def _messageCB(self, con, msg): def _messageCB(self, con, msg):
'''Called when we receive a message''' '''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 # check if the message is pubsub#event
if msg.getTag('event') is not None: if msg.getTag('event') is not None:
self._pubsubEventCB(con, msg) self._pubsubEventCB(con, msg)
@ -1421,18 +1438,15 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
return return
if msg.getTag('feature') and msg.getTag('feature').namespace == \ if msg.getTag('feature') and msg.getTag('feature').namespace == \
common.xmpp.NS_FEATURE: common.xmpp.NS_FEATURE:
self._FeatureNegCB(con, msg) self._FeatureNegCB(con, msg, session)
return return
msgtxt = msg.getBody() msgtxt = msg.getBody()
msghtml = msg.getXHTML() msghtml = msg.getXHTML()
mtype = msg.getType()
subject = msg.getSubject() # if not there, it's None subject = msg.getSubject() # if not there, it's None
thread = msg.getThread()
tim = msg.getTimestamp() tim = msg.getTimestamp()
tim = time.strptime(tim, '%Y%m%dT%H:%M:%S') tim = time.strptime(tim, '%Y%m%dT%H:%M:%S')
tim = time.localtime(timegm(tim)) tim = time.localtime(timegm(tim))
frm = helpers.get_full_jid_from_iq(msg)
jid = helpers.get_jid_from_iq(msg) jid = helpers.get_jid_from_iq(msg)
no_log_for = gajim.config.get_per('accounts', self.name, no_log_for = gajim.config.get_per('accounts', self.name,
'no_log_for') 'no_log_for')
@ -1541,13 +1555,42 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
gajim.logger.write('single_msg_recv', frm, msgtxt, tim = tim, gajim.logger.write('single_msg_recv', frm, msgtxt, tim = tim,
subject = subject) subject = subject)
mtype = 'normal' mtype = 'normal'
treat_as = gajim.config.get('treat_incoming_messages') treat_as = gajim.config.get('treat_incoming_messages')
if treat_as: if treat_as:
mtype = treat_as mtype = treat_as
self.dispatch('MSG', (frm, msgtxt, tim, encrypted, mtype, 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 # END messageCB
def get_session(self, jid, thread_id, type):
'''returns an existing session between this connection and 'jid' or starts a new one.'''
try:
if type == 'chat' and not thread_id:
return self.find_null_session(jid)
else:
return self.sessions[jid][thread_id]
except KeyError:
return self.make_new_session(jid, thread_id, type)
def find_null_session(self, jid):
'''returns the session between this connecting and 'jid' that we last sent a message in.'''
all = self.sessions[jid].values()
null_sessions = filter(lambda s: not s.received_thread_id, all)
null_sessions.sort(key=lambda s: s.last_send)
return null_sessions[-1]
def make_new_session(self, jid, thread_id = None, type = 'chat'):
sess = StanzaSession(self, jid, thread_id, type)
if not jid in self.sessions:
self.sessions[jid] = {}
self.sessions[jid][sess.thread_id] = sess
return sess
def _pubsubEventCB(self, con, msg): def _pubsubEventCB(self, con, msg):
''' Called when we receive <message/> with pubsub event. ''' ''' Called when we receive <message/> with pubsub event. '''
# TODO: Logging? (actually services where logging would be useful, should # TODO: Logging? (actually services where logging would be useful, should

View file

@ -16,7 +16,7 @@
import common.gajim import common.gajim
import random, string #import random, string
class Contact: class Contact:
'''Information concerning each contact''' '''Information concerning each contact'''
@ -53,18 +53,18 @@ class Contact:
self.last_status_time = last_status_time self.last_status_time = last_status_time
# XEP-0201 # XEP-0201
self.sessions = {} # self.sessions = {}
def new_session(self): # def new_session(self):
thread_id = "".join([random.choice(string.letters) for x in xrange(0,32)]) # thread_id = "".join([random.choice(string.letters) for x in xrange(0,32)])
self.sessions[self.get_full_jid()] = thread_id # self.sessions[self.get_full_jid()] = thread_id
return thread_id # return thread_id
def get_session(self): # def get_session(self):
try: # try:
return self.sessions[self.get_full_jid()] # return self.sessions[self.get_full_jid()]
except KeyError: # except KeyError:
return None # return None
def get_full_jid(self): def get_full_jid(self):
if self.resource: if self.resource:

View file

@ -820,7 +820,7 @@ def allow_sound_notification(sound_event, advanced_notif_num = None):
return True return True
return False return False
def get_chat_control(account, contact): def get_chat_control(account, contact, session):
full_jid_with_resource = contact.jid full_jid_with_resource = contact.jid
if contact.resource: if contact.resource:
full_jid_with_resource += '/' + contact.resource full_jid_with_resource += '/' + contact.resource
@ -829,16 +829,16 @@ def get_chat_control(account, contact):
# Look for a chat control that has the given resource, or default to # Look for a chat control that has the given resource, or default to
# one without resource # one without resource
ctrl = gajim.interface.msg_win_mgr.get_control(full_jid_with_resource, ctrl = gajim.interface.msg_win_mgr.get_control(full_jid_with_resource,
account) account, session.thread_id)
if ctrl: if ctrl:
return ctrl return ctrl
elif not highest_contact or not highest_contact.resource: elif not highest_contact or not highest_contact.resource:
# unknow contact or offline message # unknow contact or offline message
return gajim.interface.msg_win_mgr.get_control(contact.jid, account) return gajim.interface.msg_win_mgr.get_control(contact.jid, account, session.thread_id)
elif highest_contact and contact.resource != \ elif highest_contact and contact.resource != \
highest_contact.resource: highest_contact.resource:
return None return None
return gajim.interface.msg_win_mgr.get_control(contact.jid, account) return gajim.interface.msg_win_mgr.get_control(contact.jid, account, session.thread_id)
def reduce_chars_newlines(text, max_chars = 0, max_lines = 0): def reduce_chars_newlines(text, max_chars = 0, max_lines = 0):
'''Cut the chars after 'max_chars' on each line '''Cut the chars after 'max_chars' on each line

View file

@ -0,0 +1,51 @@
import gajim
from common import xmpp
from common import helpers
import random
import string
class StanzaSession:
def __init__(self, conn, jid, thread_id, type):
self.conn = conn
if isinstance(jid, str) or isinstance(jid, unicode):
self.jid = xmpp.JID(jid)
else:
self.jid = jid
self.type = type
if thread_id:
self.received_thread_id = True
self.thread_id = thread_id
else:
self.received_thread_id = False
if type == 'normal':
self.thread_id = None
else:
self.thread_id = self.generate_thread_id()
self.last_send = 0
def generate_thread_id(self):
return "".join([random.choice(string.letters) for x in xrange(0,32)])
def get_control(self, advanced_notif_num = None):
account = self.conn.name
highest_contact = gajim.contacts.get_contact_with_highest_priority(account, str(self.jid))
contact = gajim.contacts.get_contact(account, self.jid.getStripped(), self.jid.getResource())
if isinstance(contact, list):
# there was no resource (maybe we're reading unread messages after shutdown). just take the first one for now :/
contact = contact[0]
ctrl = gajim.interface.msg_win_mgr.get_control(str(self.jid), account, self.thread_id)
# if not ctrl:
# if highest_contact and contact.resource == highest_contact.resource and not str(self.jid) == gajim.get_jid_from_account(account):
# ctrl = gajim.interface.msg_win_mgr.get_control(self.jid.getStripped(), account, self.thread_id)
if not ctrl and helpers.allow_popup_window(account, advanced_notif_num):
gajim.new_chat(contact, account, resource = resource_for_chat, session = self)
return ctrl

View file

@ -1686,7 +1686,7 @@ class SingleMessageWindow:
or 'receive'. or 'receive'.
''' '''
def __init__(self, account, to = '', action = '', from_whom = '', def __init__(self, account, to = '', action = '', from_whom = '',
subject = '', message = '', resource = '', thread = None): subject = '', message = '', resource = '', session = None):
self.account = account self.account = account
self.action = action self.action = action
@ -1695,7 +1695,7 @@ class SingleMessageWindow:
self.to = to self.to = to
self.from_whom = from_whom self.from_whom = from_whom
self.resource = resource self.resource = resource
self.thread = thread self.session = session
self.xml = gtkgui_helpers.get_glade('single_message_window.glade') self.xml = gtkgui_helpers.get_glade('single_message_window.glade')
self.window = self.xml.get_widget('single_message_window') self.window = self.xml.get_widget('single_message_window')
@ -1897,7 +1897,7 @@ class SingleMessageWindow:
# FIXME: allow GPG message some day # FIXME: allow GPG message some day
gajim.connections[self.account].send_message(to_whom_jid, message, gajim.connections[self.account].send_message(to_whom_jid, message,
keyID = None, type = 'normal', subject=subject, thread = self.thread) keyID = None, type = 'normal', subject=subject, session = self.session)
self.subject_entry.set_text('') # we sent ok, clear the subject self.subject_entry.set_text('') # we sent ok, clear the subject
self.message_tv_buffer.set_text('') # we sent ok, clear the textview self.message_tv_buffer.set_text('') # we sent ok, clear the textview
@ -1914,7 +1914,7 @@ class SingleMessageWindow:
self.window.destroy() self.window.destroy()
SingleMessageWindow(self.account, to = self.from_whom, SingleMessageWindow(self.account, to = self.from_whom,
action = 'send', from_whom = self.from_whom, subject = self.subject, action = 'send', from_whom = self.from_whom, subject = self.subject,
message = self.message, thread = self.thread) message = self.message, session = self.session)
def on_send_and_close_button_clicked(self, widget): def on_send_and_close_button_clicked(self, widget):
self.send_single_message() self.send_single_message()
@ -2099,7 +2099,7 @@ class PrivacyListWindow:
jid_entry_completion.set_text_column(0) jid_entry_completion.set_text_column(0)
jid_entry_completion.set_model(jids_list_store) jid_entry_completion.set_model(jids_list_store)
jid_entry_completion.set_popup_completion(True) 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': if action == 'EDIT':
self.refresh_rules() self.refresh_rules()

View file

@ -443,9 +443,9 @@ class Interface:
(jid_from, file_props)) (jid_from, file_props))
conn.disconnect_transfer(file_props) conn.disconnect_transfer(file_props)
return return
ctrl = self.msg_win_mgr.get_control(jid_from, account) for ctrl in self.msg_win_mgr.get_controls(jid=jid_from, acct=account):
if ctrl and ctrl.type_id == message_control.TYPE_GC: if ctrl and ctrl.type_id == message_control.TYPE_GC:
ctrl.print_conversation('Error %s: %s' % (array[2], array[1])) ctrl.print_conversation('Error %s: %s' % (array[2], array[1]))
def handle_event_con_type(self, account, con_type): def handle_event_con_type(self, account, con_type):
# ('CON_TYPE', account, con_type) which can be 'ssl', 'tls', 'tcp' # ('CON_TYPE', account, con_type) which can be 'ssl', 'tls', 'tcp'
@ -667,7 +667,7 @@ class Interface:
def handle_event_msg(self, account, array): def handle_event_msg(self, account, array):
# 'MSG' (account, (jid, msg, time, encrypted, msg_type, subject, # 'MSG' (account, (jid, msg, time, encrypted, msg_type, subject,
# chatstate, msg_id, composing_jep, user_nick, xhtml, thread)) # chatstate, msg_id, composing_jep, user_nick, xhtml, session))
# user_nick is JEP-0172 # user_nick is JEP-0172
full_jid_with_resource = array[0] full_jid_with_resource = array[0]
@ -682,13 +682,13 @@ class Interface:
msg_id = array[7] msg_id = array[7]
composing_jep = array[8] composing_jep = array[8]
xhtml = array[10] xhtml = array[10]
thread = array[11] session = array[11]
if gajim.config.get('ignore_incoming_xhtml'): if gajim.config.get('ignore_incoming_xhtml'):
xhtml = None xhtml = None
if gajim.jid_is_transport(jid): if gajim.jid_is_transport(jid):
jid = jid.replace('@', '') jid = jid.replace('@', '')
groupchat_control = self.msg_win_mgr.get_control(jid, account) groupchat_control = self.msg_win_mgr.get_control(jid, account, session.thread_id)
if not groupchat_control and \ if not groupchat_control and \
gajim.interface.minimized_controls.has_key(account) and \ gajim.interface.minimized_controls.has_key(account) and \
jid in gajim.interface.minimized_controls[account]: jid in gajim.interface.minimized_controls[account]:
@ -700,26 +700,27 @@ class Interface:
pm = True pm = True
msg_type = 'pm' msg_type = 'pm'
chat_control = None # chat_control = None
jid_of_control = full_jid_with_resource # jid_of_control = full_jid_with_resource
highest_contact = gajim.contacts.get_contact_with_highest_priority( highest_contact = gajim.contacts.get_contact_with_highest_priority(
account, jid) account, jid)
# Look for a chat control that has the given resource, or default to one # Look for a chat control that has the given resource, or default to one
# without resource # without resource
ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account) chat_control = session.get_control()
if ctrl: # ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account, session.thread_id)
chat_control = ctrl # if ctrl:
elif not pm and (not highest_contact or not highest_contact.resource): # chat_control = ctrl
# elif not pm and (not highest_contact or not highest_contact.resource):
# unknow contact or offline message # unknow contact or offline message
jid_of_control = jid # jid_of_control = jid
chat_control = self.msg_win_mgr.get_control(jid, account) # chat_control = self.msg_win_mgr.get_control(jid, account, session.thread_id)
elif highest_contact and resource != highest_contact.resource and \ # elif highest_contact and resource != highest_contact.resource and \
highest_contact.show != 'offline': # highest_contact.show != 'offline':
jid_of_control = full_jid_with_resource # jid_of_control = full_jid_with_resource
chat_control = None # chat_control = None
elif not pm: # elif not pm:
jid_of_control = jid # jid_of_control = jid
chat_control = self.msg_win_mgr.get_control(jid, account) # chat_control = self.msg_win_mgr.get_control(jid, account, session.thread_id)
# Handle chat states # Handle chat states
contact = gajim.contacts.get_contact(account, jid, resource) contact = gajim.contacts.get_contact(account, jid, resource)
@ -753,10 +754,12 @@ class Interface:
if gajim.config.get('ignore_unknown_contacts') and \ if gajim.config.get('ignore_unknown_contacts') and \
not gajim.contacts.get_contact(account, jid) and not pm: not gajim.contacts.get_contact(account, jid) and not pm:
return return
if not contact: if not contact:
# contact is not in the roster, create a fake one to display # contact is not in the roster, create a fake one to display
# notification # 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', advanced_notif_num = notify.get_advanced_notification('message_received',
account, contact) account, contact)
@ -766,7 +769,7 @@ class Interface:
if not gajim.events.get_events(account, jid, ['normal']): if not gajim.events.get_events(account, jid, ['normal']):
first = True first = True
elif not chat_control and not gajim.events.get_events(account, elif not chat_control and not gajim.events.get_events(account,
jid_of_control, [msg_type]): # msg_type can be chat or pm full_jid_with_resource, [msg_type]): # msg_type can be chat or pm
first = True first = True
if pm: if pm:
@ -778,18 +781,19 @@ class Interface:
if encrypted: if encrypted:
self.roster.on_message(jid, message, array[2], account, array[3], self.roster.on_message(jid, message, array[2], account, array[3],
msg_type, subject, resource, msg_id, array[9], msg_type, subject, resource, msg_id, array[9],
advanced_notif_num, thread = thread) advanced_notif_num, session = session)
else: else:
# xhtml in last element # xhtml in last element
self.roster.on_message(jid, message, array[2], account, array[3], self.roster.on_message(jid, message, array[2], account, array[3],
msg_type, subject, resource, msg_id, array[9], msg_type, subject, resource, msg_id, array[9],
advanced_notif_num, xhtml = xhtml, thread = thread) advanced_notif_num, xhtml = xhtml, session = session)
nickname = gajim.get_name_from_jid(account, jid) nickname = gajim.get_name_from_jid(account, jid)
# Check and do wanted notifications # Check and do wanted notifications
msg = message msg = message
if subject: if subject:
msg = _('Subject: %s') % subject + '\n' + msg msg = _('Subject: %s') % subject + '\n' + msg
notify.notify('new_message', jid_of_control, account, [msg_type, notify.notify('new_message', full_jid_with_resource, account, [msg_type,
first, nickname, msg], advanced_notif_num) first, nickname, msg], advanced_notif_num)
if self.remote_ctrl: if self.remote_ctrl:
@ -1008,11 +1012,14 @@ class Interface:
elif self.msg_win_mgr.has_window(jid, account): elif self.msg_win_mgr.has_window(jid, account):
win = self.msg_win_mgr.get_window(jid, account) win = self.msg_win_mgr.get_window(jid, account)
ctrl = win.get_control(jid, account) ctrl = win.get_control(jid, account)
if win and ctrl.type_id != message_control.TYPE_GC:
ctrl.show_avatar() for ctrl in self.msg_win_mgr.get_controls(jid=jid, acct=account):
if ctrl.type_id != message_control.TYPE_GC:
ctrl.show_avatar()
# Show avatar in roster or gc_roster # Show avatar in roster or gc_roster
gc_ctrl = self.msg_win_mgr.get_control(jid, account) 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: if gc_ctrl and gc_ctrl.type_id == message_control.TYPE_GC:
gc_ctrl.draw_avatar(resource) gc_ctrl.draw_avatar(resource)
else: else:
@ -1656,25 +1663,24 @@ class Interface:
AtomWindow.newAtomEntry(atom_entry) AtomWindow.newAtomEntry(atom_entry)
def handle_session_negotiation(self, account, data): def handle_session_negotiation(self, account, data):
jid, thread_id, form = data jid, session, form = data
# XXX check negotiation state, etc. # XXX check negotiation state, etc.
# XXX check if we can autoaccept # XXX check if we can autoaccept
if form.getType() == 'form': if form.getType() == 'form':
ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account) ctrl = session.get_control()
if not ctrl: # ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account)
resource = jid.getResource() # if not ctrl:
contact = gajim.contacts.get_contact(account, str(jid), resource) # resource = jid.getResource()
if not contact: # contact = gajim.contacts.get_contact(account, str(jid), resource)
connection = gajim.connections[account] # if not contact:
contact = gajim.contacts.create_contact(jid = jid.getStripped(), resource = resource, show = connection.get_status()) # connection = gajim.connections[account]
self.roster.new_chat(contact, account, resource = resource) # 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_thread_id(thread_id) negotiation.FeatureNegotiationWindow(account, jid, session, form)
negotiation.FeatureNegotiationWindow(account, jid, thread_id, form)
def handle_event_privacy_lists_received(self, account, data): def handle_event_privacy_lists_received(self, account, data):
# ('PRIVACY_LISTS_RECEIVED', account, list) # ('PRIVACY_LISTS_RECEIVED', account, list)

View file

@ -37,8 +37,6 @@ class MessageControl:
self.hide_chat_buttons_current = False self.hide_chat_buttons_current = False
self.resource = resource self.resource = resource
self.thread_id = self.contact.get_session()
gajim.last_message_time[self.account][self.get_full_jid()] = 0 gajim.last_message_time[self.account][self.get_full_jid()] = 0
self.xml = gtkgui_helpers.get_glade('message_window.glade', widget_name) self.xml = gtkgui_helpers.get_glade('message_window.glade', widget_name)
@ -112,14 +110,6 @@ class MessageControl:
def get_specific_unread(self): def get_specific_unread(self):
return len(gajim.events.get_events(self.account, self.contact.jid)) return len(gajim.events.get_events(self.account, self.contact.jid))
def set_thread_id(self, thread_id):
if thread_id == self.thread_id:
return
if self.thread_id:
print "starting a new session, forgetting about the old one!"
self.thread_id = thread_id
self.contact.sessions[self.contact.get_full_jid()] = thread_id
def send_message(self, message, keyID = '', type = 'chat', def send_message(self, message, keyID = '', type = 'chat',
chatstate = None, msg_id = None, composing_jep = None, resource = None, chatstate = None, msg_id = None, composing_jep = None, resource = None,
user_nick = None): user_nick = None):
@ -127,11 +117,8 @@ class MessageControl:
''' '''
jid = self.contact.jid jid = self.contact.jid
if not self.thread_id:
self.thread_id = self.contact.new_session()
# Send and update history # Send and update history
return gajim.connections[self.account].send_message(jid, message, keyID, return gajim.connections[self.account].send_message(jid, message, keyID,
type = type, chatstate = chatstate, msg_id = msg_id, type = type, chatstate = chatstate, msg_id = msg_id,
composing_jep = composing_jep, resource = self.resource, composing_jep = composing_jep, resource = self.resource,
user_nick = user_nick, thread = self.thread_id) user_nick = user_nick, session = self.session)

View file

@ -123,8 +123,9 @@ class MessageWindow:
def get_num_controls(self): def get_num_controls(self):
n = 0 n = 0
for dict in self._controls.values(): for sess_dict in self._controls.values():
n += len(dict) for dict in sess_dict.values():
n += len(dict)
return n return n
def _on_window_focus(self, widget, event): def _on_window_focus(self, widget, event):
@ -165,7 +166,9 @@ class MessageWindow:
if not self._controls.has_key(control.account): if not self._controls.has_key(control.account):
self._controls[control.account] = {} self._controls[control.account] = {}
fjid = control.get_full_jid() fjid = control.get_full_jid()
self._controls[control.account][fjid] = control if not self._controls.has_key(fjid):
self._controls[control.account][fjid] = {}
self._controls[control.account][fjid][control.session.thread_id] = control
if self.get_num_controls() == 2: if self.get_num_controls() == 2:
# is first conversation_textview scrolled down ? # is first conversation_textview scrolled down ?
@ -292,8 +295,8 @@ class MessageWindow:
else: else:
gtkgui_helpers.set_unset_urgency_hint(self.window, False) gtkgui_helpers.set_unset_urgency_hint(self.window, False)
def set_active_tab(self, jid, acct): def set_active_tab(self, jid, acct, thread_id):
ctrl = self._controls[acct][jid] ctrl = self._controls[acct][jid][thread_id]
ctrl_page = self.notebook.page_num(ctrl.widget) ctrl_page = self.notebook.page_num(ctrl.widget)
self.notebook.set_current_page(ctrl_page) self.notebook.set_current_page(ctrl_page)
@ -317,7 +320,9 @@ class MessageWindow:
self.notebook.remove_page(self.notebook.page_num(ctrl.widget)) self.notebook.remove_page(self.notebook.page_num(ctrl.widget))
fjid = ctrl.get_full_jid() fjid = ctrl.get_full_jid()
del self._controls[ctrl.account][fjid] del self._controls[ctrl.account][fjid][ctrl.session.thread_id]
if len(self._controls[ctrl.account][fjid]) == 0:
del self._controls[ctrl.account][fjid]
if len(self._controls[ctrl.account]) == 0: if len(self._controls[ctrl.account]) == 0:
del self._controls[ctrl.account] del self._controls[ctrl.account]
@ -415,7 +420,19 @@ class MessageWindow:
for ctrl in self.controls(): for ctrl in self.controls():
ctrl.update_tags() ctrl.update_tags()
def get_control(self, key, acct): 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):
'''Return the MessageControl for jid or n, where n is a notebook page index. '''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 may be None'''
if isinstance(key, str): if isinstance(key, str):
@ -424,7 +441,7 @@ class MessageWindow:
if isinstance(key, unicode): if isinstance(key, unicode):
jid = key jid = key
try: try:
return self._controls[acct][jid] return self._controls[acct][jid][thread_id]
except: except:
return None return None
else: else:
@ -436,9 +453,10 @@ class MessageWindow:
return self._widget_to_control(nth_child) return self._widget_to_control(nth_child)
def controls(self): def controls(self):
for ctrl_dict in self._controls.values(): for jid_dict in self._controls.values():
for ctrl in ctrl_dict.values(): for sess_dict in jid_dict.values():
yield ctrl for ctrl in sess_dict.values():
yield ctrl
def move_to_next_unread_tab(self, forward): def move_to_next_unread_tab(self, forward):
ind = self.notebook.get_current_page() ind = self.notebook.get_current_page()
@ -659,14 +677,22 @@ class MessageWindowMgr:
return w return w
return None return None
def get_window(self, jid, acct): def get_window(self, jid, acct, thread_id):
for win in self.windows(): for win in self.windows():
if win.get_control(jid, acct): if win.has_control(jid, acct, thread_id):
return win return win
return None return None
def has_window(self, jid, acct): def get_windows(self, jid, acct):
return self.get_window(jid, acct) != None 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 one_window_opened(self, contact, acct, type): def one_window_opened(self, contact, acct, type):
try: try:
@ -773,18 +799,20 @@ class MessageWindowMgr:
del self._windows[k] del self._windows[k]
return return
def get_control(self, jid, acct): def get_control(self, jid, acct, thread_id):
'''Amongst all windows, return the MessageControl for jid''' '''Amongst all windows, return the MessageControl for jid'''
win = self.get_window(jid, acct) win = self.get_window(jid, acct, thread_id)
if win: if win:
return win.get_control(jid, acct) return win.get_control(jid, acct, thread_id)
return None return None
def get_controls(self, type = None, acct = None): def get_controls(self, type = None, acct = None, jid = None):
ctrls = [] ctrls = []
for c in self.controls(): for c in self.controls():
if acct and c.account != acct: if acct and c.account != acct:
continue continue
if jid and c.get_full_jid() != jid:
continue
if not type or c.type_id == type: if not type or c.type_id == type:
ctrls.append(c) ctrls.append(c)
return ctrls return ctrls

View file

@ -7,11 +7,11 @@ from common import xmpp
class FeatureNegotiationWindow: class FeatureNegotiationWindow:
'''FeatureNegotiotionWindow class''' '''FeatureNegotiotionWindow class'''
def __init__(self, account, jid, thread_id, form): def __init__(self, account, jid, session, form):
self.account = account self.account = account
self.jid = jid self.jid = jid
self.form = form self.form = form
self.thread_id = thread_id self.session = session
self.xml = gtkgui_helpers.get_glade('data_form_window.glade', 'data_form_window') self.xml = gtkgui_helpers.get_glade('data_form_window.glade', 'data_form_window')
self.window = self.xml.get_widget('data_form_window') self.window = self.xml.get_widget('data_form_window')
@ -27,7 +27,7 @@ class FeatureNegotiationWindow:
def on_ok_button_clicked(self, widget): def on_ok_button_clicked(self, widget):
acceptance = xmpp.Message(self.jid) acceptance = xmpp.Message(self.jid)
acceptance.setThread(self.thread_id) acceptance.setThread(self.session.thread_id)
feature = acceptance.NT.feature feature = acceptance.NT.feature
feature.setNamespace(xmpp.NS_FEATURE) feature.setNamespace(xmpp.NS_FEATURE)
@ -44,7 +44,7 @@ class FeatureNegotiationWindow:
# XXX determine whether to reveal presence # XXX determine whether to reveal presence
rejection = xmpp.Message(self.jid) rejection = xmpp.Message(self.jid)
rejection.setThread(self.thread_id) rejection.setThread(self.session.thread_id)
feature = rejection.NT.feature feature = rejection.NT.feature
feature.setNamespace(xmpp.NS_FEATURE) feature.setNamespace(xmpp.NS_FEATURE)

View file

@ -40,7 +40,7 @@ try:
except ImportError: except ImportError:
USER_HAS_PYNOTIFY = False USER_HAS_PYNOTIFY = False
def get_show_in_roster(event, account, contact): def get_show_in_roster(event, account, contact, session):
'''Return True if this event must be shown in roster, else False''' '''Return True if this event must be shown in roster, else False'''
if event == 'gc_message_received': if event == 'gc_message_received':
return True return True
@ -51,7 +51,7 @@ def get_show_in_roster(event, account, contact):
if gajim.config.get_per('notifications', str(num), 'roster') == 'no': if gajim.config.get_per('notifications', str(num), 'roster') == 'no':
return False return False
if event == 'message_received': if event == 'message_received':
chat_control = helpers.get_chat_control(account, contact) chat_control = helpers.get_chat_control(account, contact, session)
if chat_control: if chat_control:
return False return False
return True return True

View file

@ -1190,10 +1190,14 @@ class RosterWindow:
'''reads from db the unread messages, and fire them up''' '''reads from db the unread messages, and fire them up'''
for jid in gajim.contacts.get_jid_list(account): for jid in gajim.contacts.get_jid_list(account):
results = gajim.logger.get_unread_msgs_for_jid(jid) results = gajim.logger.get_unread_msgs_for_jid(jid)
# XXX results should contain sessions anyways
session = gajim.connections[account].make_new_session(jid)
for result in results: for result in results:
tim = time.localtime(float(result[2])) tim = time.localtime(float(result[2]))
self.on_message(jid, result[1], tim, account, msg_type = 'chat', self.on_message(jid, result[1], tim, account, msg_type = 'chat',
msg_id = result[0]) msg_id = result[0], session = session)
def fill_contacts_and_groups_dicts(self, array, account): def fill_contacts_and_groups_dicts(self, array, account):
'''fill gajim.contacts and gajim.groups''' '''fill gajim.contacts and gajim.groups'''
@ -1255,8 +1259,8 @@ class RosterWindow:
gajim.transport_avatar[account][host].append(contact1.jid) 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 a chat window opened, update it with new contact
# instance # instance
chat_control = gajim.interface.msg_win_mgr.get_control(ji, account) chat_controls = gajim.interface.msg_win_mgr.get_controls(jid=ji, acct=account)
if chat_control: for chat_control in chat_controls:
chat_control.contact = contact1 chat_control.contact = contact1
def chg_contact_status(self, contact, show, status, account): def chg_contact_status(self, contact, show, status, account):
@ -1283,14 +1287,14 @@ class RosterWindow:
jid_list = [contact.jid] jid_list = [contact.jid]
for jid in jid_list: for jid in jid_list:
if gajim.interface.msg_win_mgr.has_window(jid, account): if gajim.interface.msg_win_mgr.has_window(jid, account):
win = gajim.interface.msg_win_mgr.get_window(jid, account) for win in gajim.interface.msg_win_mgr.get_windows(jid, account):
ctrl = win.get_control(jid, account) for ctrl in win.get_controls(jid=jid, acct=account):
ctrl.contact = gajim.contacts.get_contact_with_highest_priority( ctrl.contact = gajim.contacts.get_contact_with_highest_priority(
account, contact.jid) account, contact.jid)
ctrl.update_ui() ctrl.update_ui()
win.redraw_tab(ctrl) win.redraw_tab(ctrl)
name = contact.get_shown_name() name = contact.get_shown_name()
# if multiple resources (or second one disconnecting) # if multiple resources (or second one disconnecting)
if (len(contact_instances) > 1 or (len(contact_instances) == 1 and \ if (len(contact_instances) > 1 or (len(contact_instances) == 1 and \
@ -3477,18 +3481,22 @@ class RosterWindow:
# We call this here to avoid race conditions with widget validation # We call this here to avoid race conditions with widget validation
chat_control.read_queue() chat_control.read_queue()
def new_chat(self, contact, account, resource = None): def new_chat(self, contact, account, resource = None, session = None):
# Get target window, create a control, and associate it with the window # Get target window, create a control, and associate it with the window
type_ = message_control.TYPE_CHAT type_ = message_control.TYPE_CHAT
fjid = contact.jid fjid = contact.jid
if resource: if resource:
fjid += '/' + resource fjid += '/' + resource
mw = gajim.interface.msg_win_mgr.get_window(fjid, account)
if not session:
session = gajim.connections[account].make_new_session(fjid)
mw = gajim.interface.msg_win_mgr.get_window(fjid, account, session.thread_id)
if not mw: if not mw:
mw = gajim.interface.msg_win_mgr.create_window(contact, account, type_) mw = gajim.interface.msg_win_mgr.create_window(contact, account, type_)
chat_control = ChatControl(mw, contact, account, resource) chat_control = ChatControl(mw, contact, account, session, resource)
mw.new_tab(chat_control) mw.new_tab(chat_control)
@ -3496,6 +3504,8 @@ class RosterWindow:
# We call this here to avoid race conditions with widget validation # We call this here to avoid race conditions with widget validation
chat_control.read_queue() chat_control.read_queue()
return session
def new_chat_from_jid(self, account, fjid): def new_chat_from_jid(self, account, fjid):
jid, resource = gajim.get_room_and_nick_from_fjid(fjid) jid, resource = gajim.get_room_and_nick_from_fjid(fjid)
if resource: if resource:
@ -3531,7 +3541,7 @@ class RosterWindow:
def on_message(self, jid, msg, tim, account, encrypted = False, def on_message(self, jid, msg, tim, account, encrypted = False,
msg_type = '', subject = None, resource = '', msg_id = None, msg_type = '', subject = None, resource = '', msg_id = None,
user_nick = '', advanced_notif_num = None, xhtml = None, thread = None): user_nick = '', advanced_notif_num = None, xhtml = None, session = None):
'''when we receive a message''' '''when we receive a message'''
contact = None contact = None
# if chat window will be for specific resource # if chat window will be for specific resource
@ -3569,16 +3579,18 @@ class RosterWindow:
path = self.get_path(jid, account) # Try to get line of contact in roster 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 # Look for a chat control that has the given resource
ctrl = gajim.interface.msg_win_mgr.get_control(fjid, account) # ctrl = gajim.interface.msg_win_mgr.get_control(fjid, account)
if not ctrl: # if not ctrl:
# if not, if message comes from highest prio, get control or open one # if not, if message comes from highest prio, get control or open one
# without resource # without resource
if highest_contact and contact.resource == highest_contact.resource \ # if highest_contact and contact.resource == highest_contact.resource \
and not jid == gajim.get_jid_from_account(account): # and not jid == gajim.get_jid_from_account(account):
ctrl = gajim.interface.msg_win_mgr.get_control(jid, account) # ctrl = gajim.interface.msg_win_mgr.get_control(jid, account)
fjid = jid # fjid = jid
resource_for_chat = None # resource_for_chat = None
# Do we have a queue? # Do we have a queue?
no_queue = len(gajim.events.get_events(account, fjid)) == 0 no_queue = len(gajim.events.get_events(account, fjid)) == 0
@ -3588,7 +3600,7 @@ class RosterWindow:
if msg_type == 'normal' and popup: # it's single message to be autopopuped if msg_type == 'normal' and popup: # it's single message to be autopopuped
dialogs.SingleMessageWindow(account, contact.jid, dialogs.SingleMessageWindow(account, contact.jid,
action = 'receive', from_whom = jid, subject = subject, action = 'receive', from_whom = jid, subject = subject,
message = msg, resource = resource, thread = thread) message = msg, resource = resource, session = session)
return return
# We print if window is opened and it's not a single message # We print if window is opened and it's not a single message
@ -3596,8 +3608,6 @@ class RosterWindow:
typ = '' typ = ''
if msg_type == 'error': if msg_type == 'error':
typ = 'status' typ = 'status'
if thread:
ctrl.set_thread_id(thread)
ctrl.print_conversation(msg, typ, tim = tim, encrypted = encrypted, ctrl.print_conversation(msg, typ, tim = tim, encrypted = encrypted,
subject = subject, xhtml = xhtml) subject = subject, xhtml = xhtml)
if msg_id: if msg_id:
@ -3610,26 +3620,26 @@ class RosterWindow:
if msg_type == 'normal': if msg_type == 'normal':
type_ = 'normal' type_ = 'normal'
event_type = 'single_message_received' event_type = 'single_message_received'
show_in_roster = notify.get_show_in_roster(event_type, account, contact) show_in_roster = notify.get_show_in_roster(event_type, account, contact, session)
show_in_systray = notify.get_show_in_systray(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, event = gajim.events.create_event(type_, (msg, subject, msg_type, tim,
encrypted, resource, msg_id, xhtml, thread), show_in_roster = show_in_roster, encrypted, resource, msg_id, xhtml, session), show_in_roster = show_in_roster,
show_in_systray = show_in_systray) show_in_systray = show_in_systray)
gajim.events.add_event(account, fjid, event) gajim.events.add_event(account, fjid, event)
if popup: # if popup:
if not ctrl: # if not ctrl:
self.new_chat(contact, account, resource = resource_for_chat) # self.new_chat(contact, account, resource = resource_for_chat)
if path and not self.dragging and gajim.config.get( # if path and not self.dragging and gajim.config.get(
'scroll_roster_to_last_message'): # 'scroll_roster_to_last_message'):
# we curently see contact in our roster OR he # # we curently see contact in our roster OR he
# is not in the roster at all. # # is not in the roster at all.
# show and select his line in roster # show and select his line in roster
# do not change selection while DND'ing # do not change selection while DND'ing
self.tree.expand_row(path[0:1], False) # self.tree.expand_row(path[0:1], False)
self.tree.expand_row(path[0:2], False) # self.tree.expand_row(path[0:2], False)
self.tree.scroll_to_cell(path) # self.tree.scroll_to_cell(path)
self.tree.set_cursor(path) # self.tree.set_cursor(path)
else: if not popup:
if no_queue: # We didn't have a queue: we change icons if no_queue: # We didn't have a queue: we change icons
self.draw_contact(jid, account) self.draw_contact(jid, account)
self.show_title() # we show the * or [n] self.show_title() # we show the * or [n]
@ -3875,7 +3885,7 @@ class RosterWindow:
if event.type_ == 'normal': if event.type_ == 'normal':
dialogs.SingleMessageWindow(account, jid, dialogs.SingleMessageWindow(account, jid,
action = 'receive', from_whom = jid, subject = data[1], action = 'receive', from_whom = jid, subject = data[1],
message = data[0], resource = data[5], thread = data[8]) message = data[0], resource = data[5], session = data[8])
gajim.interface.remove_first_event(account, jid, event.type_) gajim.interface.remove_first_event(account, jid, event.type_)
return True return True
elif event.type_ == 'file-request': elif event.type_ == 'file-request':
@ -3912,22 +3922,22 @@ class RosterWindow:
jid = jid + u'/' + resource jid = jid + u'/' + resource
adhoc_commands.CommandWindow(account, jid) adhoc_commands.CommandWindow(account, jid)
def on_open_chat_window(self, widget, contact, account, resource = None): def on_open_chat_window(self, widget, contact, account, resource = None, session = None):
# Get the window containing the chat # Get the window containing the chat
fjid = contact.jid fjid = contact.jid
if resource: if resource:
fjid += '/' + resource fjid += '/' + resource
win = gajim.interface.msg_win_mgr.get_window(fjid, account)
if not win: session = self.new_chat(contact, account, resource=resource, session=session)
self.new_chat(contact, account, resource = resource) win = gajim.interface.msg_win_mgr.get_window(fjid, account, session.thread_id)
win = gajim.interface.msg_win_mgr.get_window(fjid, account) ctrl = win.get_control(fjid, account, session.thread_id)
ctrl = win.get_control(fjid, account) # last message is long time ago
# last message is long time ago gajim.last_message_time[account][ctrl.get_full_jid()] = 0
gajim.last_message_time[account][ctrl.get_full_jid()] = 0
win.set_active_tab(fjid, account) win.set_active_tab(fjid, account, session.thread_id)
if gajim.connections[account].is_zeroconf and \ if gajim.connections[account].is_zeroconf and \
gajim.connections[account].status in ('offline', 'invisible'): gajim.connections[account].status in ('offline', 'invisible'):
win.get_control(fjid, account).got_disconnected() win.get_control(fjid, account, session.thread_id).got_disconnected()
win.window.present() win.window.present()
@ -3967,7 +3977,10 @@ class RosterWindow:
jid = child_jid jid = child_jid
else: else:
child_iter = model.iter_next(child_iter) child_iter = model.iter_next(child_iter)
session = None
if first_ev: if first_ev:
session = first_ev.parameters[8]
fjid = jid fjid = jid
if resource: if resource:
fjid += '/' + resource fjid += '/' + resource
@ -3978,7 +3991,7 @@ class RosterWindow:
c = gajim.contacts.get_contact_with_highest_priority(account, jid) c = gajim.contacts.get_contact_with_highest_priority(account, jid)
if jid == gajim.get_jid_from_account(account): if jid == gajim.get_jid_from_account(account):
resource = c.resource resource = c.resource
self.on_open_chat_window(widget, c, account, resource = resource) self.on_open_chat_window(widget, c, account, resource = resource, session=session)
def on_roster_treeview_row_activated(self, widget, path, col = 0): def on_roster_treeview_row_activated(self, widget, path, col = 0):
'''When an iter is double clicked: open the first event window''' '''When an iter is double clicked: open the first event window'''