summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/roster.py49
-rw-r--r--src/tabs.py14
-rw-r--r--src/windows.py62
3 files changed, 72 insertions, 53 deletions
diff --git a/src/roster.py b/src/roster.py
index 5ddbdbb2..8c1b8f3e 100644
--- a/src/roster.py
+++ b/src/roster.py
@@ -115,8 +115,6 @@ class Roster(object):
key=lambda x: x.name.lower() if x.name else ''
)
- log.debug("Current groups: %s", group_list)
-
for sorting in sort.split(':'):
if sorting == 'reverse':
group_list = list(reversed(group_list))
@@ -145,6 +143,28 @@ class Roster(object):
"""
return [self[jid] for jid in self.jids()]
+ def get_contacts_sorted_filtered(self, sort=''):
+ """
+ Return a list of all the contacts sorted with a criteria
+ """
+ contact_list = []
+ for contact in self.get_contacts():
+ if contact.bare_jid != self.jid:
+ if self.contact_filter:
+ if self.contact_filter[0](contact, self.contact_filter[1]):
+ contact_list.append(contact)
+ else:
+ contact_list.append(contact)
+ contact_list = sorted(contact_list, key=SORTING_METHODS['name'])
+
+ for sorting in sort.split(':'):
+ if sorting == 'reverse':
+ contact_list = list(reversed(contact_list))
+ else:
+ method = SORTING_METHODS.get(sorting, lambda x: 0)
+ contact_list = sorted(contact_list, key=method)
+ return contact_list
+
def save_to_config_file(self):
"""
Save various information to the config file
@@ -184,28 +204,11 @@ class Roster(object):
def __len__(self):
"""
- Return the number of line that would be printed
- for the whole roster
+ Return the number of contacts
+ (used to return the display size, but now we have
+ the display cache in RosterWin for that)
"""
- length = 0
- show_offline = config.get('roster_show_offline', 'false') == 'true'
- for group in self.groups.values():
- if not show_offline and group.get_nb_connected_contacts() == 0:
- continue
- before = length
- if not group.name in self.folded_groups:
- for contact in group.get_contacts(self.contact_filter):
- # We do not count the offline contacts (depending on config)
- if not show_offline and\
- len(contact) == 0:
- continue
- length += 1 # One for the contact's line
- if not contact.folded(group.name):
- # One for each resource, if the contact is unfolded
- length += len(contact)
- if not self.contact_filter or before != length:
- length += 1 # One for the group's line itself if needed
- return length
+ return len(self.contacts)
def __repr__(self):
ret = '== Roster:\nContacts:\n'
diff --git a/src/tabs.py b/src/tabs.py
index c0a34f29..fb6b393b 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -3012,6 +3012,8 @@ class RosterInfoTab(Tab):
self.input = windows.CommandInput("[Search]", self.on_search_terminate, self.on_search_terminate, self.set_roster_filter)
self.input.resize(1, self.width, self.height-1, 0)
self.input.disable_history()
+ roster.modified()
+ self.refresh()
return True
@refresh_wrapper.always
@@ -3024,11 +3026,13 @@ class RosterInfoTab(Tab):
def set_roster_filter_slow(self, txt):
roster.contact_filter = (jid_and_name_match_slow, txt)
+ roster.modified()
self.refresh()
return False
def set_roster_filter(self, txt):
roster.contact_filter = (jid_and_name_match, txt)
+ roster.modified()
self.refresh()
return False
@@ -3037,6 +3041,7 @@ class RosterInfoTab(Tab):
curses.curs_set(0)
roster.contact_filter = None
self.reset_help_message()
+ roster.modified()
return False
def on_close(self):
@@ -3851,12 +3856,12 @@ def jid_and_name_match(contact, txt):
"""
Match jid with text precisely
"""
- roster.modified()
if not txt:
return True
- if txt in safeJID(contact.bare_jid).user:
+ txt = txt.lower()
+ if txt in safeJID(contact.bare_jid).bare.lower():
return True
- if txt in contact.name:
+ if txt in contact.name.lower():
return True
return False
@@ -3865,10 +3870,9 @@ def jid_and_name_match_slow(contact, txt):
A function used to know if a contact in the roster should
be shown in the roster
"""
- roster.modified()
if not txt:
return True # Everything matches when search is empty
- user = safeJID(contact.bare_jid).user
+ user = safeJID(contact.bare_jid).bare
if diffmatch(txt, user):
return True
if contact.name and diffmatch(txt, contact.name):
diff --git a/src/windows.py b/src/windows.py
index 66b52f1d..bd348859 100644
--- a/src/windows.py
+++ b/src/windows.py
@@ -1742,10 +1742,13 @@ class RosterWin(Win):
Win.__init__(self)
self.pos = 0 # cursor position in the contact list
self.start_pos = 1 # position of the start of the display
- self.roster_len = 0
self.selected_row = None
self.roster_cache = []
+ @property
+ def roster_len(self):
+ return len(self.roster_cache)
+
def move_cursor_down(self, number=1):
"""
Return True if we scrolled, False otherwise
@@ -1809,28 +1812,36 @@ class RosterWin(Win):
with g_lock:
if roster.needs_rebuild:
log.debug('The roster has changed, rebuilding the cacheā€¦')
- show_offline = config.get('roster_show_offline', 'false') == 'true'
- sort = config.get('roster_sort', 'jid:show') or 'jid:show'
- group_sort = config.get('roster_group_sort', 'name') or 'name'
- self.roster_cache = []
- # build the cache
- for group in roster.get_groups(group_sort):
- contacts_filtered = group.get_contacts(roster.contact_filter)
- if (not show_offline and group.get_nb_connected_contacts() == 0) or not contacts_filtered:
- continue # Ignore empty groups
- self.roster_cache.append(group)
- if group.folded:
- continue # ignore folded groups
- for contact in group.get_contacts(roster.contact_filter, sort):
- if not show_offline and len(contact) == 0:
- continue # ignore offline contacts
+ # This is a search
+ if roster.contact_filter:
+ self.roster_cache = []
+ sort = config.get('roster_sort', 'jid:show') or 'jid:show'
+ for contact in roster.get_contacts_sorted_filtered(sort):
self.roster_cache.append(contact)
- if not contact.folded(group.name):
- for resource in contact.get_resources():
- self.roster_cache.append(resource)
+ else:
+ show_offline = config.get('roster_show_offline', 'false') == 'true' or roster.contact_filter
+ sort = config.get('roster_sort', 'jid:show') or 'jid:show'
+ group_sort = config.get('roster_group_sort', 'name') or 'name'
+ self.roster_cache = []
+ # build the cache
+ for group in roster.get_groups(group_sort):
+ contacts_filtered = group.get_contacts(roster.contact_filter)
+ if (not show_offline and group.get_nb_connected_contacts() == 0) or not contacts_filtered:
+ continue # Ignore empty groups
+ self.roster_cache.append(group)
+ if group.folded:
+ continue # ignore folded groups
+ for contact in group.get_contacts(roster.contact_filter, sort):
+ if not show_offline and len(contact) == 0:
+ continue # ignore offline contacts
+ self.roster_cache.append(contact)
+ if not contact.folded(group.name):
+ for resource in contact.get_resources():
+ self.roster_cache.append(resource)
roster.last_built = datetime.now()
if self.selected_row in self.roster_cache:
- self.pos = self.roster_cache.index(self.selected_row)
+ if self.pos < self.roster_len and self.roster_cache[self.pos] != self.selected_row:
+ self.pos = self.roster_cache.index(self.selected_row)
def refresh(self, roster):
"""
@@ -1840,16 +1851,17 @@ class RosterWin(Win):
log.debug('Refresh: %s',self.__class__.__name__)
self.build_roster_cache(roster)
with g_lock:
- self.roster_len = len(roster);
- self.move_cursor_up(self.roster_len + self.pos if self.pos >= self.roster_len else 0)
+ # make sure we are within bounds
+ self.move_cursor_up((self.roster_len + self.pos) if self.pos >= self.roster_len else 0)
self._win.erase()
self._win.move(0, 0)
self.draw_roster_information(roster)
y = 1
group = "none"
+ # scroll down if needed
+ if self.start_pos+self.height <= self.pos+2:
+ self.scroll_down(self.pos - self.start_pos - self.height + (self.height//2))
# draw the roster from the cache
- if self.start_pos+self.height < self.pos:
- self.start_pos = self.pos - (self.height//2)
for item in self.roster_cache[self.start_pos-1:self.start_pos+self.height]:
draw_selected = False
@@ -1887,7 +1899,7 @@ class RosterWin(Win):
"""
self.addstr('Roster: %s/%s contacts' % (
roster.get_nb_connected_contacts(),
- len(roster.contacts))
+ len(roster))
,to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
self.finish_line(get_theme().COLOR_INFORMATION_BAR)