2 * Copyright (C) 1998 Peter Zelezny.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22 #include <sys/types.h>
27 #include <gtk/gtkcheckbutton.h>
28 #include <gtk/gtkentry.h>
29 #include <gtk/gtkstock.h>
30 #include <gtk/gtkhbox.h>
31 #include <gtk/gtkhbbox.h>
32 #include <gtk/gtkframe.h>
33 #include <gtk/gtkhseparator.h>
34 #include <gtk/gtkversion.h>
36 #include <gtk/gtkliststore.h>
37 #include <gtk/gtktreeview.h>
38 #include <gtk/gtktreeselection.h>
39 #include <gtk/gtkcellrenderertext.h>
40 #include <gtk/gtkcellrenderertoggle.h>
42 #include "../common/xchat.h"
43 #include "../common/ignore.h"
44 #include "../common/cfgfiles.h"
45 #include "../common/fe.h"
62 static GtkWidget
*ignorewin
= 0;
64 static GtkWidget
*num_ctcp
;
65 static GtkWidget
*num_priv
;
66 static GtkWidget
*num_chan
;
67 static GtkWidget
*num_noti
;
68 static GtkWidget
*num_invi
;
73 return gtk_tree_view_get_model (g_object_get_data (G_OBJECT (ignorewin
), "view"));
77 ignore_get_flags (GtkTreeModel
*model
, GtkTreeIter
*iter
)
79 gboolean chan
, priv
, noti
, ctcp
, dcc
, invi
, unig
;
82 gtk_tree_model_get (model
, iter
, 1, &chan
, 2, &priv
, 3, ¬i
,
83 4, &ctcp
, 5, &dcc
, 6, &invi
, 7, &unig
, -1);
102 mask_edited (GtkCellRendererText
*render
, gchar
*path
, gchar
*new, gpointer dat
)
104 GtkListStore
*store
= GTK_LIST_STORE (get_store ());
109 gtkutil_treemodel_string_to_iter (GTK_TREE_MODEL (store
), path
, &iter
);
110 gtk_tree_model_get (GTK_TREE_MODEL (store
), &iter
, 0, &old
, -1);
112 if (!strcmp (old
, new)) /* no change */
114 else if (ignore_exists (new)) /* duplicate, ignore */
115 fe_message (_("That mask already exists."), FE_MSG_ERROR
);
118 /* delete old mask, and add new one with original flags */
119 ignore_del (old
, NULL
);
120 flags
= ignore_get_flags (GTK_TREE_MODEL (store
), &iter
);
121 ignore_add (new, flags
);
124 gtk_list_store_set (store
, &iter
, MASK_COLUMN
, new, -1);
131 option_toggled (GtkCellRendererToggle
*render
, gchar
*path
, gpointer data
)
133 GtkListStore
*store
= GTK_LIST_STORE (get_store ());
135 int col_id
= GPOINTER_TO_INT (data
);
140 gtkutil_treemodel_string_to_iter (GTK_TREE_MODEL (store
), path
, &iter
);
143 gtk_tree_model_get (GTK_TREE_MODEL (store
), &iter
, col_id
, &active
, -1);
144 gtk_list_store_set (store
, &iter
, col_id
, !active
, -1);
146 /* update ignore list */
147 gtk_tree_model_get (GTK_TREE_MODEL (store
), &iter
, 0, &mask
, -1);
148 flags
= ignore_get_flags (GTK_TREE_MODEL (store
), &iter
);
149 if (ignore_add (mask
, flags
) != 2)
150 g_warning ("ignore treeview is out of sync!\n");
156 ignore_treeview_new (GtkWidget
*box
)
160 GtkTreeViewColumn
*col
;
161 GtkCellRenderer
*render
;
164 store
= gtk_list_store_new (N_COLUMNS
, G_TYPE_STRING
,
165 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
,
166 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
,
167 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
,
168 G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
);
169 g_return_val_if_fail (store
!= NULL
, NULL
);
171 view
= gtkutil_treeview_new (box
, GTK_TREE_MODEL (store
),
173 MASK_COLUMN
, _("Mask"),
174 CHAN_COLUMN
, _("Channel"),
175 PRIV_COLUMN
, _("Private"),
176 NOTICE_COLUMN
, _("Notice"),
177 CTCP_COLUMN
, _("CTCP"),
178 DCC_COLUMN
, _("DCC"),
179 INVITE_COLUMN
, _("Invite"),
180 UNIGNORE_COLUMN
, _("Unignore"),
183 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view
), TRUE
);
184 gtk_tree_view_column_set_expand (gtk_tree_view_get_column (GTK_TREE_VIEW (view
), 0), TRUE
);
186 /* attach to signals and customise columns */
187 for (col_id
=0; (col
= gtk_tree_view_get_column (GTK_TREE_VIEW (view
), col_id
));
190 GList
*list
= gtk_tree_view_column_get_cell_renderers (col
);
193 for (tmp
= list
; tmp
; tmp
= tmp
->next
)
196 if (col_id
> 0) /* it's a toggle button column */
198 g_signal_connect (render
, "toggled", G_CALLBACK (option_toggled
),
199 GINT_TO_POINTER (col_id
));
200 } else /* mask column */
202 g_object_set (G_OBJECT (render
), "editable", TRUE
, NULL
);
203 g_signal_connect (render
, "edited", G_CALLBACK (mask_edited
), NULL
);
204 /* make this column sortable */
205 gtk_tree_view_column_set_sort_column_id (col
, col_id
);
206 gtk_tree_view_column_set_min_width (col
, 272);
209 gtk_tree_view_column_set_alignment (col
, 0.5);
215 gtk_widget_show (view
);
220 ignore_delete_entry_clicked (GtkWidget
* wid
, struct session
*sess
)
222 GtkTreeView
*view
= g_object_get_data (G_OBJECT (ignorewin
), "view");
223 GtkListStore
*store
= GTK_LIST_STORE (gtk_tree_view_get_model (view
));
228 if (gtkutil_treeview_get_selected (view
, &iter
, 0, &mask
, -1))
230 /* delete this row, select next one */
231 if (gtk_list_store_remove (store
, &iter
))
233 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (store
), &iter
);
234 gtk_tree_view_scroll_to_cell (view
, path
, NULL
, TRUE
, 1.0, 0.0);
235 gtk_tree_view_set_cursor (view
, path
, NULL
, FALSE
);
236 gtk_tree_path_free (path
);
239 ignore_del (mask
, NULL
);
245 ignore_store_new (int cancel
, char *mask
, gpointer data
)
247 GtkTreeView
*view
= g_object_get_data (G_OBJECT (ignorewin
), "view");
248 GtkListStore
*store
= GTK_LIST_STORE (get_store ());
251 int flags
= IG_CHAN
| IG_PRIV
| IG_NOTI
| IG_CTCP
| IG_DCC
| IG_INVI
;
255 /* check if it already exists */
256 if (ignore_exists (mask
))
258 fe_message (_("That mask already exists."), FE_MSG_ERROR
);
262 ignore_add (mask
, flags
);
264 gtk_list_store_append (store
, &iter
);
265 /* ignore everything by default */
266 gtk_list_store_set (store
, &iter
, 0, mask
, 1, TRUE
, 2, TRUE
, 3, TRUE
,
267 4, TRUE
, 5, TRUE
, 6, TRUE
, 7, FALSE
, -1);
268 /* make sure the new row is visible and selected */
269 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (store
), &iter
);
270 gtk_tree_view_scroll_to_cell (view
, path
, NULL
, TRUE
, 1.0, 0.0);
271 gtk_tree_view_set_cursor (view
, path
, NULL
, FALSE
);
272 gtk_tree_path_free (path
);
276 ignore_clear_entry_clicked (GtkWidget
* wid
, gpointer unused
)
278 GtkListStore
*store
= GTK_LIST_STORE (get_store ());
282 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store
), &iter
))
284 /* remove from ignore_list */
288 gtk_tree_model_get (GTK_TREE_MODEL (store
), &iter
, MASK_COLUMN
, &mask
, -1);
289 ignore_del (mask
, NULL
);
292 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store
), &iter
));
294 /* remove from GUI */
295 gtk_list_store_clear (store
);
300 ignore_new_entry_clicked (GtkWidget
* wid
, struct session
*sess
)
302 fe_get_str (_("Enter mask to ignore:"), "nick!userid@host.com",
303 ignore_store_new
, NULL
);
308 close_ignore_gui_callback ()
315 ignore_stats_entry (GtkWidget
* box
, char *label
, int value
)
320 sprintf (buf
, "%d", value
);
321 gtkutil_label_new (label
, box
);
322 wid
= gtkutil_entry_new (16, box
, 0, 0);
323 gtk_widget_set_size_request (wid
, 30, -1);
324 gtk_editable_set_editable (GTK_EDITABLE (wid
), FALSE
);
325 gtk_widget_set_sensitive (GTK_WIDGET (wid
), FALSE
);
326 gtk_entry_set_text (GTK_ENTRY (wid
), buf
);
334 GtkWidget
*vbox
, *box
, *stat_box
, *frame
;
338 GSList
*temp
= ignore_list
;
340 gboolean
private, chan
, notice
, ctcp
, dcc
, invite
, unignore
;
344 mg_bring_tofront (ignorewin
);
349 mg_create_generic_tab ("IgnoreList", _("XChat: Ignore list"),
350 FALSE
, TRUE
, close_ignore_gui_callback
,
351 NULL
, 600, 256, &vbox
, 0);
353 view
= ignore_treeview_new (vbox
);
354 g_object_set_data (G_OBJECT (ignorewin
), "view", view
);
356 frame
= gtk_frame_new (_("Ignore Stats:"));
357 gtk_widget_show (frame
);
359 stat_box
= gtk_hbox_new (0, 2);
360 gtk_container_set_border_width (GTK_CONTAINER (stat_box
), 6);
361 gtk_container_add (GTK_CONTAINER (frame
), stat_box
);
362 gtk_widget_show (stat_box
);
364 num_chan
= ignore_stats_entry (stat_box
, _("Channel:"), ignored_chan
);
365 num_priv
= ignore_stats_entry (stat_box
, _("Private:"), ignored_priv
);
366 num_noti
= ignore_stats_entry (stat_box
, _("Notice:"), ignored_noti
);
367 num_ctcp
= ignore_stats_entry (stat_box
, _("CTCP:"), ignored_ctcp
);
368 num_invi
= ignore_stats_entry (stat_box
, _("Invite:"), ignored_invi
);
370 gtk_box_pack_start (GTK_BOX (vbox
), frame
, 0, 0, 5);
372 box
= gtk_hbutton_box_new ();
373 gtk_button_box_set_layout (GTK_BUTTON_BOX (box
), GTK_BUTTONBOX_SPREAD
);
374 gtk_box_pack_start (GTK_BOX (vbox
), box
, FALSE
, FALSE
, 2);
375 gtk_container_set_border_width (GTK_CONTAINER (box
), 5);
376 gtk_widget_show (box
);
378 gtkutil_button (box
, GTK_STOCK_NEW
, 0, ignore_new_entry_clicked
, 0,
380 gtkutil_button (box
, GTK_STOCK_DELETE
, 0, ignore_delete_entry_clicked
,
382 gtkutil_button (box
, GTK_STOCK_CLEAR
, 0, ignore_clear_entry_clicked
,
385 store
= GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (view
)));
389 struct ignore
*ignore
= temp
->data
;
392 chan
= (ignore
->type
& IG_CHAN
);
393 private = (ignore
->type
& IG_PRIV
);
394 notice
= (ignore
->type
& IG_NOTI
);
395 ctcp
= (ignore
->type
& IG_CTCP
);
396 dcc
= (ignore
->type
& IG_DCC
);
397 invite
= (ignore
->type
& IG_INVI
);
398 unignore
= (ignore
->type
& IG_UNIG
);
400 gtk_list_store_append (store
, &iter
);
401 gtk_list_store_set (store
, &iter
,
404 PRIV_COLUMN
, private,
405 NOTICE_COLUMN
, notice
,
408 INVITE_COLUMN
, invite
,
409 UNIGNORE_COLUMN
, unignore
,
414 gtk_widget_show (ignorewin
);
418 fe_ignore_update (int level
)
420 /* some ignores have changed via /ignore, we should update
422 /* level 1 = the list only. */
423 /* level 2 = the numbers only. */
424 /* for now, ignore level 1, since the ignore GUI isn't realtime,
425 only saved when you click OK */
428 if (level
== 2 && ignorewin
)
430 sprintf (buf
, "%d", ignored_ctcp
);
431 gtk_entry_set_text (GTK_ENTRY (num_ctcp
), buf
);
433 sprintf (buf
, "%d", ignored_noti
);
434 gtk_entry_set_text (GTK_ENTRY (num_noti
), buf
);
436 sprintf (buf
, "%d", ignored_chan
);
437 gtk_entry_set_text (GTK_ENTRY (num_chan
), buf
);
439 sprintf (buf
, "%d", ignored_invi
);
440 gtk_entry_set_text (GTK_ENTRY (num_invi
), buf
);
442 sprintf (buf
, "%d", ignored_priv
);
443 gtk_entry_set_text (GTK_ENTRY (num_priv
), buf
);