2 * Dialog boxes for (display and capture) filter editing
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 #include <epan/filesystem.h>
37 #include "filter_dlg.h"
38 #include "dlg_utils.h"
39 #include "gui_utils.h"
40 #include "simple_dialog.h"
41 #include "dfilter_expr_dlg.h"
42 #include "compat_macros.h"
43 #include "gtkglobals.h"
45 #include <epan/prefs.h>
47 #define E_FILT_DIALOG_PTR_KEY "filter_dialog_ptr"
48 #define E_FILT_BUTTON_PTR_KEY "filter_button_ptr"
49 #define E_FILT_PARENT_FILTER_TE_KEY "filter_parent_filter_te"
50 #define E_FILT_CONSTRUCT_ARGS_KEY "filter_construct_args"
51 #define E_FILT_LIST_ITEM_MODEL_KEY "filter_list_item_model"
52 #define E_FILT_LBL_KEY "filter_label"
53 #define E_FILT_FILTER_L_KEY "filter_filter_l"
54 #define E_FILT_CHG_BT_KEY "filter_chg_bt"
55 #define E_FILT_COPY_BT_KEY "filter_copy_bt"
56 #define E_FILT_DEL_BT_KEY "filter_del_bt"
57 #define E_FILT_NAME_TE_KEY "filter_name_te"
58 #define E_FILT_DBLFUNC_KEY "filter_dblfunc"
59 #define E_FILT_DBLARG_KEY "filter_dblarg"
60 #define E_FILT_DBLACTIVATE_KEY "filter_dblactivate"
62 typedef struct _filter_cb_data {
67 static GtkWidget *filter_dialog_new(GtkWidget *button, GtkWidget *filter_te,
68 filter_list_type_t list_type,
69 construct_args_t *construct_args);
70 static void filter_dlg_dclick(GtkWidget *dummy, gpointer main_w_arg,
72 static void filter_dlg_ok_cb(GtkWidget *ok_bt, gpointer dummy);
73 static void filter_dlg_apply_cb(GtkWidget *apply_bt, gpointer dummy);
74 static void filter_apply(GtkWidget *main_w, gboolean destroy);
75 static void filter_dlg_save(filter_list_type_t list_type);
76 static void filter_dlg_save_cb(GtkWidget *save_bt, gpointer parent_w);
77 static void filter_dlg_destroy_cb(GtkWidget *win, gpointer data);
80 filter_dlg_delete_event_cb(GtkWidget *prefs_w, GdkEvent *event, gpointer data);
82 filter_dlg_cancel_cb(GtkWidget *cancel_bt, gpointer data);
84 static gint filter_sel_list_button_cb(GtkWidget *, GdkEventButton *,
86 #if GTK_MAJOR_VERSION < 2
87 static void filter_sel_list_cb(GtkWidget *, gpointer);
89 static void filter_sel_list_cb(GtkTreeSelection *, gpointer);
91 static void filter_new_bt_clicked_cb(GtkWidget *, gpointer);
92 static void filter_del_bt_clicked_cb(GtkWidget *, gpointer);
93 static void filter_name_te_changed_cb(GtkWidget *, gpointer);
96 /* Create a filter dialog for constructing a capture filter.
98 This is to be used as a callback for a button next to a text entry box,
99 which, when clicked, pops up this dialog to allow you to construct a
100 display filter by browsing the list of saved filters (the dialog
101 for constructing expressions assumes display filter syntax, not
102 capture filter syntax). The "OK" button sets the text entry box to the
103 constructed filter and activates that text entry box (which should have
104 no effect in the main capture dialog); this dialog is then dismissed. */
106 capture_filter_construct_cb(GtkWidget *w, gpointer user_data _U_)
108 GtkWidget *filter_browse_w;
109 GtkWidget *parent_filter_te;
110 /* No Apply button, and "OK" just sets our text widget, it doesn't
111 activate it (i.e., it doesn't cause us to try to open the file). */
112 static construct_args_t args = {
113 "Wireshark: Capture Filter",
119 /* Has a filter dialog box already been opened for that button? */
120 filter_browse_w = OBJECT_GET_DATA(w, E_FILT_DIALOG_PTR_KEY);
122 if (filter_browse_w != NULL) {
123 /* Yes. Just re-activate that dialog box. */
124 reactivate_window(filter_browse_w);
128 /* No. Get the text entry attached to the button. */
129 parent_filter_te = OBJECT_GET_DATA(w, E_FILT_TE_PTR_KEY);
131 /* Now create a new dialog, without an "Add Expression..." button. */
132 filter_browse_w = filter_dialog_new(w, parent_filter_te,
133 CFILTER_LIST, &args);
137 /* Create a filter dialog for constructing a display filter.
139 This is to be used as a callback for a button next to a text entry box,
140 which, when clicked, pops up this dialog to allow you to construct a
141 display filter by browsing the list of saved filters and/or by adding
142 test expressions constructed with another dialog. The "OK" button
143 sets the text entry box to the constructed filter and activates that
144 text entry box, causing the filter to be used; this dialog is then
147 If "wants_apply_button" is non-null, we add an "Apply" button that
148 acts like "OK" but doesn't dismiss this dialog. */
150 display_filter_construct_cb(GtkWidget *w, gpointer construct_args_ptr)
152 construct_args_t *construct_args = construct_args_ptr;
153 GtkWidget *filter_browse_w;
154 GtkWidget *parent_filter_te;
156 /* Has a filter dialog box already been opened for the button? */
157 filter_browse_w = OBJECT_GET_DATA(w, E_FILT_DIALOG_PTR_KEY);
159 if (filter_browse_w != NULL) {
160 /* Yes. Just re-activate that dialog box. */
161 reactivate_window(filter_browse_w);
165 /* No. Get the text entry attached to the button. */
166 parent_filter_te = OBJECT_GET_DATA(w, E_FILT_TE_PTR_KEY);
168 /* Now create a new dialog, possibly with an "Apply" button, and
169 definitely with an "Add Expression..." button. */
170 filter_browse_w = filter_dialog_new(w, parent_filter_te,
171 DFILTER_LIST, construct_args);
174 /* Should be called when a button that creates filters is destroyed; it
175 destroys any filter dialog created by that button. */
177 filter_button_destroy_cb(GtkWidget *button, gpointer user_data _U_)
181 /* Is there a filter edit/selection dialog associated with this
183 filter_w = OBJECT_GET_DATA(button, E_FILT_DIALOG_PTR_KEY);
185 if (filter_w != NULL) {
186 /* Yes. Break the association, and destroy the dialog. */
187 OBJECT_SET_DATA(button, E_FILT_DIALOG_PTR_KEY, NULL);
188 window_destroy(filter_w);
193 static GtkWidget *global_cfilter_w;
195 /* Create a filter dialog for editing capture filters; this is to be used
196 as a callback for menu items, toolbars, etc.. */
198 cfilter_dialog_cb(GtkWidget *w _U_)
200 /* No Apply button, and there's no text widget to set, much less
201 activate, on "OK". */
202 static construct_args_t args = {
203 "Wireshark: Capture Filter",
209 /* Has a filter dialog box already been opened for editing
211 if (global_cfilter_w != NULL) {
212 /* Yes. Just reactivate it. */
213 reactivate_window(global_cfilter_w);
218 * No. Create one; we didn't pop this up as a result of pressing
219 * a button next to some text entry field, so don't associate it
220 * with a text entry field or button.
222 global_cfilter_w = filter_dialog_new(NULL, NULL, CFILTER_LIST, &args);
226 /* Create a filter dialog for editing display filters; this is to be used
227 as a callback for menu items, toolbars, etc.. */
229 dfilter_dialog_cb(GtkWidget *w _U_)
231 static construct_args_t args = {
232 "Wireshark: Display Filter",
238 display_filter_construct_cb(OBJECT_GET_DATA(top_level, E_FILT_BT_PTR_KEY), &args);
241 /* List of capture filter dialogs, so that if the list of filters changes
242 (the model, if you will), we can update all of their lists displaying
243 the filters (the views). */
244 static GList *cfilter_dialogs;
246 /* List of display filter dialogs, so that if the list of filters changes
247 (the model, if you will), we can update all of their lists displaying
248 the filters (the views). */
249 static GList *dfilter_dialogs;
252 remember_filter_dialog(GtkWidget *main_w, GList **filter_dialogs)
254 *filter_dialogs = g_list_append(*filter_dialogs, main_w);
257 /* Remove a filter dialog from the specified list of filter_dialogs. */
259 forget_filter_dialog(GtkWidget *main_w, filter_list_type_t list_type)
263 case CFILTER_EDITED_LIST:
264 cfilter_dialogs = g_list_remove(cfilter_dialogs, main_w);
267 case DFILTER_EDITED_LIST:
268 dfilter_dialogs = g_list_remove(dfilter_dialogs, main_w);
272 g_assert_not_reached();
277 /* Get the dialog list corresponding to a particular filter list. */
279 get_filter_dialog_list(filter_list_type_t list_type)
283 case CFILTER_EDITED_LIST:
284 return cfilter_dialogs;
286 case DFILTER_EDITED_LIST:
287 return dfilter_dialogs;
290 g_assert_not_reached();
297 fill_list(GtkWidget *main_w, filter_list_type_t list_type)
301 const gchar *filter_te_str = NULL;
302 #if GTK_MAJOR_VERSION < 2
306 GtkWidget *filter_l = OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY);
308 gboolean l_select = FALSE;
309 GtkTreeView *filter_l;
312 GtkTreeIter sel_iter;
314 filter_l = GTK_TREE_VIEW(OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY));
315 store = GTK_LIST_STORE(gtk_tree_view_get_model(filter_l));
319 fl_entry = get_filter_list_first(list_type);
320 while (fl_entry != NULL) {
321 filt = (filter_def *) fl_entry->data;
322 #if GTK_MAJOR_VERSION < 2
323 nl_lb = gtk_label_new(filt->name);
324 nl_item = gtk_list_item_new();
326 SIGNAL_CONNECT(nl_item, "button_press_event", filter_sel_list_button_cb,
329 gtk_misc_set_alignment (GTK_MISC (nl_lb), 0.0, 0.5);
330 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
331 gtk_widget_show(nl_lb);
332 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
333 gtk_widget_show(nl_item);
334 OBJECT_SET_DATA(nl_item, E_FILT_LBL_KEY, nl_lb);
335 OBJECT_SET_DATA(nl_item, E_FILT_LIST_ITEM_MODEL_KEY, fl_entry);
337 gtk_list_store_append(store, &iter);
338 gtk_list_store_set(store, &iter, 0, filt->name,
342 if (filter_te_str && filt->strval) {
343 if (strcmp(filter_te_str, filt->strval) == 0) {
344 #if GTK_MAJOR_VERSION < 2
353 fl_entry = fl_entry->next;
359 clear_list(GtkWidget *main_w) {
360 GtkWidget *filter_l = OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY);
361 #if GTK_MAJOR_VERSION >= 2
362 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(filter_l));
365 #if GTK_MAJOR_VERSION < 2
366 gtk_list_clear_items(GTK_LIST(filter_l), 0, -1);
368 gtk_list_store_clear(GTK_LIST_STORE(model));
374 filter_dialog_new(GtkWidget *button, GtkWidget *parent_filter_te,
375 filter_list_type_t list_type, construct_args_t *construct_args)
377 GtkWidget *main_w, /* main window */
378 *main_vb, /* main container */
379 *bbox, /* button container */
380 *ok_bt, /* "OK" button */
381 *apply_bt, /* "Apply" button */
382 *save_bt, /* "Save" button */
383 *cancel_bt, /* "Cancel" button */
384 *help_bt; /* "Help" button */
385 GtkWidget *filter_vb, /* filter settings box */
403 GtkTooltips *tooltips;
404 static filter_list_type_t cfilter_list_type = CFILTER_EDITED_LIST;
405 static filter_list_type_t dfilter_list_type = DFILTER_EDITED_LIST;
406 filter_list_type_t *filter_list_type_p;
407 GList **filter_dialogs;
408 const gchar *filter_te_str = NULL;
409 #if GTK_MAJOR_VERSION < 2
410 GtkWidget *l_select = NULL;
412 gboolean l_select = FALSE;
414 GtkCellRenderer *renderer;
415 GtkTreeViewColumn *column;
416 GtkTreeSelection *sel;
417 GtkTreeIter sel_iter;
420 /* Get a pointer to a static variable holding the type of filter on
421 which we're working, so we can pass that pointer to callback
426 filter_dialogs = &cfilter_dialogs;
427 filter_list_type_p = &cfilter_list_type;
428 list_type = CFILTER_EDITED_LIST;
432 filter_dialogs = &dfilter_dialogs;
433 filter_list_type_p = &dfilter_list_type;
434 list_type = DFILTER_EDITED_LIST;
438 g_assert_not_reached();
439 filter_dialogs = NULL;
440 filter_list_type_p = NULL;
444 tooltips = gtk_tooltips_new ();
446 main_w = dlg_window_new(construct_args->title);
447 gtk_window_set_default_size(GTK_WINDOW(main_w), 400, 400);
448 OBJECT_SET_DATA(main_w, E_FILT_CONSTRUCT_ARGS_KEY, construct_args);
450 if(construct_args->modal_and_transient) {
451 GdkWindow* parent = gtk_widget_get_parent_window(parent_filter_te);
452 gtk_window_set_transient_for(GTK_WINDOW(main_w), GTK_WINDOW(parent));
453 gtk_window_set_modal(GTK_WINDOW(main_w), TRUE);
456 main_vb = gtk_vbox_new(FALSE, 0);
457 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
458 gtk_container_add(GTK_CONTAINER(main_w), main_vb);
459 gtk_widget_show(main_vb);
461 /* Make sure everything is set up */
462 if (parent_filter_te)
463 filter_te_str = gtk_entry_get_text(GTK_ENTRY(parent_filter_te));
465 /* Container for each row of widgets */
466 filter_vb = gtk_vbox_new(FALSE, 0);
467 gtk_container_border_width(GTK_CONTAINER(filter_vb), 0);
468 gtk_container_add(GTK_CONTAINER(main_vb), filter_vb);
469 gtk_widget_show(filter_vb);
471 /* Top row: Buttons and filter list */
472 top_hb = gtk_hbox_new(FALSE, 0);
473 gtk_container_add(GTK_CONTAINER(filter_vb), top_hb);
474 gtk_widget_show(top_hb);
476 edit_fr = gtk_frame_new("Edit");
477 gtk_box_pack_start(GTK_BOX(top_hb), edit_fr, FALSE, FALSE, 0);
478 gtk_widget_show(edit_fr);
480 list_bb = gtk_vbox_new(TRUE, 0);
481 gtk_container_border_width(GTK_CONTAINER(list_bb), 5);
482 gtk_container_add(GTK_CONTAINER(edit_fr), list_bb);
483 gtk_widget_show(list_bb);
485 new_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_NEW);
486 SIGNAL_CONNECT(new_bt, "clicked", filter_new_bt_clicked_cb, filter_list_type_p);
487 #if GTK_MAJOR_VERSION < 2
488 WIDGET_SET_SIZE(new_bt, 50, 20);
490 gtk_widget_show(new_bt);
491 gtk_box_pack_start (GTK_BOX (list_bb), new_bt, FALSE, FALSE, 0);
492 gtk_tooltips_set_tip (tooltips, new_bt,
493 "Create a new filter at the end of the list (with the current properties)", NULL);
495 del_bt = BUTTON_NEW_FROM_STOCK(GTK_STOCK_DELETE);
496 gtk_widget_set_sensitive(del_bt, FALSE);
497 SIGNAL_CONNECT(del_bt, "clicked", filter_del_bt_clicked_cb, filter_list_type_p);
498 OBJECT_SET_DATA(main_w, E_FILT_DEL_BT_KEY, del_bt);
499 #if GTK_MAJOR_VERSION < 2
500 WIDGET_SET_SIZE(del_bt, 50, 20);
502 gtk_widget_show(del_bt);
503 gtk_box_pack_start (GTK_BOX (list_bb), del_bt, FALSE, FALSE, 0);
504 gtk_tooltips_set_tip (tooltips, del_bt, ("Delete the selected filter"), NULL);
506 filter_fr = gtk_frame_new("Filter");
507 gtk_box_pack_start(GTK_BOX(top_hb), filter_fr, TRUE, TRUE, 0);
508 gtk_widget_show(filter_fr);
510 filter_sc = scrolled_window_new(NULL, NULL);
511 #if GTK_MAJOR_VERSION >= 2
512 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(filter_sc),
516 gtk_container_set_border_width (GTK_CONTAINER (filter_sc), 5);
517 gtk_container_add(GTK_CONTAINER(filter_fr), filter_sc);
518 gtk_widget_show(filter_sc);
520 #if GTK_MAJOR_VERSION < 2
521 filter_l = gtk_list_new();
522 gtk_list_set_selection_mode(GTK_LIST(filter_l), GTK_SELECTION_SINGLE);
523 SIGNAL_CONNECT(filter_l, "selection_changed", filter_sel_list_cb,
526 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
527 filter_l = tree_view_new(GTK_TREE_MODEL(store));
528 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(filter_l), FALSE);
529 renderer = gtk_cell_renderer_text_new();
530 column = gtk_tree_view_column_new_with_attributes("", renderer, "text",
532 gtk_tree_view_column_set_sort_column_id(column, 0);
533 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_l), column);
534 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_l));
535 gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
536 SIGNAL_CONNECT(sel, "changed", filter_sel_list_cb, filter_vb);
537 SIGNAL_CONNECT(filter_l, "button_press_event", filter_sel_list_button_cb,
540 OBJECT_SET_DATA(main_w, E_FILT_FILTER_L_KEY, filter_l);
541 #if GTK_MAJOR_VERSION < 2
542 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(filter_sc),
545 gtk_container_add(GTK_CONTAINER(filter_sc), filter_l);
547 gtk_widget_show(filter_l);
549 OBJECT_SET_DATA(filter_l, E_FILT_DBLFUNC_KEY, filter_dlg_dclick);
550 OBJECT_SET_DATA(filter_l, E_FILT_DBLARG_KEY, main_w);
551 /* This is a Boolean, but we make it a non-null pointer for TRUE
552 and a null pointer for FALSE, as object data is a pointer. */
553 OBJECT_SET_DATA(filter_l, E_FILT_DBLACTIVATE_KEY,
554 construct_args->activate_on_ok ? "" : NULL);
557 fill_list(main_w, list_type);
559 #if GTK_MAJOR_VERSION >= 2
560 g_object_unref(G_OBJECT(store));
564 props_fr = gtk_frame_new("Properties");
565 gtk_box_pack_start(GTK_BOX(filter_vb), props_fr, FALSE, FALSE, 0);
566 gtk_widget_show(props_fr);
568 props_vb = gtk_vbox_new(FALSE, 3);
569 gtk_container_border_width(GTK_CONTAINER(props_vb), 5);
570 gtk_container_add(GTK_CONTAINER(props_fr), props_vb);
571 gtk_widget_show(props_vb);
573 /* row: Filter name entry */
574 middle_hb = gtk_hbox_new(FALSE, 3);
575 gtk_container_add(GTK_CONTAINER(props_vb), middle_hb);
576 gtk_widget_show(middle_hb);
578 name_lb = gtk_label_new("Filter name:");
579 gtk_box_pack_start(GTK_BOX(middle_hb), name_lb, FALSE, FALSE, 0);
580 gtk_widget_show(name_lb);
582 name_te = gtk_entry_new();
583 gtk_box_pack_start(GTK_BOX(middle_hb), name_te, TRUE, TRUE, 0);
584 OBJECT_SET_DATA(main_w, E_FILT_NAME_TE_KEY, name_te);
585 SIGNAL_CONNECT(name_te, "changed", filter_name_te_changed_cb, filter_list_type_p);
586 gtk_widget_show(name_te);
588 /* row: Filter text entry */
589 bottom_hb = gtk_hbox_new(FALSE, 3);
590 gtk_container_add(GTK_CONTAINER(props_vb), bottom_hb);
591 gtk_widget_show(bottom_hb);
593 filter_lb = gtk_label_new("Filter string:");
594 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_lb, FALSE, FALSE, 0);
595 gtk_widget_show(filter_lb);
597 filter_te = gtk_entry_new();
598 gtk_box_pack_start(GTK_BOX(bottom_hb), filter_te, TRUE, TRUE, 0);
599 OBJECT_SET_DATA(main_w, E_FILT_FILTER_TE_KEY, filter_te);
600 SIGNAL_CONNECT(filter_te, "changed", filter_name_te_changed_cb, filter_list_type_p);
601 gtk_widget_show(filter_te);
603 OBJECT_SET_DATA(main_w, E_FILT_PARENT_FILTER_TE_KEY, parent_filter_te);
605 if (list_type == DFILTER_EDITED_LIST) {
606 gtk_tooltips_set_tip(tooltips, filter_te,
607 "Enter a display filter. "
608 "The background color of this field is changed by a continuous syntax check (green is valid, red is invalid).",
611 /* Create the "Add Expression..." button, to pop up a dialog
612 for constructing filter comparison expressions. */
613 add_expression_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_ADD_EXPRESSION);
614 SIGNAL_CONNECT(add_expression_bt, "clicked", filter_add_expr_bt_cb, main_w);
615 gtk_box_pack_start(GTK_BOX(bottom_hb), add_expression_bt, FALSE, FALSE, 0);
616 gtk_widget_show(add_expression_bt);
617 gtk_tooltips_set_tip (tooltips, add_expression_bt, ("Add an expression to the filter string"), NULL);
621 /* button row (create all possible buttons and hide the unrequired later - it's a lot easier) */
622 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_SAVE, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
623 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5);
624 gtk_widget_show(bbox);
626 ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
627 SIGNAL_CONNECT(ok_bt, "clicked", filter_dlg_ok_cb, filter_list_type_p);
628 gtk_tooltips_set_tip (tooltips, ok_bt, ("Apply the filters and close this dialog"), NULL);
630 /* Catch the "activate" signal on the filter name and filter
631 expression text entries, so that if the user types Return
632 there, we act as if the "OK" button had been selected, as
633 happens if Return is typed if some widget that *doesn't*
634 handle the Return key has the input focus. */
635 if (parent_filter_te != NULL) {
636 dlg_set_activate(name_te, ok_bt);
637 dlg_set_activate(filter_te, ok_bt);
640 apply_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_APPLY);
641 SIGNAL_CONNECT(apply_bt, "clicked", filter_dlg_apply_cb, NULL);
642 gtk_tooltips_set_tip (tooltips, apply_bt, ("Apply the filters and keep this dialog open"), NULL);
644 save_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_SAVE);
645 SIGNAL_CONNECT(save_bt, "clicked", filter_dlg_save_cb, filter_list_type_p);
646 gtk_tooltips_set_tip (tooltips, save_bt, ("Save the filters permanently and keep this dialog open"), NULL);
648 cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
649 gtk_tooltips_set_tip (tooltips, cancel_bt, ("Cancel the changes"), NULL);
650 SIGNAL_CONNECT(cancel_bt, "clicked", filter_dlg_cancel_cb, filter_list_type_p);
652 help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
653 if (list_type == CFILTER_EDITED_LIST) {
654 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_CAPTURE_FILTERS_DIALOG);
656 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_DISPLAY_FILTERS_DIALOG);
658 gtk_tooltips_set_tip (tooltips, help_bt, ("Show topic specific help"), NULL);
661 gtk_widget_grab_default(ok_bt);
664 remember_filter_dialog(main_w, filter_dialogs);
666 if (button != NULL) {
667 /* This dialog box was created by a "Filter" button.
668 Set the E_FILT_BUTTON_PTR_KEY for the new dialog to point to
670 OBJECT_SET_DATA(main_w, E_FILT_BUTTON_PTR_KEY, button);
672 /* Set the E_FILT_DIALOG_PTR_KEY for the button to point to us */
673 OBJECT_SET_DATA(button, E_FILT_DIALOG_PTR_KEY, main_w);
676 /* DO SELECTION THINGS *AFTER* SHOWING THE DIALOG! */
677 /* otherwise the updatings can get confused */
678 #if GTK_MAJOR_VERSION < 2
680 gtk_list_select_child(GTK_LIST(filter_l), l_select);
681 } else if (filter_te_str && filter_te_str[0]) {
682 gtk_entry_set_text(GTK_ENTRY(name_te), "New filter");
683 gtk_entry_set_text(GTK_ENTRY(filter_te), filter_te_str);
687 gtk_tree_selection_select_iter(sel, &sel_iter);
688 } else if (filter_te_str && filter_te_str[0]) {
689 gtk_entry_set_text(GTK_ENTRY(name_te), "New filter");
690 gtk_entry_set_text(GTK_ENTRY(filter_te), filter_te_str);
694 SIGNAL_CONNECT(main_w, "delete_event", filter_dlg_delete_event_cb, filter_list_type_p);
695 SIGNAL_CONNECT(main_w, "destroy", filter_dlg_destroy_cb, filter_list_type_p);
697 gtk_widget_show(main_w);
699 /* hide the Ok button, if we don't have to apply it and our caller wants a Save button */
700 if (parent_filter_te == NULL && prefs.gui_use_pref_save) {
701 gtk_widget_hide(ok_bt);
704 /* hide the Apply button, if our caller don't wants one */
705 if (!construct_args->wants_apply_button) {
706 gtk_widget_hide(apply_bt);
709 /* hide the Save button if the user uses implicit save */
710 if (!prefs.gui_use_pref_save) {
711 gtk_widget_hide(save_bt);
714 window_present(main_w);
720 filter_dlg_dclick(GtkWidget *filter_l, gpointer main_w_arg, gpointer activate)
722 GtkWidget *main_w = GTK_WIDGET(main_w_arg);
723 GtkWidget *parent_filter_te =
724 OBJECT_GET_DATA(main_w, E_FILT_PARENT_FILTER_TE_KEY);
727 #if GTK_MAJOR_VERSION < 2
731 GtkTreeSelection *sel;
735 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_l));
738 if (parent_filter_te != NULL) {
740 * We have a text entry widget associated with this dialog
741 * box; is one of the filters in the list selected?
743 #if GTK_MAJOR_VERSION < 2
744 sl = GTK_LIST(filter_l)->selection;
747 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
750 * Yes. Is there a filter definition for that filter?
752 #if GTK_MAJOR_VERSION < 2
753 l_item = GTK_OBJECT(sl->data);
754 flp = (GList *)OBJECT_GET_DATA(l_item,
755 E_FILT_LIST_ITEM_MODEL_KEY);
757 gtk_tree_model_get(model, &iter, 1, &flp, -1);
761 * Yes - put it in the text entry widget.
763 filt = (filter_def *) flp->data;
764 gtk_entry_set_text(GTK_ENTRY(parent_filter_te),
768 * Are we supposed to cause the filter we
769 * put there to be applied?
771 if (activate != NULL) {
775 SIGNAL_EMIT_BY_NAME(parent_filter_te, "activate", NULL);
781 window_destroy(main_w);
785 filter_dlg_ok_cb(GtkWidget *ok_bt, gpointer data)
787 filter_list_type_t list_type = *(filter_list_type_t *)data;
790 * Destroy the dialog box and apply the filter.
792 filter_apply(gtk_widget_get_toplevel(ok_bt), TRUE);
794 /* if we don't have a Save button, just save the settings now */
795 if (!prefs.gui_use_pref_save) {
796 filter_dlg_save(list_type);
801 filter_dlg_apply_cb(GtkWidget *apply_bt, gpointer dummy _U_)
804 * Apply the filter, but don't destroy the dialog box.
806 filter_apply(gtk_widget_get_toplevel(apply_bt), FALSE);
810 filter_apply(GtkWidget *main_w, gboolean destroy)
812 construct_args_t *construct_args =
813 OBJECT_GET_DATA(main_w, E_FILT_CONSTRUCT_ARGS_KEY);
814 GtkWidget *parent_filter_te =
815 OBJECT_GET_DATA(main_w, E_FILT_PARENT_FILTER_TE_KEY);
816 GtkWidget *filter_te;
817 const gchar *filter_string;
819 if (parent_filter_te != NULL) {
821 * We have a text entry widget associated with this dialog
822 * box; put the filter in our text entry widget into that
825 filter_te = OBJECT_GET_DATA(main_w, E_FILT_FILTER_TE_KEY);
827 (const gchar *)gtk_entry_get_text(GTK_ENTRY(filter_te));
828 gtk_entry_set_text(GTK_ENTRY(parent_filter_te), filter_string);
834 * Destroy the filter dialog box.
836 window_destroy(main_w);
839 if (parent_filter_te != NULL) {
841 * We have a text entry widget associated with this dialog
842 * box; activate that widget to cause the filter we put
843 * there to be applied if we're supposed to do so.
845 * We do this after dismissing the filter dialog box,
846 * as activating the widget the dialog box to which
847 * it belongs to be dismissed, and that may cause it
848 * to destroy our dialog box if the filter succeeds.
849 * This means that our subsequent attempt to destroy
852 * We don't know whether it'll destroy our dialog box,
853 * so we can't rely on it to do so. Instead, we
854 * destroy it ourselves, which will clear the
855 * E_FILT_DIALOG_PTR_KEY pointer for their dialog box,
856 * meaning they won't think it has one and won't try
859 if (construct_args->activate_on_ok) {
860 SIGNAL_EMIT_BY_NAME(parent_filter_te, "activate", NULL);
867 filter_dlg_save(filter_list_type_t list_type)
872 const char *filter_type;
876 case CFILTER_EDITED_LIST:
877 filter_type = "capture";
878 list_type = CFILTER_LIST;
879 copy_filter_list(CFILTER_LIST, CFILTER_EDITED_LIST);
882 case DFILTER_EDITED_LIST:
883 filter_type = "display";
884 list_type = DFILTER_LIST;
885 copy_filter_list(DFILTER_LIST, DFILTER_EDITED_LIST);
889 g_assert_not_reached();
894 /* Create the directory that holds personal configuration files,
896 if (create_persconffile_dir(&pf_dir_path) == -1) {
897 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
898 "Can't create directory\n\"%s\"\nfor filter files: %s.",
899 pf_dir_path, strerror(errno));
904 save_filter_list(list_type, &f_path, &f_save_errno);
905 if (f_path != NULL) {
906 /* We had an error saving the filter. */
907 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
908 "Could not save to your %s filter file\n\"%s\": %s.",
909 filter_type, f_path, strerror(f_save_errno));
916 filter_dlg_save_cb(GtkWidget *save_bt _U_, gpointer data)
918 filter_list_type_t list_type = *(filter_list_type_t *)data;
920 filter_dlg_save(list_type);
924 /* update a remaining dialog if another one was cancelled */
925 static void filter_dlg_update_list_cb(gpointer data, gpointer user_data)
927 GtkWidget *main_w = data;
928 filter_list_type_t list_type = *(filter_list_type_t *)user_data;
930 /* refill the list */
932 fill_list(main_w, list_type);
936 /* cancel button pressed, revert changes and exit dialog */
938 filter_dlg_cancel_cb(GtkWidget *cancel_bt, gpointer data)
940 filter_list_type_t list_type = *(filter_list_type_t *)data;
941 GtkWidget *main_w = gtk_widget_get_toplevel(cancel_bt);
942 static GList *filter_list;
945 window_destroy(GTK_WIDGET(main_w));
947 /* if this was the last open filter dialog, revert the changes made */
948 filter_list = get_filter_dialog_list(list_type);
949 if(g_list_length(filter_list) == 0) {
950 /* revert changes in the edited list */
952 case CFILTER_EDITED_LIST:
953 copy_filter_list(CFILTER_EDITED_LIST, CFILTER_LIST);
955 case DFILTER_EDITED_LIST:
956 copy_filter_list(DFILTER_EDITED_LIST, DFILTER_LIST);
959 g_assert_not_reached();
965 /* update other open filter dialogs */
966 g_list_foreach(get_filter_dialog_list(list_type), filter_dlg_update_list_cb, &list_type);
970 /* Treat this as a cancel, by calling "filter_dlg_cancel_cb()" */
972 filter_dlg_delete_event_cb(GtkWidget *main_w, GdkEvent *event _U_,
975 filter_dlg_cancel_cb(main_w, data);
981 filter_dlg_destroy_cb(GtkWidget *win, gpointer data)
983 filter_list_type_t list_type = *(filter_list_type_t *)data;
986 /* Get the button that requested that we be popped up, if any.
987 (It should arrange to destroy us if it's destroyed, so
988 that we don't get a pointer to a non-existent window here.) */
989 button = OBJECT_GET_DATA(win, E_FILT_BUTTON_PTR_KEY);
991 if (button != NULL) {
992 /* Tell it we no longer exist. */
993 OBJECT_SET_DATA(button, E_FILT_DIALOG_PTR_KEY, NULL);
995 /* This is an editing dialog popped up from, for example,
996 a menu item; note that we no longer have one. */
1000 case CFILTER_EDITED_LIST:
1001 g_assert(win == global_cfilter_w);
1002 global_cfilter_w = NULL;
1006 g_assert_not_reached();
1011 /* Remove this from the list of filter dialog windows. */
1012 forget_filter_dialog(win, list_type);
1015 #if GTK_MAJOR_VERSION < 2
1017 filter_sel_list_button_cb(GtkWidget *widget, GdkEventButton *event,
1021 filter_sel_list_button_cb(GtkWidget *list, GdkEventButton *event,
1025 #if GTK_MAJOR_VERSION < 2
1026 GtkWidget *list = func_data;
1028 void (* func)(GtkWidget *, gpointer, gpointer);
1030 gpointer func_activate;
1032 #if GTK_MAJOR_VERSION < 2
1033 if (!GTK_IS_LIST_ITEM(widget)) return FALSE;
1035 if (event->type == GDK_2BUTTON_PRESS) {
1036 func = OBJECT_GET_DATA(list, E_FILT_DBLFUNC_KEY);
1037 func_arg = OBJECT_GET_DATA(list, E_FILT_DBLARG_KEY);
1038 func_activate = OBJECT_GET_DATA(list, E_FILT_DBLACTIVATE_KEY);
1041 (*func)(list, func_arg, func_activate);
1047 #if GTK_MAJOR_VERSION < 2
1049 filter_sel_list_cb(GtkWidget *l, gpointer data _U_)
1052 filter_sel_list_cb(GtkTreeSelection *sel, gpointer data _U_)
1055 #if GTK_MAJOR_VERSION < 2
1056 GtkWidget *main_w = gtk_widget_get_toplevel(l);
1060 GtkWidget *filter_l = GTK_WIDGET(gtk_tree_selection_get_tree_view(sel));
1061 GtkWidget *main_w = gtk_widget_get_toplevel(filter_l);
1062 GtkTreeModel *model;
1065 GtkWidget *name_te = OBJECT_GET_DATA(main_w, E_FILT_NAME_TE_KEY);
1066 GtkWidget *filter_te = OBJECT_GET_DATA(main_w, E_FILT_FILTER_TE_KEY);
1067 GtkWidget *chg_bt = OBJECT_GET_DATA(main_w, E_FILT_CHG_BT_KEY);
1068 GtkWidget *copy_bt = OBJECT_GET_DATA(main_w, E_FILT_COPY_BT_KEY);
1069 GtkWidget *del_bt = OBJECT_GET_DATA(main_w, E_FILT_DEL_BT_KEY);
1071 gchar *name = NULL, *strval = NULL;
1073 gint sensitivity = FALSE;
1075 #if GTK_MAJOR_VERSION < 2
1077 sl = GTK_LIST(l)->selection;
1081 if (sl) { /* Something was selected */
1082 l_item = GTK_OBJECT(sl->data);
1083 flp = (GList *) OBJECT_GET_DATA(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
1085 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
1086 gtk_tree_model_get(model, &iter, 1, &flp, -1);
1089 filt = (filter_def *) flp->data;
1090 name = g_strdup(filt->name);
1091 strval = g_strdup(filt->strval);
1097 * Did you know that this function is called when the window is destroyed?
1099 * This means that we have to:
1101 * attach to the top-level window data items containing pointers to
1102 * the widgets we affect here;
1104 * give each of those widgets their own destroy callbacks;
1106 * clear that pointer when the widget is destroyed;
1108 * don't do anything to the widget if the pointer we get back is
1111 * so that if we're called after any of the widgets we'd affect are
1112 * destroyed, we know that we shouldn't do anything to those widgets.
1114 if (name_te != NULL)
1115 gtk_entry_set_text(GTK_ENTRY(name_te), name ? name : "");
1116 if (filter_te != NULL)
1117 gtk_entry_set_text(GTK_ENTRY(filter_te), strval ? strval : "");
1119 gtk_widget_set_sensitive(chg_bt, sensitivity);
1120 if (copy_bt != NULL)
1121 gtk_widget_set_sensitive(copy_bt, sensitivity);
1123 gtk_widget_set_sensitive(del_bt, sensitivity);
1130 /* To do: add input checking to each of these callbacks */
1132 /* Structure containing arguments to be passed to "new_filter_cb()".
1134 "active_filter_l" is the list in the dialog box in which "New" or
1135 "Copy" was clicked; in that dialog box, but not in any other dialog
1136 box, we select the newly created list item.
1138 "nflp" is the GList member in the model (filter list) for the new
1141 GtkWidget *active_filter_l;
1143 } new_filter_cb_args_t;
1146 new_filter_cb(gpointer data, gpointer user_data)
1148 GtkWidget *main_w = data;
1149 #if GTK_MAJOR_VERSION < 2
1150 GtkWidget *filter_l = OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY);
1151 GtkWidget *nl_lb, *nl_item;
1153 GtkTreeView *filter_l;
1154 GtkListStore *store;
1157 new_filter_cb_args_t *args = user_data;
1158 filter_def *nfilt = args->nflp->data;
1160 #if GTK_MAJOR_VERSION < 2
1161 nl_lb = gtk_label_new(nfilt->name);
1162 nl_item = gtk_list_item_new();
1163 gtk_misc_set_alignment(GTK_MISC(nl_lb), 0.0, 0.5);
1164 gtk_container_add(GTK_CONTAINER(nl_item), nl_lb);
1165 gtk_widget_show(nl_lb);
1166 gtk_container_add(GTK_CONTAINER(filter_l), nl_item);
1167 gtk_widget_show(nl_item);
1168 OBJECT_SET_DATA(nl_item, E_FILT_LBL_KEY, nl_lb);
1169 OBJECT_SET_DATA(GTK_OBJECT(nl_item), E_FILT_LIST_ITEM_MODEL_KEY,
1171 if (filter_l == args->active_filter_l) {
1172 /* Select the item. */
1173 gtk_list_select_child(GTK_LIST(filter_l), nl_item);
1176 filter_l = GTK_TREE_VIEW(OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY));
1177 store = GTK_LIST_STORE(gtk_tree_view_get_model(filter_l));
1178 gtk_list_store_append(store, &iter);
1179 gtk_list_store_set(store, &iter, 0, nfilt->name, 1, args->nflp, -1);
1180 if (GTK_WIDGET(filter_l) == args->active_filter_l) {
1181 /* Select the item. */
1182 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(filter_l),
1189 filter_new_bt_clicked_cb(GtkWidget *w, gpointer data)
1191 GtkWidget *main_w = gtk_widget_get_toplevel(w);
1192 GtkWidget *name_te = OBJECT_GET_DATA(main_w, E_FILT_NAME_TE_KEY);
1193 GtkWidget *filter_te = OBJECT_GET_DATA(main_w, E_FILT_FILTER_TE_KEY);
1194 GtkWidget *filter_l = OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY);
1195 filter_list_type_t list_type = *(filter_list_type_t *)data;
1197 const gchar *name, *strval;
1198 new_filter_cb_args_t args;
1200 name = gtk_entry_get_text(GTK_ENTRY(name_te));
1201 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
1203 /* if the user didn't entered a name, set default one */
1204 if (strlen(name) == 0) {
1208 /* if the user didn't entered a string value, set default one */
1209 if (strlen(strval) == 0) {
1213 /* Add a new entry to the filter list. */
1214 fl_entry = add_to_filter_list(list_type, name, strval);
1216 /* Update all the filter list widgets, not just the one in
1217 the dialog box in which we clicked on "Copy". */
1218 args.active_filter_l = filter_l;
1219 args.nflp = fl_entry;
1220 g_list_foreach(get_filter_dialog_list(list_type), new_filter_cb, &args);
1224 #if GTK_MAJOR_VERSION < 2
1226 chg_list_item_cb(GtkWidget *nl_item, gpointer data)
1229 chg_list_item_cb(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
1234 filter_def *filt = flp->data;
1235 #if GTK_MAJOR_VERSION < 2
1237 GTK_LABEL(OBJECT_GET_DATA(nl_item, E_FILT_LBL_KEY));
1239 OBJECT_GET_DATA(nl_item, E_FILT_LIST_ITEM_MODEL_KEY);
1244 #if GTK_MAJOR_VERSION >= 2
1245 gtk_tree_model_get(model, iter, 1, &nl_model, -1);
1247 /* Is this the item corresponding to the filter list item in question? */
1248 if (flp == nl_model) {
1249 /* Yes - change the label to correspond to the new name for the
1251 #if GTK_MAJOR_VERSION < 2
1252 gtk_label_set(nl_lb, filt->name);
1254 gtk_list_store_set(GTK_LIST_STORE(model), iter, 0, filt->name, -1);
1258 #if GTK_MAJOR_VERSION >= 2
1264 chg_filter_cb(gpointer data, gpointer user_data)
1266 GtkWidget *main_w = data;
1267 GtkWidget *filter_l = OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY);
1269 #if GTK_MAJOR_VERSION < 2
1270 gtk_container_foreach(GTK_CONTAINER(filter_l), chg_list_item_cb, user_data);
1272 gtk_tree_model_foreach(gtk_tree_view_get_model(GTK_TREE_VIEW(filter_l)),
1273 chg_list_item_cb, user_data);
1278 filter_name_te_changed_cb(GtkWidget *w, gpointer data)
1280 GtkWidget *main_w = gtk_widget_get_toplevel(w);
1281 GtkWidget *name_te = OBJECT_GET_DATA(main_w, E_FILT_NAME_TE_KEY);
1282 GtkWidget *filter_te = OBJECT_GET_DATA(main_w, E_FILT_FILTER_TE_KEY);
1283 GtkWidget *filter_l = OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY);
1286 filter_list_type_t list_type = *(filter_list_type_t *)data;
1287 const gchar *name = "";
1288 const gchar *strval = "";
1290 #if GTK_MAJOR_VERSION < 2
1295 GtkTreeSelection *sel;
1296 GtkTreeModel *model;
1300 #if GTK_MAJOR_VERSION < 2
1301 sl = GTK_LIST(filter_l)->selection;
1303 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_l));
1305 name = gtk_entry_get_text(GTK_ENTRY(name_te));
1306 strval = gtk_entry_get_text(GTK_ENTRY(filter_te));
1308 if (DFILTER_EDITED_LIST == list_type) {
1309 /* colorize filter string entry */
1310 filter_te_syntax_check_cb(filter_te);
1313 /* if something was selected */
1314 #if GTK_MAJOR_VERSION < 2
1316 l_item = GTK_OBJECT(sl->data);
1317 fl_entry = (GList *) OBJECT_GET_DATA(l_item,
1318 E_FILT_LIST_ITEM_MODEL_KEY);
1319 nl_lb = (GtkLabel *) OBJECT_GET_DATA(l_item, E_FILT_LBL_KEY);
1320 if (fl_entry != NULL && nl_lb != NULL) {
1322 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
1323 gtk_tree_model_get(model, &iter, 1, &fl_entry, -1);
1324 if (fl_entry != NULL) {
1326 filt = (filter_def *) fl_entry->data;
1328 if (strlen(name) > 0 && strlen(strval) > 0 && filt) {
1330 g_free(filt->strval);
1331 filt->name = g_strdup(name);
1332 filt->strval = g_strdup(strval);
1334 /* Update all the filter list widgets, not just the one in
1335 the dialog box in which we clicked on "Copy". */
1336 g_list_foreach(get_filter_dialog_list(list_type), chg_filter_cb,
1344 delete_filter_cb(gpointer data, gpointer user_data)
1346 GtkWidget *main_w = data;
1347 GtkWidget *filter_l = OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY);
1348 #if GTK_MAJOR_VERSION < 2
1349 gint pos = *(gint *)user_data;
1351 gchar *pos = (gchar *)user_data;
1352 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(filter_l));
1356 #if GTK_MAJOR_VERSION < 2
1357 gtk_list_clear_items(GTK_LIST(filter_l), pos, pos + 1);
1359 gtk_tree_model_get_iter_from_string(model, &iter, pos);
1360 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
1365 filter_del_bt_clicked_cb(GtkWidget *w, gpointer data)
1367 GtkWidget *main_w = gtk_widget_get_toplevel(w);
1368 GtkWidget *filter_l = OBJECT_GET_DATA(main_w, E_FILT_FILTER_L_KEY);
1369 filter_list_type_t list_type = *(filter_list_type_t *)data;
1371 #if GTK_MAJOR_VERSION < 2
1377 GtkTreeSelection *sel;
1378 GtkTreeModel *model;
1383 #if GTK_MAJOR_VERSION < 2
1384 sl = GTK_LIST(filter_l)->selection;
1385 if (sl) { /* Something was selected */
1386 l_item = GTK_OBJECT(sl->data);
1387 pos = gtk_list_child_position(GTK_LIST(filter_l),
1388 GTK_WIDGET(l_item));
1389 fl_entry = (GList *) OBJECT_GET_DATA(l_item, E_FILT_LIST_ITEM_MODEL_KEY);
1391 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_l));
1392 /* If something was selected */
1393 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
1394 gtk_tree_model_get(model, &iter, 1, &fl_entry, -1);
1395 path = gtk_tree_model_get_path(model, &iter);
1396 pos = gtk_tree_path_to_string(path);
1397 gtk_tree_path_free(path);
1399 if (fl_entry != NULL) {
1400 /* Remove the entry from the filter list. */
1401 remove_from_filter_list(list_type, fl_entry);
1403 /* Update all the filter list widgets, not just the one in
1404 the dialog box in which we clicked on "Delete". */
1405 #if GTK_MAJOR_VERSION < 2
1406 g_list_foreach(get_filter_dialog_list(list_type), delete_filter_cb,
1409 g_list_foreach(get_filter_dialog_list(list_type), delete_filter_cb, pos);
1412 #if GTK_MAJOR_VERSION >= 2
1419 filter_add_expr_bt_cb(GtkWidget *w _U_, gpointer main_w_arg)
1421 GtkWidget *main_w = GTK_WIDGET(main_w_arg);
1422 GtkWidget *filter_te;
1424 filter_te = OBJECT_GET_DATA(main_w, E_FILT_FILTER_TE_KEY);
1425 dfilter_expr_dlg_new(filter_te);
1429 color_filter_te(GtkWidget *w, guint16 red, guint16 green, guint16 blue)
1439 style = gtk_style_copy(gtk_widget_get_style(w));
1440 style->base[GTK_STATE_NORMAL] = bg;
1441 gtk_widget_set_style(w, style);
1442 gtk_style_unref(style);
1446 colorize_filter_te_as_empty(GtkWidget *w)
1449 color_filter_te(w, 0xFFFF, 0xFFFF, 0xFFFF);
1453 colorize_filter_te_as_invalid(GtkWidget *w)
1456 color_filter_te(w, 0xFFFF, 0xAFFF, 0xAFFF);
1460 colorize_filter_te_as_valid(GtkWidget *w)
1463 color_filter_te(w, 0xAFFF, 0xFFFF, 0xAFFF);
1467 filter_te_syntax_check_cb(GtkWidget *w)
1469 const gchar *strval;
1472 strval = gtk_entry_get_text(GTK_ENTRY(w));
1474 /* colorize filter string entry */
1475 if (strval && dfilter_compile(strval, &dfp)) {
1478 if (strlen(strval) == 0)
1479 colorize_filter_te_as_empty(w);
1481 colorize_filter_te_as_valid(w);
1483 colorize_filter_te_as_invalid(w);