implement roster iter cache to speed iter search.

This commit is contained in:
Yann Leboulanger 2010-07-24 00:12:16 +02:00
parent 2d9c32c16e
commit e70fd78d20
1 changed files with 83 additions and 92 deletions

View File

@ -98,43 +98,50 @@ class RosterWindow:
name -- the account name
model -- the data model (default TreeFilterModel)
"""
if not model:
model = self.modelfilter
if model is None:
return
account_iter = model.get_iter_root()
model = self.modelfilter
if model is None:
return
if self.regroup:
return account_iter
while account_iter:
account_name = model[account_iter][C_ACCOUNT]
if account_name and name == account_name.decode('utf-8'):
break
account_iter = model.iter_next(account_iter)
return account_iter
if 'account' not in self._iters:
return None
it = self._iters['account']
else:
it = self._iters[name]['account']
if model == self.model or it is None:
return it
try:
return self.modelfilter.convert_child_iter_to_iter(it)
except RuntimeError:
return None
def _get_group_iter(self, name, account, account_iter=None, model=None):
def _get_group_iter(self, name, account, model=None):
"""
Return the gtk.TreeIter of the given group or None if not found
Keyword arguments:
name -- the group name
account -- the account name
account_iter -- the iter of the account the model (default None)
model -- the data model (default TreeFilterModel)
"""
if not model:
if model is None:
model = self.modelfilter
if not account_iter:
account_iter = self._get_account_iter(account, model)
group_iter = model.iter_children(account_iter)
# C_NAME column contacts the pango escaped group name
while group_iter:
group_name = model[group_iter][C_JID].decode('utf-8')
if name == group_name:
break
group_iter = model.iter_next(group_iter)
return group_iter
if model is None:
return
if name not in self._iters[account]['groups']:
return None
it = self._iters[account]['groups'][name]
if model == self.model or it is None:
return it
try:
return self.modelfilter.convert_child_iter_to_iter(it)
except RuntimeError:
return None
def _get_self_contact_iter(self, account, model=None):
@ -145,19 +152,10 @@ class RosterWindow:
account -- the account of SelfContact
model -- the data model (default TreeFilterModel)
"""
if not model:
model = self.modelfilter
iterAcct = self._get_account_iter(account, model)
iterC = model.iter_children(iterAcct)
# There might be several SelfContacts in merged account view
while iterC:
if model[iterC][C_TYPE] != 'self_contact':
break
iter_account = model[iterC][C_ACCOUNT]
if account == iter_account.decode('utf-8'):
return iterC
iterC = model.iter_next(iterC)
jid = gajim.get_jid_from_account(account)
its = self._get_contact_iter(jid, account, model=model)
if its:
return its[0]
return None
@ -171,61 +169,36 @@ class RosterWindow:
contact -- the contact (default None)
model -- the data model (default TreeFilterModel)
"""
if not model:
if model is None:
model = self.modelfilter
# when closing Gajim model can be none (async pbs?)
if model is None:
return []
if jid == gajim.get_jid_from_account(account):
contact_iter = self._get_self_contact_iter(account, model)
if contact_iter:
return [contact_iter]
else:
return []
if not contact:
contact = gajim.contacts.get_first_contact_from_jid(account, jid)
if not contact:
# We don't know this contact
return []
acct = self._get_account_iter(account, model)
found = [] # the contact iters. One per group
for group in contact.get_shown_groups():
group_iter = self._get_group_iter(group, account, acct, model)
contact_iter = model.iter_children(group_iter)
if jid not in self._iters[account]['contacts']:
return []
while contact_iter:
# Loop over all contacts in this group
iter_jid = model[contact_iter][C_JID]
if iter_jid and jid == iter_jid.decode('utf-8') and \
account == model[contact_iter][C_ACCOUNT].decode('utf-8'):
# only one iter per group
found.append(contact_iter)
contact_iter = None
elif model.iter_has_child(contact_iter):
# it's a big brother and has children
contact_iter = model.iter_children(contact_iter)
else:
# try to find next contact:
# other contact in this group or
# brother contact
next_contact_iter = model.iter_next(contact_iter)
if next_contact_iter:
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)
if parent_iter and model[parent_iter][C_TYPE] == \
'contact':
contact_iter = model.iter_next(parent_iter)
else:
# we tested all
# contacts in this group
contact_iter = None
return found
its = self._iters[account]['contacts'][jid]
if not its:
return []
if model == self.model:
return its
its2 = []
for it in its:
try:
its2.append(self.modelfilter.convert_child_iter_to_iter(it))
except RuntimeError:
pass
return its2
def _iter_is_separator(self, model, titer):
@ -278,10 +251,11 @@ class RosterWindow:
if self.regroup:
# Merged accounts view
show = helpers.get_global_show()
self.model.append(None, [
gajim.interface.jabber_state_images['16'][show],
_('Merged accounts'), 'account', '', 'all',
None, None, None, None, None, None])
it = self.model.append(None, [
gajim.interface.jabber_state_images['16'][show],
_('Merged accounts'), 'account', '', 'all', None, None, None,
None, None, None])
self._iters['account'] = it
else:
show = gajim.SHOW_LIST[gajim.connections[account].connected]
our_jid = gajim.get_jid_from_account(account)
@ -293,11 +267,11 @@ class RosterWindow:
gtk.STOCK_DIALOG_AUTHENTICATION,
gtk.ICON_SIZE_MENU)
self.model.append(None, [
gajim.interface.jabber_state_images['16'][show],
gobject.markup_escape_text(account), 'account',
our_jid, account, None, None, None, None, None,
tls_pixbuf])
it = self.model.append(None, [
gajim.interface.jabber_state_images['16'][show],
gobject.markup_escape_text(account), 'account', our_jid,
account, None, None, None, None, None, tls_pixbuf])
self._iters[account]['account'] = it
self.draw_account(account)
@ -362,13 +336,17 @@ class RosterWindow:
contact.get_shown_name(), 'contact', contact.jid, account,
None, None, None, None, None, None))
added_iters.append(it)
if contact.jid in self._iters[account]['contacts']:
self._iters[account]['contacts'][contact.jid].append(it)
else:
self._iters[account]['contacts'][contact.jid] = [it]
else:
# We are a normal contact. Add us to our groups.
if not groups:
groups = contact.get_shown_groups()
for group in groups:
child_iterG = self._get_group_iter(group, account,
model = self.model)
model=self.model)
if not child_iterG:
# Group is not yet in roster, add it!
child_iterA = self._get_account_iter(account, self.model)
@ -378,6 +356,7 @@ class RosterWindow:
'group', group, account, None, None, None, None, None,
None])
self.draw_group(group, account)
self._iters[account]['groups'][group] = child_iterG
if contact.is_transport():
typestr = 'agent'
@ -393,6 +372,10 @@ class RosterWindow:
contact.jid, account, None, None, None,
None, None, None))
added_iters.append(i_)
if contact.jid in self._iters[account]['contacts']:
self._iters[account]['contacts'][contact.jid].append(i_)
else:
self._iters[account]['contacts'][contact.jid] = [i_]
# Restore the group expand state
if account + group in self.collapsed_rows:
@ -455,8 +438,10 @@ class RosterWindow:
if group in gajim.groups[account]:
del gajim.groups[account][group]
self.model.remove(parent_i)
del self._iters[account]['groups'][group]
else:
self.model.remove(i)
del self._iters[account]['contacts'][contact.jid]
return True
def _add_metacontact_family(self, family, account):
@ -633,8 +618,9 @@ class RosterWindow:
self.model)) == 0, 'Self contact %s already in roster' % jid
child_iterA = self._get_account_iter(account, self.model)
self.model.append(child_iterA, (None, gajim.nicks[account],
'self_contact', jid, account, None, None, None, None, None, None))
self._iters[account]['contacts'][jid] = [self.model.append(child_iterA,
(None, gajim.nicks[account], 'self_contact', jid, account, None,
None, None, None, None, None))]
self.draw_completely(jid, account)
self.draw_account(account)
@ -1398,7 +1384,9 @@ class RosterWindow:
self.on_modelfilter_row_has_child_toggled)
self.tree.set_model(self.modelfilter)
self._iters = {}
for acct in gajim.contacts.get_accounts():
self._iters[acct] = {'account': None, 'groups': {}, 'contacts': {}}
self.add_account(acct)
self.add_account_contacts(acct)
# Recalculate column width for ellipsizing
@ -1729,6 +1717,8 @@ class RosterWindow:
# Most of the logic SHOULD NOT be done at GUI level
if account not in gajim.contacts.get_accounts():
gajim.contacts.add_account(account)
self._iters[account] = {'account': None, 'groups': {},
'contacts': {}}
if account not in gajim.groups:
gajim.groups[account] = {}
if gajim.config.get('show_self_contact') == 'always':
@ -5854,6 +5844,7 @@ class RosterWindow:
# sel.connect('changed',
# self.on_treeview_selection_changed)
self._iters = {}
# holds a list of (jid, account) tupples
self._last_selected_contact = []
self.transports_state_images = {'16': {}, '32': {}, 'opened': {},