From d5bbc403c939969803ebd34ce2037a370d803015 Mon Sep 17 00:00:00 2001 From: Stephan Erb Date: Tue, 10 Jun 2008 21:18:55 +0000 Subject: [PATCH] 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" --- src/gajim.py | 25 +++++++++------ src/roster_window.py | 74 +++++++++++--------------------------------- 2 files changed, 33 insertions(+), 66 deletions(-) diff --git a/src/gajim.py b/src/gajim.py index 20867a677..4d4562852 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -609,7 +609,11 @@ class Interface: def handle_event_notify(self, account, array): # 'NOTIFY' (account, (jid, status, status message, resource, priority, # 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', 'invisible'] # Ignore invalid show @@ -664,17 +668,20 @@ class Interface: if contact1: if contact1.show in statuss: old_show = statuss.index(contact1.show) + # nick changed if contact_nickname is not None and \ contact1.contact_name != contact_nickname: contact1.contact_name = contact_nickname self.roster.draw_contact(jid, account) + if old_show == new_show and contact1.status == status_message and \ contact1.priority == priority: # no change return else: contact1 = gajim.contacts.get_first_contact_from_jid(account, ji) 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: return contact1 = gajim.contacts.create_contact(jid = ji, @@ -687,14 +694,15 @@ class Interface: lcontact.append(contact1) elif contact1.show in statuss: old_show = statuss.index(contact1.show) + # FIXME: What Am I? if (resources != [''] and (len(lcontact) != 1 or lcontact[0].show != 'offline')) and jid.find('@') > 0: old_show = 0 contact1 = gajim.contacts.copy_contact(contact1) lcontact.append(contact1) 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: # It's not an agent @@ -725,6 +733,7 @@ class Interface: # We're connected since more that 30 seconds contact1.last_status_time = time.localtime() contact1.contact_nickname = contact_nickname + if gajim.jid_is_transport(jid): # It must be an agent if ji in jid_list: @@ -852,10 +861,7 @@ class Interface: if jid in gajim.contacts.get_jid_list(account): c = gajim.contacts.get_first_contact_from_jid(account, jid) c.resource = array[1] - self.roster.remove_contact(c.jid, account) - if _('Not in Roster') in c.groups: - c.groups.remove(_('Not in Roster')) - self.roster.add_contact(c.jid, account) + self.roster.remove_contact_from_groups(c.jid, account, [('Not in Roster'),]) else: keyID = '' attached_keys = gajim.config.get_per('accounts', account, @@ -922,8 +928,7 @@ class Interface: if c.jid in gajim.to_be_removed[account]: # This way we'll really remove it gajim.to_be_removed[account].remove(c.jid) - gajim.contacts.remove_jid(account, c.jid) - self.roster.remove_contact(c.jid, account) + self.roster.remove_contact(c.jid, account, backend = True) def handle_event_register_agent_info(self, account, array): # ('REGISTER_AGENT_INFO', account, (agent, infos, is_form)) diff --git a/src/roster_window.py b/src/roster_window.py index 13c47ee3c..4113a76c7 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -760,33 +760,6 @@ class RosterWindow: self.remove_contact(jid, account, force = True, backend = 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): '''Add contact to given groups and redraw them. @@ -1165,13 +1138,15 @@ class RosterWindow: Show contact if it has pending events ''' 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) if family: # There might be a new big brother self._recalibrate_metacontact_family(family, account) - else: - self.draw_contact(jid, account) + self.draw_contact(jid, account) self.draw_account(account) for group in contact.groups: @@ -1496,7 +1471,7 @@ class RosterWindow: gajim.groups[account] = {} for jid in array.keys(): # 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 gajim.contacts.remove_jid(account, jid, remove_meta=False) jids = jid.split('/') @@ -1827,6 +1802,7 @@ class RosterWindow: # We come back from invisible, join bookmarks gajim.interface.auto_join_bookmarks(account) + def chg_contact_status(self, contact, show, status, account): '''When a contact changes his or her status''' contact_instances = gajim.contacts.get_contacts(account, contact.jid) @@ -1834,10 +1810,13 @@ class RosterWindow: contact.status = status # name is to show in conversation window name = contact.get_shown_name() - + + # The contact has several resources if len(contact_instances) > 1: if contact.resource != '': name += '/' + contact.resource + + # Remove resource when going offline if show in ('offline', 'error') and \ len(gajim.events.get_events(account, contact.get_full_jid())) == 0: jid_with_resource = contact.jid + '/' + contact.resource @@ -1848,13 +1827,13 @@ class RosterWindow: for ctrl in win.get_controls(jid_with_resource, account): ctrl.update_ui() win.redraw_tab(ctrl) - gajim.contacts.remove_contact(account, contact) + elif contact.jid == gajim.get_jid_from_account(account) and \ - show == 'offline': - # Our SelfContact went offline. Remove him from roster and contacts - self.remove_contact(contact.jid, account) - gajim.contacts.remove_contact(account, contact) + show in ('offline', 'error'): + # SelfContact went offline. Remove him when last pending message was read + self.remove_contact(contact.jid, account, backend = True) + # print status in chat window and update status/GPG image if gajim.interface.msg_win_mgr.has_window(contact.jid, account): win = gajim.interface.msg_win_mgr.get_window(contact.jid, account) @@ -1909,8 +1888,7 @@ class RosterWindow: # Remove SelfContact from roster and remove it. # It might be gone when we return self_jid = gajim.get_jid_from_account(account) - self.remove_contact(self_jid, account) - gajim.contacts.remove_jid(account, self_jid) + self.remove_contact(self_jid, account, backend = True) self.actions_menu_needs_rebuild = True self.update_status_combobox() # 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_): '''When an agent is requested to be removed. list_ is a list of (contact, account) tuple''' - # FIXME remove transport contacts for (contact, account) in list_: if gajim.config.get_per('accounts', account, 'hostname') == \ contact.jid: @@ -2579,16 +2556,9 @@ class RosterWindow: for contact in gajim.contacts.get_contacts_from_group(account, group): if not dlg.is_checked(): 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: gajim.connections[account].unsubscribe(contact.jid) - for c in gajim.contacts.get_contacts(account, contact.jid): - 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) + self.remove_contact(contact.jid, account, backend = True) def on_assign_pgp_key(self, widget, contact, account): attached_keys = gajim.config.get_per('accounts', account, @@ -2964,21 +2934,13 @@ class RosterWindow: remove_auth = False for (contact, account) in list_: gajim.connections[account].unsubscribe(contact.jid, remove_auth) - for c in gajim.contacts.get_contacts(account, contact.jid): - self.remove_contact(c.jid, account) - gajim.contacts.remove_jid(account, contact.jid) - self.draw_account(account) + self.remove_contact(contact.jid, account, backend = True) if not remove_auth and contact.sub == 'both': contact.name = '' contact.groups = [] contact.sub = 'from' gajim.contacts.add_contact(account, contact) 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_): on_ok(False, list_)