diff --git a/data/default_config.cfg b/data/default_config.cfg index 76e02d57..8871de15 100644 --- a/data/default_config.cfg +++ b/data/default_config.cfg @@ -230,18 +230,20 @@ roster_show_offline = false # - 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) +# - sname: case-sensitive name sorting (uppercase first) # - resource: sort by resource number # - online: sort by online presence (online or not) # 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 +# colons (":"). Keep in mind that if there are more than 3 or 4 your +# sorting is most likely inefficient. +roster_sort = jid:show # How to sort the roster groups. # The principles are the same as roster_sort. # Available methods are: # - reverse: reverse the sorting # - name: sort by group name (alphabetical order) +# - sname: case-sensitive name sorting (uppercase first) # - fold: sort unfolded/folded # - connected: sort by number of connected contacts # - size: sort by group size diff --git a/doc/en/configure.txt b/doc/en/configure.txt index 8331d2ea..dc802690 100644 --- a/doc/en/configure.txt +++ b/doc/en/configure.txt @@ -279,7 +279,7 @@ section of this documentation. Set this to true if you want to display the offline contacts too. -*roster_sort*:: jid_show +*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 @@ -294,7 +294,7 @@ section of this documentation. * online: sort by online presence (online or not) 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 + separated by colons (":"). If there are more than 3 or 4 chained sorting methods, your sorting is most likely inefficient. *roster_group_sort*:: name diff --git a/src/roster.py b/src/roster.py index c5f89218..af3c3563 100644 --- a/src/roster.py +++ b/src/roster.py @@ -13,35 +13,14 @@ import logging log = logging.getLogger(__name__) from config import config -from os import path as p from contact import Contact +from roster_sorting import SORTING_METHODS, GROUP_SORTING_METHODS + +from os import path as p from sleekxmpp.xmlstream.stanzabase import JID from sleekxmpp.exceptions import IqError -def sort_group_name(group): - return group.name.lower() - -def sort_group_folded(group): - return group.folded - -def sort_group_connected(group): - return - group.get_nb_connected_contacts() - -def sort_group_size(group): - return - len(group) - -def sort_group_none(group): - return 0 if group.name != 'none' else 1 - -GROUP_SORTING_METHODS = { - 'name': sort_group_name, - 'fold': sort_group_folded, - 'connected': sort_group_connected, - 'size': sort_group_size, - 'none': sort_group_none, -} - class Roster(object): """ The proxy class to get the roster from SleekXMPP. @@ -121,7 +100,7 @@ class Roster(object): """Return a list of the RosterGroups""" group_list = sorted(filter(lambda x: bool(x), self.groups.values()), key=lambda x: x.name.lower()) - for sorting in sort.split('_'): + for sorting in sort.split(':'): if sorting == 'reverse': group_list = list(reversed(group_list)) else: @@ -230,43 +209,6 @@ class Roster(object): except IOError: return -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 5 - 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 - -def sort_online(contact): - result = sort_show(contact) - return 0 if result < 5 else 1 - -SORTING_METHODS = { - 'jid': sort_jid, - 'show': sort_show, - 'resource': sort_resource_nb, - 'name': sort_name, - 'online': sort_online, -} - class RosterGroup(object): """ A RosterGroup is a group containing contacts @@ -312,7 +254,7 @@ class RosterGroup(object): else [contact for contact in self.contacts.copy() if contact_filter[0](contact, contact_filter[1])] contact_list = sorted(contact_list, key=SORTING_METHODS['name']) - for sorting in sort.split('_'): + for sorting in sort.split(':'): if sorting == 'reverse': contact_list = list(reversed(contact_list)) else: diff --git a/src/roster_sorting.py b/src/roster_sorting.py new file mode 100644 index 00000000..c57f0dce --- /dev/null +++ b/src/roster_sorting.py @@ -0,0 +1,90 @@ +""" +Defines the roster sorting methods used in roster.py +(for contacts/groups) +""" + +########################### Contacts sorting ############################ + +PRESENCE_PRIORITY = {'unavailable': 5, + 'xa': 4, + 'away': 3, + 'dnd': 2, + '': 1, + 'available': 1} + +def sort_jid(contact): + """Sort by contact JID""" + return contact.bare_jid + +def sort_show(contact): + """Sort by show (from high availability to low)""" + res = contact.get_highest_priority_resource() + if not res: + return 5 + show = res.presence + if show not in PRESENCE_PRIORITY: + return 0 + return PRESENCE_PRIORITY[show] + +def sort_resource_nb(contact): + """Sort by number of connected resources""" + return - len(contact) + +def sort_name(contact): + """Sort by name (case insensitive)""" + return contact.name.lower() or contact.bare_jid + +def sort_sname(contact): + """Sort by name (case sensitive)""" + return contact.name or contact.bare_jid + +def sort_online(contact): + """Sort by connected/disconnected""" + result = sort_show(contact) + return 0 if result < 5 else 1 + +SORTING_METHODS = { + 'jid': sort_jid, + 'sname': sort_sname, + 'show': sort_show, + 'resource': sort_resource_nb, + 'name': sort_name, + 'online': sort_online, +} + + +######################## Roster Groups sorting ########################## + +def sort_group_name(group): + """Sort by name (case insensitive)""" + return group.name.lower() + +def sort_group_sname(group): + """Sort by name (case-sensitive)""" + return group.name + +def sort_group_folded(group): + """Sort by folded/unfolded""" + return group.folded + +def sort_group_connected(group): + """Sort by number of connected contacts""" + return - group.get_nb_connected_contacts() + +def sort_group_size(group): + """Sort by group size""" + return - len(group) + +def sort_group_none(group): + """Put the none group at the end, if any""" + return 0 if group.name != 'none' else 1 + +GROUP_SORTING_METHODS = { + 'name': sort_group_name, + 'fold': sort_group_folded, + 'connected': sort_group_connected, + 'size': sort_group_size, + 'none': sort_group_none, + 'sname': sort_group_sname, +} +