From 1625a4f41fa6727e41b0546687d72a3101b2b2bf Mon Sep 17 00:00:00 2001 From: mathieui Date: Tue, 31 Jul 2012 23:40:53 +0200 Subject: [PATCH] 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 --- data/default_config.cfg | 13 +++++++++ doc/en/configure.txt | 17 ++++++++++++ src/roster.py | 61 +++++++++++++++++++++++++++++------------ src/windows.py | 3 +- 4 files changed, 75 insertions(+), 19 deletions(-) diff --git a/data/default_config.cfg b/data/default_config.cfg index d674e098..aedd2413 100644 --- a/data/default_config.cfg +++ b/data/default_config.cfg @@ -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 diff --git a/doc/en/configure.txt b/doc/en/configure.txt index f72d1627..aa880d7b 100644 --- a/doc/en/configure.txt +++ b/doc/en/configure.txt @@ -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 diff --git a/src/roster.py b/src/roster.py index 56c65d8f..84771678 100644 --- a/src/roster.py +++ b/src/roster.py @@ -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() diff --git a/src/windows.py b/src/windows.py index a46edb1e..da80c989 100644 --- a/src/windows.py +++ b/src/windows.py @@ -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: