Fixing a few modelfilter bugs.

* Show all groups in merged accounts view that have online contacts. Fixes #3890
 * Allow metacontacts over several accounts. Fixes #3889
 * Fix on_drop_in_group when two accounts in merged view have the same contact
 * Fix potential traceback when receiving a message
This commit is contained in:
Stephan Erb 2008-04-26 10:18:33 +00:00
parent 613753f308
commit 8929f4e630
1 changed files with 116 additions and 59 deletions

View File

@ -298,7 +298,8 @@ class RosterWindow:
print "" print ""
def _add_entity(self, contact, account, groups = None, big_brother_contact = None): def _add_entity(self, contact, account, groups = None, big_brother_contact = None,
big_brother_account = None):
'''Add the given contact to roster data model. '''Add the given contact to roster data model.
Contact is added regardless if he is already in roster or not. Contact is added regardless if he is already in roster or not.
@ -316,7 +317,7 @@ class RosterWindow:
# Add contact under big brother # Add contact under big brother
parent_iters = self._get_contact_iter(big_brother_contact.jid, parent_iters = self._get_contact_iter(big_brother_contact.jid,
account, self.model) big_brother_account, self.model)
assert len(parent_iters) > 0,\ assert len(parent_iters) > 0,\
"Big brother is not yet in roster!" "Big brother is not yet in roster!"
@ -356,6 +357,11 @@ class RosterWindow:
i_ = self.model.append(child_iterG, (None, contact.get_shown_name(), i_ = self.model.append(child_iterG, (None, contact.get_shown_name(),
typestr, contact.jid, account, None, None)) typestr, contact.jid, account, None, None))
added_iters.append(i_) added_iters.append(i_)
# Restore the group expand state
if group not in gajim.groups[account]:
# FIXME: care about expand/collapse state
gajim.groups[account][group] = {'expand': True}
assert len(added_iters), "%s has not been added to roster!" % contact.jid assert len(added_iters), "%s has not been added to roster!" % contact.jid
return added_iters return added_iters
@ -406,7 +412,7 @@ class RosterWindow:
return True return True
def _add_metacontact_family(self, family): def _add_metacontact_family(self, family, account):
'''Add the give Metacontact family to roster data model. '''Add the give Metacontact family to roster data model.
Add Big Brother to his groups and all others under him. Add Big Brother to his groups and all others under him.
@ -416,17 +422,27 @@ class RosterWindow:
Keyword arguments: Keyword arguments:
family -- the family, see Contacts.get_metacontacts_family() family -- the family, see Contacts.get_metacontacts_family()
''' '''
big_brother_data = gajim.contacts.get_metacontacts_big_brother(family)
if self.regroup:
# group all together
nearby_family = family
else:
# we want one nearby_family per account
nearby_family = [data for data in family
if account == data['account']]
big_brother_data = gajim.contacts.get_metacontacts_big_brother(nearby_family)
big_brother_jid = big_brother_data['jid'] big_brother_jid = big_brother_data['jid']
big_brother_account = big_brother_data['account'] big_brother_account = big_brother_data['account']
big_brother_contact = gajim.contacts.get_first_contact_from_jid(big_brother_account, big_brother_jid) big_brother_contact = gajim.contacts.get_first_contact_from_jid(big_brother_account, big_brother_jid)
assert len(self._get_contact_iter(big_brother_jid, big_brother_account, self.model)) == 0,\ assert len(self._get_contact_iter(big_brother_jid, big_brother_account, self.model)) == 0,\
"Big brother %s already in roster" % big_brother_jid "Big brother %s already in roster \n Family: %s" % (big_brother_jid, family)
self._add_entity(big_brother_contact, big_brother_account) self._add_entity(big_brother_contact, big_brother_account)
brothers = [] brothers = []
for data in family: # Filter family members
for data in nearby_family:
if data == big_brother_data: if data == big_brother_data:
continue # already added continue # already added
@ -437,34 +453,46 @@ class RosterWindow:
if not _contact: if not _contact:
# Corresponding account is not connected # Corresponding account is not connected
continue continue
assert len(self._get_contact_iter(_jid, _account, self.model)) == 0,\ assert len(self._get_contact_iter(_jid, _account, self.model)) == 0,\
"%s already in roster" % _jid "%s already in roster. \n Family: " % (_jid, nearby_family)
self._add_entity(_contact, _account, big_brother_contact = big_brother_contact) self._add_entity(_contact, _account, big_brother_contact = big_brother_contact,
big_brother_account = big_brother_account)
brothers.append((_contact, _account)) brothers.append((_contact, _account))
brothers.insert(0, (big_brother_contact, big_brother_account)) brothers.insert(0, (big_brother_contact, big_brother_account))
return brothers return brothers
def _remove_metacontact_family(self, family): def _remove_metacontact_family(self, family, account):
'''Remove the give Metacontact family from roster data model. '''Remove the give Metacontact family from roster data model.
See Contacts.get_metacontacts_family() and RosterWindow._remove_entity() See Contacts.get_metacontacts_family() and RosterWindow._remove_entity()
''' '''
if self.regroup:
# remove all
nearby_family = family
else:
# remove nearby_family per account
nearby_family = [data for data in family
if account == data['account']]
# Family might has changed (actual big brother not on top). # Family might has changed (actual big brother not on top).
# Remove in correct order: Childs first # Remove childs first then big brother
for data in family: family_in_roster = False
for data in nearby_family:
_account = data['account'] _account = data['account']
_jid = data['jid'] _jid = data['jid']
_contact = gajim.contacts.get_first_contact_from_jid(_account, _jid) _contact = gajim.contacts.get_first_contact_from_jid(_account, _jid)
if not _contact:
# Corresponding account is not online
continue
iters = self._get_contact_iter(_jid, _account, self.model) iters = self._get_contact_iter(_jid, _account, self.model)
assert iters, "%s shall be removed but is not in roster" % _jid if not iters or not _contact:
# Family might not be up to date.
# Only try to remove what is actually in the roster
continue
assert iters, "%s shall be removed but is not in roster \n Family: %s" % (_jid, family)
family_in_roster = True
parent_iter = self.model.iter_parent(iters[0]) parent_iter = self.model.iter_parent(iters[0])
parent_type = self.model[parent_iter][C_TYPE] parent_type = self.model[parent_iter][C_TYPE]
@ -480,7 +508,10 @@ class RosterWindow:
assert ok, "%s was not removed" % _jid assert ok, "%s was not removed" % _jid
assert len(self._get_contact_iter(_jid, _account, self.model)) == 0,\ assert len(self._get_contact_iter(_jid, _account, self.model)) == 0,\
"%s is removed but still in roster" % _jid "%s is removed but still in roster" % _jid
if not family_in_roster:
return False
iters = self._get_contact_iter(old_big_jid, old_big_account, self.model) iters = self._get_contact_iter(old_big_jid, old_big_account, self.model)
assert len(iters) > 0, "Old Big Brother %s is not in roster anymore" % old_big_jid assert len(iters) > 0, "Old Big Brother %s is not in roster anymore" % old_big_jid
assert not self.model.iter_children(iters[0]),\ assert not self.model.iter_children(iters[0]),\
@ -558,14 +589,17 @@ class RosterWindow:
contacts = [] contacts = []
if family: if family:
# We have a family. So we are a metacontact. # We have a family. So we are a metacontact.
# Add our whole family # Add all family members that we shall be grouped with
contacts = self._add_metacontact_family(family) if self.regroup:
# remove existing family members to regroup them
self._remove_metacontact_family(family, account)
contacts = self._add_metacontact_family(family, account)
else: else:
# We are a normal contact # We are a normal contact
contacts = [(contact, account),] contacts = [(contact, account),]
self._add_entity(contact, account) self._add_entity(contact, account)
# Draw all groups of the contact # Draw the contact and its groups contact
if contact.is_transport(): if contact.is_transport():
contact.groups = [_('Transports')] contact.groups = [_('Transports')]
if is_observer: if is_observer:
@ -573,24 +607,14 @@ class RosterWindow:
groups = contact.groups groups = contact.groups
if not groups: if not groups:
groups = [_('General')] groups = [_('General')]
for group in groups:
# Restore the group expand state
if group not in gajim.groups[account]:
#if account + group in self.collapsed_rows:
#ishidden = False
#else:
ishidden = True
gajim.groups[account][group] = {'expand': ishidden}
if not self.starting:
self.draw_group(group, account)
if not self.starting: if not self.starting:
for c, acc in contacts: for c, acc in contacts:
self.draw_contact(c.jid, acc) self.draw_contact(c.jid, acc)
self.draw_avatar(c.jid, acc) self.draw_avatar(c.jid, acc)
for group in groups:
self.draw_group(group, account)
self.draw_account(account) self.draw_account(account)
return contacts[0][0] # it's contact/big brother with highest priority return contacts[0][0] # it's contact/big brother with highest priority
@ -617,7 +641,7 @@ class RosterWindow:
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.
self._remove_metacontact_family(family) self._remove_metacontact_family(family, account)
else: else:
self._remove_entity(contact, account) self._remove_entity(contact, account)
@ -730,7 +754,7 @@ class RosterWindow:
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:
if group not in contact.groups: if group not in contact.groups:
# statement needed for drap from meta to group # we might be dropped from meta to group
contact.groups.append(group) contact.groups.append(group)
gajim.connections[account].update_contact(jid, contact.name, gajim.connections[account].update_contact(jid, contact.name,
contact.groups) contact.groups)
@ -961,7 +985,16 @@ class RosterWindow:
brothers = [] brothers = []
family = gajim.contacts.get_metacontacts_family(account, jid) family = gajim.contacts.get_metacontacts_family(account, jid)
if family: # Are we a metacontact (have a familiy) if family: # Are we a metacontact (have a familiy)
big_brother_data = gajim.contacts.get_metacontacts_big_brother(family)
if self.regroup:
# group all together
nearby_family = family
else:
# we want one nearby_family per account
nearby_family = [data for data in family
if account == data['account']]
big_brother_data = gajim.contacts.get_metacontacts_big_brother(nearby_family)
big_brother_jid = big_brother_data['jid'] big_brother_jid = big_brother_data['jid']
big_brother_account = big_brother_data['account'] big_brother_account = big_brother_data['account']
@ -975,8 +1008,8 @@ class RosterWindow:
else: else:
# We are the new big brother but haven't been before # We are the new big brother but haven't been before
# Remove us and all our brothers and then re-add us so that # Remove us and all our brothers and then re-add us so that
self._remove_metacontact_family(family) self._remove_metacontact_family(family, account)
brothers = self._add_metacontact_family(family) brothers = self._add_metacontact_family(family, account)
big_brother_c, big_brother_acc = brothers[0] big_brother_c, big_brother_acc = brothers[0]
brothers = brothers[1:] brothers = brothers[1:]
self.draw_avatar(big_brother_c.jid, big_brother_acc) self.draw_avatar(big_brother_c.jid, big_brother_acc)
@ -1177,11 +1210,22 @@ class RosterWindow:
if not type_: if not type_:
return False return False
if type_ == 'account': if type_ == 'account':
# Always show account
return True return True
account = model[iter][C_ACCOUNT] account = model[iter][C_ACCOUNT]
if not account: if not account:
return False return False
account = account.decode('utf-8') account = account.decode('utf-8')
if self.regroup:
# C_ACCOUNT for groups depends on the order
# accounts were connected
# Check all accounts for online group contacts
accounts = gajim.contacts.get_accounts()
else:
accounts = [account]
jid = model[iter][C_JID] jid = model[iter][C_JID]
if not jid: if not jid:
return False return False
@ -1191,12 +1235,13 @@ class RosterWindow:
group = jid group = jid
if group == _('Transports'): if group == _('Transports'):
return gajim.config.get('show_transports_group') return gajim.config.get('show_transports_group')
for contact in gajim.contacts.iter_contacts(account): for _acc in accounts:
# Is this contact in this group ? for contact in gajim.contacts.iter_contacts(_acc):
if group in contact.groups or (group == _('General') and not \ # Is this contact in this group ?
contact.groups): if group in contact.groups or (group == _('General') and not \
if self.contact_is_visible(contact, account): contact.groups):
return True if self.contact_is_visible(contact, _acc):
return True
return False return False
if type_ == 'contact': if type_ == 'contact':
contact = gajim.contacts.get_first_contact_from_jid(account, jid) contact = gajim.contacts.get_first_contact_from_jid(account, jid)
@ -1903,6 +1948,7 @@ class RosterWindow:
# If visible, try to get first line of contact in roster # If visible, try to get first line of contact in roster
path = None
iters = self._get_contact_iter(jid, account) iters = self._get_contact_iter(jid, account)
if iters: if iters:
path = self.modelfilter.get_path(iters[0]) path = self.modelfilter.get_path(iters[0])
@ -3526,11 +3572,12 @@ class RosterWindow:
else: else:
gajim.config.set('confirm_metacontacts', 'yes') gajim.config.set('confirm_metacontacts', 'yes')
# We might have dropped on a metacontact. Readd it. # We might have dropped on a metacontact.
# Remove it and readd later with updated family info
dest_family = gajim.contacts.get_metacontacts_family(account_dest, dest_family = gajim.contacts.get_metacontacts_family(account_dest,
c_dest.jid) c_dest.jid)
if dest_family: if dest_family:
self._remove_metacontact_family(dest_family) self._remove_metacontact_family(dest_family, account_dest)
else: else:
self._remove_entity(c_dest, account_dest) self._remove_entity(c_dest, account_dest)
@ -3541,18 +3588,25 @@ class RosterWindow:
# Remove old source contact(s) # Remove old source contact(s)
if was_big_brother: if was_big_brother:
# We have got little brothers. Readd them all # We have got little brothers. Readd them all
self._remove_metacontact_family(old_family) self._remove_metacontact_family(old_family, account_source)
else: else:
# We are only a litle brother. Simply remove us from our big brother # We are only a litle brother. Simply remove us from our big brother
self._remove_entity(c_source, account_source) if self._get_contact_iter(c_source.jid, account_source):
# When we have been in the group before.
# Do not try to remove us again
self._remove_entity(c_source, account_source)
own_data = {} own_data = {}
own_data['jid'] = c_source.jid own_data['jid'] = c_source.jid
own_data['account'] = account_source own_data['account'] = account_source
old_family.append(own_data) # Don't touch the rest of the family
old_family = [own_data]
# Apply new tag and update contact # Apply new tag and update contact
for data in old_family: for data in old_family:
if account_source != data['account'] and not self.regroup:
continue
_account = data['account'] _account = data['account']
_jid = data['jid'] _jid = data['jid']
_contact = gajim.contacts.get_first_contact_from_jid(_account, _jid) _contact = gajim.contacts.get_first_contact_from_jid(_account, _jid)
@ -3566,7 +3620,7 @@ class RosterWindow:
# Re-add all and update GUI # Re-add all and update GUI
new_family = gajim.contacts.get_metacontacts_family(account_source, new_family = gajim.contacts.get_metacontacts_family(account_source,
c_source.jid) c_source.jid)
brothers = self._add_metacontact_family(new_family) brothers = self._add_metacontact_family(new_family, account_source)
for c, acc in brothers: for c, acc in brothers:
self.draw_contact(c.jid, acc) self.draw_contact(c.jid, acc)
@ -3608,10 +3662,13 @@ class RosterWindow:
# Little brother # Little brother
# Remove whole family. Remove us from the family. # Remove whole family. Remove us from the family.
# Then re-add other family members. # Then re-add other family members.
self._remove_metacontact_family(family) self._remove_metacontact_family(family, account)
gajim.contacts.remove_metacontact(account, c_source.jid) gajim.contacts.remove_metacontact(account, c_source.jid)
for data in family: for data in family:
if data['jid'] == c_source.jid: if account != data['account'] and not self.regroup:
continue
if data['jid'] == c_source.jid and\
data['account'] == account:
continue continue
self.add_contact(data['jid'], data['account']) self.add_contact(data['jid'], data['account'])
break; break;
@ -3619,7 +3676,7 @@ class RosterWindow:
self.add_contact_to_groups(c_source.jid, account, [grp_dest,]) self.add_contact_to_groups(c_source.jid, account, [grp_dest,])
else: else:
# Simple contact # Normal contact
self.remove_contact_from_groups(c_source.jid, account, [grp_source,]) self.remove_contact_from_groups(c_source.jid, account, [grp_source,])
self.add_contact_to_groups(c_source.jid, account, [grp_dest,]) self.add_contact_to_groups(c_source.jid, account, [grp_dest,])
@ -5656,8 +5713,8 @@ class RosterWindow:
self.tree = self.xml.get_widget('roster_treeview') self.tree = self.xml.get_widget('roster_treeview')
sel = self.tree.get_selection() sel = self.tree.get_selection()
sel.set_mode(gtk.SELECTION_MULTIPLE) sel.set_mode(gtk.SELECTION_MULTIPLE)
sel.connect('changed', #sel.connect('changed',
self.on_treeview_selection_changed) # self.on_treeview_selection_changed)
self._last_selected_contact = [] # holds a list of (jid, account) tupples self._last_selected_contact = [] # holds a list of (jid, account) tupples
self.transports_state_images = {'16': {}, '32': {}, 'opened': {}, self.transports_state_images = {'16': {}, '32': {}, 'opened': {},