Reimplement _get_contact_iter to be faster in bigger rosters.
This commit is contained in:
parent
299f560749
commit
df5a4c2281
|
@ -99,19 +99,21 @@ class RosterWindow:
|
||||||
return account_iter
|
return account_iter
|
||||||
|
|
||||||
|
|
||||||
def _get_group_iter(self, name, account, model = None):
|
def _get_group_iter(self, name, account, account_iter = None, model = None):
|
||||||
''' Return the gtk.TreeIter of the given group or None if not found.
|
''' Return the gtk.TreeIter of the given group or None if not found.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
name -- the group name
|
name -- the group name
|
||||||
account -- the account name
|
account -- the account name
|
||||||
|
account_iter -- the iter of the account the model (default None)
|
||||||
model -- the data model (default TreeFilterModel)
|
model -- the data model (default TreeFilterModel)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
if not model:
|
if not model:
|
||||||
model = self.modelfilter
|
model = self.modelfilter
|
||||||
root = self._get_account_iter(account, model)
|
if not account_iter:
|
||||||
group_iter = model.iter_children(root)
|
account_iter = self._get_account_iter(account, model)
|
||||||
|
group_iter = model.iter_children(account_iter)
|
||||||
# C_NAME column contacts the pango escaped group name
|
# C_NAME column contacts the pango escaped group name
|
||||||
while group_iter:
|
while group_iter:
|
||||||
group_name = model[group_iter][C_JID].decode('utf-8')
|
group_name = model[group_iter][C_JID].decode('utf-8')
|
||||||
|
@ -139,62 +141,71 @@ class RosterWindow:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _get_contact_iter(self, jid, account, model = None):
|
def _get_contact_iter(self, jid, account, contact = None, model = None):
|
||||||
''' Return a list of gtk.TreeIter of the given jid.
|
''' Return a list of gtk.TreeIter of the given contact.
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
jid -- the jid without resource
|
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:
|
if not model:
|
||||||
model = self.modelfilter
|
model = self.modelfilter
|
||||||
|
if model is None: # when closing Gajim model can be none (async pbs?)
|
||||||
|
return []
|
||||||
|
|
||||||
if jid == gajim.get_jid_from_account(account):
|
if jid == gajim.get_jid_from_account(account):
|
||||||
iter = self._get_self_contact_iter(account, model)
|
iter = self._get_self_contact_iter(account, model)
|
||||||
if iter:
|
if iter:
|
||||||
return [iter]
|
return [iter]
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
if not contact:
|
||||||
|
contact = gajim.contacts.get_first_contact_from_jid(account, jid)
|
||||||
|
if not contact:
|
||||||
|
# We don't know this contact
|
||||||
|
return
|
||||||
|
|
||||||
|
groups = contact.groups
|
||||||
|
if not groups:
|
||||||
|
groups = [_('General')]
|
||||||
acct = self._get_account_iter(account, model)
|
acct = self._get_account_iter(account, model)
|
||||||
found = []
|
found = [] # the contact iters. One per group
|
||||||
if model is None: # when closing Gajim model can be none (async pbs?)
|
for group in groups:
|
||||||
return found
|
group_iter = self._get_group_iter(group, account, acct, model)
|
||||||
group_iter = model.iter_children(acct)
|
|
||||||
while group_iter:
|
|
||||||
contact_iter = model.iter_children(group_iter)
|
contact_iter = model.iter_children(group_iter)
|
||||||
|
|
||||||
while contact_iter:
|
while contact_iter:
|
||||||
|
# Loop over all contacts in this group
|
||||||
iter_jid = model[contact_iter][C_JID]
|
iter_jid = model[contact_iter][C_JID]
|
||||||
if iter_jid and jid == iter_jid.decode('utf-8') and \
|
if iter_jid and jid == iter_jid.decode('utf-8') and \
|
||||||
account == model[contact_iter][C_ACCOUNT].decode('utf-8'):
|
account == model[contact_iter][C_ACCOUNT].decode('utf-8'):
|
||||||
|
# only one iter per group
|
||||||
found.append(contact_iter)
|
found.append(contact_iter)
|
||||||
# find next contact iter
|
contact_iter = None
|
||||||
if model.iter_has_child(contact_iter):
|
elif model.iter_has_child(contact_iter):
|
||||||
# his first child if it has some
|
# it's a big brother and has children
|
||||||
contact_iter = model.iter_children(contact_iter)
|
contact_iter = model.iter_children(contact_iter)
|
||||||
else:
|
else:
|
||||||
|
# try to find next contact:
|
||||||
|
# other contact in this group or brother contact
|
||||||
next_contact_iter = model.iter_next(contact_iter)
|
next_contact_iter = model.iter_next(contact_iter)
|
||||||
if not next_contact_iter:
|
if next_contact_iter:
|
||||||
# now we need to go up
|
contact_iter = next_contact_iter
|
||||||
|
else:
|
||||||
|
# It's the last one. Go up if we are big brother
|
||||||
parent_iter = model.iter_parent(contact_iter)
|
parent_iter = model.iter_parent(contact_iter)
|
||||||
parent_type = model[parent_iter][C_TYPE]
|
if parent_iter and model[parent_iter][C_TYPE] == 'contact':
|
||||||
while parent_type != 'group':
|
|
||||||
contact_iter = model.iter_next(parent_iter)
|
contact_iter = model.iter_next(parent_iter)
|
||||||
if contact_iter:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
parent_iter = model.iter_parent(parent_iter)
|
|
||||||
parent_type = model[parent_iter][C_TYPE]
|
|
||||||
else:
|
else:
|
||||||
# we tested all contacts in this group
|
# we tested all contacts in this group
|
||||||
contact_iter = None
|
contact_iter = None
|
||||||
else:
|
|
||||||
# his brother if he has
|
|
||||||
contact_iter = next_contact_iter
|
|
||||||
group_iter = model.iter_next(group_iter)
|
|
||||||
return found
|
return found
|
||||||
|
|
||||||
|
|
||||||
def _iter_is_separator(self, model, iter):
|
def _iter_is_separator(self, model, iter):
|
||||||
''' Return True if the given iter is a separator.
|
''' Return True if the given iter is a separator.
|
||||||
|
|
||||||
|
@ -317,7 +328,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,
|
||||||
big_brother_account, self.model)
|
big_brother_account, big_brother_contact, 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!"
|
||||||
|
|
||||||
|
@ -336,7 +347,7 @@ class RosterWindow:
|
||||||
if not groups:
|
if not groups:
|
||||||
groups = [_('General')]
|
groups = [_('General')]
|
||||||
for group in groups:
|
for group in groups:
|
||||||
child_iterG = self._get_group_iter(group, account, self.model)
|
child_iterG = self._get_group_iter(group, account, model = self.model)
|
||||||
if not child_iterG:
|
if not child_iterG:
|
||||||
# Group is not yet in roster, add it!
|
# Group is not yet in roster, add it!
|
||||||
child_iterA = self._get_account_iter(account, self.model)
|
child_iterA = self._get_account_iter(account, self.model)
|
||||||
|
@ -386,7 +397,7 @@ class RosterWindow:
|
||||||
groups -- list of groups to remove the contact from. (default groups in contact.groups).
|
groups -- list of groups to remove the contact from. (default groups in contact.groups).
|
||||||
|
|
||||||
'''
|
'''
|
||||||
iters = self._get_contact_iter(contact.jid, account, self.model)
|
iters = self._get_contact_iter(contact.jid, account, contact, self.model)
|
||||||
assert iters, "%s shall be removed but is not in roster" % contact.jid
|
assert iters, "%s shall be removed but is not in roster" % contact.jid
|
||||||
|
|
||||||
parent_iter = self.model.iter_parent(iters[0])
|
parent_iter = self.model.iter_parent(iters[0])
|
||||||
|
@ -442,7 +453,7 @@ class RosterWindow:
|
||||||
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, big_brother_contact, self.model)) == 0,\
|
||||||
"Big brother %s already in roster \n Family: %s" % (big_brother_jid, family)
|
"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)
|
||||||
|
|
||||||
|
@ -460,7 +471,7 @@ class RosterWindow:
|
||||||
# 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, _contact, self.model)) == 0,\
|
||||||
"%s already in roster. \n Family: " % (_jid, nearby_family)
|
"%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)
|
big_brother_account = big_brother_account)
|
||||||
|
@ -491,7 +502,7 @@ class RosterWindow:
|
||||||
_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)
|
||||||
|
|
||||||
iters = self._get_contact_iter(_jid, _account, self.model)
|
iters = self._get_contact_iter(_jid, _account, _contact, self.model)
|
||||||
if not iters or not _contact:
|
if not iters or not _contact:
|
||||||
# Family might not be up to date.
|
# Family might not be up to date.
|
||||||
# Only try to remove what is actually in the roster
|
# Only try to remove what is actually in the roster
|
||||||
|
@ -512,13 +523,13 @@ class RosterWindow:
|
||||||
|
|
||||||
ok = self._remove_entity(_contact, _account)
|
ok = self._remove_entity(_contact, _account)
|
||||||
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, _contact, self.model)) == 0,\
|
||||||
"%s is removed but still in roster" % _jid
|
"%s is removed but still in roster" % _jid
|
||||||
|
|
||||||
if not family_in_roster:
|
if not family_in_roster:
|
||||||
return False
|
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, old_big_contact, 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]),\
|
||||||
"Old Big Brother still has children" % old_big_jid
|
"Old Big Brother still has children" % old_big_jid
|
||||||
|
@ -529,7 +540,7 @@ class RosterWindow:
|
||||||
|
|
||||||
ok = self._remove_entity(old_big_contact, old_big_account)
|
ok = self._remove_entity(old_big_contact, old_big_account)
|
||||||
assert ok, "Old Big Brother %s not removed" % old_big_jid
|
assert ok, "Old Big Brother %s not removed" % old_big_jid
|
||||||
assert len(self._get_contact_iter(old_big_jid, old_big_account, self.model)) == 0,\
|
assert len(self._get_contact_iter(old_big_jid, old_big_account, old_big_contact, self.model)) == 0,\
|
||||||
"Old Big Brother %s is removed but still in roster" % old_big_jid
|
"Old Big Brother %s is removed but still in roster" % old_big_jid
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -543,7 +554,7 @@ class RosterWindow:
|
||||||
jid = gajim.get_jid_from_account(account)
|
jid = gajim.get_jid_from_account(account)
|
||||||
contact = gajim.contacts.get_first_contact_from_jid(account, jid)
|
contact = gajim.contacts.get_first_contact_from_jid(account, jid)
|
||||||
|
|
||||||
assert len(self._get_contact_iter(jid, account, self.model)) == 0,\
|
assert len(self._get_contact_iter(jid, account, contact, self.model)) == 0,\
|
||||||
"Self contact %s already in roster" % jid
|
"Self contact %s already in roster" % jid
|
||||||
|
|
||||||
child_iterA = self._get_account_iter(account, self.model)
|
child_iterA = self._get_account_iter(account, self.model)
|
||||||
|
@ -572,12 +583,11 @@ class RosterWindow:
|
||||||
account -- the corresponding account.
|
account -- the corresponding account.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
if len(self._get_contact_iter(jid, account, self.model)):
|
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
||||||
|
if len(self._get_contact_iter(jid, account, contact, self.model)):
|
||||||
# If contact already in roster, do nothing
|
# If contact already in roster, do nothing
|
||||||
return
|
return
|
||||||
|
|
||||||
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
|
||||||
|
|
||||||
if jid == gajim.get_jid_from_account(account):
|
if jid == gajim.get_jid_from_account(account):
|
||||||
if contact.resource != gajim.connections[account].server_resource:
|
if contact.resource != gajim.connections[account].server_resource:
|
||||||
return self._add_self_contact(account)
|
return self._add_self_contact(account)
|
||||||
|
@ -637,12 +647,12 @@ class RosterWindow:
|
||||||
account -- the corresponding account.
|
account -- the corresponding account.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
iters = self._get_contact_iter(jid, account, self.model)
|
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
||||||
|
|
||||||
|
iters = self._get_contact_iter(jid, account, contact, self.model)
|
||||||
if not iters:
|
if not iters:
|
||||||
return
|
return
|
||||||
|
|
||||||
contact = gajim.contacts.get_contact_with_highest_priority(account, jid)
|
|
||||||
|
|
||||||
# Remove contact from roster
|
# Remove contact from roster
|
||||||
family = gajim.contacts.get_metacontacts_family(account, jid)
|
family = gajim.contacts.get_metacontacts_family(account, jid)
|
||||||
if family:
|
if family:
|
||||||
|
@ -872,7 +882,7 @@ class RosterWindow:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def draw_group(self, group, account):
|
def draw_group(self, group, account):
|
||||||
child_iter = self._get_group_iter(group, account, self.model)
|
child_iter = self._get_group_iter(group, account, model = self.model)
|
||||||
if not child_iter:
|
if not child_iter:
|
||||||
# Eg. We redraw groups after we removed a entitiy
|
# Eg. We redraw groups after we removed a entitiy
|
||||||
# and its empty groups
|
# and its empty groups
|
||||||
|
@ -908,14 +918,14 @@ class RosterWindow:
|
||||||
def draw_contact(self, jid, account, selected = False, focus = False):
|
def draw_contact(self, jid, account, selected = False, focus = False):
|
||||||
'''draw the correct state image, name BUT not avatar'''
|
'''draw the correct state image, name BUT not avatar'''
|
||||||
# focus is about if the roster window has toplevel-focus or not
|
# focus is about if the roster window has toplevel-focus or not
|
||||||
|
|
||||||
child_iters = self._get_contact_iter(jid, account, self.model)
|
|
||||||
if not child_iters:
|
|
||||||
return False
|
|
||||||
|
|
||||||
contact_instances = gajim.contacts.get_contacts(account, jid)
|
contact_instances = gajim.contacts.get_contacts(account, jid)
|
||||||
contact = gajim.contacts.get_highest_prio_contact_from_contacts(
|
contact = gajim.contacts.get_highest_prio_contact_from_contacts(
|
||||||
contact_instances)
|
contact_instances)
|
||||||
|
|
||||||
|
child_iters = self._get_contact_iter(jid, account, contact, self.model)
|
||||||
|
if not child_iters:
|
||||||
|
return False
|
||||||
|
|
||||||
name = gobject.markup_escape_text(contact.get_shown_name())
|
name = gobject.markup_escape_text(contact.get_shown_name())
|
||||||
|
|
||||||
# gets number of unread gc marked messages
|
# gets number of unread gc marked messages
|
||||||
|
@ -1008,8 +1018,7 @@ class RosterWindow:
|
||||||
|
|
||||||
if big_brother_jid == jid and big_brother_account == account:
|
if big_brother_jid == jid and big_brother_account == account:
|
||||||
# We are the big brother. But have also been before?
|
# We are the big brother. But have also been before?
|
||||||
iters = self._get_contact_iter(jid, account, self.model)
|
if self.model.iter_has_child(child_iters[0]):
|
||||||
if self.model.iter_has_child(iters[0]):
|
|
||||||
# We have children. We must have been
|
# We have children. We must have been
|
||||||
# big brother even before
|
# big brother even before
|
||||||
pass
|
pass
|
||||||
|
@ -1035,8 +1044,8 @@ class RosterWindow:
|
||||||
if c_icon_name in ('event', 'muc_active', 'muc_inactive'):
|
if c_icon_name in ('event', 'muc_active', 'muc_inactive'):
|
||||||
icon_name = c_icon_name
|
icon_name = c_icon_name
|
||||||
break
|
break
|
||||||
|
|
||||||
iters = self._get_contact_iter(jid, account)
|
iters = self._get_contact_iter(jid, account, contact)
|
||||||
if iters and self.modelfilter.iter_has_child(iters[0]):
|
if iters and self.modelfilter.iter_has_child(iters[0]):
|
||||||
# We are big brother contact and visible in the roster
|
# We are big brother contact and visible in the roster
|
||||||
iter = iters[0]
|
iter = iters[0]
|
||||||
|
@ -1078,7 +1087,8 @@ class RosterWindow:
|
||||||
icon_name = icon_name)
|
icon_name = icon_name)
|
||||||
|
|
||||||
img = state_images[icon_name]
|
img = state_images[icon_name]
|
||||||
child_iters = self._get_contact_iter(jid, account, self.model)
|
# Old iters might be invalid!
|
||||||
|
child_iters = self._get_contact_iter(jid, account, model = self.model)
|
||||||
for child_iter in child_iters:
|
for child_iter in child_iters:
|
||||||
self.model[child_iter][C_IMG] = img
|
self.model[child_iter][C_IMG] = img
|
||||||
self.model[child_iter][C_NAME] = name
|
self.model[child_iter][C_NAME] = name
|
||||||
|
@ -1090,7 +1100,7 @@ class RosterWindow:
|
||||||
|
|
||||||
|
|
||||||
def draw_avatar(self, jid, account):
|
def draw_avatar(self, jid, account):
|
||||||
iters = self._get_contact_iter(jid, account, self.model)
|
iters = self._get_contact_iter(jid, account, model = self.model)
|
||||||
if not iters or not gajim.config.get('show_avatars_in_roster'):
|
if not iters or not gajim.config.get('show_avatars_in_roster'):
|
||||||
return
|
return
|
||||||
jid = self.model[iters[0]][C_JID]
|
jid = self.model[iters[0]][C_JID]
|
||||||
|
@ -1976,7 +1986,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
|
path = None
|
||||||
iters = self._get_contact_iter(jid, account)
|
iters = self._get_contact_iter(jid, account, contact = contact)
|
||||||
if iters:
|
if iters:
|
||||||
path = self.modelfilter.get_path(iters[0])
|
path = self.modelfilter.get_path(iters[0])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue