From 8e8852fa9f0171bb2c0826303b97655a32e481ca Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 17 Nov 2015 23:37:33 +0000 Subject: Added /roster order name|presence --- src/command/command.c | 15 ++++++ src/command/commands.c | 20 ++++++++ src/config/preferences.c | 5 ++ src/config/preferences.h | 1 + src/roster_list.c | 116 ++++++++++++++++++++++++++++++++++++++++++++--- src/roster_list.h | 3 ++ src/ui/console.c | 4 ++ src/ui/rosterwin.c | 30 ++++++++++-- 8 files changed, 184 insertions(+), 10 deletions(-) diff --git a/src/command/command.c b/src/command/command.c index 4241acb4..2a98ba75 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -277,6 +277,7 @@ static struct cmd_t command_defs[] = "/roster show [offline|resource|presence|status|empty]", "/roster hide [offline|resource|presence|status|empty]", "/roster by group|presence|none", + "/roster order name|presence" "/roster size ", "/roster add []", "/roster remove ", @@ -303,6 +304,8 @@ static struct cmd_t command_defs[] = { "by group", "Group contacts in the roster panel by roster group." }, { "by presence", "Group contacts in the roster panel by presence." }, { "by none", "No grouping in the roster panel." }, + { "order name", "Order roster items by name only." }, + { "order presence", "Order roster items by presence, and then by name." }, { "size ", "Percentage of the screen taken up by the roster (1-99)." }, { "add []", "Add a new item to the roster." }, { "remove ", "Removes an item from the roster." }, @@ -1771,6 +1774,7 @@ static Autocomplete wins_ac; static Autocomplete roster_ac; static Autocomplete roster_option_ac; static Autocomplete roster_by_ac; +static Autocomplete roster_order_ac; static Autocomplete roster_remove_all_ac; static Autocomplete group_ac; static Autocomplete bookmark_ac; @@ -2014,6 +2018,7 @@ cmd_init(void) autocomplete_add(roster_ac, "show"); autocomplete_add(roster_ac, "hide"); autocomplete_add(roster_ac, "by"); + autocomplete_add(roster_ac, "order"); autocomplete_add(roster_ac, "size"); roster_option_ac = autocomplete_new(); @@ -2028,6 +2033,10 @@ cmd_init(void) autocomplete_add(roster_by_ac, "presence"); autocomplete_add(roster_by_ac, "none"); + roster_order_ac = autocomplete_new(); + autocomplete_add(roster_order_ac, "name"); + autocomplete_add(roster_order_ac, "presence"); + roster_remove_all_ac = autocomplete_new(); autocomplete_add(roster_remove_all_ac, "contacts"); @@ -2282,6 +2291,7 @@ cmd_uninit(void) autocomplete_free(roster_ac); autocomplete_free(roster_option_ac); autocomplete_free(roster_by_ac); + autocomplete_free(roster_order_ac); autocomplete_free(roster_remove_all_ac); autocomplete_free(group_ac); autocomplete_free(bookmark_ac); @@ -2468,6 +2478,7 @@ cmd_reset_autocomplete(ProfWin *window) autocomplete_reset(roster_ac); autocomplete_reset(roster_option_ac); autocomplete_reset(roster_by_ac); + autocomplete_reset(roster_order_ac); autocomplete_reset(roster_remove_all_ac); autocomplete_reset(group_ac); autocomplete_reset(titlebar_ac); @@ -2881,6 +2892,10 @@ _roster_autocomplete(ProfWin *window, const char *const input) if (result) { return result; } + result = autocomplete_param_with_ac(input, "/roster order", roster_order_ac, TRUE); + if (result) { + return result; + } result = autocomplete_param_with_ac(input, "/roster", roster_ac, TRUE); if (result) { return result; diff --git a/src/command/commands.c b/src/command/commands.c index 40a041c9..67f8ae98 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -1872,6 +1872,26 @@ cmd_roster(ProfWin *window, const char *const command, gchar **args) cons_bad_cmd_usage(command); return TRUE; } + // roster item order + } else if (g_strcmp0(args[0], "order") == 0) { + if (g_strcmp0(args[1], "name") == 0) { + cons_show("Ordering roster by name"); + prefs_set_string(PREF_ROSTER_ORDER, "name"); + if (conn_status == JABBER_CONNECTED) { + rosterwin_roster(); + } + return TRUE; + } else if (g_strcmp0(args[1], "presence") == 0) { + cons_show("Ordering roster by presence"); + prefs_set_string(PREF_ROSTER_ORDER, "presence"); + if (conn_status == JABBER_CONNECTED) { + rosterwin_roster(); + } + return TRUE; + } else { + cons_bad_cmd_usage(command); + return TRUE; + } // add contact } else if (strcmp(args[0], "add") == 0) { if (conn_status != JABBER_CONNECTED) { diff --git a/src/config/preferences.c b/src/config/preferences.c index b8f6d607..8348edb7 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -601,6 +601,7 @@ _get_group(preference_t pref) case PREF_ROSTER_STATUS: case PREF_ROSTER_EMPTY: case PREF_ROSTER_BY: + case PREF_ROSTER_ORDER: case PREF_RESOURCE_TITLE: case PREF_RESOURCE_MESSAGE: case PREF_ENC_WARN: @@ -778,6 +779,8 @@ _get_key(preference_t pref) return "roster.empty"; case PREF_ROSTER_BY: return "roster.by"; + case PREF_ROSTER_ORDER: + return "roster.order"; case PREF_RESOURCE_TITLE: return "resource.title"; case PREF_RESOURCE_MESSAGE: @@ -861,6 +864,8 @@ _get_default_string(preference_t pref) return "all"; case PREF_ROSTER_BY: return "presence"; + case PREF_ROSTER_ORDER: + return "name"; case PREF_TIME_CONSOLE: return "%H:%M:%S"; case PREF_TIME_CHAT: diff --git a/src/config/preferences.h b/src/config/preferences.h index ff830cce..55b46b07 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -68,6 +68,7 @@ typedef enum { PREF_ROSTER_STATUS, PREF_ROSTER_EMPTY, PREF_ROSTER_BY, + PREF_ROSTER_ORDER, PREF_MUC_PRIVILEGES, PREF_PRESENCE, PREF_WRAP, diff --git a/src/roster_list.c b/src/roster_list.c index 0ba20107..fe3063dd 100644 --- a/src/roster_list.c +++ b/src/roster_list.c @@ -67,7 +67,8 @@ static gboolean _key_equals(void *key1, void *key2); static gboolean _datetimes_equal(GDateTime *dt1, GDateTime *dt2); static void _replace_name(const char *const current_name, const char *const new_name, const char *const barejid); static void _add_name_and_barejid(const char *const name, const char *const barejid); -static gint _compare_contacts(PContact a, PContact b); +static gint _compare_name(PContact a, PContact b); +static gint _compare_presence(PContact a, PContact b); void roster_clear(void) @@ -373,7 +374,7 @@ roster_get_contacts_by_presence(const char *const presence) while (g_hash_table_iter_next(&iter, &key, &value)) { PContact contact = (PContact)value; if (g_strcmp0(p_contact_presence(contact), presence) == 0) { - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_name); } } @@ -381,6 +382,23 @@ roster_get_contacts_by_presence(const char *const presence) return result; } +GSList* +roster_get_contacts_ord_presence(void) +{ + GSList *result = NULL; + GHashTableIter iter; + gpointer key; + gpointer value; + + g_hash_table_iter_init(&iter, contacts); + while (g_hash_table_iter_next(&iter, &key, &value)) { + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_presence); + } + + // return all contact structs + return result; +} + GSList* roster_get_contacts(void) { @@ -391,7 +409,7 @@ roster_get_contacts(void) g_hash_table_iter_init(&iter, contacts); while (g_hash_table_iter_next(&iter, &key, &value)) { - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_name); } // return all contact structs @@ -409,7 +427,7 @@ roster_get_contacts_online(void) g_hash_table_iter_init(&iter, contacts); while (g_hash_table_iter_next(&iter, &key, &value)) { if(strcmp(p_contact_presence(value), "offline")) - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_name); } // return all contact structs @@ -446,6 +464,26 @@ roster_fulljid_autocomplete(const char *const search_str) return autocomplete_complete(fulljid_ac, search_str, TRUE); } +GSList* +roster_get_nogroup_ord_presence(void) +{ + GSList *result = NULL; + GHashTableIter iter; + gpointer key; + gpointer value; + + g_hash_table_iter_init(&iter, contacts); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GSList *groups = p_contact_groups(value); + if (groups == NULL) { + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_presence); + } + } + + // return all contact structs + return result; +} + GSList* roster_get_nogroup(void) { @@ -458,7 +496,31 @@ roster_get_nogroup(void) while (g_hash_table_iter_next(&iter, &key, &value)) { GSList *groups = p_contact_groups(value); if (groups == NULL) { - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_name); + } + } + + // return all contact structs + return result; +} + +GSList* +roster_get_group_ord_presence(const char *const group) +{ + GSList *result = NULL; + GHashTableIter iter; + gpointer key; + gpointer value; + + g_hash_table_iter_init(&iter, contacts); + while (g_hash_table_iter_next(&iter, &key, &value)) { + GSList *groups = p_contact_groups(value); + while (groups) { + if (strcmp(groups->data, group) == 0) { + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_presence); + break; + } + groups = g_slist_next(groups); } } @@ -479,7 +541,7 @@ roster_get_group(const char *const group) GSList *groups = p_contact_groups(value); while (groups) { if (strcmp(groups->data, group) == 0) { - result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_contacts); + result = g_slist_insert_sorted(result, value, (GCompareFunc)_compare_name); break; } groups = g_slist_next(groups); @@ -560,7 +622,7 @@ _add_name_and_barejid(const char *const name, const char *const barejid) } static gint -_compare_contacts(PContact a, PContact b) +_compare_name(PContact a, PContact b) { const char * utf8_str_a = NULL; const char * utf8_str_b = NULL; @@ -580,3 +642,43 @@ _compare_contacts(PContact a, PContact b) return result; } + +static gint +_get_presence_weight(const char *presence) +{ + if (g_strcmp0(presence, "chat") == 0) { + return 0; + } else if (g_strcmp0(presence, "online") == 0) { + return 1; + } else if (g_strcmp0(presence, "away") == 0) { + return 2; + } else if (g_strcmp0(presence, "xa") == 0) { + return 3; + } else if (g_strcmp0(presence, "dnd") == 0) { + return 4; + } else { // offline + return 5; + } +} + +static gint +_compare_presence(PContact a, PContact b) +{ + const char *presence_a = p_contact_presence(a); + const char *presence_b = p_contact_presence(b); + + // if presence different, order by presence + if (g_strcmp0(presence_a, presence_b) != 0) { + int weight_a = _get_presence_weight(presence_a); + int weight_b = _get_presence_weight(presence_b); + if (weight_a < weight_b) { + return -1; + } else { + return 1; + } + + // otherwise order by name + } else { + return _compare_name(a, b); + } +} diff --git a/src/roster_list.h b/src/roster_list.h index 01def408..da4bbbcd 100644 --- a/src/roster_list.h +++ b/src/roster_list.h @@ -55,16 +55,19 @@ gboolean roster_add(const char *const barejid, const char *const name, GSList *g gboolean pending_out); char* roster_barejid_from_name(const char *const name); GSList* roster_get_contacts(void); +GSList* roster_get_contacts_ord_presence(void); GSList* roster_get_contacts_online(void); gboolean roster_has_pending_subscriptions(void); char* roster_contact_autocomplete(const char *const search_str); char* roster_fulljid_autocomplete(const char *const search_str); GSList* roster_get_group(const char *const group); +GSList* roster_get_group_ord_presence(const char *const group); GSList* roster_get_groups(void); char* roster_group_autocomplete(const char *const search_str); char* roster_barejid_autocomplete(const char *const search_str); GSList* roster_get_contacts_by_presence(const char *const presence); GSList* roster_get_nogroup(void); +GSList* roster_get_nogroup_ord_presence(void); char* roster_get_msg_display_name(const char *const barejid, const char *const resource); #endif diff --git a/src/ui/console.c b/src/ui/console.c index 8825cf69..882a9b54 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -1226,6 +1226,10 @@ cons_roster_setting(void) cons_show("Roster by (/roster) : %s", by); prefs_free_string(by); + char *order = prefs_get_string(PREF_ROSTER_ORDER); + cons_show("Roster order (/roster) : %s", order); + prefs_free_string(order); + int size = prefs_get_roster_size(); cons_show("Roster size (/roster) : %d", size); } diff --git a/src/ui/rosterwin.c b/src/ui/rosterwin.c index b721dbfe..95d374bd 100644 --- a/src/ui/rosterwin.c +++ b/src/ui/rosterwin.c @@ -167,7 +167,15 @@ _rosterwin_contacts_by_group(ProfLayoutSplit *layout, char *group) g_string_free(title, TRUE); wattroff(layout->subwin, theme_attrs(THEME_ROSTER_HEADER)); - GSList *contacts = roster_get_group(group); + GSList *contacts = NULL; + + char *order = prefs_get_string(PREF_ROSTER_ORDER); + if (g_strcmp0(order, "presence") == 0) { + contacts = roster_get_group_ord_presence(group); + } else { + contacts = roster_get_group(group); + } + if (contacts) { GSList *curr_contact = contacts; while (curr_contact) { @@ -182,7 +190,15 @@ _rosterwin_contacts_by_group(ProfLayoutSplit *layout, char *group) static void _rosterwin_contacts_by_no_group(ProfLayoutSplit *layout) { - GSList *contacts = roster_get_nogroup(); + GSList *contacts = NULL; + + char *order = prefs_get_string(PREF_ROSTER_ORDER); + if (g_strcmp0(order, "presence") == 0) { + contacts = roster_get_nogroup_ord_presence(); + } else { + contacts = roster_get_nogroup(); + } + if (contacts) { wattron(layout->subwin, theme_attrs(THEME_ROSTER_HEADER)); win_printline_nowrap(layout->subwin, " -no group"); @@ -228,7 +244,15 @@ rosterwin_roster(void) g_slist_free_full(groups, free); _rosterwin_contacts_by_no_group(layout); } else { - GSList *contacts = roster_get_contacts(); + GSList *contacts = NULL; + + char *order = prefs_get_string(PREF_ROSTER_ORDER); + if (g_strcmp0(order, "presence") == 0) { + contacts = roster_get_contacts_ord_presence(); + } else { + contacts = roster_get_contacts(); + } + if (contacts) { werase(layout->subwin); -- cgit 1.4.1-2-gfad0