merge of '6696045322d43e1d7c9634a33cf10ca2323c061c'
[pidgin-git.git] / finch / plugins / grouping.c
blobb312c7dc3b14146cf286d53c9c637d3c35ea20cd
1 /**
2 * @file grouping.c Provides different grouping options.
4 * Copyright (C) 2008 Sadrul Habib Chowdhury <sadrul@users.sourceforge.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 #define PURPLE_PLUGIN
23 #include "internal.h"
24 #include "purple.h"
26 #include "gntblist.h"
27 #include "gntplugin.h"
29 #include "gnttree.h"
31 static FinchBlistManager *default_manager;
33 /**
34 * Online/Offline
36 static PurpleBlistNode online = {.type = PURPLE_BLIST_OTHER_NODE},
37 offline = {.type = PURPLE_BLIST_OTHER_NODE};
39 static gboolean on_offline_init()
41 GntTree *tree = finch_blist_get_tree();
43 gnt_tree_add_row_after(tree, &online,
44 gnt_tree_create_row(tree, _("Online")), NULL, NULL);
45 gnt_tree_add_row_after(tree, &offline,
46 gnt_tree_create_row(tree, _("Offline")), NULL, &online);
48 return TRUE;
51 static gboolean on_offline_can_add_node(PurpleBlistNode *node)
53 switch (purple_blist_node_get_type(node)) {
54 case PURPLE_BLIST_CONTACT_NODE:
56 PurpleContact *contact = (PurpleContact*)node;
57 if (contact->currentsize > 0)
58 return TRUE;
59 return FALSE;
61 break;
62 case PURPLE_BLIST_BUDDY_NODE:
64 PurpleBuddy *buddy = (PurpleBuddy*)node;
65 if (PURPLE_BUDDY_IS_ONLINE(buddy))
66 return TRUE;
67 if (purple_prefs_get_bool("/finch/blist/showoffline") &&
68 purple_account_is_connected(purple_buddy_get_account(buddy)))
69 return TRUE;
70 return FALSE;
72 break;
73 case PURPLE_BLIST_CHAT_NODE:
75 PurpleChat *chat = (PurpleChat*)node;
76 return purple_account_is_connected(purple_chat_get_account(chat));
78 break;
79 default:
80 return FALSE;
84 static gpointer on_offline_find_parent(PurpleBlistNode *node)
86 gpointer ret = NULL;
88 switch (purple_blist_node_get_type(node)) {
89 case PURPLE_BLIST_CONTACT_NODE:
90 node = PURPLE_BLIST_NODE(purple_contact_get_priority_buddy(PURPLE_CONTACT(node)));
91 ret = PURPLE_BUDDY_IS_ONLINE((PurpleBuddy*)node) ? &online : &offline;
92 break;
93 case PURPLE_BLIST_BUDDY_NODE:
94 ret = purple_blist_node_get_parent(node);
95 finch_blist_manager_add_node(ret);
96 break;
97 case PURPLE_BLIST_CHAT_NODE:
98 ret = &online;
99 break;
100 default:
101 break;
103 return ret;
106 static gboolean on_offline_create_tooltip(gpointer selected_row, GString **body, char **tool_title)
108 PurpleBlistNode *node = selected_row;
110 if (purple_blist_node_get_type(node) == PURPLE_BLIST_OTHER_NODE) {
111 /* There should be some easy way of getting the total online count,
112 * or total number of chats. Doing a loop here will probably be pretty
113 * expensive. */
114 if (body)
115 *body = g_string_new(node == &online ? _("Online Buddies") : _("Offline Buddies"));
116 return TRUE;
117 } else {
118 return default_manager ? default_manager->create_tooltip(selected_row, body, tool_title) : FALSE;
122 static FinchBlistManager on_offline =
124 "on-offline",
125 N_("Online/Offline"),
126 on_offline_init,
127 NULL,
128 on_offline_can_add_node,
129 on_offline_find_parent,
130 on_offline_create_tooltip,
131 {NULL, NULL, NULL, NULL}
135 * Meebo-like Grouping.
137 static PurpleBlistNode meebo = {.type = PURPLE_BLIST_OTHER_NODE};
138 static gboolean meebo_init()
140 GntTree *tree = finch_blist_get_tree();
141 if (!g_list_find(gnt_tree_get_rows(tree), &meebo)) {
142 gnt_tree_add_row_last(tree, &meebo,
143 gnt_tree_create_row(tree, _("Offline")), NULL);
145 return TRUE;
148 static gpointer meebo_find_parent(PurpleBlistNode *node)
150 if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
151 PurpleBuddy *buddy = purple_contact_get_priority_buddy((PurpleContact*)node);
152 if (buddy && !PURPLE_BUDDY_IS_ONLINE(buddy)) {
153 return &meebo;
156 return default_manager->find_parent(node);
159 static FinchBlistManager meebo_group =
161 "meebo",
162 N_("Meebo"),
163 meebo_init,
164 NULL,
165 NULL,
166 meebo_find_parent,
167 NULL,
168 {NULL, NULL, NULL, NULL}
172 * No Grouping.
174 static gboolean no_group_init()
176 GntTree *tree = finch_blist_get_tree();
177 g_object_set(G_OBJECT(tree), "expander-level", 0, NULL);
178 return TRUE;
181 static gboolean no_group_uninit()
183 GntTree *tree = finch_blist_get_tree();
184 g_object_set(G_OBJECT(tree), "expander-level", 1, NULL);
185 return TRUE;
188 static gboolean no_group_can_add_node(PurpleBlistNode *node)
190 return on_offline_can_add_node(node); /* These happen to be the same */
193 static gpointer no_group_find_parent(PurpleBlistNode *node)
195 gpointer ret = NULL;
197 switch (purple_blist_node_get_type(node)) {
198 case PURPLE_BLIST_BUDDY_NODE:
199 ret = purple_blist_node_get_parent(node);
200 finch_blist_manager_add_node(ret);
201 break;
202 default:
203 break;
205 return ret;
208 static FinchBlistManager no_group =
210 "no-group",
211 N_("No Grouping"),
212 no_group_init,
213 no_group_uninit,
214 no_group_can_add_node,
215 no_group_find_parent,
216 NULL,
217 {NULL, NULL, NULL, NULL}
221 * Nested Grouping
223 static GHashTable *groups;
225 static gboolean
226 nested_group_init(void)
228 groups = g_hash_table_new_full(g_str_hash, g_str_equal,
229 g_free, g_free);
230 return TRUE;
233 static gboolean
234 nested_group_uninit(void)
236 g_hash_table_destroy(groups);
237 groups = NULL;
238 return TRUE;
241 static gpointer
242 nested_group_find_parent(PurpleBlistNode *node)
244 char *name;
245 PurpleGroup *group;
246 char *sep;
247 PurpleBlistNode *ret, *parent;
248 GntTree *tree;
250 if (!PURPLE_BLIST_NODE_IS_GROUP(node))
251 return default_manager->find_parent(node);
253 group = (PurpleGroup *)node;
254 name = g_strdup(purple_group_get_name(group));
255 if (!(sep = strchr(name, '/'))) {
256 g_free(name);
257 return default_manager->find_parent(node);
260 tree = finch_blist_get_tree();
261 parent = NULL;
263 while (sep) {
264 *sep = 0;
265 if (*(sep + 1) && (ret = (PurpleBlistNode *)purple_find_group(name))) {
266 finch_blist_manager_add_node(ret);
267 parent = ret;
268 } else if (!(ret = g_hash_table_lookup(groups, name))) {
269 ret = g_new0(PurpleBlistNode, 1);
270 g_hash_table_insert(groups, g_strdup(name), ret);
271 ret->type = PURPLE_BLIST_OTHER_NODE;
272 gnt_tree_add_row_last(tree, ret,
273 gnt_tree_create_row(tree, name), parent);
274 parent = ret;
276 *sep = '/';
277 sep = strchr(sep + 1, '/');
280 g_free(name);
281 return ret;
284 static gboolean
285 nested_group_create_tooltip(gpointer selected_row, GString **body, char **title)
287 PurpleBlistNode *node = selected_row;
288 if (!node ||
289 purple_blist_node_get_type(node) != PURPLE_BLIST_OTHER_NODE)
290 return default_manager->create_tooltip(selected_row, body, title);
291 if (body)
292 *body = g_string_new(_("Nested Subgroup")); /* Perhaps list the child groups/subgroups? */
293 return TRUE;
296 static gboolean
297 nested_group_can_add_node(PurpleBlistNode *node)
299 PurpleBlistNode *group;
300 int len;
302 if (!PURPLE_BLIST_NODE_IS_GROUP(node))
303 return default_manager->can_add_node(node);
305 if (default_manager->can_add_node(node))
306 return TRUE;
308 len = strlen(purple_group_get_name((PurpleGroup*)node));
309 group = purple_blist_get_root();
310 for (; group; group = purple_blist_node_get_sibling_next(group)) {
311 if (group == node)
312 continue;
313 if (strncmp(purple_group_get_name((PurpleGroup *)node),
314 purple_group_get_name((PurpleGroup *)group), len) == 0 &&
315 default_manager->can_add_node(group))
316 return TRUE;
318 return FALSE;
321 static FinchBlistManager nested_group =
323 "nested",
324 N_("Nested Grouping (experimental)"),
325 .init = nested_group_init,
326 .uninit = nested_group_uninit,
327 .find_parent = nested_group_find_parent,
328 .create_tooltip = nested_group_create_tooltip,
329 .can_add_node = nested_group_can_add_node,
332 static gboolean
333 plugin_load(PurplePlugin *plugin)
335 default_manager = finch_blist_manager_find("default");
337 finch_blist_install_manager(&on_offline);
338 finch_blist_install_manager(&meebo_group);
339 finch_blist_install_manager(&no_group);
340 finch_blist_install_manager(&nested_group);
341 return TRUE;
344 static gboolean
345 plugin_unload(PurplePlugin *plugin)
347 finch_blist_uninstall_manager(&on_offline);
348 finch_blist_uninstall_manager(&meebo_group);
349 finch_blist_uninstall_manager(&no_group);
350 finch_blist_uninstall_manager(&nested_group);
351 return TRUE;
354 static PurplePluginInfo info =
356 PURPLE_PLUGIN_MAGIC,
357 PURPLE_MAJOR_VERSION,
358 PURPLE_MINOR_VERSION,
359 PURPLE_PLUGIN_STANDARD,
360 FINCH_PLUGIN_TYPE,
362 NULL,
363 PURPLE_PRIORITY_DEFAULT,
364 "grouping",
365 N_("Grouping"),
366 VERSION,
367 N_("Provides alternate buddylist grouping options."),
368 N_("Provides alternate buddylist grouping options."),
369 "Sadrul H Chowdhury <sadrul@users.sourceforge.net>",
370 PURPLE_WEBSITE,
371 plugin_load,
372 plugin_unload,
373 NULL,
374 NULL,
375 NULL,
376 NULL,
377 NULL,
378 NULL,NULL,NULL,NULL
381 static void
382 init_plugin(PurplePlugin *plugin)
386 PURPLE_INIT_PLUGIN(grouping, init_plugin, info)