Various roster fixes.

* don't traceback when selfcontact is disconnecting
 * make more use of "remove contact after last event removed" mechanism
 * correctly redraw bigbrothers after status change
 * handle situation where we receive a message, go offline without reading it and reconnect after another resource has moved the sending contact to another group.

know bugs: newly added transports added to "not in roster group"
This commit is contained in:
Stephan Erb 2008-06-10 21:18:55 +00:00
parent 399233f293
commit d5bbc403c9
2 changed files with 33 additions and 66 deletions

View File

@ -609,7 +609,11 @@ class Interface:
def handle_event_notify(self, account, array): def handle_event_notify(self, account, array):
# 'NOTIFY' (account, (jid, status, status message, resource, priority, # 'NOTIFY' (account, (jid, status, status message, resource, priority,
# keyID, timestamp, contact_nickname)) # keyID, timestamp, contact_nickname))
# if we're here it means contact changed show #
# Contact changed show
# FIXME: Drop and rewrite...
statuss = ['offline', 'error', 'online', 'chat', 'away', 'xa', 'dnd', statuss = ['offline', 'error', 'online', 'chat', 'away', 'xa', 'dnd',
'invisible'] 'invisible']
# Ignore invalid show # Ignore invalid show
@ -664,17 +668,20 @@ class Interface:
if contact1: if contact1:
if contact1.show in statuss: if contact1.show in statuss:
old_show = statuss.index(contact1.show) old_show = statuss.index(contact1.show)
# nick changed
if contact_nickname is not None and \ if contact_nickname is not None and \
contact1.contact_name != contact_nickname: contact1.contact_name != contact_nickname:
contact1.contact_name = contact_nickname contact1.contact_name = contact_nickname
self.roster.draw_contact(jid, account) self.roster.draw_contact(jid, account)
if old_show == new_show and contact1.status == status_message and \ if old_show == new_show and contact1.status == status_message and \
contact1.priority == priority: # no change contact1.priority == priority: # no change
return return
else: else:
contact1 = gajim.contacts.get_first_contact_from_jid(account, ji) contact1 = gajim.contacts.get_first_contact_from_jid(account, ji)
if not contact1: if not contact1:
# presence of another resource of our jid # Presence of another resource of our jid
# Create SelfContact and add to roster
if resource == gajim.connections[account].server_resource: if resource == gajim.connections[account].server_resource:
return return
contact1 = gajim.contacts.create_contact(jid = ji, contact1 = gajim.contacts.create_contact(jid = ji,
@ -687,14 +694,15 @@ class Interface:
lcontact.append(contact1) lcontact.append(contact1)
elif contact1.show in statuss: elif contact1.show in statuss:
old_show = statuss.index(contact1.show) old_show = statuss.index(contact1.show)
# FIXME: What Am I?
if (resources != [''] and (len(lcontact) != 1 or if (resources != [''] and (len(lcontact) != 1 or
lcontact[0].show != 'offline')) and jid.find('@') > 0: lcontact[0].show != 'offline')) and jid.find('@') > 0:
old_show = 0 old_show = 0
contact1 = gajim.contacts.copy_contact(contact1) contact1 = gajim.contacts.copy_contact(contact1)
lcontact.append(contact1) lcontact.append(contact1)
contact1.resource = resource contact1.resource = resource
# FIXME ugly workaround for self contact
self.roster.add_contact(contact1.jid, account) self.roster.add_contact(contact1.jid, account)
if contact1.jid.find('@') > 0 and len(lcontact) == 1: if contact1.jid.find('@') > 0 and len(lcontact) == 1:
# It's not an agent # It's not an agent
@ -725,6 +733,7 @@ class Interface:
# We're connected since more that 30 seconds # We're connected since more that 30 seconds
contact1.last_status_time = time.localtime() contact1.last_status_time = time.localtime()
contact1.contact_nickname = contact_nickname contact1.contact_nickname = contact_nickname
if gajim.jid_is_transport(jid): if gajim.jid_is_transport(jid):
# It must be an agent # It must be an agent
if ji in jid_list: if ji in jid_list:
@ -852,10 +861,7 @@ class Interface:
if jid in gajim.contacts.get_jid_list(account): if jid in gajim.contacts.get_jid_list(account):
c = gajim.contacts.get_first_contact_from_jid(account, jid) c = gajim.contacts.get_first_contact_from_jid(account, jid)
c.resource = array[1] c.resource = array[1]
self.roster.remove_contact(c.jid, account) self.roster.remove_contact_from_groups(c.jid, account, [('Not in Roster'),])
if _('Not in Roster') in c.groups:
c.groups.remove(_('Not in Roster'))
self.roster.add_contact(c.jid, account)
else: else:
keyID = '' keyID = ''
attached_keys = gajim.config.get_per('accounts', account, attached_keys = gajim.config.get_per('accounts', account,
@ -922,8 +928,7 @@ class Interface:
if c.jid in gajim.to_be_removed[account]: if c.jid in gajim.to_be_removed[account]:
# This way we'll really remove it # This way we'll really remove it
gajim.to_be_removed[account].remove(c.jid) gajim.to_be_removed[account].remove(c.jid)
gajim.contacts.remove_jid(account, c.jid) self.roster.remove_contact(c.jid, account, backend = True)
self.roster.remove_contact(c.jid, account)
def handle_event_register_agent_info(self, account, array): def handle_event_register_agent_info(self, account, array):
# ('REGISTER_AGENT_INFO', account, (agent, infos, is_form)) # ('REGISTER_AGENT_INFO', account, (agent, infos, is_form))

View File

@ -760,33 +760,6 @@ class RosterWindow:
self.remove_contact(jid, account, force = True, backend = True) self.remove_contact(jid, account, force = True, backend = True)
return True return True
#FIXME:
# We need to define a generic way to keep contacts in roster
# as long as they have pending events or as we
# still chat with them
def _readd_contact_to_roster_if_needed(self, contact, account):
need_readd = False
if len(gajim.events.get_events(account, contact.jid)):
need_readd = True
elif gajim.interface.msg_win_mgr.has_window(contact.jid, account):
if _('Not in Roster') in contact.groups:
# Close chat window
msg_win = gajim.interface.msg_win_mgr.get_window(contact.jid,
account)
for ctrl in gajim.interface.msg_win_mgr.get_chat_controls(
contact.jid, account):
msg_win.remove_tab(ctrl, msg_win.CLOSE_CLOSE_BUTTON)
else:
need_readd = True
if need_readd:
c = gajim.contacts.create_contact(jid = contact.jid,
name = '', groups = [_('Not in Roster')],
show = 'not in roster', status = '', ask = 'none',
keyID = contact.keyID)
gajim.contacts.add_contact(account, c)
self.add_contact(contact.jid, account)
def add_contact_to_groups(self, jid, account, groups): def add_contact_to_groups(self, jid, account, groups):
'''Add contact to given groups and redraw them. '''Add contact to given groups and redraw them.
@ -1165,13 +1138,15 @@ class RosterWindow:
Show contact if it has pending events Show contact if it has pending events
''' '''
contact = gajim.contacts.get_first_contact_from_jid(account, jid) contact = gajim.contacts.get_first_contact_from_jid(account, jid)
if not contact:
# idle draw or just removed SelfContact
return
family = gajim.contacts.get_metacontacts_family(account, jid) family = gajim.contacts.get_metacontacts_family(account, jid)
if family: if family:
# There might be a new big brother # There might be a new big brother
self._recalibrate_metacontact_family(family, account) self._recalibrate_metacontact_family(family, account)
else: self.draw_contact(jid, account)
self.draw_contact(jid, account)
self.draw_account(account) self.draw_account(account)
for group in contact.groups: for group in contact.groups:
@ -1496,7 +1471,7 @@ class RosterWindow:
gajim.groups[account] = {} gajim.groups[account] = {}
for jid in array.keys(): for jid in array.keys():
# Remove the contact in roster. It might has changed # Remove the contact in roster. It might has changed
self.remove_contact(jid, account) self.remove_contact(jid, account, force = True)
# Remove old Contact instances # Remove old Contact instances
gajim.contacts.remove_jid(account, jid, remove_meta=False) gajim.contacts.remove_jid(account, jid, remove_meta=False)
jids = jid.split('/') jids = jid.split('/')
@ -1827,6 +1802,7 @@ class RosterWindow:
# We come back from invisible, join bookmarks # We come back from invisible, join bookmarks
gajim.interface.auto_join_bookmarks(account) gajim.interface.auto_join_bookmarks(account)
def chg_contact_status(self, contact, show, status, account): def chg_contact_status(self, contact, show, status, account):
'''When a contact changes his or her status''' '''When a contact changes his or her status'''
contact_instances = gajim.contacts.get_contacts(account, contact.jid) contact_instances = gajim.contacts.get_contacts(account, contact.jid)
@ -1834,10 +1810,13 @@ class RosterWindow:
contact.status = status contact.status = status
# name is to show in conversation window # name is to show in conversation window
name = contact.get_shown_name() name = contact.get_shown_name()
# The contact has several resources
if len(contact_instances) > 1: if len(contact_instances) > 1:
if contact.resource != '': if contact.resource != '':
name += '/' + contact.resource name += '/' + contact.resource
# Remove resource when going offline
if show in ('offline', 'error') and \ if show in ('offline', 'error') and \
len(gajim.events.get_events(account, contact.get_full_jid())) == 0: len(gajim.events.get_events(account, contact.get_full_jid())) == 0:
jid_with_resource = contact.jid + '/' + contact.resource jid_with_resource = contact.jid + '/' + contact.resource
@ -1848,13 +1827,13 @@ class RosterWindow:
for ctrl in win.get_controls(jid_with_resource, account): for ctrl in win.get_controls(jid_with_resource, account):
ctrl.update_ui() ctrl.update_ui()
win.redraw_tab(ctrl) win.redraw_tab(ctrl)
gajim.contacts.remove_contact(account, contact) gajim.contacts.remove_contact(account, contact)
elif contact.jid == gajim.get_jid_from_account(account) and \ elif contact.jid == gajim.get_jid_from_account(account) and \
show == 'offline': show in ('offline', 'error'):
# Our SelfContact went offline. Remove him from roster and contacts # SelfContact went offline. Remove him when last pending message was read
self.remove_contact(contact.jid, account) self.remove_contact(contact.jid, account, backend = True)
gajim.contacts.remove_contact(account, contact)
# print status in chat window and update status/GPG image # print status in chat window and update status/GPG image
if gajim.interface.msg_win_mgr.has_window(contact.jid, account): if gajim.interface.msg_win_mgr.has_window(contact.jid, account):
win = gajim.interface.msg_win_mgr.get_window(contact.jid, account) win = gajim.interface.msg_win_mgr.get_window(contact.jid, account)
@ -1909,8 +1888,7 @@ class RosterWindow:
# Remove SelfContact from roster and remove it. # Remove SelfContact from roster and remove it.
# It might be gone when we return # It might be gone when we return
self_jid = gajim.get_jid_from_account(account) self_jid = gajim.get_jid_from_account(account)
self.remove_contact(self_jid, account) self.remove_contact(self_jid, account, backend = True)
gajim.contacts.remove_jid(account, self_jid)
self.actions_menu_needs_rebuild = True self.actions_menu_needs_rebuild = True
self.update_status_combobox() self.update_status_combobox()
# Force the rebuild now since the on_activates on the menu itself does # Force the rebuild now since the on_activates on the menu itself does
@ -2310,7 +2288,6 @@ class RosterWindow:
def on_remove_agent(self, widget, list_): def on_remove_agent(self, widget, list_):
'''When an agent is requested to be removed. list_ is a list of '''When an agent is requested to be removed. list_ is a list of
(contact, account) tuple''' (contact, account) tuple'''
# FIXME remove transport contacts
for (contact, account) in list_: for (contact, account) in list_:
if gajim.config.get_per('accounts', account, 'hostname') == \ if gajim.config.get_per('accounts', account, 'hostname') == \
contact.jid: contact.jid:
@ -2579,16 +2556,9 @@ class RosterWindow:
for contact in gajim.contacts.get_contacts_from_group(account, group): for contact in gajim.contacts.get_contacts_from_group(account, group):
if not dlg.is_checked(): if not dlg.is_checked():
self.remove_contact_from_groups(contact.jid,account, [group]) self.remove_contact_from_groups(contact.jid,account, [group])
gajim.connections[account].update_contact(contact.jid,
contact.name, contact.groups)
self.add_contact(contact.jid, account)
else: else:
gajim.connections[account].unsubscribe(contact.jid) gajim.connections[account].unsubscribe(contact.jid)
for c in gajim.contacts.get_contacts(account, contact.jid): self.remove_contact(contact.jid, account, backend = True)
self.remove_contact(c.jid, account)
gajim.contacts.remove_jid(account, c.jid)
self._readd_contact_to_roster_if_needed(contact, account)
self.draw_account(account)
def on_assign_pgp_key(self, widget, contact, account): def on_assign_pgp_key(self, widget, contact, account):
attached_keys = gajim.config.get_per('accounts', account, attached_keys = gajim.config.get_per('accounts', account,
@ -2964,21 +2934,13 @@ class RosterWindow:
remove_auth = False remove_auth = False
for (contact, account) in list_: for (contact, account) in list_:
gajim.connections[account].unsubscribe(contact.jid, remove_auth) gajim.connections[account].unsubscribe(contact.jid, remove_auth)
for c in gajim.contacts.get_contacts(account, contact.jid): self.remove_contact(contact.jid, account, backend = True)
self.remove_contact(c.jid, account)
gajim.contacts.remove_jid(account, contact.jid)
self.draw_account(account)
if not remove_auth and contact.sub == 'both': if not remove_auth and contact.sub == 'both':
contact.name = '' contact.name = ''
contact.groups = [] contact.groups = []
contact.sub = 'from' contact.sub = 'from'
gajim.contacts.add_contact(account, contact) gajim.contacts.add_contact(account, contact)
self.add_contact(contact.jid, account) self.add_contact(contact.jid, account)
else:
if _('Not in Roster') in contact.groups:
gajim.events.remove_events(account, contact.jid)
self._readd_contact_to_roster_if_needed(contact, account)
def on_ok2(list_): def on_ok2(list_):
on_ok(False, list_) on_ok(False, list_)