1 /* X-Chat
2 * Copyright (C) 1998 Peter Zelezny.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22
23 #include "fe-gtk.h"
24
25 #include <gdk/gdkkeysyms.h>
26
27 #include "../common/hexchat.h"
28 #include "../common/util.h"
29 #include "../common/userlist.h"
30 #include "../common/modes.h"
31 #include "../common/text.h"
32 #include "../common/notify.h"
33 #include "../common/hexchatc.h"
34 #include "../common/fe.h"
35 #include "gtkutil.h"
36 #include "palette.h"
37 #include "maingui.h"
38 #include "menu.h"
39 #include "pixmaps.h"
40 #include "userlistgui.h"
41 #include "fkeys.h"
42
43 enum
44 {
45 COL_PIX=0, /* GdkPixbuf * */
46 COL_NICK=1, /* char * */
47 COL_HOST=2, /* char * */
48 COL_USER=3, /* struct User * */
49 COL_GDKCOLOR=4 /* GdkColor * */
50 };
51
52
53 GdkPixbuf *
get_user_icon(server * serv,struct User * user)54 get_user_icon (server *serv, struct User *user)
55 {
56 char *pre;
57 int level;
58
59 if (!user)
60 return NULL;
61
62 /* these ones are hardcoded */
63 switch (user->prefix[0])
64 {
65 case 0: return NULL;
66 case '+': return pix_ulist_voice;
67 case '%': return pix_ulist_halfop;
68 case '@': return pix_ulist_op;
69 }
70
71 /* find out how many levels above Op this user is */
72 pre = strchr (serv->nick_prefixes, '@');
73 if (pre && pre != serv->nick_prefixes)
74 {
75 pre--;
76 level = 0;
77 while (1)
78 {
79 if (pre[0] == user->prefix[0])
80 {
81 switch (level)
82 {
83 case 0: return pix_ulist_owner; /* 1 level above op */
84 case 1: return pix_ulist_founder; /* 2 levels above op */
85 case 2: return pix_ulist_netop; /* 3 levels above op */
86 }
87 break; /* 4+, no icons */
88 }
89 level++;
90 if (pre == serv->nick_prefixes)
91 break;
92 pre--;
93 }
94 }
95
96 return NULL;
97 }
98
99 void
fe_userlist_numbers(session * sess)100 fe_userlist_numbers (session *sess)
101 {
102 char tbuf[256];
103
104 if (sess == current_tab || !sess->gui->is_tab)
105 {
106 if (sess->total)
107 {
108 g_snprintf (tbuf, sizeof (tbuf), _("%d ops, %d total"), sess->ops, sess->total);
109 tbuf[sizeof (tbuf) - 1] = 0;
110 gtk_label_set_text (GTK_LABEL (sess->gui->namelistinfo), tbuf);
111 } else
112 {
113 gtk_label_set_text (GTK_LABEL (sess->gui->namelistinfo), NULL);
114 }
115
116 if (sess->type == SESS_CHANNEL && prefs.hex_gui_win_ucount)
117 fe_set_title (sess);
118 }
119 }
120
121 static void
scroll_to_iter(GtkTreeIter * iter,GtkTreeView * treeview,GtkTreeModel * model)122 scroll_to_iter (GtkTreeIter *iter, GtkTreeView *treeview, GtkTreeModel *model)
123 {
124 GtkTreePath *path = gtk_tree_model_get_path (model, iter);
125 if (path)
126 {
127 gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.5);
128 gtk_tree_path_free (path);
129 }
130 }
131
132 /* select a row in the userlist by nick-name */
133
134 void
userlist_select(session * sess,char * name)135 userlist_select (session *sess, char *name)
136 {
137 GtkTreeIter iter;
138 GtkTreeView *treeview = GTK_TREE_VIEW (sess->gui->user_tree);
139 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
140 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
141 struct User *row_user;
142
143 if (gtk_tree_model_get_iter_first (model, &iter))
144 {
145 do
146 {
147 gtk_tree_model_get (model, &iter, COL_USER, &row_user, -1);
148 if (sess->server->p_cmp (row_user->nick, name) == 0)
149 {
150 if (gtk_tree_selection_iter_is_selected (selection, &iter))
151 gtk_tree_selection_unselect_iter (selection, &iter);
152 else
153 gtk_tree_selection_select_iter (selection, &iter);
154
155 /* and make sure it's visible */
156 scroll_to_iter (&iter, treeview, model);
157 return;
158 }
159 }
160 while (gtk_tree_model_iter_next (model, &iter));
161 }
162 }
163
164 char **
userlist_selection_list(GtkWidget * widget,int * num_ret)165 userlist_selection_list (GtkWidget *widget, int *num_ret)
166 {
167 GtkTreeIter iter;
168 GtkTreeView *treeview = (GtkTreeView *) widget;
169 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
170 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
171 struct User *user;
172 int i, num_sel;
173 char **nicks;
174
175 *num_ret = 0;
176 /* first, count the number of selections */
177 num_sel = 0;
178 if (gtk_tree_model_get_iter_first (model, &iter))
179 {
180 do
181 {
182 if (gtk_tree_selection_iter_is_selected (selection, &iter))
183 num_sel++;
184 }
185 while (gtk_tree_model_iter_next (model, &iter));
186 }
187
188 if (num_sel < 1)
189 return NULL;
190
191 nicks = g_new (char *, num_sel + 1);
192
193 i = 0;
194 gtk_tree_model_get_iter_first (model, &iter);
195 do
196 {
197 if (gtk_tree_selection_iter_is_selected (selection, &iter))
198 {
199 gtk_tree_model_get (model, &iter, COL_USER, &user, -1);
200 nicks[i] = g_strdup (user->nick);
201 i++;
202 nicks[i] = NULL;
203 }
204 }
205 while (gtk_tree_model_iter_next (model, &iter));
206
207 *num_ret = i;
208 return nicks;
209 }
210
211 void
fe_userlist_set_selected(struct session * sess)212 fe_userlist_set_selected (struct session *sess)
213 {
214 GtkListStore *store = sess->res->user_model;
215 GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sess->gui->user_tree));
216 GtkTreeIter iter;
217 struct User *user;
218
219 /* if it's not front-most tab it doesn't own the GtkTreeView! */
220 if (store != (GtkListStore*) gtk_tree_view_get_model (GTK_TREE_VIEW (sess->gui->user_tree)))
221 return;
222
223 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter))
224 {
225 do
226 {
227 gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, COL_USER, &user, -1);
228
229 if (gtk_tree_selection_iter_is_selected (selection, &iter))
230 user->selected = 1;
231 else
232 user->selected = 0;
233
234 } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter));
235 }
236 }
237
238 static GtkTreeIter *
find_row(GtkTreeView * treeview,GtkTreeModel * model,struct User * user,int * selected)239 find_row (GtkTreeView *treeview, GtkTreeModel *model, struct User *user,
240 int *selected)
241 {
242 static GtkTreeIter iter;
243 struct User *row_user;
244
245 *selected = FALSE;
246 if (gtk_tree_model_get_iter_first (model, &iter))
247 {
248 do
249 {
250 gtk_tree_model_get (model, &iter, COL_USER, &row_user, -1);
251 if (row_user == user)
252 {
253 if (gtk_tree_view_get_model (treeview) == model)
254 {
255 if (gtk_tree_selection_iter_is_selected (gtk_tree_view_get_selection (treeview), &iter))
256 *selected = TRUE;
257 }
258 return &iter;
259 }
260 }
261 while (gtk_tree_model_iter_next (model, &iter));
262 }
263
264 return NULL;
265 }
266
267 void
userlist_set_value(GtkWidget * treeview,gfloat val)268 userlist_set_value (GtkWidget *treeview, gfloat val)
269 {
270 gtk_adjustment_set_value (
271 gtk_tree_view_get_vadjustment (GTK_TREE_VIEW (treeview)), val);
272 }
273
274 gfloat
userlist_get_value(GtkWidget * treeview)275 userlist_get_value (GtkWidget *treeview)
276 {
277 return gtk_adjustment_get_value (gtk_tree_view_get_vadjustment (GTK_TREE_VIEW (treeview)));
278 }
279
280 int
fe_userlist_remove(session * sess,struct User * user)281 fe_userlist_remove (session *sess, struct User *user)
282 {
283 GtkTreeIter *iter;
284 /* GtkAdjustment *adj;
285 gfloat val, end;*/
286 int sel;
287
288 iter = find_row (GTK_TREE_VIEW (sess->gui->user_tree),
289 GTK_TREE_MODEL(sess->res->user_model), user, &sel);
290 if (!iter)
291 return 0;
292
293 /* adj = gtk_tree_view_get_vadjustment (GTK_TREE_VIEW (sess->gui->user_tree));
294 val = adj->value;*/
295
296 gtk_list_store_remove (sess->res->user_model, iter);
297
298 /* is it the front-most tab? */
299 /* if (gtk_tree_view_get_model (GTK_TREE_VIEW (sess->gui->user_tree))
300 == sess->res->user_model)
301 {
302 end = adj->upper - adj->lower - adj->page_size;
303 if (val > end)
304 val = end;
305 gtk_adjustment_set_value (adj, val);
306 }*/
307
308 return sel;
309 }
310
311 void
fe_userlist_rehash(session * sess,struct User * user)312 fe_userlist_rehash (session *sess, struct User *user)
313 {
314 GtkTreeIter *iter;
315 int sel;
316 int nick_color = 0;
317
318 iter = find_row (GTK_TREE_VIEW (sess->gui->user_tree),
319 GTK_TREE_MODEL(sess->res->user_model), user, &sel);
320 if (!iter)
321 return;
322
323 if (prefs.hex_away_track && user->away)
324 nick_color = COL_AWAY;
325 else if (prefs.hex_gui_ulist_color)
326 nick_color = text_color_of(user->nick);
327
328 gtk_list_store_set (GTK_LIST_STORE (sess->res->user_model), iter,
329 COL_HOST, user->hostname,
330 COL_GDKCOLOR, nick_color ? &colors[nick_color] : NULL,
331 -1);
332 }
333
334 void
fe_userlist_insert(session * sess,struct User * newuser,gboolean sel)335 fe_userlist_insert (session *sess, struct User *newuser, gboolean sel)
336 {
337 GtkTreeModel *model = GTK_TREE_MODEL(sess->res->user_model);
338 GdkPixbuf *pix = get_user_icon (sess->server, newuser);
339 GtkTreeIter iter;
340 char *nick;
341 int nick_color = 0;
342
343 if (prefs.hex_away_track && newuser->away)
344 nick_color = COL_AWAY;
345 else if (prefs.hex_gui_ulist_color)
346 nick_color = text_color_of(newuser->nick);
347
348 nick = newuser->nick;
349 if (!prefs.hex_gui_ulist_icons)
350 {
351 nick = g_malloc (strlen (newuser->nick) + 2);
352 nick[0] = newuser->prefix[0];
353 if (nick[0] == '\0' || nick[0] == ' ')
354 strcpy (nick, newuser->nick);
355 else
356 strcpy (nick + 1, newuser->nick);
357 pix = NULL;
358 }
359
360 gtk_list_store_insert_with_values (GTK_LIST_STORE (model), &iter, 0,
361 COL_PIX, pix,
362 COL_NICK, nick,
363 COL_HOST, newuser->hostname,
364 COL_USER, newuser,
365 COL_GDKCOLOR, nick_color ? &colors[nick_color] : NULL,
366 -1);
367
368 if (!prefs.hex_gui_ulist_icons)
369 {
370 g_free (nick);
371 }
372
373 /* is it me? */
374 if (newuser->me && sess->gui->nick_box)
375 {
376 if (!sess->gui->is_tab || sess == current_tab)
377 mg_set_access_icon (sess->gui, pix, sess->server->is_away);
378 }
379
380 /* is it the front-most tab? */
381 if (gtk_tree_view_get_model (GTK_TREE_VIEW (sess->gui->user_tree))
382 == model)
383 {
384 if (sel)
385 gtk_tree_selection_select_iter (gtk_tree_view_get_selection
386 (GTK_TREE_VIEW (sess->gui->user_tree)), &iter);
387 }
388 }
389
390 void
fe_userlist_clear(session * sess)391 fe_userlist_clear (session *sess)
392 {
393 gtk_list_store_clear (sess->res->user_model);
394 }
395
396 static void
userlist_dnd_drop(GtkTreeView * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint ttime,gpointer userdata)397 userlist_dnd_drop (GtkTreeView *widget, GdkDragContext *context,
398 gint x, gint y, GtkSelectionData *selection_data,
399 guint info, guint ttime, gpointer userdata)
400 {
401 struct User *user;
402 gchar *data;
403 GtkTreePath *path;
404 GtkTreeModel *model;
405 GtkTreeIter iter;
406
407 if (!gtk_tree_view_get_path_at_pos (widget, x, y, &path, NULL, NULL, NULL))
408 return;
409
410 model = gtk_tree_view_get_model (widget);
411 if (!gtk_tree_model_get_iter (model, &iter, path))
412 return;
413 gtk_tree_model_get (model, &iter, COL_USER, &user, -1);
414
415 data = (char *)gtk_selection_data_get_data (selection_data);
416
417 if (data)
418 mg_dnd_drop_file (current_sess, user->nick, data);
419 }
420
421 static gboolean
userlist_dnd_motion(GtkTreeView * widget,GdkDragContext * context,gint x,gint y,guint ttime,gpointer tree)422 userlist_dnd_motion (GtkTreeView *widget, GdkDragContext *context, gint x,
423 gint y, guint ttime, gpointer tree)
424 {
425 GtkTreePath *path;
426 GtkTreeSelection *sel;
427
428 if (!tree)
429 return FALSE;
430
431 if (gtk_tree_view_get_path_at_pos (widget, x, y, &path, NULL, NULL, NULL))
432 {
433 sel = gtk_tree_view_get_selection (widget);
434 gtk_tree_selection_unselect_all (sel);
435 gtk_tree_selection_select_path (sel, path);
436 }
437
438 return FALSE;
439 }
440
441 static gboolean
userlist_dnd_leave(GtkTreeView * widget,GdkDragContext * context,guint ttime)442 userlist_dnd_leave (GtkTreeView *widget, GdkDragContext *context, guint ttime)
443 {
444 gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (widget));
445 return TRUE;
446 }
447
448 static int
userlist_alpha_cmp(GtkTreeModel * model,GtkTreeIter * iter_a,GtkTreeIter * iter_b,gpointer userdata)449 userlist_alpha_cmp (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer userdata)
450 {
451 struct User *user_a, *user_b;
452
453 gtk_tree_model_get (model, iter_a, COL_USER, &user_a, -1);
454 gtk_tree_model_get (model, iter_b, COL_USER, &user_b, -1);
455
456 return nick_cmp_alpha (user_a, user_b, ((session*)userdata)->server);
457 }
458
459 static int
userlist_ops_cmp(GtkTreeModel * model,GtkTreeIter * iter_a,GtkTreeIter * iter_b,gpointer userdata)460 userlist_ops_cmp (GtkTreeModel *model, GtkTreeIter *iter_a, GtkTreeIter *iter_b, gpointer userdata)
461 {
462 struct User *user_a, *user_b;
463
464 gtk_tree_model_get (model, iter_a, COL_USER, &user_a, -1);
465 gtk_tree_model_get (model, iter_b, COL_USER, &user_b, -1);
466
467 return nick_cmp_az_ops (((session*)userdata)->server, user_a, user_b);
468 }
469
470 GtkListStore *
userlist_create_model(session * sess)471 userlist_create_model (session *sess)
472 {
473 GtkListStore *store;
474 GtkTreeIterCompareFunc cmp_func;
475 GtkSortType sort_type;
476
477 store = gtk_list_store_new (5, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING,
478 G_TYPE_POINTER, GDK_TYPE_COLOR);
479
480 switch (prefs.hex_gui_ulist_sort)
481 {
482 case 0:
483 cmp_func = userlist_ops_cmp;
484 sort_type = GTK_SORT_ASCENDING;
485 break;
486 case 1:
487 cmp_func = userlist_alpha_cmp;
488 sort_type = GTK_SORT_ASCENDING;
489 break;
490 case 2:
491 cmp_func = userlist_ops_cmp;
492 sort_type = GTK_SORT_DESCENDING;
493 break;
494 case 3:
495 cmp_func = userlist_alpha_cmp;
496 sort_type = GTK_SORT_DESCENDING;
497 break;
498 default:
499 /* No sorting */
500 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE(store), NULL, NULL, NULL);
501 return store;
502 }
503
504 gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE(store), cmp_func, sess, NULL);
505 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(store),
506 GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID, sort_type);
507
508 return store;
509 }
510
511 static void
userlist_add_columns(GtkTreeView * treeview)512 userlist_add_columns (GtkTreeView * treeview)
513 {
514 GtkCellRenderer *renderer;
515
516 /* icon column */
517 renderer = gtk_cell_renderer_pixbuf_new ();
518 if (prefs.hex_gui_compact)
519 g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
520 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
521 -1, NULL, renderer,
522 "pixbuf", 0, NULL);
523
524 /* nick column */
525 renderer = gtk_cell_renderer_text_new ();
526 if (prefs.hex_gui_compact)
527 g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
528 gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1);
529 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
530 -1, NULL, renderer,
531 "text", 1, "foreground-gdk", 4, NULL);
532
533 if (prefs.hex_gui_ulist_show_hosts)
534 {
535 /* hostname column */
536 renderer = gtk_cell_renderer_text_new ();
537 if (prefs.hex_gui_compact)
538 g_object_set (G_OBJECT (renderer), "ypad", 0, NULL);
539 gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (renderer), 1);
540 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (treeview),
541 -1, NULL, renderer,
542 "text", 2, NULL);
543 }
544 }
545
546 static gint
userlist_click_cb(GtkWidget * widget,GdkEventButton * event,gpointer userdata)547 userlist_click_cb (GtkWidget *widget, GdkEventButton *event, gpointer userdata)
548 {
549 char **nicks;
550 int i;
551 GtkTreeSelection *sel;
552 GtkTreePath *path;
553
554 if (!event)
555 return FALSE;
556
557 if (!(event->state & STATE_CTRL) &&
558 event->type == GDK_2BUTTON_PRESS && prefs.hex_gui_ulist_doubleclick[0])
559 {
560 nicks = userlist_selection_list (widget, &i);
561 if (nicks)
562 {
563 nick_command_parse (current_sess, prefs.hex_gui_ulist_doubleclick, nicks[0],
564 nicks[0]);
565 while (i)
566 {
567 i--;
568 g_free (nicks[i]);
569 }
570 g_free (nicks);
571 }
572 return TRUE;
573 }
574
575 if (event->button == 3)
576 {
577 /* do we have a multi-selection? */
578 nicks = userlist_selection_list (widget, &i);
579 if (nicks && i > 1)
580 {
581 menu_nickmenu (current_sess, event, nicks[0], i);
582 while (i)
583 {
584 i--;
585 g_free (nicks[i]);
586 }
587 g_free (nicks);
588 return TRUE;
589 }
590 if (nicks)
591 {
592 g_free (nicks[0]);
593 g_free (nicks);
594 }
595
596 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
597 if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
598 event->x, event->y, &path, 0, 0, 0))
599 {
600 gtk_tree_selection_unselect_all (sel);
601 gtk_tree_selection_select_path (sel, path);
602 gtk_tree_path_free (path);
603 nicks = userlist_selection_list (widget, &i);
604 if (nicks)
605 {
606 menu_nickmenu (current_sess, event, nicks[0], i);
607 while (i)
608 {
609 i--;
610 g_free (nicks[i]);
611 }
612 g_free (nicks);
613 }
614 } else
615 {
616 gtk_tree_selection_unselect_all (sel);
617 }
618
619 return TRUE;
620 }
621
622 return FALSE;
623 }
624
625 static gboolean
userlist_key_cb(GtkWidget * wid,GdkEventKey * evt,gpointer userdata)626 userlist_key_cb (GtkWidget *wid, GdkEventKey *evt, gpointer userdata)
627 {
628 if (evt->keyval >= GDK_KEY_asterisk && evt->keyval <= GDK_KEY_z)
629 {
630 /* dirty trick to avoid auto-selection */
631 SPELL_ENTRY_SET_EDITABLE (current_sess->gui->input_box, FALSE);
632 gtk_widget_grab_focus (current_sess->gui->input_box);
633 SPELL_ENTRY_SET_EDITABLE (current_sess->gui->input_box, TRUE);
634 gtk_widget_event (current_sess->gui->input_box, (GdkEvent *)evt);
635 return TRUE;
636 }
637
638 return FALSE;
639 }
640
641 GtkWidget *
userlist_create(GtkWidget * box)642 userlist_create (GtkWidget *box)
643 {
644 GtkWidget *sw, *treeview;
645 static const GtkTargetEntry dnd_dest_targets[] =
646 {
647 {"text/uri-list", 0, 1},
648 {"HEXCHAT_CHANVIEW", GTK_TARGET_SAME_APP, 75 }
649 };
650 static const GtkTargetEntry dnd_src_target[] =
651 {
652 {"HEXCHAT_USERLIST", GTK_TARGET_SAME_APP, 75 }
653 };
654
655 sw = gtk_scrolled_window_new (NULL, NULL);
656 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
657 GTK_SHADOW_ETCHED_IN);
658 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
659 prefs.hex_gui_ulist_show_hosts ?
660 GTK_POLICY_AUTOMATIC :
661 GTK_POLICY_NEVER,
662 GTK_POLICY_AUTOMATIC);
663 gtk_box_pack_start (GTK_BOX (box), sw, TRUE, TRUE, 0);
664 gtk_widget_show (sw);
665
666 treeview = gtk_tree_view_new ();
667 gtk_widget_set_name (treeview, "hexchat-userlist");
668 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
669 gtk_tree_selection_set_mode (gtk_tree_view_get_selection
670 (GTK_TREE_VIEW (treeview)),
671 GTK_SELECTION_MULTIPLE);
672
673 /* set up drops */
674 gtk_drag_dest_set (treeview, GTK_DEST_DEFAULT_ALL, dnd_dest_targets, 2,
675 GDK_ACTION_MOVE | GDK_ACTION_COPY | GDK_ACTION_LINK);
676 gtk_drag_source_set (treeview, GDK_BUTTON1_MASK, dnd_src_target, 1, GDK_ACTION_MOVE);
677
678 /* file DND (for DCC) */
679 g_signal_connect (G_OBJECT (treeview), "drag_motion",
680 G_CALLBACK (userlist_dnd_motion), treeview);
681 g_signal_connect (G_OBJECT (treeview), "drag_leave",
682 G_CALLBACK (userlist_dnd_leave), 0);
683 g_signal_connect (G_OBJECT (treeview), "drag_data_received",
684 G_CALLBACK (userlist_dnd_drop), treeview);
685
686 g_signal_connect (G_OBJECT (treeview), "button_press_event",
687 G_CALLBACK (userlist_click_cb), 0);
688 g_signal_connect (G_OBJECT (treeview), "key_press_event",
689 G_CALLBACK (userlist_key_cb), 0);
690
691 /* tree/chanview DND */
692 g_signal_connect (G_OBJECT (treeview), "drag_begin",
693 G_CALLBACK (mg_drag_begin_cb), NULL);
694 g_signal_connect (G_OBJECT (treeview), "drag_drop",
695 G_CALLBACK (mg_drag_drop_cb), NULL);
696 g_signal_connect (G_OBJECT (treeview), "drag_motion",
697 G_CALLBACK (mg_drag_motion_cb), NULL);
698 g_signal_connect (G_OBJECT (treeview), "drag_end",
699 G_CALLBACK (mg_drag_end_cb), NULL);
700
701 userlist_add_columns (GTK_TREE_VIEW (treeview));
702
703 gtk_container_add (GTK_CONTAINER (sw), treeview);
704 gtk_widget_show (treeview);
705
706 return treeview;
707 }
708
709 void
userlist_show(session * sess)710 userlist_show (session *sess)
711 {
712 gtk_tree_view_set_model (GTK_TREE_VIEW (sess->gui->user_tree),
713 GTK_TREE_MODEL(sess->res->user_model));
714 }
715
716 void
fe_uselect(session * sess,char * word[],int do_clear,int scroll_to)717 fe_uselect (session *sess, char *word[], int do_clear, int scroll_to)
718 {
719 int thisname;
720 char *name;
721 GtkTreeIter iter;
722 GtkTreeView *treeview = GTK_TREE_VIEW (sess->gui->user_tree);
723 GtkTreeModel *model = gtk_tree_view_get_model (treeview);
724 GtkTreeSelection *selection = gtk_tree_view_get_selection (treeview);
725 struct User *row_user;
726
727 if (gtk_tree_model_get_iter_first (model, &iter))
728 {
729 if (do_clear)
730 gtk_tree_selection_unselect_all (selection);
731
732 do
733 {
734 if (*word[0])
735 {
736 gtk_tree_model_get (model, &iter, COL_USER, &row_user, -1);
737 thisname = 0;
738 while ( *(name = word[thisname++]) )
739 {
740 if (sess->server->p_cmp (row_user->nick, name) == 0)
741 {
742 gtk_tree_selection_select_iter (selection, &iter);
743 if (scroll_to)
744 scroll_to_iter (&iter, treeview, model);
745 break;
746 }
747 }
748 }
749
750 }
751 while (gtk_tree_model_iter_next (model, &iter));
752 }
753 }
754