Improve speed of groupchat roster
- Save reference to contact in a dict instead of iterating the whole model - Sort roster only once after all contacts have been added to the roster - Speed up get_gc_contact() Fixes #9334
This commit is contained in:
parent
52e09cf526
commit
27dd36cca3
|
@ -643,10 +643,10 @@ class GC_Contacts():
|
||||||
return list(self._rooms[room_jid].keys())
|
return list(self._rooms[room_jid].keys())
|
||||||
|
|
||||||
def get_gc_contact(self, room_jid, nick):
|
def get_gc_contact(self, room_jid, nick):
|
||||||
nick_list = self.get_nick_list(room_jid)
|
try:
|
||||||
if not nick in nick_list:
|
|
||||||
return None
|
|
||||||
return self._rooms[room_jid][nick]
|
return self._rooms[room_jid][nick]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
|
||||||
def is_gc_contact(self, jid):
|
def is_gc_contact(self, jid):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -399,11 +399,15 @@ class GroupchatControl(ChatControlBase):
|
||||||
hpaned_position = app.config.get('gc-hpaned-position')
|
hpaned_position = app.config.get('gc-hpaned-position')
|
||||||
self.hpaned.set_position(hpaned_position)
|
self.hpaned.set_position(hpaned_position)
|
||||||
|
|
||||||
|
# Holds the Gtk.TreeRowReference for each contact
|
||||||
|
self._contact_refs = {}
|
||||||
|
# Holds the Gtk.TreeRowReference for each role
|
||||||
|
self._role_refs = {}
|
||||||
|
|
||||||
#status_image, shown_nick, type, nickname, avatar
|
#status_image, shown_nick, type, nickname, avatar
|
||||||
self.columns = [Gtk.Image, str, str, str, Gtk.Image]
|
self.columns = [Gtk.Image, str, str, str, Gtk.Image]
|
||||||
self.model = Gtk.TreeStore(*self.columns)
|
self.model = Gtk.TreeStore(*self.columns)
|
||||||
self.model.set_sort_func(Column.NICK, self.tree_compare_iters)
|
self.model.set_sort_func(Column.NICK, self.tree_compare_iters)
|
||||||
self.model.set_sort_column_id(Column.NICK, Gtk.SortType.ASCENDING)
|
|
||||||
|
|
||||||
# columns
|
# columns
|
||||||
column = Gtk.TreeViewColumn()
|
column = Gtk.TreeViewColumn()
|
||||||
|
@ -1297,15 +1301,10 @@ class GroupchatControl(ChatControlBase):
|
||||||
app.interface.roster.draw_contact(self.room_jid, self.account)
|
app.interface.roster.draw_contact(self.room_jid, self.account)
|
||||||
|
|
||||||
def get_contact_iter(self, nick):
|
def get_contact_iter(self, nick):
|
||||||
role_iter = self.model.get_iter_first()
|
try:
|
||||||
while role_iter:
|
ref = self._contact_refs[nick]
|
||||||
user_iter = self.model.iter_children(role_iter)
|
return self.model.get_iter(ref.get_path())
|
||||||
while user_iter:
|
except KeyError:
|
||||||
if nick == self.model[user_iter][Column.NICK]:
|
|
||||||
return user_iter
|
|
||||||
else:
|
|
||||||
user_iter = self.model.iter_next(user_iter)
|
|
||||||
role_iter = self.model.iter_next(role_iter)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def print_old_conversation(self, text, contact='', tim=None, xhtml = None,
|
def print_old_conversation(self, text, contact='', tim=None, xhtml = None,
|
||||||
|
@ -1606,6 +1605,9 @@ class GroupchatControl(ChatControlBase):
|
||||||
|
|
||||||
app.gc_connected[self.account][self.room_jid] = True
|
app.gc_connected[self.account][self.room_jid] = True
|
||||||
ChatControlBase.got_connected(self)
|
ChatControlBase.got_connected(self)
|
||||||
|
|
||||||
|
# Sort model and assign it to treeview
|
||||||
|
self.model.set_sort_column_id(Column.NICK, Gtk.SortType.ASCENDING)
|
||||||
self.list_treeview.set_model(self.model)
|
self.list_treeview.set_model(self.model)
|
||||||
self.list_treeview.expand_all()
|
self.list_treeview.expand_all()
|
||||||
# We don't redraw the whole banner here, because only icon change
|
# We don't redraw the whole banner here, because only icon change
|
||||||
|
@ -1621,7 +1623,12 @@ class GroupchatControl(ChatControlBase):
|
||||||
def got_disconnected(self):
|
def got_disconnected(self):
|
||||||
formattings_button = self.xml.get_object('formattings_button')
|
formattings_button = self.xml.get_object('formattings_button')
|
||||||
formattings_button.set_sensitive(False)
|
formattings_button.set_sensitive(False)
|
||||||
|
|
||||||
|
self.model.set_sort_column_id(Gtk.TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
|
||||||
|
Gtk.SortType.ASCENDING)
|
||||||
self.list_treeview.set_model(None)
|
self.list_treeview.set_model(None)
|
||||||
|
self._contact_refs = {}
|
||||||
|
self._role_refs = {}
|
||||||
self.model.clear()
|
self.model.clear()
|
||||||
nick_list = app.contacts.get_nick_list(self.account, self.room_jid)
|
nick_list = app.contacts.get_nick_list(self.account, self.room_jid)
|
||||||
for nick in nick_list:
|
for nick in nick_list:
|
||||||
|
@ -2042,42 +2049,56 @@ class GroupchatControl(ChatControlBase):
|
||||||
|
|
||||||
name = nick
|
name = nick
|
||||||
|
|
||||||
role_iter = self.get_role_iter(role)
|
# Add Contact
|
||||||
if not role_iter:
|
|
||||||
image = gtkgui_helpers.get_image_from_icon_name('closed', self.scale_factor)
|
|
||||||
role_iter = self.model.append(None,
|
|
||||||
[image, role, 'role', role_name, None] + [None] * self.nb_ext_renderers)
|
|
||||||
self.draw_all_roles()
|
|
||||||
iter_ = self.model.append(role_iter, [None, nick, 'contact', name, None] + \
|
|
||||||
[None] * self.nb_ext_renderers)
|
|
||||||
if not nick in app.contacts.get_nick_list(self.account,
|
|
||||||
self.room_jid):
|
|
||||||
gc_contact = app.contacts.create_gc_contact(
|
gc_contact = app.contacts.create_gc_contact(
|
||||||
room_jid=self.room_jid, account=self.account,
|
room_jid=self.room_jid, account=self.account,
|
||||||
name=nick, show=show, status=status, role=role,
|
name=nick, show=show, status=status, role=role,
|
||||||
affiliation=affiliation, jid=j, resource=resource,
|
affiliation=affiliation, jid=j, resource=resource,
|
||||||
avatar_sha=avatar_sha)
|
avatar_sha=avatar_sha)
|
||||||
app.contacts.add_gc_contact(self.account, gc_contact)
|
app.contacts.add_gc_contact(self.account, gc_contact)
|
||||||
else:
|
|
||||||
gc_contact = app.contacts.get_gc_contact(self.account, self.room_jid, nick)
|
# Create Role
|
||||||
|
role_iter = self.get_role_iter(role)
|
||||||
|
if not role_iter:
|
||||||
|
image = gtkgui_helpers.get_image_from_icon_name('closed',
|
||||||
|
self.scale_factor)
|
||||||
|
ext_columns = [None] * self.nb_ext_renderers
|
||||||
|
row = [image, role, 'role', role_name, None] + ext_columns
|
||||||
|
role_iter = self.model.append(None, row)
|
||||||
|
self._role_refs[role] = Gtk.TreeRowReference(
|
||||||
|
self.model, self.model.get_path(role_iter))
|
||||||
|
self.draw_all_roles()
|
||||||
|
|
||||||
|
# Avatar
|
||||||
|
image = None
|
||||||
|
if app.config.get('show_avatars_in_roster'):
|
||||||
|
surface = app.interface.get_avatar(
|
||||||
|
avatar_sha, AvatarSize.ROSTER, self.scale_factor)
|
||||||
|
image = Gtk.Image.new_from_surface(surface)
|
||||||
|
|
||||||
|
# Add to model
|
||||||
|
ext_columns = [None] * self.nb_ext_renderers
|
||||||
|
row = [image, nick, 'contact', name, None] + ext_columns
|
||||||
|
iter_ = self.model.append(role_iter, row)
|
||||||
|
self._contact_refs[nick] = Gtk.TreeRowReference(
|
||||||
|
self.model, self.model.get_path(iter_))
|
||||||
|
|
||||||
self.draw_contact(nick)
|
self.draw_contact(nick)
|
||||||
self.draw_avatar(gc_contact)
|
|
||||||
|
|
||||||
if nick == self.nick: # we became online
|
if nick == self.nick: # we became online
|
||||||
self.got_connected()
|
self.got_connected()
|
||||||
if self.list_treeview.get_model():
|
if self.list_treeview.get_model():
|
||||||
self.list_treeview.expand_row((self.model.get_path(role_iter)), False)
|
self.list_treeview.expand_row(
|
||||||
|
(self.model.get_path(role_iter)), False)
|
||||||
if self.is_continued:
|
if self.is_continued:
|
||||||
self.draw_banner_text()
|
self.draw_banner_text()
|
||||||
return iter_
|
return iter_
|
||||||
|
|
||||||
def get_role_iter(self, role):
|
def get_role_iter(self, role):
|
||||||
role_iter = self.model.get_iter_first()
|
try:
|
||||||
while role_iter:
|
ref = self._role_refs[role]
|
||||||
role_name = self.model[role_iter][Column.NICK]
|
return self.model.get_iter(ref.get_path())
|
||||||
if role == role_name:
|
except KeyError:
|
||||||
return role_iter
|
|
||||||
role_iter = self.model.iter_next(role_iter)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def remove_contact(self, nick):
|
def remove_contact(self, nick):
|
||||||
|
@ -2087,13 +2108,20 @@ class GroupchatControl(ChatControlBase):
|
||||||
iter_ = self.get_contact_iter(nick)
|
iter_ = self.get_contact_iter(nick)
|
||||||
if not iter_:
|
if not iter_:
|
||||||
return
|
return
|
||||||
gc_contact = app.contacts.get_gc_contact(self.account, self.room_jid,
|
gc_contact = app.contacts.get_gc_contact(
|
||||||
nick)
|
self.account, self.room_jid, nick)
|
||||||
if gc_contact:
|
if gc_contact:
|
||||||
app.contacts.remove_gc_contact(self.account, gc_contact)
|
app.contacts.remove_gc_contact(self.account, gc_contact)
|
||||||
|
|
||||||
parent_iter = self.model.iter_parent(iter_)
|
parent_iter = self.model.iter_parent(iter_)
|
||||||
|
if parent_iter is None:
|
||||||
|
# This is not a child, should never happen
|
||||||
|
return
|
||||||
self.model.remove(iter_)
|
self.model.remove(iter_)
|
||||||
|
del self._contact_refs[nick]
|
||||||
if self.model.iter_n_children(parent_iter) == 0:
|
if self.model.iter_n_children(parent_iter) == 0:
|
||||||
|
role = self.model[parent_iter][Column.NICK]
|
||||||
|
del self._role_refs[role]
|
||||||
self.model.remove(parent_iter)
|
self.model.remove(parent_iter)
|
||||||
|
|
||||||
def _message_sent(self, obj):
|
def _message_sent(self, obj):
|
||||||
|
|
Loading…
Reference in New Issue