aboutsummaryrefslogtreecommitdiffstats
path: root/gtk/prefs_dlg.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2000-07-05 09:41:07 +0000
committerGuy Harris <guy@alum.mit.edu>2000-07-05 09:41:07 +0000
commitb1f950b377a99de3fdba8814434b0019c0df3506 (patch)
tree1b304d0bd143ae0727409660feb1e8c0b487eb8a /gtk/prefs_dlg.c
parented5651a90939c40d1ca64a0b0e67b89b8031da21 (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.c297
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));
}