Add a roster_sort option to sort the contacts inside the roster groups

- defaults to jid_show (which means that they are sorted into sub-groups
  by show and are sorted by JID inside those)
- See the default config file or the documentation for details
This commit is contained in:
mathieui 2012-07-31 23:40:53 +02:00
parent 4096e7f427
commit 1625a4f41f
4 changed files with 75 additions and 19 deletions

View file

@ -223,6 +223,19 @@ show_roster_jids = true
# If set to true, the roster will display the offline contacts too
roster_show_offline = false
# How to sort the contacts inside the roster groups.
# They are used sequentially, (from left to right)
# Available sorting methods are:
# - reverse: reverse the sorting
# - jid: sort by JID (alphabetical order)
# - show: sort by show (available/away/xa/…)
# - name: Sort by roster name (if no name, then the bare jid is used)
# - resource: Sort by resource number
# You can arrange them however you like, and you have to separate them with
# underscores "_". Keep in mind that if there are more than 3 or 4 your sorting
# is most likely inefficient.
roster_sort = jid_show
# The terminal can beep on various event. Put the event you want in a list
# (separated by spaces).
# The events can be

View file

@ -279,6 +279,23 @@ section of this documentation.
Set this to true if you want to display the offline contacts too.
*roster_sort*:: jid_show
How you want the contacts to be sorted inside the roster groups. The given
methods are used sequentially (from left to right), so the last one is the
one on the far right.
Available methods are :
* reverse: reverse the current sorting
* jid: sort by JID (alphabetical order)
* show: sort by show (available/away/xa/…)
* name: Sort by roster name (if no name, then the bare jid is used)
* resource: Sort by resource number
Those methods can be arranged however you like, and they have to be
separated by underscores ("_"). If there are more than 3 or 4 chained
sorting methods, your sorting is most likely inefficient.
*beep_on*:: highlight private
The terminal can beep on various event. Put the event you want in a list

View file

@ -198,12 +198,37 @@ class Roster(object):
except IOError:
return
PRESENCE_PRIORITY = {'unavailable': 0,
'xa': 1,
'away': 2,
'dnd': 3,
'': 4,
'available': 4}
PRESENCE_PRIORITY = {'unavailable': 5,
'xa': 4,
'away': 3,
'dnd': 2,
'': 1,
'available': 1}
def sort_jid(contact):
return contact.bare_jid
def sort_show(contact):
res = contact.get_highest_priority_resource()
if not res:
return 0
show = res.presence
if show not in PRESENCE_PRIORITY:
return 0
return PRESENCE_PRIORITY[show]
def sort_resource_nb(contact):
return - len(contact)
def sort_name(contact):
return contact.name.lower() or contact.bare_jid
SORTING_METHODS = {
'jid': sort_jid,
'show': sort_show,
'resource': sort_resource_nb,
'name': sort_name,
}
class RosterGroup(object):
"""
@ -244,20 +269,19 @@ class RosterGroup(object):
if contact in self.contacts:
self.contacts.remove(contact)
def get_contacts(self, contact_filter):
def get_contacts(self, contact_filter=None, sort=''):
"""Return the group contacts, filtered and sorted"""
def compare_contact(a):
res = a.get_highest_priority_resource()
if not res:
return 0
show = res.presence
if show not in PRESENCE_PRIORITY:
return 5
return PRESENCE_PRIORITY[show]
contact_list = self.contacts if not contact_filter\
contact_list = self.contacts.copy() if not contact_filter\
else [contact for contact in self.contacts.copy() if contact_filter[0](contact, contact_filter[1])]
contact_list = sorted(contact_list, key=lambda x: x.bare_jid)
return sorted(contact_list, key=compare_contact, reverse=True)
for sorting in sort.split('_'):
method = SORTING_METHODS.get(sorting, lambda x: 0)
if sorting == 'reverse':
contact_list = list(reversed(contact_list))
else:
contact_list = sorted(contact_list, key=method)
return contact_list
def toggle_folded(self):
"""Fold/unfold the group in the roster"""
@ -273,5 +297,6 @@ class RosterGroup(object):
"""Return the number of connected contacts"""
return len([1 for contact in self.contacts if contact.resources])
# Shared roster object
roster = Roster()

View file

@ -1609,6 +1609,7 @@ class RosterWin(Win):
self.draw_roster_information(roster)
y = 1
show_offline = config.get('roster_show_offline', 'false') == 'true'
sort = config.get('roster_sort', 'jid_show') or 'jid_show'
for group in roster.get_groups()[:]:
contacts_filtered = group.get_contacts(roster.contact_filter)
if (not show_offline and group.get_nb_connected_contacts() == 0) or not contacts_filtered:
@ -1621,7 +1622,7 @@ class RosterWin(Win):
y += 1
if group.folded:
continue
for contact in group.get_contacts(roster.contact_filter)[:]:
for contact in group.get_contacts(roster.contact_filter, sort):
if not show_offline and len(contact) == 0:
continue
if y-1 == self.pos: