Don't remove contacts from roster when they have pending events.
* update documentation and fix indentation * don't remove offline contacts from roster when we open the last pending, non chat message event * store account and jid per event
This commit is contained in:
parent
8973b91070
commit
4b6fabadd9
|
@ -48,6 +48,9 @@ class Event:
|
|||
self.parameters = parameters
|
||||
self.show_in_roster = show_in_roster
|
||||
self.show_in_systray = show_in_systray
|
||||
# Set when adding the event
|
||||
self.jid = None
|
||||
self.account = None
|
||||
|
||||
class Events:
|
||||
'''Information concerning all events'''
|
||||
|
@ -112,6 +115,8 @@ class Events:
|
|||
self._events[account][jid] = [event]
|
||||
else:
|
||||
self._events[account][jid].append(event)
|
||||
event.jid = jid
|
||||
event.account = account
|
||||
self.fire_event_added(event)
|
||||
|
||||
def remove_events(self, account, jid, event = None, types = []):
|
||||
|
|
40
src/gajim.py
40
src/gajim.py
|
@ -1573,22 +1573,7 @@ class Interface:
|
|||
not name and not groups:
|
||||
if contacts:
|
||||
c = contacts[0]
|
||||
self.roster.remove_contact(c.jid, account)
|
||||
gajim.contacts.remove_jid(account, jid)
|
||||
self.roster.draw_account(account)
|
||||
if gajim.events.get_events(account, c.jid):
|
||||
keyID = ''
|
||||
attached_keys = gajim.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
if jid in attached_keys:
|
||||
keyID = attached_keys[attached_keys.index(jid) + 1]
|
||||
contact = gajim.contacts.create_contact(jid = c.jid,
|
||||
name = '', groups = [_('Not in Roster')],
|
||||
show = 'not in roster', status = '', sub = 'none',
|
||||
keyID = keyID)
|
||||
gajim.contacts.add_contact(account, contact)
|
||||
self.roster.add_contact(contact.jid, account)
|
||||
#FIXME if it was the only one in its group, remove the group
|
||||
self.roster.remove_contact(c.jid, account, backend = True)
|
||||
return
|
||||
elif not contacts:
|
||||
if sub == 'remove':
|
||||
|
@ -1602,7 +1587,7 @@ class Interface:
|
|||
re_add = False
|
||||
# if sub changed: remove and re-add, maybe observer status changed
|
||||
if contacts[0].sub != sub:
|
||||
self.roster.remove_contact(contacts[0].jid, account)
|
||||
self.roster.remove_contact(contacts[0].jid, account, force = True)
|
||||
re_add = True
|
||||
for contact in contacts:
|
||||
if not name:
|
||||
|
@ -1614,7 +1599,6 @@ class Interface:
|
|||
contact.groups = groups
|
||||
if re_add:
|
||||
self.roster.add_contact(jid, account)
|
||||
self.roster.draw_contact(jid, account)
|
||||
if self.remote_ctrl:
|
||||
self.remote_ctrl.raise_signal('RosterInfo', (account, array))
|
||||
|
||||
|
@ -2405,26 +2389,6 @@ class Interface:
|
|||
# Select the contact in roster, it's visible because it has events.
|
||||
self.roster.select_contact(jid, account)
|
||||
|
||||
def remove_first_event(self, account, jid, type_ = None):
|
||||
event = gajim.events.get_first_event(account, jid, type_)
|
||||
self.remove_event(account, jid, event)
|
||||
|
||||
def remove_event(self, account, jid, event):
|
||||
if gajim.events.remove_events(account, jid, event):
|
||||
# No such event found
|
||||
return
|
||||
# no other event?
|
||||
if not len(gajim.events.get_events(account, jid)):
|
||||
contact = gajim.contacts.get_contact_with_highest_priority(account,
|
||||
jid)
|
||||
show_transport = gajim.config.get('show_transports_group')
|
||||
if contact and (contact.show in ('error', 'offline') and \
|
||||
not gajim.config.get('showoffline') or (
|
||||
gajim.jid_is_transport(jid) and not show_transport)):
|
||||
self.roster.remove_contact(contact.jid, account)
|
||||
self.roster.show_title()
|
||||
self.roster.draw_contact(jid, account)
|
||||
|
||||
def handle_event(self, account, fjid, type_):
|
||||
w = None
|
||||
resource = gajim.get_resource_from_jid(fjid)
|
||||
|
|
|
@ -154,11 +154,11 @@ class RosterWindow:
|
|||
def _get_contact_iter(self, jid, account, contact = None, model = None):
|
||||
''' Return a list of gtk.TreeIter of the given contact.
|
||||
|
||||
Keyword arguments:
|
||||
Keyword arguments:
|
||||
jid -- the jid without resource
|
||||
account -- the account
|
||||
account -- the account
|
||||
contact -- the contact (default None)
|
||||
model -- the data model (default TreeFilterModel)
|
||||
model -- the data model (default TreeFilterModel)
|
||||
|
||||
'''
|
||||
if not model:
|
||||
|
@ -220,7 +220,7 @@ class RosterWindow:
|
|||
''' Return True if the given iter is a separator.
|
||||
|
||||
Keyword arguments:
|
||||
model -- the data model
|
||||
model -- the data model
|
||||
iter -- the gtk.TreeIter to test
|
||||
'''
|
||||
if model[titer][0] == 'SEPARATOR':
|
||||
|
@ -231,8 +231,8 @@ class RosterWindow:
|
|||
def _iter_contact_rows(self, model = None):
|
||||
'''Iterate over all contact rows in given model.
|
||||
|
||||
Keyword arguments:
|
||||
model -- the data model (default TreeFilterModel)
|
||||
Keyword argument
|
||||
model -- the data model (default TreeFilterModel)
|
||||
'''
|
||||
if not model:
|
||||
model = self.modelfilter
|
||||
|
@ -328,9 +328,9 @@ class RosterWindow:
|
|||
|
||||
Keyword arguments:
|
||||
contact -- the contact to add
|
||||
account -- the contacts account
|
||||
groups -- list of groups to add the contact to. (default groups in contact.groups).
|
||||
Parameter ignored when big_brother_contact is specified.
|
||||
account -- the contacts account
|
||||
groups -- list of groups to add the contact to. (default groups in contact.groups).
|
||||
Parameter ignored when big_brother_contact is specified.
|
||||
big_brother_contact -- if specified contact is added as child big_brother_contact. (default None)
|
||||
'''
|
||||
added_iters = []
|
||||
|
@ -405,8 +405,8 @@ class RosterWindow:
|
|||
|
||||
Keyword arguments:
|
||||
contact -- the contact to add
|
||||
account -- the contacts account
|
||||
groups -- list of groups to remove the contact from. (default groups in contact.groups).
|
||||
account -- the contacts account
|
||||
groups -- list of groups to remove the contact from. (default groups in contact.groups).
|
||||
|
||||
'''
|
||||
iters = self._get_contact_iter(contact.jid, account, contact, self.model)
|
||||
|
@ -650,7 +650,7 @@ class RosterWindow:
|
|||
return contacts[0][0] # it's contact/big brother with highest priority
|
||||
|
||||
|
||||
def remove_contact(self, jid, account):
|
||||
def remove_contact(self, jid, account, force = False, backend = False):
|
||||
'''Remove contact from roster.
|
||||
|
||||
Remove contact from all its group. Remove empty groups or redraw otherwise.
|
||||
|
@ -661,6 +661,8 @@ class RosterWindow:
|
|||
Keyword arguments:
|
||||
jid -- the contact's jid or SelfJid to remove SelfContact
|
||||
account -- the corresponding account.
|
||||
force -- remove contact even it has pending evens (Default False)
|
||||
backend -- also remove contact instance (Default False)
|
||||
|
||||
'''
|
||||
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
||||
|
@ -669,27 +671,40 @@ class RosterWindow:
|
|||
if not iters:
|
||||
return
|
||||
|
||||
# Remove contact from roster
|
||||
family = gajim.contacts.get_metacontacts_family(account, jid)
|
||||
if family:
|
||||
# We have a family. So we are a metacontact.
|
||||
self._remove_metacontact_family(family, account)
|
||||
else:
|
||||
self._remove_entity(contact, account)
|
||||
if not force and self.contact_has_pending_roster_events(contact, account):
|
||||
# Contact has pending events
|
||||
key = (jid, account)
|
||||
if not key in self.contacts_to_be_removed.keys():
|
||||
self.contacts_to_be_removed[key] = {'backend': backend}
|
||||
return False
|
||||
else:
|
||||
# no more pending events
|
||||
# Remove contact from roster directly
|
||||
family = gajim.contacts.get_metacontacts_family(account, jid)
|
||||
if family:
|
||||
# We have a family. So we are a metacontact.
|
||||
self._remove_metacontact_family(family, account)
|
||||
else:
|
||||
self._remove_entity(contact, account)
|
||||
|
||||
# Draw all groups of the contact
|
||||
groups = contact.groups
|
||||
if contact.is_observer():
|
||||
contact.groups = [_('Observers')]
|
||||
if not groups:
|
||||
groups = [_('General')]
|
||||
for group in groups:
|
||||
self.draw_group(group, account)
|
||||
# Draw all groups of the contact
|
||||
groups = contact.groups
|
||||
if contact.is_observer():
|
||||
contact.groups = [_('Observers')]
|
||||
if not groups:
|
||||
groups = [_('General')]
|
||||
|
||||
if backend:
|
||||
# Remove contact before redrawing, otherwise the old
|
||||
# numbers will still be show
|
||||
gajim.contacts.remove_jid(account, jid)
|
||||
|
||||
for group in groups:
|
||||
self.draw_group(group, account)
|
||||
self.draw_account(account)
|
||||
|
||||
return True
|
||||
|
||||
self.draw_account(account)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def add_groupchat(self, jid, account, status = ''):
|
||||
'''Add groupchat to roster and draw it.
|
||||
|
@ -711,12 +726,7 @@ class RosterWindow:
|
|||
def remove_groupchat(self, jid, account):
|
||||
'''Remove groupchat from roster and redraw account and group.'''
|
||||
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
||||
self.remove_contact(jid, account)
|
||||
gajim.contacts.remove_contact(account, contact)
|
||||
# When we redraw the group in remove_contact the
|
||||
# contact does still exist and so the group is still showing
|
||||
# the old numbers.
|
||||
self.draw_group(_('Groupchats'), account)
|
||||
self.remove_contact(jid, account, force = True, backend = True)
|
||||
return True
|
||||
|
||||
|
||||
|
@ -737,15 +747,9 @@ class RosterWindow:
|
|||
def remove_transport(self, jid, account):
|
||||
'''Remove transport from roster and redraw account and group.'''
|
||||
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
||||
self.remove_contact(jid, account)
|
||||
gajim.contacts.remove_contact(account, contact)
|
||||
# When we redraw the group in remove_contact the
|
||||
# contact does still exist and so the group is still showing
|
||||
# the old numbers.
|
||||
self.draw_group(_('Transports'), account)
|
||||
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
|
||||
|
@ -771,6 +775,7 @@ class RosterWindow:
|
|||
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.
|
||||
|
||||
|
@ -783,7 +788,7 @@ class RosterWindow:
|
|||
groups -- list of Groups to add the contact too.
|
||||
|
||||
'''
|
||||
self.remove_contact(jid, account)
|
||||
self.remove_contact(jid, account, force = True)
|
||||
|
||||
for contact in gajim.contacts.get_contacts(account, jid):
|
||||
for group in groups:
|
||||
|
@ -809,7 +814,7 @@ class RosterWindow:
|
|||
groups -- list of Groups to remove the contact from
|
||||
|
||||
'''
|
||||
self.remove_contact(jid, account)
|
||||
self.remove_contact(jid, account, force = True)
|
||||
|
||||
for contact in gajim.contacts.get_contacts(account, jid):
|
||||
for group in groups:
|
||||
|
@ -843,6 +848,9 @@ class RosterWindow:
|
|||
|
||||
#FIXME: integrate into add_contact()
|
||||
def add_to_not_in_the_roster(self, account, jid, nick = '', resource = ''):
|
||||
print "add to not in the roster"
|
||||
import traceback
|
||||
traceback.print_stack()
|
||||
keyID = ''
|
||||
attached_keys = gajim.config.get_per('accounts', account,
|
||||
'attached_gpg_keys').split()
|
||||
|
@ -1238,7 +1246,7 @@ class RosterWindow:
|
|||
|
||||
|
||||
def select_contact(self, jid, account):
|
||||
'''Select contact in roster. If contact is hidden but has eventsi,
|
||||
'''Select contact in roster. If contact is hidden but has events,
|
||||
show him.'''
|
||||
# Refiltering SHOULD NOT be needed:
|
||||
# When a contact gets a new event he will be redrawn and his
|
||||
|
@ -1299,16 +1307,22 @@ class RosterWindow:
|
|||
self.filtering = True
|
||||
self.modelfilter.refilter()
|
||||
self.filtering = False
|
||||
|
||||
def contact_is_visible(self, contact, account):
|
||||
# show it if pending events
|
||||
|
||||
def contact_has_pending_roster_events(self, contact, account):
|
||||
''' Return True if the contact or one if it resources has pending events'''
|
||||
# jid has pending events
|
||||
if gajim.events.get_nb_roster_events(account, contact.jid) > 0:
|
||||
return True
|
||||
# count events from all resources
|
||||
# check events of all resources
|
||||
for contact_ in gajim.contacts.get_contacts(account, contact.jid):
|
||||
if contact_.resource and gajim.events.get_nb_roster_events(account,
|
||||
contact_.get_full_jid()) > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def contact_is_visible(self, contact, account):
|
||||
if self.contact_has_pending_roster_events(contact, account):
|
||||
return True
|
||||
# XEP-0162
|
||||
hide = contact.is_hidden_from_roster()
|
||||
if hide and contact.sub != 'from':
|
||||
|
@ -1639,6 +1653,24 @@ class RosterWindow:
|
|||
minimize = bm['minimize'] in ('1', 'true')
|
||||
gajim.interface.join_gc_room(account, jid, bm['nick'],
|
||||
bm['password'], minimize = minimize)
|
||||
|
||||
def on_event_removed(self, event_list):
|
||||
'''Remove contacts on last events removed.
|
||||
|
||||
Only performed if removal was requested before but the contact
|
||||
still had pending events
|
||||
'''
|
||||
no_more_pending = ((event.jid.split('/')[0], event.account) for event in event_list
|
||||
if len(gajim.events.get_events(event.account, event.jid)))
|
||||
|
||||
for jid, account in no_more_pending:
|
||||
self.draw_contact(jid, account)
|
||||
# Remove contacts in roster if removal was requested
|
||||
key = (jid, account)
|
||||
if key in self.contacts_to_be_removed.keys():
|
||||
del self.contacts_to_be_removed[key]
|
||||
self.remove_contact(jid, account, backend = True)
|
||||
self.show_title()
|
||||
|
||||
def open_event(self, account, jid, event):
|
||||
'''If an event was handled, return True, else return False'''
|
||||
|
@ -1648,31 +1680,31 @@ class RosterWindow:
|
|||
dialogs.SingleMessageWindow(account, jid,
|
||||
action='receive', from_whom=jid, subject=data[1], message=data[0],
|
||||
resource=data[5], session=data[8], form_node=data[9])
|
||||
gajim.interface.remove_first_event(account, jid, event.type_)
|
||||
gajim.events.get_first_event(account, jid, event.type_)
|
||||
return True
|
||||
elif event.type_ == 'file-request':
|
||||
contact = gajim.contacts.get_contact_with_highest_priority(account,
|
||||
jid)
|
||||
gajim.interface.remove_first_event(account, jid, event.type_)
|
||||
gajim.events.get_first_event(account, jid, event.type_)
|
||||
ft.show_file_request(account, contact, data)
|
||||
return True
|
||||
elif event.type_ in ('file-request-error', 'file-send-error'):
|
||||
gajim.interface.remove_first_event(account, jid, event.type_)
|
||||
gajim.events.get_first_event(account, jid, event.type_)
|
||||
ft.show_send_error(data)
|
||||
return True
|
||||
elif event.type_ in ('file-error', 'file-stopped'):
|
||||
gajim.interface.remove_first_event(account, jid, event.type_)
|
||||
gajim.events.get_first_event(account, jid, event.type_)
|
||||
ft.show_stopped(jid, data)
|
||||
return True
|
||||
elif event.type_ == 'file-completed':
|
||||
gajim.interface.remove_first_event(account, jid, event.type_)
|
||||
gajim.events.get_first_event(account, jid, event.type_)
|
||||
ft.show_completed(jid, data)
|
||||
return True
|
||||
elif event.type_ == 'gc-invitation':
|
||||
dialogs.InvitationReceivedDialog(account, data[0], jid, data[2],
|
||||
data[1])
|
||||
gajim.interface.remove_first_event(account, jid, event.type_)
|
||||
return True
|
||||
gajim.events.get_first_event(account, jid, event.type_)
|
||||
return True
|
||||
return False
|
||||
|
||||
################################################################################
|
||||
|
@ -2311,14 +2343,14 @@ 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:
|
||||
# We remove the server contact
|
||||
# remove it from treeview
|
||||
gajim.connections[account].unsubscribe(contact.jid)
|
||||
self.remove_contact(contact.jid, account)
|
||||
gajim.contacts.remove_contact(account, contact)
|
||||
self.remove_contact(contact.jid, account, backend = True)
|
||||
return
|
||||
|
||||
def remove(list_):
|
||||
|
@ -2326,9 +2358,7 @@ class RosterWindow:
|
|||
full_jid = contact.get_full_jid()
|
||||
gajim.connections[account].unsubscribe_agent(full_jid)
|
||||
# remove transport from treeview
|
||||
self.remove_contact(contact.jid, account)
|
||||
gajim.contacts.remove_jid(account, contact.jid)
|
||||
gajim.contacts.remove_contact(account, contact)
|
||||
self.remove_contact(contact.jid, account, backend = True)
|
||||
|
||||
# Check if there are unread events from some contacts
|
||||
has_unread_events = False
|
||||
|
@ -5751,6 +5781,11 @@ class RosterWindow:
|
|||
# Workaroung: For strange reasons signal is behaving like row-changed
|
||||
self._toggeling_row = False
|
||||
|
||||
# Remove contact from roster when last event opened
|
||||
# { (contact, account): { backend: boolean }
|
||||
self.contacts_to_be_removed = {}
|
||||
gajim.events.event_removed_subscribe(self.on_event_removed)
|
||||
|
||||
# when this value become 0 we quit main application. If it's more than 0
|
||||
# it means we are waiting for this number of accounts to disconnect before
|
||||
# quitting
|
||||
|
|
Loading…
Reference in New Issue