summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTingPing <tingping@tingping.se>2014-12-31 03:34:55 -0500
committerTingPing <tingping@tingping.se>2014-12-31 03:56:36 -0500
commit9f7444baa2001616f227ba9a442be824a57e56b9 (patch)
tree3bf087644d0421eeb1de1dea75429095ba6feffd
parentfef580ed7faaba17e2c8fea504b8587850502220 (diff)
Move userlist sorting to frontend
This Fixes possible crashes when the two
usertrees get out of sync and a double free occurs.

Also now requires restart to change sort orders.

Fixes #1252
Fixes #818 (probably)
-rw-r--r--src/common/fe.h3
-rw-r--r--src/common/hexchat.h4
-rw-r--r--src/common/userlist.c58
-rw-r--r--src/common/userlist.h2
-rw-r--r--src/fe-gtk/maingui.c4
-rw-r--r--src/fe-gtk/setup.c2
-rw-r--r--src/fe-gtk/userlistgui.c74
-rw-r--r--src/fe-gtk/userlistgui.h2
-rw-r--r--src/fe-text/fe-text.c6
9 files changed, 88 insertions, 67 deletions
diff --git a/src/common/fe.h b/src/common/fe.h
index 2ca15c60..9d8919ac 100644
--- a/src/common/fe.h
+++ b/src/common/fe.h
@@ -88,11 +88,10 @@ void fe_progressbar_start (struct session *sess);
 void fe_progressbar_end (struct server *serv);
 void fe_print_text (struct session *sess, char *text, time_t stamp,
 					gboolean no_activity);
-void fe_userlist_insert (struct session *sess, struct User *newuser, int row, int sel);
+void fe_userlist_insert (struct session *sess, struct User *newuser, gboolean sel);
 int fe_userlist_remove (struct session *sess, struct User *user);
 void fe_userlist_rehash (struct session *sess, struct User *user);
 void fe_userlist_update (struct session *sess, struct User *user);
-void fe_userlist_move (struct session *sess, struct User *user, int new_row);
 void fe_userlist_numbers (struct session *sess);
 void fe_userlist_clear (struct session *sess);
 void fe_userlist_set_selected (struct session *sess);
diff --git a/src/common/hexchat.h b/src/common/hexchat.h
index dfb1c52f..a5b61a26 100644
--- a/src/common/hexchat.h
+++ b/src/common/hexchat.h
@@ -37,6 +37,7 @@
 #endif
 
 #include "history.h"
+#include "tree.h"
 
 #ifdef USE_OPENSSL
 #include <openssl/ssl.h>		  /* SSL_() */
@@ -369,8 +370,7 @@ typedef struct session
 	guint8 text_strip;
 
 	struct server *server;
-	void *usertree_alpha;			/* pure alphabetical tree */
-	void *usertree;					/* ordered with Ops first */
+	tree *usertree;					/* alphabetical tree */
 	struct User *me;					/* points to myself in the usertree */
 	char channel[CHANLEN];
 	char waitchannel[CHANLEN];		  /* waiting to join channel (/join sent) */
diff --git a/src/common/userlist.c b/src/common/userlist.c
index ed794ddb..aa0f8f16 100644
--- a/src/common/userlist.c
+++ b/src/common/userlist.c
@@ -29,7 +29,7 @@
 #include "util.h"
 
 
-static int
+int
 nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2)
 {
 	unsigned int access1 = user1->access;
@@ -52,30 +52,12 @@ nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2)
 	return serv->p_cmp (user1->nick, user2->nick);
 }
 
-static int
+int
 nick_cmp_alpha (struct User *user1, struct User *user2, server *serv)
 {
 	return serv->p_cmp (user1->nick, user2->nick);
 }
 
-static int
-nick_cmp (struct User *user1, struct User *user2, server *serv)
-{
-	switch (prefs.hex_gui_ulist_sort)
-	{
-	case 0:
-		return nick_cmp_az_ops (serv, user1, user2);
-	case 1:
-		return serv->p_cmp (user1->nick, user2->nick);
-	case 2:
-		return -1 * nick_cmp_az_ops (serv, user1, user2);
-	case 3:
-		return -1 * serv->p_cmp (user1->nick, user2->nick);
-	default:
-		return -1;
-	}
-}
-
 /*
  insert name in appropriate place in linked list. Returns row number or:
   -1: duplicate
@@ -86,11 +68,9 @@ userlist_insertname (session *sess, struct User *newuser)
 {
 	if (!sess->usertree)
 	{
-		sess->usertree = tree_new ((tree_cmp_func *)nick_cmp, sess->server);
-		sess->usertree_alpha = tree_new ((tree_cmp_func *)nick_cmp_alpha, sess->server);
+		sess->usertree = tree_new ((tree_cmp_func *)nick_cmp_alpha, sess->server);
 	}
 
-	tree_insert (sess->usertree_alpha, newuser);
 	return tree_insert (sess->usertree, newuser);
 }
 
@@ -188,10 +168,8 @@ userlist_free (session *sess)
 {
 	tree_foreach (sess->usertree, (tree_traverse_func *)free_user, NULL);
 	tree_destroy (sess->usertree);
-	tree_destroy (sess->usertree_alpha);
 
 	sess->usertree = NULL;
-	sess->usertree_alpha = NULL;
 	sess->me = NULL;
 
 	sess->ops = 0;
@@ -219,8 +197,8 @@ userlist_find (struct session *sess, const char *name)
 {
 	int pos;
 
-	if (sess->usertree_alpha)
-		return tree_find (sess->usertree_alpha, name,
+	if (sess->usertree)
+		return tree_find (sess->usertree, name,
 								(tree_cmp_func *)find_cmp, sess->server, &pos);
 
 	return NULL;
@@ -283,7 +261,7 @@ userlist_update_mode (session *sess, char *name, char mode, char sign)
 
 	/* remove from binary trees, before we loose track of it */
 	tree_remove (sess->usertree, user, &pos);
-	tree_remove (sess->usertree_alpha, user, &pos);
+	fe_userlist_remove (sess, user);
 
 	/* which bit number is affected? */
 	access = mode_access (sess->server, mode, &prefix);
@@ -313,11 +291,8 @@ userlist_update_mode (session *sess, char *name, char mode, char sign)
 	update_counts (sess, user, prefix, level, offset);
 
 	/* insert it back into its new place */
-	tree_insert (sess->usertree_alpha, user);
-	pos = tree_insert (sess->usertree, user);
-
-	/* let GTK move it too */
-	fe_userlist_move (sess, user, pos);
+	tree_insert (sess->usertree, user);
+	fe_userlist_insert (sess, user, FALSE);
 	fe_userlist_numbers (sess);
 }
 
@@ -330,14 +305,12 @@ userlist_change (struct session *sess, char *oldname, char *newname)
 	if (user)
 	{
 		tree_remove (sess->usertree, user, &pos);
-		tree_remove (sess->usertree_alpha, user, &pos);
+		fe_userlist_remove (sess, user);
 
 		safe_strcpy (user->nick, newname, NICKLEN);
 
-		tree_insert (sess->usertree_alpha, user);
-
-		fe_userlist_move (sess, user, tree_insert (sess->usertree, user));
-		fe_userlist_numbers (sess);
+		tree_insert (sess->usertree, user);
+		fe_userlist_insert (sess, user, FALSE);
 
 		return 1;
 	}
@@ -376,7 +349,6 @@ userlist_remove_user (struct session *sess, struct User *user)
 		sess->me = NULL;
 
 	tree_remove (sess->usertree, user, &pos);
-	tree_remove (sess->usertree_alpha, user, &pos);
 	free_user (user, NULL);
 }
 
@@ -442,7 +414,7 @@ userlist_add (struct session *sess, char *name, char *hostname,
 	if (user->me)
 		sess->me = user;
 
-	fe_userlist_insert (sess, user, row, FALSE);
+	fe_userlist_insert (sess, user, FALSE);
 	fe_userlist_numbers (sess);
 }
 
@@ -456,7 +428,7 @@ rehash_cb (struct User *user, session *sess)
 void
 userlist_rehash (session *sess)
 {
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)rehash_cb, sess);
+	tree_foreach (sess->usertree, (tree_traverse_func *)rehash_cb, sess);
 }
 
 static int
@@ -471,7 +443,7 @@ userlist_flat_list (session *sess)
 {
 	GSList *list = NULL;
 
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)flat_cb, &list);
+	tree_foreach (sess->usertree, (tree_traverse_func *)flat_cb, &list);
 	return g_slist_reverse (list);
 }
 
@@ -487,6 +459,6 @@ userlist_double_list(session *sess)
 {
 	GList *list = NULL;
 
-	tree_foreach (sess->usertree_alpha, (tree_traverse_func *)double_cb, &list);
+	tree_foreach (sess->usertree, (tree_traverse_func *)double_cb, &list);
 	return list;
 }
diff --git a/src/common/userlist.h b/src/common/userlist.h
index ebf95606..0c53dc71 100644
--- a/src/common/userlist.h
+++ b/src/common/userlist.h
@@ -61,5 +61,7 @@ void userlist_update_mode (session *sess, char *name, char mode, char sign);
 GSList *userlist_flat_list (session *sess);
 GList *userlist_double_list (session *sess);
 void userlist_rehash (session *sess);
+int nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2);
+int nick_cmp_alpha (struct User *user1, struct User *user2, server *serv);
 
 #endif
diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c
index b1764a0a..2eabe8b7 100644
--- a/src/fe-gtk/maingui.c
+++ b/src/fe-gtk/maingui.c
@@ -1715,7 +1715,7 @@ mg_add_chan (session *sess)
 	{
 		sess->res->buffer = gtk_xtext_buffer_new (GTK_XTEXT (sess->gui->xtext));
 		gtk_xtext_set_time_stamp (sess->res->buffer, prefs.hex_stamp_text);
-		sess->res->user_model = userlist_create_model ();
+		sess->res->user_model = userlist_create_model (sess);
 	}
 }
 
@@ -3164,7 +3164,7 @@ mg_create_topwindow (session *sess)
 		sess->res->buffer = gtk_xtext_buffer_new (GTK_XTEXT (sess->gui->xtext));
 		gtk_xtext_buffer_show (GTK_XTEXT (sess->gui->xtext), sess->res->buffer, TRUE);
 		gtk_xtext_set_time_stamp (sess->res->buffer, prefs.hex_stamp_text);
-		sess->res->user_model = userlist_create_model ();
+		sess->res->user_model = userlist_create_model (sess);
 	}
 
 	userlist_show (sess);
diff --git a/src/fe-gtk/setup.c b/src/fe-gtk/setup.c
index cc5d25bf..e3969ff3 100644
--- a/src/fe-gtk/setup.c
+++ b/src/fe-gtk/setup.c
@@ -2114,6 +2114,8 @@ setup_apply (struct hexchatprefs *pr)
 		noapply = TRUE;
 	if (DIFF (hex_gui_ulist_style))
 		noapply = TRUE;
+	if (DIFF (hex_gui_ulist_sort))
+		noapply = TRUE;
 
 	if (DIFF (hex_gui_tab_dots))
 		do_layout = TRUE;
diff --git a/src/fe-gtk/userlistgui.c b/src/fe-gtk/userlistgui.c
index b95eb522..943bd17b 100644
--- a/src/fe-gtk/userlistgui.c
+++ b/src/fe-gtk/userlistgui.c
@@ -332,9 +332,9 @@ fe_userlist_rehash (session *sess, struct User *user)
 }
 
 void
-fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
+fe_userlist_insert (session *sess, struct User *newuser, gboolean sel)
 {
-	GtkTreeModel *model = sess->res->user_model;
+	GtkTreeModel *model = GTK_TREE_MODEL(sess->res->user_model);
 	GdkPixbuf *pix = get_user_icon (sess->server, newuser);
 	GtkTreeIter iter;
 	char *nick;
@@ -357,7 +357,7 @@ fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
 		pix = NULL;
 	}
 
-	gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, row,
+	gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, 0,
 									COL_PIX, pix,
 									COL_NICK, nick,
 									COL_HOST, newuser->hostname,
@@ -396,12 +396,6 @@ fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
 }
 
 void
-fe_userlist_move (session *sess, struct User *user, int new_row)
-{
-	fe_userlist_insert (sess, user, new_row, fe_userlist_remove (sess, user));
-}
-
-void
 fe_userlist_clear (session *sess)
 {
 	gtk_list_store_clear (sess->res->user_model);
@@ -459,11 +453,67 @@ userlist_dnd_leave (GtkTreeView *widget, GdkDragContext *context, guint ttime)
 	return TRUE;
 }
 
-void *
-userlist_create_model (void)
+static int
+userlist_alpha_cmp (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer userdata)
+{
+	struct User *user_a, *user_b;
+
+	gtk_tree_model_get (model, iter_a, COL_USER, &user_a, -1);
+	gtk_tree_model_get (model, iter_b, COL_USER, &user_b, -1);
+
+	return nick_cmp_alpha (user_a, user_b, ((session*)userdata)->server);
+}
+
+static int
+userlist_ops_cmp (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer userdata)
+{
+	struct User *user_a, *user_b;
+
+	gtk_tree_model_get (model, iter_a, COL_USER, &user_a, -1);
+	gtk_tree_model_get (model, iter_b, COL_USER, &user_b, -1);
+
+	return nick_cmp_az_ops (((session*)userdata)->server, user_a, user_b);
+}
+
+GtkListStore *
+userlist_create_model (session *sess)
 {
-	return gtk_list_store_new (5, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
+	GtkListStore *store;
+	GtkTreeIterCompareFunc cmp_func;
+	GtkSortType sort_type;
+
+	store = gtk_list_store_new (5, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
 										G_TYPE_POINTER, GDK_TYPE_COLOR);
+
+	switch (prefs.hex_gui_ulist_sort)
+	{
+	case 0:
+		cmp_func = userlist_ops_cmp;
+		sort_type = GTK_SORT_ASCENDING;
+		break;
+	case 1:
+		cmp_func = userlist_alpha_cmp;
+		sort_type = GTK_SORT_ASCENDING;
+		break;
+	case 2:
+		cmp_func = userlist_ops_cmp;
+		sort_type = GTK_SORT_DESCENDING;
+		break;
+	case 3:
+		cmp_func = userlist_alpha_cmp;
+		sort_type = GTK_SORT_DESCENDING;
+		break;
+	default:
+		/* No sorting */
+		gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE(store), NULL, NULL, NULL);
+		return store;
+	}
+
+	gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE(store), cmp_func, sess, NULL);
+	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
+						GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, sort_type);
+
+	return store;
 }
 
 static void
diff --git a/src/fe-gtk/userlistgui.h b/src/fe-gtk/userlistgui.h
index 993fe8f0..7633246a 100644
--- a/src/fe-gtk/userlistgui.h
+++ b/src/fe-gtk/userlistgui.h
@@ -23,7 +23,7 @@
 void userlist_set_value (GtkWidget *treeview, gfloat val);
 gfloat userlist_get_value (GtkWidget *treeview);
 GtkWidget *userlist_create (GtkWidget *box);
-void *userlist_create_model (void);
+void *userlist_create_model (session *sess);
 void userlist_show (session *sess);
 void userlist_select (session *sess, char *name);
 char **userlist_selection_list (GtkWidget *widget, int *num_ret);
diff --git a/src/fe-text/fe-text.c b/src/fe-text/fe-text.c
index 2dd93e2a..a709fe9e 100644
--- a/src/fe-text/fe-text.c
+++ b/src/fe-text/fe-text.c
@@ -678,7 +678,7 @@ fe_progressbar_end (struct server *serv)
 {
 }
 void
-fe_userlist_insert (struct session *sess, struct User *newuser, int row, int sel)
+fe_userlist_insert (struct session *sess, struct User *newuser, gboolean sel)
 {
 }
 int
@@ -691,10 +691,6 @@ fe_userlist_rehash (struct session *sess, struct User *user)
 {
 }
 void
-fe_userlist_move (struct session *sess, struct User *user, int new_row)
-{
-}
-void
 fe_userlist_numbers (struct session *sess)
 {
 }