diff options
author | Guy Harris <guy@alum.mit.edu> | 2000-07-05 09:41:07 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2000-07-05 09:41:07 +0000 |
commit | b1f950b377a99de3fdba8814434b0019c0df3506 (patch) | |
tree | 1b304d0bd143ae0727409660feb1e8c0b487eb8a /gtk/prefs_dlg.c | |
parent | ed5651a90939c40d1ca64a0b0e67b89b8031da21 (diff) |
Add support for a global "ethereal.conf" preferences file, stored in the
same directory as the "manuf" file ("/etc" or "/usr/local/etc", most
likely).
Add a mechanism to allow modules (e.g., dissectors) to register
preference values, which:
can be put into the global or the user's preference file;
can be set from the command line, with arguments to the "-o"
flag;
can be set from tabs in the "Preferences" dialog box.
Use that mechanism to register the "Decode IPv4 TOS field as DiffServ
field" variable for IP as a preference.
Stuff that still needs to be done:
documenting the API for registering preferences;
documenting the "-o" values in the man page (probably needs a
flag similar to "-G", and a Perl script to turn the output into
documentation as is done with the list of field);
handling error checking for numeric values (range checking,
making sure that if the user changes the variable from the GUI
they change it to a valid numeric value);
using the callbacks to, for example, update the display when
preferences are changed (could be expensive);
panic if the user specifies a numeric value with a base other
than 10, 8, or 16.
We may also want to clean up the existing wired-in preferences not to
take effect the instant you tweak the widget, and to add an "Apply"
button to the "Preferences" dialog.
svn path=/trunk/; revision=2117
Diffstat (limited to 'gtk/prefs_dlg.c')
-rw-r--r-- | gtk/prefs_dlg.c | 297 |
1 files changed, 296 insertions, 1 deletions
diff --git a/gtk/prefs_dlg.c b/gtk/prefs_dlg.c index 76d09247e8..a107816ac5 100644 --- a/gtk/prefs_dlg.c +++ b/gtk/prefs_dlg.c @@ -1,7 +1,7 @@ /* prefs_dlg.c * Routines for handling preferences * - * $Id: prefs_dlg.c,v 1.13 2000/07/05 06:33:02 guy Exp $ + * $Id: prefs_dlg.c,v 1.14 2000/07/05 09:41:07 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@zing.org> @@ -59,6 +59,8 @@ #include "dlg_utils.h" #include "simple_dialog.h" +#include "prefs-int.h" + static void prefs_main_ok_cb(GtkWidget *, gpointer); static void prefs_main_save_cb(GtkWidget *, gpointer); static void prefs_main_cancel_cb(GtkWidget *, gpointer); @@ -78,6 +80,154 @@ static void prefs_main_destroy_cb(GtkWidget *, gpointer); */ static GtkWidget *prefs_w; +static void +pref_show(pref_t *pref, gpointer user_data) +{ + GtkWidget *main_tb = user_data; + const char *title; + char *label_string; + GtkWidget *label, *menu, *menu_item, *widget, *button; + GSList *rb_group; + char uint_str[10+1]; + const enum_val *enum_valp; + int menu_index, index; + + /* Give this preference a label which is its title, followed by a colon, + and left-align it. */ + title = pref->title; + label_string = g_malloc(strlen(title) + 2); + strcpy(label_string, title); + strcat(label_string, ":"); + label = gtk_label_new(label_string); + g_free(label_string); + gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); + + /* Attach it to the table. */ + gtk_table_attach_defaults(GTK_TABLE(main_tb), label, 0, 1, pref->ordinal, + pref->ordinal+1); + + /* Save the current value of the preference, so that we can revert it if + the user does "Apply" and then "Cancel", and create the control for + editing the preference. */ + switch (pref->type) { + + case PREF_UINT: + pref->saved_val.uint = *pref->varp.uint; + + /* XXX - there are no uint spinbuttons, so we can't use a spinbutton. + Even more annoyingly, even if there were, GLib doesn't define + G_MAXUINT - but I think ANSI C may define UINT_MAX, so we could + use that. */ + widget = gtk_entry_new(); + switch (pref->info.base) { + + case 10: + sprintf(uint_str, "%u", pref->saved_val.uint); + break; + + case 8: + sprintf(uint_str, "%o", pref->saved_val.uint); + break; + + case 16: + sprintf(uint_str, "%x", pref->saved_val.uint); + break; + } + gtk_entry_set_text(GTK_ENTRY(widget), uint_str); + pref->control = widget; + break; + + case PREF_BOOL: + pref->saved_val.bool = *pref->varp.bool; + widget = gtk_check_button_new(); + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(widget), pref->saved_val.bool); + pref->control = widget; + break; + + case PREF_ENUM: + pref->saved_val.enumval = *pref->varp.enump; + if (pref->info.enum_info.radio_buttons) { + /* Show it as radio buttons. */ + widget = gtk_hbox_new(FALSE, 0); + rb_group = NULL; + for (enum_valp = pref->info.enum_info.enumvals, index = 0; + enum_valp->name != NULL; enum_valp++, index++) { + button = gtk_radio_button_new_with_label(rb_group, enum_valp->name); + if (rb_group == NULL) + rb_group = gtk_radio_button_group(GTK_RADIO_BUTTON(button)); + gtk_box_pack_start(GTK_BOX(widget), button, FALSE, FALSE, 10); + if (enum_valp->value == pref->saved_val.enumval) + gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE); + pref->control = button; + } + } else { + /* Show it as an option menu. */ + menu = gtk_menu_new(); + menu_index = -1; + for (enum_valp = pref->info.enum_info.enumvals, index = 0; + enum_valp->name != NULL; enum_valp++, index++) { + menu_item = gtk_menu_item_new_with_label(enum_valp->name); + gtk_menu_append(GTK_MENU(menu), menu_item); + if (enum_valp->value == pref->saved_val.enumval) + menu_index = index; + } + + /* Create the option menu from the option */ + widget = gtk_option_menu_new(); + gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu); + + /* Set its current value to the variable's current value */ + if (menu_index != -1) + gtk_option_menu_set_history(GTK_OPTION_MENU(widget), menu_index); + pref->control = widget; + } + break; + + case PREF_STRING: + widget = gtk_entry_new(); + if (pref->saved_val.string != NULL) + g_free(pref->saved_val.string); + pref->saved_val.string = g_strdup(*pref->varp.string); + gtk_entry_set_text(GTK_ENTRY(widget), pref->saved_val.string); + pref->control = widget; + break; + + default: + g_assert_not_reached(); + widget = NULL; + break; + } + + gtk_table_attach_defaults(GTK_TABLE(main_tb), widget, 1, 2, pref->ordinal, + pref->ordinal+1); +} + +static void +module_prefs_show(module_t *module, gpointer user_data) +{ + GtkWidget *prefs_nb = user_data; + GtkWidget *main_vb, *main_tb, *label; + + /* Main vertical box */ + main_vb = gtk_vbox_new(FALSE, 5); + gtk_container_border_width(GTK_CONTAINER(main_vb), 5); + + /* Main table */ + main_tb = gtk_table_new(module->numprefs, 2, FALSE); + gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0); + gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10); + gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15); + + /* Add items for each of the preferences */ + prefs_pref_foreach(module, pref_show, main_tb); + + label = gtk_label_new(module->title); + gtk_notebook_append_page(GTK_NOTEBOOK(prefs_nb), main_vb, label); + + /* Show 'em what we got */ + gtk_widget_show_all(main_vb); +} + void prefs_cb(GtkWidget *w, gpointer dummy) { GtkWidget *main_vb, *top_hb, *bbox, *prefs_nb, @@ -136,6 +286,9 @@ prefs_cb(GtkWidget *w, gpointer dummy) { label = gtk_label_new ("GUI"); gtk_notebook_append_page (GTK_NOTEBOOK(prefs_nb), gui_pg, label); + /* Registered prefs */ + prefs_module_foreach(module_prefs_show, prefs_nb); + /* Button row: OK and cancel buttons */ bbox = gtk_hbutton_box_new(); gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); @@ -174,12 +327,117 @@ prefs_cb(GtkWidget *w, gpointer dummy) { } static void +pref_fetch(pref_t *pref, gpointer user_data) +{ + GtkWidget *label; + char *label_string; + char *str_val; + char *p; + guint uval; + GSList *rb_entry; + GtkWidget *button; + + /* Fetch the value of the preference, and set the appropriate variable + to it. */ + switch (pref->type) { + + case PREF_UINT: + str_val = gtk_entry_get_text(GTK_ENTRY(pref->control)); + uval = strtoul(str_val, &p, pref->info.base); +#if 0 + if (p == value || *p != '\0') + return PREFS_SET_SYNTAX_ERR; /* number was bad */ +#endif + *pref->varp.uint = uval; + break; + + case PREF_BOOL: + *pref->varp.bool = GTK_TOGGLE_BUTTON(pref->control)->active; + break; + + case PREF_ENUM: + if (pref->info.enum_info.radio_buttons) { + /* Go through the list of of radio buttons in the group, and find + the first one that's active. */ + button = NULL; + for (rb_entry = gtk_radio_button_group(GTK_RADIO_BUTTON(pref->control)); + rb_entry != NULL; + rb_entry = g_slist_next(rb_entry)) { + button = rb_entry->data; + if (GTK_TOGGLE_BUTTON(button)->active) + break; + } + /* OK, now find that button's label. */ + label = GTK_BIN(button)->child; + } else { + /* Get the label for the currently active entry in the option menu. + Yes, this is how you do it. See FAQ 6.8 in the GTK+ FAQ. */ + label = GTK_BIN(pref->control)->child; + } + + /* Get the label, and translate it to a value. */ + gtk_label_get(GTK_LABEL(label), &label_string); + *pref->varp.enump = find_val_for_string(label_string, + pref->info.enum_info.enumvals, 1); + break; + + case PREF_STRING: + str_val = gtk_entry_get_text(GTK_ENTRY(pref->control)); + if (*pref->varp.string != NULL) + g_free(*pref->varp.string); + *pref->varp.string = g_strdup(str_val); + break; + } +} + +static void +module_prefs_fetch(module_t *module, gpointer user_data) +{ + /* For all preferences in this module, fetch its value from this + module's notebook page. */ + prefs_pref_foreach(module, pref_fetch, NULL); +} + +static void +pref_clean(pref_t *pref, gpointer user_data) +{ + switch (pref->type) { + + case PREF_UINT: + break; + + case PREF_BOOL: + break; + + case PREF_ENUM: + break; + + case PREF_STRING: + if (pref->saved_val.string != NULL) { + g_free(pref->saved_val.string); + pref->saved_val.string = NULL; + } + break; + } +} + +static void +module_prefs_clean(module_t *module, gpointer user_data) +{ + /* For all preferences in this module, clean up any cruft allocated for + use by the GUI code. */ + prefs_pref_foreach(module, pref_clean, NULL); +} + +static void prefs_main_ok_cb(GtkWidget *ok_bt, gpointer parent_w) { printer_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_PRINT_PAGE_KEY)); column_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY)); stream_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY)); gui_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY)); + prefs_module_foreach(module_prefs_fetch, NULL); + prefs_module_foreach(module_prefs_clean, NULL); gtk_widget_destroy(GTK_WIDGET(parent_w)); } @@ -193,6 +451,7 @@ prefs_main_save_cb(GtkWidget *save_bt, gpointer parent_w) column_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY)); stream_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY)); gui_prefs_save(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY)); + prefs_module_foreach(module_prefs_fetch, NULL); err = write_prefs(&pf_path); if (err != 0) { simple_dialog(ESD_TYPE_WARN, NULL, @@ -202,12 +461,48 @@ prefs_main_save_cb(GtkWidget *save_bt, gpointer parent_w) } static void +pref_revert(pref_t *pref, gpointer user_data) +{ + /* Fetch the value of the preference, and set the appropriate variable + to it. */ + switch (pref->type) { + + case PREF_UINT: + *pref->varp.uint = pref->saved_val.uint; + break; + + case PREF_BOOL: + *pref->varp.bool = pref->saved_val.bool; + break; + + case PREF_ENUM: + *pref->varp.enump = pref->saved_val.enumval; + break; + + case PREF_STRING: + if (*pref->varp.string != NULL) + g_free(*pref->varp.string); + *pref->varp.string = g_strdup(pref->saved_val.string); + break; + } +} + +static void +module_prefs_revert(module_t *module, gpointer user_data) +{ + /* For all preferences in this module, revert its value to the value + it had when we popped up the Preferences dialog. */ + prefs_pref_foreach(module, pref_revert, NULL); +} + +static void prefs_main_cancel_cb(GtkWidget *cancel_bt, gpointer parent_w) { printer_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_PRINT_PAGE_KEY)); column_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY)); stream_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY)); gui_prefs_cancel(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY)); + prefs_module_foreach(module_prefs_revert, NULL); gtk_widget_destroy(GTK_WIDGET(parent_w)); } |