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