From 2e1952678f0ed2a82e6cb76d82b7d4ef9d397223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irene=20R=C3=BCngeler?= Date: Fri, 3 Aug 2012 11:15:40 +0000 Subject: [PATCH] Make the columns of the capture options dialog selectable. Changes are stored in the preferences file. The ordering can be changed by dragging the column. The order is not stored. svn path=/trunk/; revision=44239 --- epan/libwireshark.def | 1 + epan/prefs.c | 90 +++++++++++ epan/prefs.h | 3 + ui/gtk/capture_dlg.c | 339 +++++++++++++++++++++++++++++++++++++++++ ui/gtk/capture_dlg.h | 6 + ui/gtk/keys.h | 17 ++- ui/gtk/prefs_capture.c | 303 +++++++++++++++++++++++++++++++++++- ui/gtk/prefs_dlg.c | 13 +- ui/gtk/prefs_dlg.h | 3 +- 9 files changed, 761 insertions(+), 14 deletions(-) diff --git a/epan/libwireshark.def b/epan/libwireshark.def index 1b12e8c91e..37ee8c8f5a 100644 --- a/epan/libwireshark.def +++ b/epan/libwireshark.def @@ -722,6 +722,7 @@ prefs DATA prefs_apply prefs_apply_all prefs_capture_device_monitor_mode +prefs_capture_options_dialog_column_is_visible prefs_clear_string_list prefs_is_capture_device_hidden prefs_find_module diff --git a/epan/prefs.c b/epan/prefs.c index 33fa427150..e725a9f5ea 100644 --- a/epan/prefs.c +++ b/epan/prefs.c @@ -1382,11 +1382,40 @@ init_prefs(void) { int i; fmt_data *cfmt; + gchar *col_name; static const gchar *col_fmt[DEF_NUM_COLS*2] = { "No.", "%m", "Time", "%t", "Source", "%s", "Destination", "%d", "Protocol", "%p", "Length", "%L", "Info", "%i"}; +#if defined(HAVE_PCAP_CREATE) + static gint num_capture_cols = 7; + static const gchar *capture_cols[7] = { + "INTERFACE", + "LINK", + "PMODE", + "SNAPLEN", + "MONITOR", + "BUFFER", + "FILTER"}; +#elif defined(_WIN32) && !defined (HAVE_PCAP_CREATE) + static gint num_capture_cols = 6; + static const gchar *capture_cols[6] = { + "INTERFACE", + "LINK", + "PMODE", + "SNAPLEN", + "BUFFER", + "FILTER"}; +#else + static gint num_capture_cols = 5; + static const gchar *capture_cols[5] = { + "INTERFACE", + "LINK", + "PMODE", + "SNAPLEN", + "FILTER"}; +#endif if (prefs_initialized) return; @@ -1547,6 +1576,12 @@ init_prefs(void) prefs.capture_real_time = TRUE; prefs.capture_auto_scroll = TRUE; prefs.capture_show_info = FALSE; + prefs.capture_columns = NULL; + for (i = 0; i < num_capture_cols; i++) { + col_name = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN); + col_name = g_strdup(capture_cols[i]); + prefs.capture_columns = g_list_append(prefs.capture_columns, col_name); + } /* set the default values for the tap/statistics dialog box */ prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL; @@ -1659,6 +1694,7 @@ prefs_reset(void) g_free(prefs.capture_devices_descr); g_free(prefs.capture_devices_hide); g_free(prefs.capture_devices_monitor_mode); + g_list_free(prefs.capture_columns); /* * Unload all UAT preferences. @@ -2162,6 +2198,25 @@ prefs_capture_device_monitor_mode(const char *name) return FALSE; } +/* + * Returns TRUE if the user has marked this column as visible + */ +gboolean +prefs_capture_options_dialog_column_is_visible(const gchar *column) +{ + GList *curr; + gchar *col; + + for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)) { + col = (gchar *)curr->data; + if (col && (g_ascii_strcasecmp(col, column) == 0)) { + return TRUE; + } + } + return FALSE; +} + + #define PRS_COL_HIDDEN "column.hidden" #define PRS_COL_FMT "column.format" #define PRS_STREAM_CL_FG "stream.client.fg" @@ -2240,6 +2295,7 @@ prefs_capture_device_monitor_mode(const char *name) #define PRS_CAP_REAL_TIME "capture.real_time_update" #define PRS_CAP_AUTO_SCROLL "capture.auto_scroll" #define PRS_CAP_SHOW_INFO "capture.show_info" +#define PRS_CAP_COLUMNS "capture.columns" /* obsolete preference */ #define PRS_CAP_SYNTAX_CHECK_FILTER "capture.syntax_check_filter" @@ -2699,6 +2755,24 @@ set_pref(gchar *pref_name, gchar *value, void *private_data _U_, prefs.capture_auto_scroll = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE); } else if (strcmp(pref_name, PRS_CAP_SHOW_INFO) == 0) { prefs.capture_show_info = ((g_ascii_strcasecmp(value, "true") == 0)?TRUE:FALSE); + } else if (strcmp(pref_name, PRS_CAP_COLUMNS) == 0) { + gchar *col_name; + + col_l = prefs_get_string_list(value); + if (col_l == NULL) + return PREFS_SET_SYNTAX_ERR; + /* They're all valid; process them. */ + g_list_free(prefs.capture_columns); + prefs.capture_columns = NULL; + col_l_elt = g_list_first(col_l); + col_name = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN); + col_name = (gchar *)col_l_elt->data; + while(col_l_elt) { + prefs.capture_columns = g_list_append(prefs.capture_columns, col_name); + col_l_elt = col_l_elt->next; + col_name = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN); + col_name = (gchar *)col_l_elt->data; + } } else if (strcmp(pref_name, PRS_CAP_SYNTAX_CHECK_FILTER) == 0) { /* Obsolete preference. */ ; @@ -3263,6 +3337,7 @@ write_prefs(char **pf_path_return) GList *clp, *col_l; fmt_data *cfmt; GString *cols_hidden = g_string_new (""); + gchar *col; /* Needed for "-G defaultprefs" */ init_prefs(); @@ -3739,6 +3814,21 @@ write_prefs(char **pf_path_return) fprintf(pf, "#"); fprintf(pf, PRS_CAP_SHOW_INFO ": %s\n", prefs.capture_show_info == TRUE ? "TRUE" : "FALSE"); + clp = prefs.capture_columns; + col_l = NULL; + while (clp) { + col = (gchar *) clp->data; + col_l = g_list_append(col_l, g_strdup(col)); + clp = clp->next; + } + + fprintf(pf, "\n# Capture options dialog column list.\n"); + fprintf(pf, "# List of columns to be displayed.\n"); + fprintf(pf, "# Possible values: INTERFACE,LINK,PMODE,SNAPLEN,MONITOR,BUFFER,FILTER\n"); + fprintf (pf, "%s: %s\n", PRS_CAP_COLUMNS, put_string_list(col_l)); + /* This frees the list of strings, but not the strings to which it + refers; they are free'ed in put_string_list(). */ + g_list_free(col_l); /* * XXX - The following members are intentionally not written here because diff --git a/epan/prefs.h b/epan/prefs.h index 0520b830e9..e814248636 100644 --- a/epan/prefs.h +++ b/epan/prefs.h @@ -174,6 +174,7 @@ typedef struct _e_prefs { gboolean capture_real_time; gboolean capture_auto_scroll; gboolean capture_show_info; + GList *capture_columns; guint rtp_player_max_visible; guint tap_update_interval; gboolean display_hidden_proto_items; @@ -496,6 +497,8 @@ extern gboolean prefs_is_capture_device_hidden(const char *name); */ extern gboolean prefs_capture_device_monitor_mode(const char *name); +extern gboolean prefs_capture_options_dialog_column_is_visible(const gchar *column); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/ui/gtk/capture_dlg.c b/ui/gtk/capture_dlg.c index e21290e70d..633fc18d93 100644 --- a/ui/gtk/capture_dlg.c +++ b/ui/gtk/capture_dlg.c @@ -66,6 +66,8 @@ #include "ui/gtk/capture_if_dlg.h" #include "ui/gtk/main_welcome.h" #include "ui/gtk/network_icons.h" +#include "ui/gtk/menus.h" +#include "ui/gtk/prefs_dlg.h" #include "ui/gtk/main_80211_toolbar.h" #include "ui/gtk/keys.h" @@ -207,6 +209,9 @@ static GtkWidget *cap_open_w = NULL, *opt_edit_w = NULL, *ok_bt, *new_interfaces static gboolean cap_open_complete; /* valid only if cap_open_w != NULL */ static const gchar *pipe_name; static const gchar *selected_name; +static GtkWidget *columns_menu_object; +static GtkUIManager *ui_manager_columns = NULL; +static GSList *popup_menu_list = NULL; static gint marked_interface; static gint marked_row; @@ -254,6 +259,9 @@ capture_dlg_prep(gpointer parent_w); static GtkTreeModel* create_and_fill_model(GtkTreeView *view); +void +update_visible_columns_menu (void); + static gboolean query_tooltip_tree_view_cb (GtkWidget *widget, gint x, @@ -262,12 +270,242 @@ query_tooltip_tree_view_cb (GtkWidget *widget, GtkTooltip *tooltip, gpointer data); +static +gchar *col_index_to_name(gint index) +{ + gchar *col_name; + + switch (index) + { + case INTERFACE: col_name = g_strdup("INTERFACE"); + break; + case LINK: col_name = g_strdup("LINK"); + break; + case PMODE: col_name = g_strdup("PMODE"); + break; + case SNAPLEN: col_name = g_strdup("SNAPLEN"); + break; +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + case BUFFER: col_name = g_strdup("BUFFER"); + break; +#endif +#if defined (HAVE_PCAP_CREATE) + case MONITOR: col_name = g_strdup("MONITOR"); + break; +#endif + case FILTER: col_name = g_strdup("FILTER"); + break; + default: return NULL; + } + return col_name; +} + +static void +set_capture_column_visible(gchar *col, gboolean visible _U_) +{ + GList *curr; + gchar *col_name; + + if (visible && !prefs_capture_options_dialog_column_is_visible(col)) { + prefs.capture_columns = g_list_append(prefs.capture_columns, col); + } else if (!visible && prefs_capture_options_dialog_column_is_visible(col)) { + for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)) { + col_name = (gchar *)curr->data; + if (col_name && (g_ascii_strcasecmp(col_name, col) == 0)) { + prefs.capture_columns = g_list_remove(prefs.capture_columns, curr->data); + break; + } + } + } +} + +static void +toggle_visible_column_cb (GtkWidget *w _U_, gpointer data) +{ + GtkTreeView *view; + GtkTreeViewColumn *col; + gchar *col_name; + gint col_id; + + col_id = GPOINTER_TO_INT(data); + view = (GtkTreeView *)g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_id); + col_name = col_index_to_name(col_id); + gtk_tree_view_column_set_visible(col, prefs_capture_options_dialog_column_is_visible(col_name)?FALSE:TRUE); + set_capture_column_visible(col_name, prefs_capture_options_dialog_column_is_visible(col_name)?FALSE:TRUE); +} + + +static void +set_all_columns_visible (void) +{ + GtkTreeViewColumn *col; + int col_id; + GtkTreeView *view; + gchar *name; + + view = (GtkTreeView *)g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); + for (col_id = 2; col_id < NUM_COLUMNS; col_id++) { + col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_id); + gtk_tree_view_column_set_visible(col, TRUE); + if ((name = col_index_to_name(col_id)) != NULL) { + set_capture_column_visible(name, TRUE); + } + } + + if (!prefs.gui_use_pref_save) { + prefs_main_write(); + } + + update_visible_columns_menu (); +} + +static void +columns_activate_all_columns_cb(GtkAction *action _U_, gpointer user_data _U_) +{ + set_all_columns_visible (); +} + +void +update_visible_tree_view_columns(void) +{ + GtkTreeView *view; + gint col_id; + GtkTreeViewColumn *col; + + view = (GtkTreeView *)g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); + for (col_id = 2; col_id < NUM_COLUMNS; col_id++) { + col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_id); + gtk_tree_view_column_set_visible(col, prefs_capture_options_dialog_column_is_visible(col_index_to_name(col_id))?TRUE:FALSE); + } +} + + +void +update_visible_columns_menu (void) +{ + GtkWidget *menu_columns, *menu_item; + GtkTreeViewColumn *col; + GtkWidget *sub_menu; + gchar *title; + GtkTreeView *view; + gint col_id; + + menu_columns = gtk_ui_manager_get_widget(ui_manager_columns, "/ColumnsPopup/DisplayedColumns"); + /* Debug */ + if(! menu_columns){ + fprintf (stderr, "Warning: couldn't find menu_columns path=/ColumnsPopup/DisplayedColumns"); + } + + sub_menu = gtk_menu_new(); + gtk_menu_item_set_submenu (GTK_MENU_ITEM(menu_columns), sub_menu); + + view = (GtkTreeView *)g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); + for (col_id = 2; col_id < NUM_COLUMNS; col_id++) { + col = gtk_tree_view_get_column(GTK_TREE_VIEW(view), col_id); + title = col_index_to_name(col_id); + menu_item = gtk_check_menu_item_new_with_label(title); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_item), prefs_capture_options_dialog_column_is_visible(title)); + g_signal_connect(G_OBJECT(menu_item), "activate", G_CALLBACK(toggle_visible_column_cb), GINT_TO_POINTER(col_id)); + gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item); + gtk_widget_show (menu_item); + } + menu_item = gtk_menu_item_new(); + gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item); + gtk_widget_show (menu_item); + + menu_item = gtk_menu_item_new_with_label ("Display All"); + gtk_menu_shell_append (GTK_MENU_SHELL(sub_menu), menu_item); + g_signal_connect(menu_item, "activate", G_CALLBACK(columns_activate_all_columns_cb), NULL); + gtk_widget_show (menu_item); +} + +static void +columns_pref_cb(GtkAction *action _U_, gpointer user_data) +{ + GtkWidget *widget = gtk_ui_manager_get_widget(ui_manager_columns, "/ColumnsPopup/ColumnPreferences"); + prefs_page_cb( widget , user_data, PREFS_PAGE_CAPTURE); +} + +static void +columns_hide_col_cb(GtkAction *action _U_, gpointer user_data _U_) +{ + GtkTreeView *view; + GtkTreeViewColumn *col; + gint num; + gchar *name; + + view = (GtkTreeView *)g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); + col = (GtkTreeViewColumn *)g_object_get_data(G_OBJECT(view), E_MCAPTURE_COLUMNS_COLUMN_KEY); + gtk_tree_view_column_set_visible(col, FALSE); + num = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(col), E_MCAPTURE_COLUMNS_COL_KEY)); + if ((name = col_index_to_name(num)) != NULL) { + set_capture_column_visible(name, FALSE); + if (!prefs.gui_use_pref_save) { + prefs_main_write(); + } + update_visible_columns_menu (); + } +} + +static const char *ui_desc_columns_menu_popup = +"\n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" +"\n"; + +static const GtkActionEntry columns_menu_popup_action_entries[] = { + { "/Column Preferences", GTK_STOCK_PREFERENCES, "Column Preferences...", NULL, NULL, G_CALLBACK(columns_pref_cb) }, + { "/Displayed Columns", NULL, "Displayed Columns", NULL, NULL, NULL }, + { "/Displayed Columns/Display All", NULL, "Display All", NULL, NULL, G_CALLBACK(columns_activate_all_columns_cb) }, + { "/Hide Column", NULL, "Hide Column", NULL, NULL, G_CALLBACK(columns_hide_col_cb) }, +}; + #ifdef HAVE_PCAP_CREATE static void activate_monitor(GtkTreeViewColumn *tree_column, GtkCellRenderer *renderer, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data); #endif +void +init_columns_menu(void) +{ + GtkActionGroup *columns_action_group; + GError *error = NULL; + + columns_menu_object = gtk_menu_new(); + /* columns pop-up menu */ + columns_action_group = gtk_action_group_new ("ColumnsPopUpMenuActionGroup"); + + gtk_action_group_add_actions (columns_action_group, /* the action group */ + (gpointer)columns_menu_popup_action_entries, /* an array of action descriptions */ + G_N_ELEMENTS(columns_menu_popup_action_entries), /* the number of entries */ + columns_menu_object); /* data to pass to the action callbacks */ + + ui_manager_columns = gtk_ui_manager_new (); + gtk_ui_manager_insert_action_group (ui_manager_columns, + columns_action_group, + 0); /* the position at which the group will be inserted. */ + + gtk_ui_manager_add_ui_from_string (ui_manager_columns, ui_desc_columns_menu_popup, -1, &error); + if (error != NULL) + { + fprintf (stderr, "Warning: building Packet List Heading Pop-Up failed: %s\n", error->message); + g_error_free (error); + error = NULL; + } + + g_object_set_data(G_OBJECT(columns_menu_object), PM_COLUMNS_KEY, + gtk_ui_manager_get_widget(ui_manager_columns, "/ColumnsPopup")); + + popup_menu_list = g_slist_append((GSList *)popup_menu_list, ui_manager_columns); +} + /* stop the currently running capture */ void capture_stop_cb(GtkWidget *w _U_, gpointer d _U_) @@ -3561,6 +3799,41 @@ show_add_interfaces_dialog(void) ? Other ?? */ +static gboolean +columns_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + GtkWidget *menu = (GtkWidget *)data; + GdkEventButton *event_button = NULL; + + /* context menu handler */ + if(event->type == GDK_BUTTON_PRESS) { + event_button = (GdkEventButton *) event; + + /* To quote the "Gdk Event Structures" doc: + * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */ + if(event_button->button == 3) { + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, widget, + event_button->button, + event_button->time); + g_signal_stop_emission_by_name(widget, "button_press_event"); + return TRUE; + } + } + return FALSE; +} + +static gboolean +column_button_pressed_cb (GtkWidget *widget, GdkEvent *event, gpointer data) +{ + GtkWidget *col = (GtkWidget *) data; + GtkTreeView *view; + GtkWidget *menu = g_object_get_data(G_OBJECT(columns_menu_object), PM_COLUMNS_KEY); + view = (GtkTreeView *)g_object_get_data(G_OBJECT(cap_open_w), E_CAP_IFACE_KEY); + g_object_set_data(G_OBJECT(view), E_MCAPTURE_COLUMNS_COLUMN_KEY, col); + return columns_menu_handler (widget, event, menu); +} + + void capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) { @@ -3615,6 +3888,7 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) reactivate_window(cap_open_w); return; } + init_columns_menu(); /* use user-defined title if preference is set */ @@ -3689,29 +3963,74 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) gtk_tree_view_column_set_min_width(column, 200); gtk_tree_view_column_set_resizable(column, TRUE ); gtk_tree_view_column_set_alignment(column, 0.5); + g_object_set_data(G_OBJECT(column), E_MCAPTURE_COLUMNS_COL_KEY, GINT_TO_POINTER(INTERFACE)); + gtk_tree_view_column_set_clickable(column, TRUE); + gtk_tree_view_column_set_reorderable(column, TRUE); + g_signal_connect(gtk_tree_view_column_get_button(column), "button_press_event", + G_CALLBACK(column_button_pressed_cb), column); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("INTERFACE")) + gtk_tree_view_column_set_visible(column, TRUE); + else + gtk_tree_view_column_set_visible(column, FALSE); g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes ("Link-layer header", renderer, "text", LINK, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); + gtk_tree_view_column_set_clickable(column, TRUE); + gtk_tree_view_column_set_reorderable(column, TRUE); gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW (view),LINK), TRUE ); + g_object_set_data(G_OBJECT(column), E_MCAPTURE_COLUMNS_COL_KEY, GINT_TO_POINTER(LINK)); + g_signal_connect(gtk_tree_view_column_get_button(column), "button_press_event", + G_CALLBACK(column_button_pressed_cb), column); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("LINK")) + gtk_tree_view_column_set_visible(column, TRUE); + else + gtk_tree_view_column_set_visible(column, FALSE); gtk_tree_view_column_set_alignment(column, 0.5); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Prom. Mode", renderer, "text", PMODE, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); g_object_set(renderer, "xalign", 0.5, NULL); + gtk_tree_view_column_set_clickable(column, TRUE); + gtk_tree_view_column_set_reorderable(column, TRUE); + g_object_set_data(G_OBJECT(column), E_MCAPTURE_COLUMNS_COL_KEY, GINT_TO_POINTER(PMODE)); + g_signal_connect(gtk_tree_view_column_get_button(column), "button_press_event", + G_CALLBACK(column_button_pressed_cb), column); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("PMODE")) + gtk_tree_view_column_set_visible(column, TRUE); + else + gtk_tree_view_column_set_visible(column, FALSE); gtk_tree_view_column_set_alignment(column, 0.5); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Snaplen [B]", renderer, "text", SNAPLEN, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); + gtk_tree_view_column_set_clickable(column, TRUE); + gtk_tree_view_column_set_reorderable(column, TRUE); + g_object_set_data(G_OBJECT(column), E_MCAPTURE_COLUMNS_COL_KEY, GINT_TO_POINTER(SNAPLEN)); + g_signal_connect(gtk_tree_view_column_get_button(column), "button_press_event", + G_CALLBACK(column_button_pressed_cb), column); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("SNAPLEN")) + gtk_tree_view_column_set_visible(column, TRUE); + else + gtk_tree_view_column_set_visible(column, FALSE); g_object_set(renderer, "xalign", 0.5, NULL); #if defined(_WIN32) || defined(HAVE_PCAP_CREATE) renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Buffer [MB]", renderer, "text", BUFFER, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); + gtk_tree_view_column_set_reorderable(column, TRUE); + g_object_set_data(G_OBJECT(column), E_MCAPTURE_COLUMNS_COL_KEY, GINT_TO_POINTER(BUFFER)); + gtk_tree_view_column_set_clickable(column, TRUE); + g_signal_connect(gtk_tree_view_column_get_button(column), "button_press_event", + G_CALLBACK(column_button_pressed_cb), column); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("BUFFER")) + gtk_tree_view_column_set_visible(column, TRUE); + else + gtk_tree_view_column_set_visible(column, FALSE); g_object_set(renderer, "xalign", 0.5, NULL); #endif @@ -3720,6 +4039,15 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) column = gtk_tree_view_column_new_with_attributes ("Mon. Mode", renderer, "text", MONITOR, NULL); gtk_tree_view_column_set_cell_data_func(column, renderer, activate_monitor, NULL, FALSE); gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); + gtk_tree_view_column_set_reorderable(column, TRUE); + g_object_set_data(G_OBJECT(column), E_MCAPTURE_COLUMNS_COL_KEY, GINT_TO_POINTER(MONITOR)); + gtk_tree_view_column_set_clickable(column, TRUE); + g_signal_connect(gtk_tree_view_column_get_button(column), "button_press_event", + G_CALLBACK(column_button_pressed_cb), column); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("MONITOR")) + gtk_tree_view_column_set_visible(column, TRUE); + else + gtk_tree_view_column_set_visible(column, FALSE); g_object_set(renderer, "xalign", 0.5, NULL); #endif @@ -3730,6 +4058,15 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) create_and_fill_model(GTK_TREE_VIEW(view)); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); + gtk_tree_view_column_set_clickable(column, TRUE); + gtk_tree_view_column_set_reorderable(column, TRUE); + g_object_set_data(G_OBJECT(column), E_MCAPTURE_COLUMNS_COL_KEY, GINT_TO_POINTER(FILTER)); + g_signal_connect(gtk_tree_view_column_get_button(column), "button_press_event", + G_CALLBACK(column_button_pressed_cb), column); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("FILTER")) + gtk_tree_view_column_set_visible(column, TRUE); + else + gtk_tree_view_column_set_visible(column, FALSE); gtk_container_add (GTK_CONTAINER (swindow), view); gtk_box_pack_start(GTK_BOX(capture_vb), swindow, TRUE, TRUE, 0); @@ -4163,6 +4500,8 @@ capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) widgets. */ capture_prep_adjust_sensitivity(NULL, cap_open_w); + update_visible_columns_menu (); + /* Catch the "activate" signal on the text entries, so that if the user types Return there, we act as if the "OK" button had been selected, as happens if Return is typed if some diff --git a/ui/gtk/capture_dlg.h b/ui/gtk/capture_dlg.h index 9efd48d5fe..91219821c7 100644 --- a/ui/gtk/capture_dlg.h +++ b/ui/gtk/capture_dlg.h @@ -114,6 +114,12 @@ options_interface_cb(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *co void capture_dlg_refresh_if(void); +void +update_visible_columns_menu (void); + +void +update_visible_tree_view_columns(void); + /* * Refresh everything visible that shows an interface list that * includes local interfaces. diff --git a/ui/gtk/keys.h b/ui/gtk/keys.h index 99647fbb86..56cd1251aa 100644 --- a/ui/gtk/keys.h +++ b/ui/gtk/keys.h @@ -30,13 +30,15 @@ */ #define E_DFILTER_CM_KEY "display_filter_combo" -#define E_DFILTER_TE_KEY "display_filter_entry" -#define E_RFILTER_TE_KEY "read_filter_te" -#define E_MPACKET_LIST_KEY "menu_packet_list" -#define E_MPACKET_LIST_ROW_KEY "menu_packet_list_row" -#define E_MPACKET_LIST_COL_KEY "menu_packet_list_col" -#define E_MPACKET_LIST_COLUMN_KEY "menu_packet_list_column" -#define E_MPACKET_LIST_PREV_COLUMN_KEY "menu_packet_list_prev_column" +#define E_DFILTER_TE_KEY "display_filter_entry" +#define E_RFILTER_TE_KEY "read_filter_te" +#define E_MPACKET_LIST_KEY "menu_packet_list" +#define E_MPACKET_LIST_ROW_KEY "menu_packet_list_row" +#define E_MPACKET_LIST_COL_KEY "menu_packet_list_col" +#define E_MPACKET_LIST_COLUMN_KEY "menu_packet_list_column" +#define E_MPACKET_LIST_PREV_COLUMN_KEY "menu_packet_list_prev_column" +#define E_MCAPTURE_COLUMNS_COL_KEY "menu_capture_columns_col" +#define E_MCAPTURE_COLUMNS_COLUMN_KEY "menu_capture_columns_column" #define PRINT_CMD_LB_KEY "printer_command_label" #define PRINT_CMD_TE_KEY "printer_command_entry" @@ -51,6 +53,7 @@ #define PM_TREE_VIEW_KEY "popup_menu_tree_view" #define PM_BYTES_VIEW_KEY "popup_menu_bytes_view" #define PM_STATUSBAR_PROFILES_KEY "popup_menu_statusbar_profiles" +#define PM_COLUMNS_KEY "popup_menu_capture_options" #define E_TB_MAIN_KEY "toolbar_main" #define E_TB_FILTER_KEY "toolbar_filter" diff --git a/ui/gtk/prefs_capture.c b/ui/gtk/prefs_capture.c index 096725cef8..396609eafa 100644 --- a/ui/gtk/prefs_capture.c +++ b/ui/gtk/prefs_capture.c @@ -65,6 +65,8 @@ #define IFOPTS_LIST_TEXT_COLS 4 #define IFOPTS_MAX_DESCR_LEN 128 #define IFOPTS_IF_NOSEL -1 +#define COLOPTS_CALLER_PTR_KEY "colopts_caller_ptr" +#define COLOPTS_DIALOG_PTR_KEY "colopts_dialog_ptr" /* interface options dialog */ static GtkWidget *cur_list, *if_dev_lb, *if_name_lb, *if_linktype_lb, *if_linktype_cb, *if_descr_te, *if_hide_cb, *if_default_if_lb; @@ -96,12 +98,25 @@ static void ifopts_write_new_linklayer(void); static void ifopts_write_new_descr(void); static void ifopts_write_new_hide(void); +/* Columns options dialog */ +#ifdef HAVE_PCAP_CREATE +static GtkWidget *col_monitor_cb; +#endif +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) +static GtkWidget *col_buf_cb; +#endif +static GtkWidget *col_interface_cb, *col_snap_cb; +static GtkWidget *col_link_cb, *col_filter_cb, *col_pmode_cb; +static void colopts_edit_destroy_cb(GtkWidget *win, gpointer data); +static void colopts_edit_cb(GtkWidget *w, gpointer data); +static void colopts_edit_ok_cb(GtkWidget *w, gpointer parent_w); + GtkWidget* capture_prefs_show(void) { GtkWidget *main_tb, *main_vb; GtkWidget *if_cbxe, *if_lb, *promisc_cb, *pcap_ng_cb, *sync_cb, *auto_scroll_cb, *show_info_cb; - GtkWidget *ifopts_lb, *ifopts_bt; + GtkWidget *ifopts_lb, *ifopts_bt, *colopts_lb, *colopts_bt; GList *if_list, *combo_list; int err; int row = 0; @@ -206,6 +221,20 @@ capture_prefs_show(void) !prefs.capture_show_info); g_object_set_data(G_OBJECT(main_vb), SHOW_INFO_KEY, show_info_cb); + /* Column properties */ + colopts_lb = gtk_label_new("Columns:"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), colopts_lb, 0, 1, row, row+1); + gtk_misc_set_alignment(GTK_MISC(colopts_lb), 1.0f, 0.5f); + gtk_widget_show(colopts_lb); + + colopts_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_EDIT); + tooltips_text = "Open a dialog box to change the visible columns."; + gtk_widget_set_tooltip_text(colopts_lb, tooltips_text); + gtk_widget_set_tooltip_text(colopts_bt, tooltips_text); + g_signal_connect(colopts_bt, "clicked", G_CALLBACK(colopts_edit_cb), NULL); + gtk_table_attach_defaults(GTK_TABLE(main_tb), colopts_bt, 1, 2, row, row+1); + row++; + /* Show 'em what we got */ gtk_widget_show_all(main_vb); @@ -271,6 +300,15 @@ capture_prefs_destroy(GtkWidget *w) /* Yes. Destroy it. */ window_destroy(dlg); } + + /* Is there an column descriptions dialog associated with this + Preferences dialog? */ + dlg = g_object_get_data(G_OBJECT(caller), COLOPTS_DIALOG_PTR_KEY); + + if (dlg != NULL) { + /* Yes. Destroy it. */ + window_destroy(dlg); + } } /* @@ -290,6 +328,209 @@ enum N_COLUMN /* The number of columns */ }; + +static void +colopts_edit_cb(GtkWidget *w, gpointer data _U_) +{ + GtkWidget *colopts_edit_dlg, *main_hb, *main_tb, + *ed_opts_fr, *main_vb, + *bbox, *ok_bt, *cancel_bt, *help_bt, *column_lb, + *col_interface_lb, *col_link_lb, *col_monitor_lb, + *col_buf_lb, *col_filter_lb, *col_pmode_lb, + *col_snap_lb; + + int row = 0; + + GtkWidget *caller = gtk_widget_get_toplevel(w); + + /* Has an edit dialog box already been opened for that top-level + widget? */ + colopts_edit_dlg = g_object_get_data(G_OBJECT(caller), COLOPTS_DIALOG_PTR_KEY); + if (colopts_edit_dlg != NULL) { + /* Yes. Just re-activate that dialog box. */ + reactivate_window(colopts_edit_dlg); + return; + } + + /* create a new dialog */ + colopts_edit_dlg = dlg_conf_window_new("Wireshark: Preferences: Capture Options Columns"); + gtk_window_set_default_size(GTK_WINDOW(colopts_edit_dlg), 300, 200); + + main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 1, FALSE); + gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5); + gtk_container_add(GTK_CONTAINER(colopts_edit_dlg), main_vb); + gtk_widget_show(main_vb); + + /* create edit options frame */ + ed_opts_fr = gtk_frame_new("Columns"); + gtk_box_pack_start(GTK_BOX(main_vb), ed_opts_fr, FALSE, FALSE, 0); + gtk_widget_show(ed_opts_fr); + + main_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5, TRUE); + gtk_container_set_border_width(GTK_CONTAINER(main_hb), 3); + gtk_container_add(GTK_CONTAINER(ed_opts_fr), main_hb); + gtk_widget_show(main_hb); + + /* table to hold description text entry and hide button */ + main_tb = gtk_table_new(IFOPTS_TABLE_ROWS, 4, FALSE); + gtk_box_pack_start(GTK_BOX(main_hb), main_tb, TRUE, FALSE, 10); + gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10); + gtk_table_set_col_spacings(GTK_TABLE(main_tb), 10); + gtk_widget_show(main_tb); + + column_lb = gtk_label_new("Select the columns to be displayed"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), column_lb, 0, 2, row, row+1); + gtk_misc_set_alignment(GTK_MISC(column_lb), 0, 0.5f); + gtk_widget_show(column_lb); + row++; + + /* create "Interface" label and button */ + col_interface_cb = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_interface_cb, 0, 1, row, row+1); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("INTERFACE")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_interface_cb), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_interface_cb), FALSE); + gtk_widget_show(col_interface_cb); + + col_interface_lb = gtk_label_new("Interface and its addresses"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_interface_lb, 1, 2, row, row+1); + gtk_misc_set_alignment(GTK_MISC(col_interface_lb), 0, 0.5f); + gtk_widget_show(col_interface_lb); + row++; + + /* create "Link Layer" label and button */ + col_link_cb = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_link_cb, 0, 1, row, row+1); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("LINK")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_link_cb), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_link_cb), FALSE); + gtk_widget_show(col_link_cb); + + col_link_lb = gtk_label_new("Link layer header"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_link_lb, 1, 2, row, row+1); + gtk_misc_set_alignment(GTK_MISC(col_link_lb), 0, 0.5f); + gtk_widget_show(col_link_lb); + row++; + + /* create "Promiscous Mode" label and button */ + col_pmode_cb = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_pmode_cb, 0, 1, row, row+1); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("PMODE")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_pmode_cb), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_pmode_cb), FALSE); + gtk_widget_show(col_pmode_cb); + + col_pmode_lb = gtk_label_new("Promiscous Mode"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_pmode_lb, 1, 2, row, row+1); + gtk_misc_set_alignment(GTK_MISC(col_pmode_lb), 0, 0.5f); + gtk_widget_show(col_pmode_lb); + row++; + + /* create "Snap length in Bytes" label and button */ + col_snap_cb = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_snap_cb, 0, 1, row, row+1); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("SNAPLEN")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_snap_cb), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_snap_cb), FALSE); + gtk_widget_show(col_snap_cb); + + col_snap_lb = gtk_label_new("Snap length in Bytes"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_snap_lb, 1, 2, row, row+1); + gtk_misc_set_alignment(GTK_MISC(col_snap_lb), 0, 0.5f); + gtk_widget_show(col_snap_lb); + row++; + +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + /* create "Buffer in Megabytes" label and button */ + col_buf_cb = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_buf_cb, 0, 1, row, row+1); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("BUFFER")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_buf_cb), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_buf_cb), FALSE); + gtk_widget_show(col_buf_cb); + + col_buf_lb = gtk_label_new("Buffer in Megabytes"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_buf_lb, 1, 2, row, row+1); + gtk_misc_set_alignment(GTK_MISC(col_buf_lb), 0, 0.5f); + gtk_widget_show(col_buf_lb); + row++; +#endif + +#ifdef HAVE_PCAP_CREATE + /* create "monitor mode" label and button */ + col_monitor_lb = gtk_label_new("Monitor mode"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_monitor_lb, 1, 2, row, row+1); + gtk_misc_set_alignment(GTK_MISC(col_monitor_lb), 0, 0.5f); + gtk_widget_show(col_monitor_lb); + + col_monitor_cb = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_monitor_cb, 0, 1, row, row+1); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("MONITOR")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_monitor_cb), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_monitor_cb), FALSE); + gtk_widget_show(col_monitor_cb); + + row++; +#endif + + /* create "Capture Filter" label and button */ + col_filter_lb = gtk_label_new("Capture filter"); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_filter_lb, 1, 2, row, row+1); + gtk_misc_set_alignment(GTK_MISC(col_filter_lb), 0, 0.5f); + gtk_widget_show(col_filter_lb); + + col_filter_cb = gtk_check_button_new(); + gtk_table_attach_defaults(GTK_TABLE(main_tb), col_filter_cb, 0, 1, row, row+1); + if (!prefs.capture_columns || prefs_capture_options_dialog_column_is_visible("FILTER")) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_filter_cb), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(col_filter_cb), FALSE); + gtk_widget_show(col_filter_cb); + + row++; + + /* button row: OK and Cancel buttons */ + bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL); + gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0); + gtk_widget_show(bbox); + + ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK); + gtk_widget_set_tooltip_text(ok_bt, "Save changes and exit dialog"); + g_signal_connect(ok_bt, "clicked", G_CALLBACK(colopts_edit_ok_cb), colopts_edit_dlg); + + cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL); + gtk_widget_set_tooltip_text(cancel_bt, "Cancel and exit dialog"); + window_set_cancel_button(colopts_edit_dlg, cancel_bt, window_cancel_button_cb); + + help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP); + g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), + (gpointer)HELP_CAPTURE_INTERFACE_OPTIONS_DIALOG); + gtk_widget_set_tooltip_text (help_bt, "Show topic specific help"); + + gtk_widget_grab_default(ok_bt); + + g_signal_connect(colopts_edit_dlg, "delete_event", G_CALLBACK(window_delete_event_cb), NULL); + /* Call a handler when we're destroyed, so we can inform + our caller, if any, that we've been destroyed. */ + g_signal_connect(colopts_edit_dlg, "destroy", G_CALLBACK(colopts_edit_destroy_cb), NULL); + + /* Set the key for the new dialog to point to our caller. */ + g_object_set_data(G_OBJECT(colopts_edit_dlg), COLOPTS_CALLER_PTR_KEY, caller); + /* Set the key for the caller to point to us */ + g_object_set_data(G_OBJECT(caller), COLOPTS_DIALOG_PTR_KEY, colopts_edit_dlg); + + gtk_widget_show(colopts_edit_dlg); /* triggers ifopts_edit_ifsel_cb() with the */ + /* "interfaces" TreeView first row selected */ + window_present(colopts_edit_dlg); +} + + static void ifopts_edit_cb(GtkWidget *w, gpointer data _U_) { @@ -303,7 +544,7 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) GtkWidget *list; GtkTreeViewColumn *column; GtkCellRenderer *renderer; - GtkTreeView *list_view; + GtkTreeView *list_view; GtkTreeSelection *selection; int row = 0; @@ -603,6 +844,48 @@ ifopts_edit_cb(GtkWidget *w, gpointer data _U_) window_present(ifopts_edit_dlg); } +/* + * User selected "OK". Create/write preferences strings. + */ +static void +colopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w) +{ + g_list_free(prefs.capture_columns); + prefs.capture_columns = NULL; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(col_interface_cb))) { + prefs.capture_columns = g_list_append(prefs.capture_columns, g_strdup("INTERFACE")); + } + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(col_link_cb))) { + prefs.capture_columns = g_list_append(prefs.capture_columns, g_strdup("LINK")); + } + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(col_pmode_cb))) { + prefs.capture_columns = g_list_append(prefs.capture_columns, g_strdup("PMODE")); + } + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(col_snap_cb))) { + prefs.capture_columns = g_list_append(prefs.capture_columns, g_strdup("SNAPLEN")); + } +#if defined(_WIN32) || defined(HAVE_PCAP_CREATE) + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(col_buf_cb))) { + prefs.capture_columns = g_list_append(prefs.capture_columns, g_strdup("BUFFER")); + } +#endif +#if defined (HAVE_PCAP_CREATE) + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(col_monitor_cb))) { + prefs.capture_columns = g_list_append(prefs.capture_columns, g_strdup("MONITOR")); + } +#endif + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(col_filter_cb))) { + prefs.capture_columns = g_list_append(prefs.capture_columns, g_strdup("FILTER")); + } + /* Now nuke this window. */ + gtk_grab_remove(GTK_WIDGET(parent_w)); + window_destroy(GTK_WIDGET(parent_w)); + if (capture_dlg_window_present()) { + update_visible_tree_view_columns(); + update_visible_columns_menu (); + } +} + /* * User selected "OK". Create/write preferences strings. */ @@ -634,6 +917,22 @@ ifopts_edit_ok_cb(GtkWidget *w _U_, gpointer parent_w) window_destroy(GTK_WIDGET(parent_w)); } +static void +colopts_edit_destroy_cb(GtkWidget *win, gpointer data _U_) +{ + GtkWidget *caller; + + /* Get the widget that requested that we be popped up, if any. + (It should arrange to destroy us if it's destroyed, so + that we don't get a pointer to a non-existent window here.) */ + caller = g_object_get_data(G_OBJECT(win), COLOPTS_CALLER_PTR_KEY); + + if (caller != NULL) { + /* Tell it we no longer exist. */ + g_object_set_data(G_OBJECT(caller), COLOPTS_DIALOG_PTR_KEY, NULL); + } +} + static void ifopts_edit_destroy_cb(GtkWidget *win, gpointer data _U_) { diff --git a/ui/gtk/prefs_dlg.c b/ui/gtk/prefs_dlg.c index c0c9b5fd43..99c4613823 100644 --- a/ui/gtk/prefs_dlg.c +++ b/ui/gtk/prefs_dlg.c @@ -424,8 +424,8 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page) GtkCellRenderer *renderer; GtkTreeViewColumn *column; gint col_offset; - prefs_tree_iter gui_iter, layout_iter, columns_iter; - gint layout_page, columns_page; + prefs_tree_iter gui_iter, layout_iter, columns_iter, capture_iter; + gint layout_page, columns_page, capture_page; if (prefs_w != NULL) { @@ -556,8 +556,8 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page) /* capture prefs */ g_strlcpy(label_str, "Capture", MAX_TREE_NODE_NAME_LEN); prefs_nb_page_add(prefs_nb, label_str, capture_prefs_show(), E_CAPTURE_PAGE_KEY); - prefs_tree_page_add(label_str, cts.page, store, NULL); - cts.page++; + capture_iter = prefs_tree_page_add(label_str, cts.page, store, NULL); + capture_page = cts.page++; #ifdef _WIN32 } #endif /* _WIN32 */ @@ -620,6 +620,10 @@ prefs_page_cb(GtkWidget *w _U_, gpointer dummy _U_, PREFS_PAGE_E prefs_page) gtk_tree_selection_select_iter(selection, &columns_iter); gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), columns_page); break; + case PREFS_PAGE_CAPTURE: + gtk_tree_selection_select_iter(selection, &capture_iter); + gtk_notebook_set_current_page(g_object_get_data(G_OBJECT(prefs_w), E_PREFSW_NOTEBOOK_KEY), capture_page); + break; default: /* Not implemented yet */ break; @@ -1829,6 +1833,7 @@ prefs_tree_select_cb(GtkTreeSelection *sel, gpointer dummy _U_) } + /* * Editor modelines * diff --git a/ui/gtk/prefs_dlg.h b/ui/gtk/prefs_dlg.h index 8dd10e4242..433ec5b43b 100644 --- a/ui/gtk/prefs_dlg.h +++ b/ui/gtk/prefs_dlg.h @@ -66,7 +66,8 @@ typedef enum { PREFS_PAGE_USER_INTERFACE, PREFS_PAGE_LAYOUT, - PREFS_PAGE_COLUMNS + PREFS_PAGE_COLUMNS, + PREFS_PAGE_CAPTURE } PREFS_PAGE_E; /** Show the preferences dialog.