Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephan Erb <steve-e@h3c.de>2008-05-30 21:42:53 +0400
committerStephan Erb <steve-e@h3c.de>2008-05-30 21:42:53 +0400
commit4b6fabadd93ed109f3a10b45bfd8d882fa91e9a6 (patch)
tree5fdac8c3e9811effb27c0b948540b95db47dc339
parent8973b910701c0eb6b122c0823fffa8a70c4ee6b9 (diff)
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
-rw-r--r--src/common/events.py5
-rwxr-xr-xsrc/gajim.py40
-rw-r--r--src/roster_window.py161
3 files changed, 105 insertions, 101 deletions
diff --git a/src/common/events.py b/src/common/events.py
index ac9625783..3658bfe81 100644
--- a/src/common/events.py
+++ b/src/common/events.py
@@ -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 = []):
diff --git a/src/gajim.py b/src/gajim.py
index 05b4154c6..8b765a9bd 100755
--- a/src/gajim.py
+++ b/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)
diff --git a/src/roster_window.py b/src/roster_window.py
index bc5268174..eac24a223 100644
--- a/src/roster_window.py
+++ b/src/roster_window.py
@@ -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