# HG changeset patch # User Sadrul Habib Chowdhury # Date 1220164277 0 # Node ID 8a488151e07aa2c0f21acdc27cc24e8a3d98f38a # Parent 4df8161acc3bb8885e095add7248cc59173277b7 Add 'Nested Grouping' option in the grouping plugin Nested groups are detected by the '/' character in the group name. For example, groups 'Work/Accounting' and 'Work/Lab' will both be nested under a 'Work' parent group. It would probably make more sense to actually name the subgroups 'Accounting' and 'Lab' in this case, and a patch to make that happen will be gladly accepted. I think some other client uses similar behaviour for group nestedness. diff -r 4df8161acc3b -r 8a488151e07a ChangeLog --- a/ChangeLog Sun Aug 31 06:23:52 2008 +0000 +++ b/ChangeLog Sun Aug 31 06:31:17 2008 +0000 @@ -1,6 +1,9 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul version 2.5.2 (??/??/????): + Finch: + * A new 'Nested Grouping' option in the 'Grouping' plugin. Group + hierarchies are defined by the '/' character in the group names version 2.5.1 (08/30/2008): libpurple: diff -r 4df8161acc3b -r 8a488151e07a finch/plugins/grouping.c --- a/finch/plugins/grouping.c Sun Aug 31 06:23:52 2008 +0000 +++ b/finch/plugins/grouping.c Sun Aug 31 06:31:17 2008 +0000 @@ -28,6 +28,8 @@ #include "gnttree.h" +static FinchBlistManager *default_manager; + /** * Online/Offline */ @@ -103,12 +105,8 @@ static gboolean on_offline_create_tooltip(gpointer selected_row, GString **body, char **tool_title) { - static FinchBlistManager *def = NULL; PurpleBlistNode *node = selected_row; - if (def == NULL) - def = finch_blist_manager_find("default"); - if (purple_blist_node_get_type(node) == PURPLE_BLIST_OTHER_NODE) { /* There should be some easy way of getting the total online count, * or total number of chats. Doing a loop here will probably be pretty @@ -117,7 +115,7 @@ *body = g_string_new(node == &online ? _("Online Buddies") : _("Offline Buddies")); return TRUE; } else { - return def ? def->create_tooltip(selected_row, body, tool_title) : FALSE; + return default_manager ? default_manager->create_tooltip(selected_row, body, tool_title) : FALSE; } } @@ -149,17 +147,13 @@ static gpointer meebo_find_parent(PurpleBlistNode *node) { - static FinchBlistManager *def = NULL; - if (def == NULL) - def = finch_blist_manager_find("default"); - if (PURPLE_BLIST_NODE_IS_CONTACT(node)) { PurpleBuddy *buddy = purple_contact_get_priority_buddy((PurpleContact*)node); if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy)) { return &meebo; } } - return def->find_parent(node); + return default_manager->find_parent(node); } static FinchBlistManager meebo_group = @@ -223,12 +217,127 @@ {NULL, NULL, NULL, NULL} }; +/** + * Nested Grouping + */ +static GHashTable *groups; + +static gboolean +nested_group_init(void) +{ + groups = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + return TRUE; +} + +static gboolean +nested_group_uninit(void) +{ + g_hash_table_destroy(groups); + groups = NULL; + return TRUE; +} + +static gpointer +nested_group_find_parent(PurpleBlistNode *node) +{ + char *name; + PurpleGroup *group; + char *sep; + PurpleBlistNode *ret, *parent; + GntTree *tree; + + if (!PURPLE_BLIST_NODE_IS_GROUP(node)) + return default_manager->find_parent(node); + + group = (PurpleGroup *)node; + name = g_strdup(purple_group_get_name(group)); + if (!(sep = strchr(name, '/'))) { + g_free(name); + return default_manager->find_parent(node); + } + + tree = finch_blist_get_tree(); + parent = NULL; + + while (sep) { + *sep = 0; + if (*(sep + 1) && (ret = (PurpleBlistNode *)purple_find_group(name))) { + finch_blist_manager_add_node(ret); + parent = ret; + } else if (!(ret = g_hash_table_lookup(groups, name))) { + ret = g_new0(PurpleBlistNode, 1); + g_hash_table_insert(groups, g_strdup(name), ret); + ret->type = PURPLE_BLIST_OTHER_NODE; + gnt_tree_add_row_last(tree, ret, + gnt_tree_create_row(tree, name), parent); + parent = ret; + } + *sep = '/'; + sep = strchr(sep + 1, '/'); + } + + g_free(name); + return ret; +} + +static gboolean +nested_group_create_tooltip(gpointer selected_row, GString **body, char **title) +{ + PurpleBlistNode *node = selected_row; + if (!node || + purple_blist_node_get_type(node) != PURPLE_BLIST_OTHER_NODE) + return default_manager->create_tooltip(selected_row, body, title); + if (body) + *body = g_string_new(_("Nested Subgroup")); /* Perhaps list the child groups/subgroups? */ + return TRUE; +} + +static gboolean +nested_group_can_add_node(PurpleBlistNode *node) +{ + PurpleBlistNode *group; + int len; + + if (!PURPLE_BLIST_NODE_IS_GROUP(node)) + return default_manager->can_add_node(node); + + if (default_manager->can_add_node(node)) + return TRUE; + + len = strlen(purple_group_get_name((PurpleGroup*)node)); + group = purple_blist_get_root(); + for (; group; group = purple_blist_node_get_sibling_next(group)) { + if (group == node) + continue; + if (strncmp(purple_group_get_name((PurpleGroup *)node), + purple_group_get_name((PurpleGroup *)group), len) == 0 && + default_manager->can_add_node(group)) + return TRUE; + } + return FALSE; +} + +static FinchBlistManager nested_group = +{ + "nested", + N_("Nested Grouping (experimental)"), + .init = nested_group_init, + .uninit = nested_group_uninit, + .find_parent = nested_group_find_parent, + .create_tooltip = nested_group_create_tooltip, + .can_add_node = nested_group_can_add_node, +}; + static gboolean plugin_load(PurplePlugin *plugin) { + default_manager = finch_blist_manager_find("default"); + finch_blist_install_manager(&on_offline); finch_blist_install_manager(&meebo_group); finch_blist_install_manager(&no_group); + finch_blist_install_manager(&nested_group); return TRUE; } @@ -238,6 +347,7 @@ finch_blist_uninstall_manager(&on_offline); finch_blist_uninstall_manager(&meebo_group); finch_blist_uninstall_manager(&no_group); + finch_blist_uninstall_manager(&nested_group); return TRUE; }