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)
This commit is contained in:
parent
fef580ed7f
commit
9f7444baa2
|
@ -88,11 +88,10 @@ void fe_progressbar_start (struct session *sess);
|
||||||
void fe_progressbar_end (struct server *serv);
|
void fe_progressbar_end (struct server *serv);
|
||||||
void fe_print_text (struct session *sess, char *text, time_t stamp,
|
void fe_print_text (struct session *sess, char *text, time_t stamp,
|
||||||
gboolean no_activity);
|
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);
|
int fe_userlist_remove (struct session *sess, struct User *user);
|
||||||
void fe_userlist_rehash (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_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_numbers (struct session *sess);
|
||||||
void fe_userlist_clear (struct session *sess);
|
void fe_userlist_clear (struct session *sess);
|
||||||
void fe_userlist_set_selected (struct session *sess);
|
void fe_userlist_set_selected (struct session *sess);
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "history.h"
|
#include "history.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
#ifdef USE_OPENSSL
|
#ifdef USE_OPENSSL
|
||||||
#include <openssl/ssl.h> /* SSL_() */
|
#include <openssl/ssl.h> /* SSL_() */
|
||||||
|
@ -369,8 +370,7 @@ typedef struct session
|
||||||
guint8 text_strip;
|
guint8 text_strip;
|
||||||
|
|
||||||
struct server *server;
|
struct server *server;
|
||||||
void *usertree_alpha; /* pure alphabetical tree */
|
tree *usertree; /* alphabetical tree */
|
||||||
void *usertree; /* ordered with Ops first */
|
|
||||||
struct User *me; /* points to myself in the usertree */
|
struct User *me; /* points to myself in the usertree */
|
||||||
char channel[CHANLEN];
|
char channel[CHANLEN];
|
||||||
char waitchannel[CHANLEN]; /* waiting to join channel (/join sent) */
|
char waitchannel[CHANLEN]; /* waiting to join channel (/join sent) */
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
static int
|
int
|
||||||
nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2)
|
nick_cmp_az_ops (server *serv, struct User *user1, struct User *user2)
|
||||||
{
|
{
|
||||||
unsigned int access1 = user1->access;
|
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);
|
return serv->p_cmp (user1->nick, user2->nick);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
nick_cmp_alpha (struct User *user1, struct User *user2, server *serv)
|
nick_cmp_alpha (struct User *user1, struct User *user2, server *serv)
|
||||||
{
|
{
|
||||||
return serv->p_cmp (user1->nick, user2->nick);
|
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:
|
insert name in appropriate place in linked list. Returns row number or:
|
||||||
-1: duplicate
|
-1: duplicate
|
||||||
|
@ -86,11 +68,9 @@ userlist_insertname (session *sess, struct User *newuser)
|
||||||
{
|
{
|
||||||
if (!sess->usertree)
|
if (!sess->usertree)
|
||||||
{
|
{
|
||||||
sess->usertree = tree_new ((tree_cmp_func *)nick_cmp, sess->server);
|
sess->usertree = tree_new ((tree_cmp_func *)nick_cmp_alpha, sess->server);
|
||||||
sess->usertree_alpha = tree_new ((tree_cmp_func *)nick_cmp_alpha, sess->server);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_insert (sess->usertree_alpha, newuser);
|
|
||||||
return tree_insert (sess->usertree, 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_foreach (sess->usertree, (tree_traverse_func *)free_user, NULL);
|
||||||
tree_destroy (sess->usertree);
|
tree_destroy (sess->usertree);
|
||||||
tree_destroy (sess->usertree_alpha);
|
|
||||||
|
|
||||||
sess->usertree = NULL;
|
sess->usertree = NULL;
|
||||||
sess->usertree_alpha = NULL;
|
|
||||||
sess->me = NULL;
|
sess->me = NULL;
|
||||||
|
|
||||||
sess->ops = 0;
|
sess->ops = 0;
|
||||||
|
@ -219,8 +197,8 @@ userlist_find (struct session *sess, const char *name)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
if (sess->usertree_alpha)
|
if (sess->usertree)
|
||||||
return tree_find (sess->usertree_alpha, name,
|
return tree_find (sess->usertree, name,
|
||||||
(tree_cmp_func *)find_cmp, sess->server, &pos);
|
(tree_cmp_func *)find_cmp, sess->server, &pos);
|
||||||
|
|
||||||
return NULL;
|
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 */
|
/* remove from binary trees, before we loose track of it */
|
||||||
tree_remove (sess->usertree, user, &pos);
|
tree_remove (sess->usertree, user, &pos);
|
||||||
tree_remove (sess->usertree_alpha, user, &pos);
|
fe_userlist_remove (sess, user);
|
||||||
|
|
||||||
/* which bit number is affected? */
|
/* which bit number is affected? */
|
||||||
access = mode_access (sess->server, mode, &prefix);
|
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);
|
update_counts (sess, user, prefix, level, offset);
|
||||||
|
|
||||||
/* insert it back into its new place */
|
/* insert it back into its new place */
|
||||||
tree_insert (sess->usertree_alpha, user);
|
tree_insert (sess->usertree, user);
|
||||||
pos = tree_insert (sess->usertree, user);
|
fe_userlist_insert (sess, user, FALSE);
|
||||||
|
|
||||||
/* let GTK move it too */
|
|
||||||
fe_userlist_move (sess, user, pos);
|
|
||||||
fe_userlist_numbers (sess);
|
fe_userlist_numbers (sess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,14 +305,12 @@ userlist_change (struct session *sess, char *oldname, char *newname)
|
||||||
if (user)
|
if (user)
|
||||||
{
|
{
|
||||||
tree_remove (sess->usertree, user, &pos);
|
tree_remove (sess->usertree, user, &pos);
|
||||||
tree_remove (sess->usertree_alpha, user, &pos);
|
fe_userlist_remove (sess, user);
|
||||||
|
|
||||||
safe_strcpy (user->nick, newname, NICKLEN);
|
safe_strcpy (user->nick, newname, NICKLEN);
|
||||||
|
|
||||||
tree_insert (sess->usertree_alpha, user);
|
tree_insert (sess->usertree, user);
|
||||||
|
fe_userlist_insert (sess, user, FALSE);
|
||||||
fe_userlist_move (sess, user, tree_insert (sess->usertree, user));
|
|
||||||
fe_userlist_numbers (sess);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -376,7 +349,6 @@ userlist_remove_user (struct session *sess, struct User *user)
|
||||||
sess->me = NULL;
|
sess->me = NULL;
|
||||||
|
|
||||||
tree_remove (sess->usertree, user, &pos);
|
tree_remove (sess->usertree, user, &pos);
|
||||||
tree_remove (sess->usertree_alpha, user, &pos);
|
|
||||||
free_user (user, NULL);
|
free_user (user, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +414,7 @@ userlist_add (struct session *sess, char *name, char *hostname,
|
||||||
if (user->me)
|
if (user->me)
|
||||||
sess->me = user;
|
sess->me = user;
|
||||||
|
|
||||||
fe_userlist_insert (sess, user, row, FALSE);
|
fe_userlist_insert (sess, user, FALSE);
|
||||||
fe_userlist_numbers (sess);
|
fe_userlist_numbers (sess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +428,7 @@ rehash_cb (struct User *user, session *sess)
|
||||||
void
|
void
|
||||||
userlist_rehash (session *sess)
|
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
|
static int
|
||||||
|
@ -471,7 +443,7 @@ userlist_flat_list (session *sess)
|
||||||
{
|
{
|
||||||
GSList *list = NULL;
|
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);
|
return g_slist_reverse (list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,6 +459,6 @@ userlist_double_list(session *sess)
|
||||||
{
|
{
|
||||||
GList *list = NULL;
|
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;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,5 +61,7 @@ void userlist_update_mode (session *sess, char *name, char mode, char sign);
|
||||||
GSList *userlist_flat_list (session *sess);
|
GSList *userlist_flat_list (session *sess);
|
||||||
GList *userlist_double_list (session *sess);
|
GList *userlist_double_list (session *sess);
|
||||||
void userlist_rehash (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
|
#endif
|
||||||
|
|
|
@ -1715,7 +1715,7 @@ mg_add_chan (session *sess)
|
||||||
{
|
{
|
||||||
sess->res->buffer = gtk_xtext_buffer_new (GTK_XTEXT (sess->gui->xtext));
|
sess->res->buffer = gtk_xtext_buffer_new (GTK_XTEXT (sess->gui->xtext));
|
||||||
gtk_xtext_set_time_stamp (sess->res->buffer, prefs.hex_stamp_text);
|
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));
|
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_buffer_show (GTK_XTEXT (sess->gui->xtext), sess->res->buffer, TRUE);
|
||||||
gtk_xtext_set_time_stamp (sess->res->buffer, prefs.hex_stamp_text);
|
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);
|
userlist_show (sess);
|
||||||
|
|
|
@ -2114,6 +2114,8 @@ setup_apply (struct hexchatprefs *pr)
|
||||||
noapply = TRUE;
|
noapply = TRUE;
|
||||||
if (DIFF (hex_gui_ulist_style))
|
if (DIFF (hex_gui_ulist_style))
|
||||||
noapply = TRUE;
|
noapply = TRUE;
|
||||||
|
if (DIFF (hex_gui_ulist_sort))
|
||||||
|
noapply = TRUE;
|
||||||
|
|
||||||
if (DIFF (hex_gui_tab_dots))
|
if (DIFF (hex_gui_tab_dots))
|
||||||
do_layout = TRUE;
|
do_layout = TRUE;
|
||||||
|
|
|
@ -332,9 +332,9 @@ fe_userlist_rehash (session *sess, struct User *user)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
GdkPixbuf *pix = get_user_icon (sess->server, newuser);
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
char *nick;
|
char *nick;
|
||||||
|
@ -357,7 +357,7 @@ fe_userlist_insert (session *sess, struct User *newuser, int row, int sel)
|
||||||
pix = NULL;
|
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_PIX, pix,
|
||||||
COL_NICK, nick,
|
COL_NICK, nick,
|
||||||
COL_HOST, newuser->hostname,
|
COL_HOST, newuser->hostname,
|
||||||
|
@ -395,12 +395,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
|
void
|
||||||
fe_userlist_clear (session *sess)
|
fe_userlist_clear (session *sess)
|
||||||
{
|
{
|
||||||
|
@ -459,11 +453,67 @@ userlist_dnd_leave (GtkTreeView *widget, GdkDragContext *context, guint ttime)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
static int
|
||||||
userlist_create_model (void)
|
userlist_alpha_cmp (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer userdata)
|
||||||
{
|
{
|
||||||
return gtk_list_store_new (5, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
|
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)
|
||||||
|
{
|
||||||
|
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);
|
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
|
static void
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
void userlist_set_value (GtkWidget *treeview, gfloat val);
|
void userlist_set_value (GtkWidget *treeview, gfloat val);
|
||||||
gfloat userlist_get_value (GtkWidget *treeview);
|
gfloat userlist_get_value (GtkWidget *treeview);
|
||||||
GtkWidget *userlist_create (GtkWidget *box);
|
GtkWidget *userlist_create (GtkWidget *box);
|
||||||
void *userlist_create_model (void);
|
void *userlist_create_model (session *sess);
|
||||||
void userlist_show (session *sess);
|
void userlist_show (session *sess);
|
||||||
void userlist_select (session *sess, char *name);
|
void userlist_select (session *sess, char *name);
|
||||||
char **userlist_selection_list (GtkWidget *widget, int *num_ret);
|
char **userlist_selection_list (GtkWidget *widget, int *num_ret);
|
||||||
|
|
|
@ -678,7 +678,7 @@ fe_progressbar_end (struct server *serv)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void
|
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
|
int
|
||||||
|
@ -691,10 +691,6 @@ fe_userlist_rehash (struct session *sess, struct User *user)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
fe_userlist_move (struct session *sess, struct User *user, int new_row)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void
|
|
||||||
fe_userlist_numbers (struct session *sess)
|
fe_userlist_numbers (struct session *sess)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue