src/gtkblist.c

changeset 5422
066c98fd4fa8
parent 5419
062efd736788
child 5427
a45fa07ef20d
--- 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;
+}

mercurial