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.parameters = parameters
|
||||||
self.show_in_roster = show_in_roster
|
self.show_in_roster = show_in_roster
|
||||||
self.show_in_systray = show_in_systray
|
self.show_in_systray = show_in_systray
|
||||||
|
# Set when adding the event
|
||||||
|
self.jid = None
|
||||||
|
self.account = None
|
||||||
|
|
||||||
class Events:
|
class Events:
|
||||||
'''Information concerning all events'''
|
'''Information concerning all events'''
|
||||||
|
@ -112,6 +115,8 @@ class Events:
|
||||||
self._events[account][jid] = [event]
|
self._events[account][jid] = [event]
|
||||||
else:
|
else:
|
||||||
self._events[account][jid].append(event)
|
self._events[account][jid].append(event)
|
||||||
|
event.jid = jid
|
||||||
|
event.account = account
|
||||||
self.fire_event_added(event)
|
self.fire_event_added(event)
|
||||||
|
|
||||||
def remove_events(self, account, jid, event = None, types = []):
|
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:
|
not name and not groups:
|
||||||
if contacts:
|
if contacts:
|
||||||
c = contacts[0]
|
c = contacts[0]
|
||||||
self.roster.remove_contact(c.jid, account)
|
self.roster.remove_contact(c.jid, account, backend = True)
|
||||||
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
|
|
||||||
return
|
return
|
||||||
elif not contacts:
|
elif not contacts:
|
||||||
if sub == 'remove':
|
if sub == 'remove':
|
||||||
|
@ -1602,7 +1587,7 @@ class Interface:
|
||||||
re_add = False
|
re_add = False
|
||||||
# if sub changed: remove and re-add, maybe observer status changed
|
# if sub changed: remove and re-add, maybe observer status changed
|
||||||
if contacts[0].sub != sub:
|
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
|
re_add = True
|
||||||
for contact in contacts:
|
for contact in contacts:
|
||||||
if not name:
|
if not name:
|
||||||
|
@ -1614,7 +1599,6 @@ class Interface:
|
||||||
contact.groups = groups
|
contact.groups = groups
|
||||||
if re_add:
|
if re_add:
|
||||||
self.roster.add_contact(jid, account)
|
self.roster.add_contact(jid, account)
|
||||||
self.roster.draw_contact(jid, account)
|
|
||||||
if self.remote_ctrl:
|
if self.remote_ctrl:
|
||||||
self.remote_ctrl.raise_signal('RosterInfo', (account, array))
|
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.
|
# Select the contact in roster, it's visible because it has events.
|
||||||
self.roster.select_contact(jid, account)
|
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_):
|
def handle_event(self, account, fjid, type_):
|
||||||
w = None
|
w = None
|
||||||
resource = gajim.get_resource_from_jid(fjid)
|
resource = gajim.get_resource_from_jid(fjid)
|
||||||
|
|
|
@ -231,7 +231,7 @@ class RosterWindow:
|
||||||
def _iter_contact_rows(self, model = None):
|
def _iter_contact_rows(self, model = None):
|
||||||
'''Iterate over all contact rows in given model.
|
'''Iterate over all contact rows in given model.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword argument
|
||||||
model -- the data model (default TreeFilterModel)
|
model -- the data model (default TreeFilterModel)
|
||||||
'''
|
'''
|
||||||
if not model:
|
if not model:
|
||||||
|
@ -650,7 +650,7 @@ class RosterWindow:
|
||||||
return contacts[0][0] # it's contact/big brother with highest priority
|
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 roster.
|
||||||
|
|
||||||
Remove contact from all its group. Remove empty groups or redraw otherwise.
|
Remove contact from all its group. Remove empty groups or redraw otherwise.
|
||||||
|
@ -661,6 +661,8 @@ class RosterWindow:
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
jid -- the contact's jid or SelfJid to remove SelfContact
|
jid -- the contact's jid or SelfJid to remove SelfContact
|
||||||
account -- the corresponding account.
|
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)
|
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
||||||
|
@ -669,7 +671,15 @@ class RosterWindow:
|
||||||
if not iters:
|
if not iters:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Remove contact from roster
|
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)
|
family = gajim.contacts.get_metacontacts_family(account, jid)
|
||||||
if family:
|
if family:
|
||||||
# We have a family. So we are a metacontact.
|
# We have a family. So we are a metacontact.
|
||||||
|
@ -683,9 +693,14 @@ class RosterWindow:
|
||||||
contact.groups = [_('Observers')]
|
contact.groups = [_('Observers')]
|
||||||
if not groups:
|
if not groups:
|
||||||
groups = [_('General')]
|
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:
|
for group in groups:
|
||||||
self.draw_group(group, account)
|
self.draw_group(group, account)
|
||||||
|
|
||||||
self.draw_account(account)
|
self.draw_account(account)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -711,12 +726,7 @@ class RosterWindow:
|
||||||
def remove_groupchat(self, jid, account):
|
def remove_groupchat(self, jid, account):
|
||||||
'''Remove groupchat from roster and redraw account and group.'''
|
'''Remove groupchat from roster and redraw account and group.'''
|
||||||
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
||||||
self.remove_contact(jid, account)
|
self.remove_contact(jid, account, force = True, backend = True)
|
||||||
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)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -737,15 +747,9 @@ class RosterWindow:
|
||||||
def remove_transport(self, jid, account):
|
def remove_transport(self, jid, account):
|
||||||
'''Remove transport from roster and redraw account and group.'''
|
'''Remove transport from roster and redraw account and group.'''
|
||||||
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
||||||
self.remove_contact(jid, account)
|
self.remove_contact(jid, account, force = True, backend = True)
|
||||||
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)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
#FIXME:
|
#FIXME:
|
||||||
# We need to define a generic way to keep contacts in roster
|
# We need to define a generic way to keep contacts in roster
|
||||||
# as long as they have pending events or as we
|
# as long as they have pending events or as we
|
||||||
|
@ -771,6 +775,7 @@ class RosterWindow:
|
||||||
gajim.contacts.add_contact(account, c)
|
gajim.contacts.add_contact(account, c)
|
||||||
self.add_contact(contact.jid, account)
|
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.
|
||||||
|
|
||||||
|
@ -783,7 +788,7 @@ class RosterWindow:
|
||||||
groups -- list of Groups to add the contact too.
|
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 contact in gajim.contacts.get_contacts(account, jid):
|
||||||
for group in groups:
|
for group in groups:
|
||||||
|
@ -809,7 +814,7 @@ class RosterWindow:
|
||||||
groups -- list of Groups to remove the contact from
|
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 contact in gajim.contacts.get_contacts(account, jid):
|
||||||
for group in groups:
|
for group in groups:
|
||||||
|
@ -843,6 +848,9 @@ class RosterWindow:
|
||||||
|
|
||||||
#FIXME: integrate into add_contact()
|
#FIXME: integrate into add_contact()
|
||||||
def add_to_not_in_the_roster(self, account, jid, nick = '', resource = ''):
|
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 = ''
|
keyID = ''
|
||||||
attached_keys = gajim.config.get_per('accounts', account,
|
attached_keys = gajim.config.get_per('accounts', account,
|
||||||
'attached_gpg_keys').split()
|
'attached_gpg_keys').split()
|
||||||
|
@ -1238,7 +1246,7 @@ class RosterWindow:
|
||||||
|
|
||||||
|
|
||||||
def select_contact(self, jid, account):
|
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.'''
|
show him.'''
|
||||||
# Refiltering SHOULD NOT be needed:
|
# Refiltering SHOULD NOT be needed:
|
||||||
# When a contact gets a new event he will be redrawn and his
|
# When a contact gets a new event he will be redrawn and his
|
||||||
|
@ -1300,15 +1308,21 @@ class RosterWindow:
|
||||||
self.modelfilter.refilter()
|
self.modelfilter.refilter()
|
||||||
self.filtering = False
|
self.filtering = False
|
||||||
|
|
||||||
def contact_is_visible(self, contact, account):
|
def contact_has_pending_roster_events(self, contact, account):
|
||||||
# show it if pending events
|
''' 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:
|
if gajim.events.get_nb_roster_events(account, contact.jid) > 0:
|
||||||
return True
|
return True
|
||||||
# count events from all resources
|
# check events of all resources
|
||||||
for contact_ in gajim.contacts.get_contacts(account, contact.jid):
|
for contact_ in gajim.contacts.get_contacts(account, contact.jid):
|
||||||
if contact_.resource and gajim.events.get_nb_roster_events(account,
|
if contact_.resource and gajim.events.get_nb_roster_events(account,
|
||||||
contact_.get_full_jid()) > 0:
|
contact_.get_full_jid()) > 0:
|
||||||
return True
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def contact_is_visible(self, contact, account):
|
||||||
|
if self.contact_has_pending_roster_events(contact, account):
|
||||||
|
return True
|
||||||
# XEP-0162
|
# XEP-0162
|
||||||
hide = contact.is_hidden_from_roster()
|
hide = contact.is_hidden_from_roster()
|
||||||
if hide and contact.sub != 'from':
|
if hide and contact.sub != 'from':
|
||||||
|
@ -1640,6 +1654,24 @@ class RosterWindow:
|
||||||
gajim.interface.join_gc_room(account, jid, bm['nick'],
|
gajim.interface.join_gc_room(account, jid, bm['nick'],
|
||||||
bm['password'], minimize = minimize)
|
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):
|
def open_event(self, account, jid, event):
|
||||||
'''If an event was handled, return True, else return False'''
|
'''If an event was handled, return True, else return False'''
|
||||||
data = event.parameters
|
data = event.parameters
|
||||||
|
@ -1648,30 +1680,30 @@ class RosterWindow:
|
||||||
dialogs.SingleMessageWindow(account, jid,
|
dialogs.SingleMessageWindow(account, jid,
|
||||||
action='receive', from_whom=jid, subject=data[1], message=data[0],
|
action='receive', from_whom=jid, subject=data[1], message=data[0],
|
||||||
resource=data[5], session=data[8], form_node=data[9])
|
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
|
return True
|
||||||
elif event.type_ == 'file-request':
|
elif event.type_ == 'file-request':
|
||||||
contact = gajim.contacts.get_contact_with_highest_priority(account,
|
contact = gajim.contacts.get_contact_with_highest_priority(account,
|
||||||
jid)
|
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)
|
ft.show_file_request(account, contact, data)
|
||||||
return True
|
return True
|
||||||
elif event.type_ in ('file-request-error', 'file-send-error'):
|
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)
|
ft.show_send_error(data)
|
||||||
return True
|
return True
|
||||||
elif event.type_ in ('file-error', 'file-stopped'):
|
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)
|
ft.show_stopped(jid, data)
|
||||||
return True
|
return True
|
||||||
elif event.type_ == 'file-completed':
|
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)
|
ft.show_completed(jid, data)
|
||||||
return True
|
return True
|
||||||
elif event.type_ == 'gc-invitation':
|
elif event.type_ == 'gc-invitation':
|
||||||
dialogs.InvitationReceivedDialog(account, data[0], jid, data[2],
|
dialogs.InvitationReceivedDialog(account, data[0], jid, data[2],
|
||||||
data[1])
|
data[1])
|
||||||
gajim.interface.remove_first_event(account, jid, event.type_)
|
gajim.events.get_first_event(account, jid, event.type_)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -2311,14 +2343,14 @@ 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:
|
||||||
# We remove the server contact
|
# We remove the server contact
|
||||||
# remove it from treeview
|
# remove it from treeview
|
||||||
gajim.connections[account].unsubscribe(contact.jid)
|
gajim.connections[account].unsubscribe(contact.jid)
|
||||||
self.remove_contact(contact.jid, account)
|
self.remove_contact(contact.jid, account, backend = True)
|
||||||
gajim.contacts.remove_contact(account, contact)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def remove(list_):
|
def remove(list_):
|
||||||
|
@ -2326,9 +2358,7 @@ class RosterWindow:
|
||||||
full_jid = contact.get_full_jid()
|
full_jid = contact.get_full_jid()
|
||||||
gajim.connections[account].unsubscribe_agent(full_jid)
|
gajim.connections[account].unsubscribe_agent(full_jid)
|
||||||
# remove transport from treeview
|
# remove transport from treeview
|
||||||
self.remove_contact(contact.jid, account)
|
self.remove_contact(contact.jid, account, backend = True)
|
||||||
gajim.contacts.remove_jid(account, contact.jid)
|
|
||||||
gajim.contacts.remove_contact(account, contact)
|
|
||||||
|
|
||||||
# Check if there are unread events from some contacts
|
# Check if there are unread events from some contacts
|
||||||
has_unread_events = False
|
has_unread_events = False
|
||||||
|
@ -5751,6 +5781,11 @@ class RosterWindow:
|
||||||
# Workaroung: For strange reasons signal is behaving like row-changed
|
# Workaroung: For strange reasons signal is behaving like row-changed
|
||||||
self._toggeling_row = False
|
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
|
# 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
|
# it means we are waiting for this number of accounts to disconnect before
|
||||||
# quitting
|
# quitting
|
||||||
|
|
Loading…
Reference in New Issue