reverted back to per-JID windows, pass around sessions instead of thread_ids

This commit is contained in:
Brendan Taylor 2007-06-05 23:19:34 +00:00
parent 370818d982
commit 7898686680
11 changed files with 167 additions and 198 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.session) self.account, self.contact)
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, self.session.thread_id) ctrl = gajim.interface.msg_win_mgr.get_control(full_jid, self.account)
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:
@ -904,7 +904,7 @@ class ChatControl(ChatControlBase):
TYPE_ID = message_control.TYPE_CHAT TYPE_ID = message_control.TYPE_CHAT
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, session, 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)
@ -935,7 +935,7 @@ class ChatControl(ChatControlBase):
# it is on enter-notify and leave-notify so no need to be per jid # it is on enter-notify and leave-notify so no need to be per jid
self.show_bigger_avatar_timeout_id = None self.show_bigger_avatar_timeout_id = None
self.bigger_avatar_window = None self.bigger_avatar_window = None
self.show_avatar(self.contact.resource) self.show_avatar(self.contact.resource)
# chatstate timers and state # chatstate timers and state
self.reset_kbd_mouse_timeout_vars() self.reset_kbd_mouse_timeout_vars()
@ -1799,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, 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: 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
@ -1817,6 +1817,9 @@ 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_session(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

@ -21,6 +21,8 @@ import os
import random import random
import socket import socket
import time
try: try:
randomsource = random.SystemRandom() randomsource = random.SystemRandom()
except: except:
@ -48,8 +50,6 @@ 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):
@ -888,8 +888,7 @@ class Connection(ConnectionHandlers):
# XEP-0201 # XEP-0201
if session: if session:
session.last_send = time.time() 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 # 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
@ -55,7 +57,7 @@ except:
class ConnectionBytestream: class ConnectionBytestream:
def __init__(self): def __init__(self):
self.files_props = {} self.files_props = {}
def is_transfer_stoped(self, file_props): def is_transfer_stoped(self, file_props):
if file_props.has_key('error') and file_props['error'] != 0: if file_props.has_key('error') and file_props['error'] != 0:
return True return True
@ -1168,14 +1170,17 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
# keep the jids we auto added (transports contacts) to not send the # keep the jids we auto added (transports contacts) to not send the
# SUBSCRIBED event to gui # SUBSCRIBED event to gui
self.automatically_added = [] 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 # 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:
HAS_IDLE = False HAS_IDLE = False
def build_http_auth_answer(self, iq_obj, answer): def build_http_auth_answer(self, iq_obj, answer):
if answer == 'yes': if answer == 'yes':
self.connection.send(iq_obj.buildReply('result')) 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)); 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 +1415,18 @@ 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')
@ -1486,7 +1500,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
if encTag and GnuPG.USE_GPG: if encTag and GnuPG.USE_GPG:
#decrypt #decrypt
encmsg = encTag.getData() encmsg = encTag.getData()
keyID = gajim.config.get_per('accounts', self.name, 'keyid') keyID = gajim.config.get_per('accounts', self.name, 'keyid')
if keyID: if keyID:
decmsg = self.gpg.decrypt(encmsg, keyID) decmsg = self.gpg.decrypt(encmsg, keyID)
@ -1545,7 +1559,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
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): def get_session(self, jid, thread_id, type):
@ -1557,7 +1571,7 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
else: else:
# it's possible we initiated a session with a bare JID and this is the # it's possible we initiated a session with a bare JID and this is the
# first time we've seen a resource # 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: if bare_jid != jid:
session = self.find_session(bare_jid, thread_id, type) session = self.find_session(bare_jid, thread_id, type)
if session: if session:
@ -1576,9 +1590,9 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
return None return None
def move_session(self, original_jid, thread_id, to_resource): 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 new_jid = gajim.get_jid_without_resource(original_jid) + '/' + to_resource
session.jid = new_jid session.jid = new_jid

View File

@ -16,8 +16,6 @@
import common.gajim import common.gajim
#import random, string
class Contact: class Contact:
'''Information concerning each contact''' '''Information concerning each contact'''
def __init__(self, jid='', name='', groups=[], show='', status='', sub='', def __init__(self, jid='', name='', groups=[], show='', status='', sub='',
@ -52,20 +50,6 @@ class Contact:
self.chatstate = chatstate self.chatstate = chatstate
self.last_status_time = last_status_time 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): def get_full_jid(self):
if self.resource: if self.resource:
return self.jid + '/' + self.resource return self.jid + '/' + self.resource
@ -169,7 +153,7 @@ class Contacts:
return Contact(jid, name, groups, show, status, sub, ask, resource, return Contact(jid, name, groups, show, status, sub, ask, resource,
priority, keyID, our_chatstate, chatstate, last_status_time, priority, keyID, our_chatstate, chatstate, last_status_time,
composing_jep) composing_jep)
def copy_contact(self, contact): def copy_contact(self, contact):
return self.create_contact(jid = contact.jid, name = contact.name, return self.create_contact(jid = contact.jid, name = contact.name,
groups = contact.groups, show = contact.show, status = contact.status, groups = contact.groups, show = contact.show, status = contact.status,

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, session): def get_chat_control(account, contact):
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, session):
# 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, session.thread_id) account)
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, session.thread_id) return gajim.interface.msg_win_mgr.get_control(contact.jid, account)
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, 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): 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

@ -196,7 +196,7 @@ class EditGroupsDialog:
for group in groups: for group in groups:
if group not in helpers.special_groups or groups[group] > 0: if group not in helpers.special_groups or groups[group] > 0:
group_list.append(group) group_list.append(group)
group_list.sort() group_list.sort()
for group in group_list: for group in group_list:
iter = store.append() iter = store.append()
store.set(iter, 0, group) # Group name store.set(iter, 0, group) # Group name
@ -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
for ctrl in self.msg_win_mgr.get_controls(jid=jid_from, acct=account): ctrl = self.msg_win_mgr.get_control(jid_from, 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'
@ -663,7 +663,7 @@ class Interface:
# It's maybe a GC_NOTIFY (specialy for MSN gc) # It's maybe a GC_NOTIFY (specialy for MSN gc)
self.handle_event_gc_notify(account, (jid, array[1], status_message, self.handle_event_gc_notify(account, (jid, array[1], status_message,
array[3], None, None, None, None, None, None, None, None)) array[3], None, None, None, None, None, None, None, None))
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,
@ -688,7 +688,7 @@ class Interface:
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, session.thread_id) groupchat_control = self.msg_win_mgr.get_control(jid, account)
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,29 +700,28 @@ 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
chat_control = session.get_control() ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account)
# ctrl = self.msg_win_mgr.get_control(full_jid_with_resource, account, session.thread_id) if ctrl:
# if ctrl: chat_control = ctrl
# chat_control = ctrl elif not pm and (not highest_contact or not highest_contact.resource):
# 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, session.thread_id) chat_control = self.msg_win_mgr.get_control(jid, account)
# 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, session.thread_id) chat_control = self.msg_win_mgr.get_control(jid, account)
# Handle chat states # Handle chat states
contact = gajim.contacts.get_contact(account, jid, resource) contact = gajim.contacts.get_contact(account, jid, resource)
if contact and isinstance(contact, list): if contact and isinstance(contact, list):
contact = contact[0] contact = contact[0]
@ -740,7 +739,7 @@ class Interface:
# got no valid jep85 answer, peer does not support it # got no valid jep85 answer, peer does not support it
contact.chatstate = False contact.chatstate = False
elif chatstate == 'active': elif chatstate == 'active':
# Brand new message, incoming. # Brand new message, incoming.
contact.our_chatstate = chatstate contact.our_chatstate = chatstate
contact.chatstate = chatstate contact.chatstate = chatstate
if msg_id: # Do not overwrite an existing msg_id with None 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 \ 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)
@ -768,8 +765,8 @@ class Interface:
if msg_type == 'normal': if msg_type == 'normal':
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,
full_jid_with_resource, [msg_type]): # msg_type can be chat or pm jid_of_control, [msg_type]): # msg_type can be chat or pm
first = True first = True
if pm: if pm:
@ -788,12 +785,11 @@ class Interface:
msg_type, subject, resource, msg_id, array[9], msg_type, subject, resource, msg_id, array[9],
advanced_notif_num, xhtml = xhtml, session = session) 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', full_jid_with_resource, account, [msg_type, notify.notify('new_message', jid_of_control, account, [msg_type,
first, nickname, msg], advanced_notif_num) first, nickname, msg], advanced_notif_num)
if self.remote_ctrl: if self.remote_ctrl:
@ -990,7 +986,7 @@ class Interface:
resource = '' resource = ''
if vcard.has_key('resource'): if vcard.has_key('resource'):
resource = vcard['resource'] resource = vcard['resource']
# vcard window # vcard window
win = None win = None
if self.instances[account]['infos'].has_key(jid): if self.instances[account]['infos'].has_key(jid):
@ -1012,14 +1008,11 @@ 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:
for ctrl in self.msg_win_mgr.get_controls(jid=jid, acct=account): ctrl.show_avatar()
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:
@ -1668,17 +1661,18 @@ class Interface:
# XXX check if we can autoaccept # XXX check if we can autoaccept
if form.getType() == 'form': if form.getType() == 'form':
ctrl = session.get_control() ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account)
# ctrl = gajim.interface.msg_win_mgr.get_control(str(jid), account) if not ctrl:
# if not ctrl: resource = jid.getResource()
# resource = jid.getResource() contact = gajim.contacts.get_contact(account, str(jid), resource)
# contact = gajim.contacts.get_contact(account, str(jid), resource) if not contact:
# if not contact: connection = gajim.connections[account]
# connection = gajim.connections[account] contact = gajim.contacts.create_contact(jid = jid.getStripped(), resource = resource, show = connection.get_status())
# contact = gajim.contacts.create_contact(jid = jid.getStripped(), resource = resource, show = connection.get_status()) self.roster.new_chat(contact, account, resource = resource)
# 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) negotiation.FeatureNegotiationWindow(account, jid, session, form)

View File

@ -110,6 +110,13 @@ 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_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', 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):

View File

@ -123,9 +123,8 @@ class MessageWindow:
def get_num_controls(self): def get_num_controls(self):
n = 0 n = 0
for sess_dict in self._controls.values(): for dict in self._controls.values():
for dict in sess_dict.values(): n += len(dict)
n += len(dict)
return n return n
def _on_window_focus(self, widget, event): def _on_window_focus(self, widget, event):
@ -166,9 +165,7 @@ 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()
if not self._controls.has_key(fjid): self._controls[control.account][fjid] = control
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 ?
@ -295,11 +292,11 @@ 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, thread_id): def set_active_tab(self, jid, acct):
ctrl = self._controls[acct][jid][thread_id] ctrl = self._controls[acct][jid]
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)
def remove_tab(self, ctrl, method, reason = None, force = False): def remove_tab(self, ctrl, method, reason = None, force = False):
'''reason is only for gc (offline status message) '''reason is only for gc (offline status message)
if force is True, do not ask any confirmation''' 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)) 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][ctrl.session.thread_id] del self._controls[ctrl.account][fjid]
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]
@ -420,19 +415,7 @@ class MessageWindow:
for ctrl in self.controls(): for ctrl in self.controls():
ctrl.update_tags() ctrl.update_tags()
def has_control(self, jid, acct, thread_id = None): def get_control(self, key, acct):
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):
@ -441,7 +424,7 @@ class MessageWindow:
if isinstance(key, unicode): if isinstance(key, unicode):
jid = key jid = key
try: try:
return self._controls[acct][jid][thread_id] return self._controls[acct][jid]
except: except:
return None return None
else: else:
@ -453,10 +436,9 @@ class MessageWindow:
return self._widget_to_control(nth_child) return self._widget_to_control(nth_child)
def controls(self): def controls(self):
for jid_dict in self._controls.values(): for ctrl_dict in self._controls.values():
for sess_dict in jid_dict.values(): for ctrl in ctrl_dict.values():
for ctrl in sess_dict.values(): yield ctrl
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()
@ -513,7 +495,7 @@ class MessageWindow:
if old_no >= 0: if old_no >= 0:
old_ctrl = self._widget_to_control(notebook.get_nth_page(old_no)) old_ctrl = self._widget_to_control(notebook.get_nth_page(old_no))
old_ctrl.set_control_active(False) old_ctrl.set_control_active(False)
new_ctrl = self._widget_to_control(notebook.get_nth_page(page_num)) new_ctrl = self._widget_to_control(notebook.get_nth_page(page_num))
new_ctrl.set_control_active(True) new_ctrl.set_control_active(True)
self.show_title(control = new_ctrl) self.show_title(control = new_ctrl)
@ -587,11 +569,11 @@ class MessageWindow:
source_child = self.notebook.get_nth_page(source_page_num) source_child = self.notebook.get_nth_page(source_page_num)
if dest_page_num != source_page_num: if dest_page_num != source_page_num:
self.notebook.reorder_child(source_child, dest_page_num) self.notebook.reorder_child(source_child, dest_page_num)
def get_tab_at_xy(self, x, y): def get_tab_at_xy(self, x, y):
'''Thanks to Gaim '''Thanks to Gaim
Return the tab under xy and 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 page_num = -1
to_right = False to_right = False
@ -612,7 +594,7 @@ class MessageWindow:
if (y >= tab_alloc.y) and \ if (y >= tab_alloc.y) and \
(y <= (tab_alloc.y + tab_alloc.height)): (y <= (tab_alloc.y + tab_alloc.height)):
page_num = i page_num = i
if y > tab_alloc.y + (tab_alloc.height / 2.0): if y > tab_alloc.y + (tab_alloc.height / 2.0):
to_right = True to_right = True
break break
@ -677,22 +659,14 @@ class MessageWindowMgr:
return w return w
return None return None
def get_window(self, jid, acct, thread_id): def get_window(self, jid, acct):
for win in self.windows(): for win in self.windows():
if win.has_control(jid, acct, thread_id): if win.get_control(jid, acct):
return win return win
return None return None
def get_windows(self, jid, acct): def has_window(self, jid, acct):
for win in self.windows(): return self.get_window(jid, acct) != None
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:
@ -704,7 +678,7 @@ class MessageWindowMgr:
'''Resizes window according to config settings''' '''Resizes window according to config settings'''
if not gajim.config.get('saveposition'): if not gajim.config.get('saveposition'):
return return
if self.mode == self.ONE_MSG_WINDOW_ALWAYS: if self.mode == self.ONE_MSG_WINDOW_ALWAYS:
size = (gajim.config.get('msgwin-width'), size = (gajim.config.get('msgwin-width'),
gajim.config.get('msgwin-height')) gajim.config.get('msgwin-height'))
@ -721,7 +695,7 @@ class MessageWindowMgr:
return return
gtkgui_helpers.resize_window(win.window, size[0], size[1]) gtkgui_helpers.resize_window(win.window, size[0], size[1])
def _position_window(self, win, acct, type): def _position_window(self, win, acct, type):
'''Moves window according to config settings''' '''Moves window according to config settings'''
if not gajim.config.get('saveposition') or\ if not gajim.config.get('saveposition') or\
@ -799,20 +773,18 @@ class MessageWindowMgr:
del self._windows[k] del self._windows[k]
return return
def get_control(self, jid, acct, thread_id): def get_control(self, jid, acct):
'''Amongst all windows, return the MessageControl for jid''' '''Amongst all windows, return the MessageControl for jid'''
win = self.get_window(jid, acct, thread_id) win = self.get_window(jid, acct)
if win: if win:
return win.get_control(jid, acct, thread_id) return win.get_control(jid, acct)
return None return None
def get_controls(self, type = None, acct = None, jid = None): def get_controls(self, type = None, acct = 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
@ -836,7 +808,7 @@ class MessageWindowMgr:
def save_state(self, msg_win): def save_state(self, msg_win):
if not gajim.config.get('saveposition'): if not gajim.config.get('saveposition'):
return return
# Save window size and position # Save window size and position
pos_x_key = 'msgwin-x-position' pos_x_key = 'msgwin-x-position'
pos_y_key = 'msgwin-y-position' pos_y_key = 'msgwin-y-position'
@ -871,11 +843,11 @@ class MessageWindowMgr:
if self.mode != self.ONE_MSG_WINDOW_NEVER: 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_x_key, x)
gajim.config.set_per('accounts', acct, pos_y_key, y) gajim.config.set_per('accounts', acct, pos_y_key, y)
else: else:
gajim.config.set(size_width_key, width) gajim.config.set(size_width_key, width)
gajim.config.set(size_height_key, height) gajim.config.set(size_height_key, height)
if self.mode != self.ONE_MSG_WINDOW_NEVER: if self.mode != self.ONE_MSG_WINDOW_NEVER:
gajim.config.set(pos_x_key, x) gajim.config.set(pos_x_key, x)
gajim.config.set(pos_y_key, y) gajim.config.set(pos_y_key, y)

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, session): def get_show_in_roster(event, account, contact):
'''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, session):
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, session) chat_control = helpers.get_chat_control(account, contact)
if chat_control: if chat_control:
return False return False
return True return True

View File

@ -1191,9 +1191,8 @@ class RosterWindow:
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 # XXX unread messages should probably have their session with them
session = gajim.connections[account].make_new_session(jid) 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',
@ -1259,8 +1258,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_controls = gajim.interface.msg_win_mgr.get_controls(jid=ji, acct=account) chat_control = gajim.interface.msg_win_mgr.get_control(ji, account)
for chat_control in chat_controls: if chat_control:
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):
@ -1287,14 +1286,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):
for win in gajim.interface.msg_win_mgr.get_windows(jid, account): win = gajim.interface.msg_win_mgr.get_window(jid, account)
for ctrl in win.get_controls(jid=jid, acct=account): ctrl = win.get_control(jid, 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 \
@ -3492,7 +3491,7 @@ class RosterWindow:
if not session: if not session:
session = gajim.connections[account].make_new_session(fjid) 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: 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_)
@ -3504,8 +3503,6 @@ 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:
@ -3579,18 +3576,16 @@ 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
@ -3608,6 +3603,8 @@ class RosterWindow:
typ = '' typ = ''
if msg_type == 'error': if msg_type == 'error':
typ = 'status' typ = 'status'
if session:
ctrl.set_session(session)
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:
@ -3620,26 +3617,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, 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) 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, session), 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)
if not popup: else:
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]
@ -3927,17 +3924,17 @@ class RosterWindow:
fjid = contact.jid fjid = contact.jid
if resource: if resource:
fjid += '/' + resource fjid += '/' + resource
win = gajim.interface.msg_win_mgr.get_window(fjid, account)
session = self.new_chat(contact, account, resource=resource, session=session) if not win:
win = gajim.interface.msg_win_mgr.get_window(fjid, account, session.thread_id) self.new_chat(contact, account, resource = resource, session = session)
ctrl = win.get_control(fjid, account, session.thread_id) win = gajim.interface.msg_win_mgr.get_window(fjid, account)
# last message is long time ago ctrl = win.get_control(fjid, account)
gajim.last_message_time[account][ctrl.get_full_jid()] = 0 # 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.set_active_tab(fjid, account)
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, session.thread_id).got_disconnected() win.get_control(fjid, account).got_disconnected()
win.window.present() win.window.present()
@ -3977,7 +3974,6 @@ 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 session = None
if first_ev: if first_ev:
session = first_ev.parameters[8] session = first_ev.parameters[8]
@ -3991,7 +3987,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, 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): 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'''