Mercurial > pidgin
changeset 5422:af62169c74fd
[gaim-migrate @ 5801]
Not to be too LSchieresque, but:
<SeanEgan> Which should I do? Finish writing sorting code or commit sorting code?
<Robot101> the latter, then the former.
This is my incomplete buddy list sorting code. Sorting methods are modular, a plugin
can add its own if it wanted to. Included are four sorting methods:
None - this will be perceived as no sorting. It sorts the list in the order specified
in blist.xml
Alphabetical - duh.
By status - this isn't really written yet, but I'm going to fix it right now. This will
sort using idle time, away status, and online status when it's written
By log file size - this puts the people you talk to the most at the top of your list. Pretty
keen, eh?
Of course this is replete with Sean Egan Hacks (TM).
Now I'm going to go eat some weird "golden crunch" cereal from nestle.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sun, 18 May 2003 03:41:31 +0000 |
parents | 7955274fa92b |
children | 5df0bd96c7ad |
files | src/gaim.h src/gaimrc.c src/gtkblist.c src/gtkblist.h src/main.c src/prefs.c |
diffstat | 6 files changed, 331 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/src/gaim.h Sun May 18 02:50:49 2003 +0000 +++ b/src/gaim.h Sun May 18 03:41:31 2003 +0000 @@ -326,6 +326,7 @@ extern GSList *unread_message_queue; extern GSList *away_time_queue; extern char web_command[2048]; +extern char sort_method[64]; extern struct save_pos blist_pos; extern struct window_size conv_size, buddy_chat_size;
--- a/src/gaimrc.c Sun May 18 02:50:49 2003 +0000 +++ b/src/gaimrc.c Sun May 18 03:41:31 2003 +0000 @@ -966,6 +966,8 @@ blist_pos.y = atoi(p->value[1]); blist_pos.width = atoi(p->value[2]); blist_pos.height = atoi(p->value[3]); + } else if (!strcmp(p->option, "sort_method")) { + strcpy(sort_method, p->value[0]); } } @@ -1056,6 +1058,7 @@ fprintf(f, "\treport_idle { %d }\n", report_idle); fprintf(f, "\tweb_browser { %d }\n", web_browser); fprintf(f, "\tweb_command { %s }\n", web_command); + fprintf(f, "\tsort_method { %s }\n", sort_method); if (current_smiley_theme) { #ifndef _WIN32 fprintf(f, "\tsmiley_theme { %s }\n", current_smiley_theme->path);
--- a/src/gtkblist.c Sun May 18 02:50:49 2003 +0000 +++ b/src/gtkblist.c Sun May 18 03:41:31 2003 +0000 @@ -31,9 +31,11 @@ #include <stdio.h> #include <stdlib.h> #include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #include <math.h> #include <time.h> -#include <ctype.h> #ifdef _WIN32 #include <gdk/gdkwin32.h> @@ -56,6 +58,12 @@ #include "win32dep.h" #endif +GSList *gaim_gtk_blist_sort_methods = NULL; +static struct gaim_gtk_blist_sort_method *current_sort_method = NULL; +static GtkTreeIter sort_method_none(GaimBlistNode *node, struct gaim_buddy_list *blist, GtkTreeIter groupiter, GtkTreeIter *cur); +static GtkTreeIter sort_method_alphabetical(GaimBlistNode *node, struct gaim_buddy_list *blist, GtkTreeIter groupiter, GtkTreeIter *cur); +static GtkTreeIter sort_method_status(GaimBlistNode *node, struct gaim_buddy_list *blist, GtkTreeIter groupiter, GtkTreeIter *cur); +static GtkTreeIter sort_method_log(GaimBlistNode *node, struct gaim_buddy_list *blist, GtkTreeIter groupiter, GtkTreeIter *cur); static struct gaim_gtk_buddy_list *gtkblist = NULL; /* part of the best damn Docklet code this side of Tahiti */ @@ -67,6 +75,8 @@ static char *item_factory_translate_func (const char *path, gpointer func_data); static gboolean get_iter_from_node(GaimBlistNode *node, GtkTreeIter *iter); +char sort_method[64]; + struct _gaim_gtk_blist_node { GtkTreeRowReference *row; }; @@ -1307,6 +1317,16 @@ return _(path); } +void gaim_gtk_blist_setup_sort_methods() +{ + gaim_gtk_blist_sort_method_reg("None", sort_method_none); + gaim_gtk_blist_sort_method_reg("Alphabetical", sort_method_alphabetical); + gaim_gtk_blist_sort_method_reg("By status", sort_method_status); + gaim_gtk_blist_sort_method_reg("By log size", sort_method_log); + gaim_gtk_blist_sort_method_set(sort_method[0] ? sort_method : "None"); +} + + static void gaim_gtk_blist_show(struct gaim_buddy_list *list) { GtkItemFactory *ift; @@ -1504,20 +1524,27 @@ gtkblist->refresh_timer = g_timeout_add(30000, (GSourceFunc)gaim_gtk_blist_refresh_timer, list); } -void gaim_gtk_blist_refresh(struct gaim_buddy_list *list) +static void redo_buddy_list(struct gaim_buddy_list *list, gboolean remove) { GaimBlistNode *group, *buddy; - + for(group = list->root; group; group = group->next) { if(!GAIM_BLIST_NODE_IS_GROUP(group)) continue; gaim_gtk_blist_update(list, group); for(buddy = group->child; buddy; buddy = buddy->next) { + if (remove) + gaim_gtk_blist_hide_node(list, buddy); gaim_gtk_blist_update(list, buddy); } } } +void gaim_gtk_blist_refresh(struct gaim_buddy_list *list) +{ + redo_buddy_list(list, FALSE); +} + void gaim_gtk_blist_update_refresh_timeout() { @@ -1676,7 +1703,6 @@ g_free(mark); } - static void gaim_gtk_blist_update(struct gaim_buddy_list *list, GaimBlistNode *node) { GtkTreeIter iter; @@ -1706,17 +1732,9 @@ expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &groupiter); else g_free(collapsed); - - oldersibling = node->prev; - while (oldersibling && !get_iter_from_node(oldersibling, &oldersiblingiter)) { - oldersibling = oldersibling->prev; - } - - gtk_tree_store_insert_after(gtkblist->treemodel, &iter, &groupiter, oldersibling ? &oldersiblingiter : NULL); - newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); - gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); - gtk_tree_path_free(newpath); - + + iter = current_sort_method->func(node, list, groupiter, NULL); + if (blist_options & OPT_BLIST_POPUP) { gtk_widget_show(gtkblist->window); gtk_window_deiconify(GTK_WINDOW(gtkblist->window)); @@ -1816,6 +1834,7 @@ gaim_gtk_blist_hide_node(list, node); } else if (GAIM_BLIST_NODE_IS_BUDDY(node) && (((struct buddy*)node)->present != GAIM_BUDDY_OFFLINE || ((blist_options & OPT_BLIST_SHOW_OFFLINE) && ((struct buddy*)node)->account->gc))) { GdkPixbuf *status, *avatar; + GtkTreeIter groupiter; char *mark; char *warning = NULL, *idle = NULL; @@ -1858,6 +1877,10 @@ idle = i2; } } + if (!selected) { + get_iter_from_node(node->parent, &groupiter); + iter = current_sort_method->func(node, list, groupiter, &iter); + } gtk_tree_store_set(gtkblist->treemodel, &iter, STATUS_ICON_COLUMN, status, @@ -2068,3 +2091,217 @@ return status; } + +/********************************************************************* + * Buddy List sorting functions * + *********************************************************************/ + +void gaim_gtk_blist_sort_method_reg(const char *name, gaim_gtk_blist_sort_function func) +{ + struct gaim_gtk_blist_sort_method *method = g_new0(struct gaim_gtk_blist_sort_method, 1); + method->name = g_strdup(name); + method->func = func; + gaim_gtk_blist_sort_methods = g_slist_append(gaim_gtk_blist_sort_methods, method); +} + +void gaim_gtk_blist_sort_method_unreg(const char *name){ + +} + +void gaim_gtk_blist_sort_method_set(const char *name){ + GSList *l = gaim_gtk_blist_sort_methods; + while (l && gaim_utf8_strcasecmp(((struct gaim_gtk_blist_sort_method*)l->data)->name, name)) + l = l->next; + + if (l) { + current_sort_method = l->data; + strcpy(sort_method, ((struct gaim_gtk_blist_sort_method*)l->data)->name); + } else if (!current_sort_method) { + gaim_gtk_blist_sort_method_set("None"); + return; + } + save_prefs(); + redo_buddy_list(gaim_get_blist(), TRUE); + +} + +/****************************************** + ** Sort Methods + ******************************************/ + +/* A sort method takes a core buddy list node, the buddy list it belongs in, the GtkTreeIter of its group and + * the nodes own iter if it has one. It returns the iter the buddy list should use to represent this buddy, be + * it a new iter, or an existing one. If it is a new iter, and cur is defined, the buddy list will probably want + * to remove cur from the buddy list. */ +static GtkTreeIter sort_method_none(GaimBlistNode *node, struct gaim_buddy_list *blist, GtkTreeIter groupiter, GtkTreeIter *cur) +{ + GtkTreePath *newpath; + struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; + GaimBlistNode *oldersibling = node->prev; + GtkTreeIter iter, oldersiblingiter; + + if (cur) + return *cur; + + while (oldersibling && !get_iter_from_node(oldersibling, &oldersiblingiter)) { + oldersibling = oldersibling->prev; + } + + gtk_tree_store_insert_after(gtkblist->treemodel, &iter, &groupiter, oldersibling ? &oldersiblingiter : NULL); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; +} + +static GtkTreeIter sort_method_alphabetical(GaimBlistNode *node, struct gaim_buddy_list *blist, GtkTreeIter groupiter, GtkTreeIter *cur) +{ + GtkTreeIter more_z, iter; + GaimBlistNode *n; + GtkTreePath *newpath; + GValue val = {0,}; + struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; + + if (cur) + return *cur; + + + if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { + gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; + } + + do { + gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); + n = g_value_get_pointer(&val); + + if (GAIM_BLIST_NODE_IS_BUDDY(n) && gaim_utf8_strcasecmp(gaim_get_buddy_alias((struct buddy*)node), + gaim_get_buddy_alias((struct buddy*)n)) < 0) { + gtk_tree_store_insert_before(gtkblist->treemodel, &iter, &groupiter, &more_z); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; + } + g_value_unset(&val); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(gtkblist->treemodel), &more_z)); + + gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; +} + +static GtkTreeIter sort_method_status(GaimBlistNode *node, struct gaim_buddy_list *blist, GtkTreeIter groupiter, GtkTreeIter *cur) +{ + GtkTreeIter more_z, iter; + GaimBlistNode *n; + GtkTreePath *newpath, *expand; + GValue val = {0,}; + struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; + char *collapsed = gaim_group_get_setting((struct group *)node->parent, "collapsed"); + if(!collapsed) + expand = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &groupiter); + else + g_free(collapsed); + + + if (cur) + gaim_gtk_blist_hide_node(blist, node); + + if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { + gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + if(expand) { + gtk_tree_view_expand_row(GTK_TREE_VIEW(gtkblist->treeview), expand, TRUE); + gtk_tree_path_free(expand); + } + return iter; + } + + do { + gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); + n = g_value_get_pointer(&val); + + if (n && GAIM_BLIST_NODE_IS_BUDDY(n)) { + struct buddy *new = (struct buddy*)node, *it = (struct buddy*)n; + if (it->idle > new->idle) + { + printf("Inserting %s before %s\n", new->name, it->name); + gtk_tree_store_insert_before(gtkblist->treemodel, &iter, &groupiter, &more_z); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; + } + g_value_unset(&val); + } + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(gtkblist->treemodel), &more_z)); + + gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; +} + +static GtkTreeIter sort_method_log(GaimBlistNode *node, struct gaim_buddy_list *blist, GtkTreeIter groupiter, GtkTreeIter *cur) +{ + GtkTreeIter more_z, iter; + GaimBlistNode *n; + GtkTreePath *newpath; + GValue val = {0,}; + struct _gaim_gtk_blist_node *gtknode = (struct _gaim_gtk_blist_node *)node->ui_data; + char *logname = g_strdup_printf("%s.log", normalize(((struct buddy*)node)->name)); + char *filename = g_build_filename(gaim_user_dir(), "logs", logname, NULL); + struct stat st, st2; + + if (cur) + return *cur; + + if (stat(filename, &st)) + st.st_size = 0; + g_free(filename); + g_free(logname); + + if (!gtk_tree_model_iter_children(GTK_TREE_MODEL(gtkblist->treemodel), &more_z, &groupiter)) { + gtk_tree_store_insert(gtkblist->treemodel, &iter, &groupiter, 0); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; + } + + do { + + gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &more_z, NODE_COLUMN, &val); + n = g_value_get_pointer(&val); + + logname = g_strdup_printf("%s.log", normalize(((struct buddy*)n)->name)); + filename = g_build_filename(gaim_user_dir(), "logs", logname, NULL); + if (stat(filename, &st2)) + st2.st_size = 0; + g_free(filename); + g_free(logname); + if (GAIM_BLIST_NODE_IS_BUDDY(n) && st.st_size > st2.st_size) { + gtk_tree_store_insert_before(gtkblist->treemodel, &iter, &groupiter, &more_z); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; + } + g_value_unset(&val); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(gtkblist->treemodel), &more_z)); + + gtk_tree_store_append(gtkblist->treemodel, &iter, &groupiter); + newpath = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter); + gtknode->row = gtk_tree_row_reference_new(GTK_TREE_MODEL(gtkblist->treemodel), newpath); + gtk_tree_path_free(newpath); + return iter; +}
--- a/src/gtkblist.h Sun May 18 02:50:49 2003 +0000 +++ b/src/gtkblist.h Sun May 18 03:41:31 2003 +0000 @@ -77,7 +77,7 @@ ((list)->ui_ops == gaim_get_gtk_blist_ui_ops()) /************************************************************************** - * @name GTK+ Conversation API + * @name GTK+ Buddy List API **************************************************************************/ /** * Returns the UI operations structure for the buddy list. @@ -126,4 +126,47 @@ GdkPixbuf *gaim_gtk_blist_get_status_icon(GaimBlistNode *node, GaimStatusIconSize size); +/************************************************************************** + * @name GTK+ Buddy List sorting functions + **************************************************************************/ + +typedef GtkTreeIter (*gaim_gtk_blist_sort_function)(GaimBlistNode *new, struct gaim_buddy_list *blist, GtkTreeIter group, GtkTreeIter *cur); + +extern GSList *gaim_gtk_blist_sort_methods; + +struct gaim_gtk_blist_sort_method { + char *name; + gaim_gtk_blist_sort_function func; +}; + +/** + * Registers a buddy list sorting method. + * + * @param name The method's name. + * @param func A pointer to the function. + * + */ +void gaim_gtk_blist_sort_method_reg(const char *name, gaim_gtk_blist_sort_function func); + +/** + * Unregisters a buddy list sorting method. + * + * @param name The method's name + */ +void gaim_gtk_blist_sort_method_unreg(const char *name); + +/** + * Sets a buddy list sorting method. + * + * @param name The method's name. + */ +void gaim_gtk_blist_sort_method_set(const char *name); + +/** + * Sets up the programs default sort methods + */ +void gaim_gtk_blist_setup_sort_methods(); + + + #endif /* _GAIM_GTK_LIST_H_ */
--- a/src/main.c Sun May 18 02:50:49 2003 +0000 +++ b/src/main.c Sun May 18 03:41:31 2003 +0000 @@ -541,6 +541,7 @@ } } + gaim_gtk_blist_setup_sort_methods(); setup_stock(); #ifndef _WIN32
--- a/src/prefs.c Sun May 18 02:50:49 2003 +0000 +++ b/src/prefs.c Sun May 18 03:41:31 2003 +0000 @@ -573,8 +573,27 @@ GtkWidget *ret; GtkWidget *vbox; GtkWidget *button, *b2; + int r = 0; + gboolean fnd = FALSE; + GList *l= NULL; + GSList *sl = gaim_gtk_blist_sort_methods; ret = gtk_vbox_new(FALSE, 18); gtk_container_set_border_width (GTK_CONTAINER (ret), 12); + + + vbox = make_frame (ret, _("Buddy List Sorting")); + while (sl) { + l = g_list_append(l, ((struct gaim_gtk_blist_sort_method*)sl->data)->name); + l = g_list_append(l, ((struct gaim_gtk_blist_sort_method*)sl->data)->name); + if (!fnd && !gaim_utf8_strcasecmp(((struct gaim_gtk_blist_sort_method*)sl->data)->name, sort_method)) + fnd = TRUE; + sl = sl->next; + if (!fnd) r++; + } + gaim_dropdown_from_list(vbox, _("Sorting:"), + (int*)&sort_method, r, l); + + g_list_free(l); vbox = make_frame (ret, _("Buddy List Toolbar")); gaim_dropdown(vbox, _("Show _buttons as:"), &blist_options, OPT_BLIST_SHOW_BUTTON_XPM | OPT_BLIST_NO_BUTTON_TEXT, @@ -2300,6 +2319,12 @@ int opt = GPOINTER_TO_INT(g_object_get_data(w, "value")); int clear = GPOINTER_TO_INT(g_object_get_data(w, "clear")); + if (option == (int*)&sort_method) { + /* Hack city -- Population: Sean Egan */ + char *name = (char*)opt; + gaim_gtk_blist_sort_method_set(name); + return; + } if (clear != -1) { *option = *option & ~clear; *option = *option | opt; @@ -2340,7 +2365,7 @@ // set_blist_tab(); } else if (option == (int *)&conv_placement_option) { gaim_conv_placement_set_active(conv_placement_option); - } + } } static GtkWidget *gaim_dropdown(GtkWidget *box, const gchar *title, int *option, int clear, ...) @@ -2409,7 +2434,10 @@ gtk_widget_show(opt); gtk_menu_shell_append(GTK_MENU_SHELL(menu), opt); - if (((clear > -1) && ((*option & clear) == value)) || *option == value) { + if (option == (int*)sort_method) { + /* Now Entering Hacksville, Estd. May 17, 2003 */ + gtk_menu_set_active(GTK_MENU(menu), clear); + } else if (((clear > -1) && ((*option & clear) == value)) || *option == value) { gtk_menu_set_active(GTK_MENU(menu), o); } o++;