This change allows a structure to be created under the "Protocols" section of the preferences.

A new function is introduced, prefs_register_protocol_subtree(), that allows the subtree the protocol should appear under to be specified. The subtree is specified as a string, with a '/' delimiting each subtree element. For example,
	prefs_register_protocol(proto_dap, prefs_register_dap);
becomes
	prefs_register_protocol_subtree("OSI/X.500", proto_dap, prefs_register_dap);

The function will create all the intermediate subtree nodes that are required, if they don't already exist. 
This allows the grouping of procotols which should make the list of protocols more manageable as even more are added. The current aim is to group by protocol family e.g. 
+ OSI
  + X.400
      X.411
      X.420
  + X.500
      DISP
      DAP
      DOP
      DSP
  + X.509
      X509AF
      X509CE
      ...

but others grouping could be envisioned (e.g. by first letter). 

As the intermediate nodes may already have preferences (e.g. OSI), then modules are now allowed to have submodules. Previously each node was either a subtree or held preferences. This is consistent with the "User Interface" node.

The subtree structure has no effect on how the preferences are saved to file, and the "Protocol Preferences..." menu option will bring up the preferences expanded to the correct node.

In addition, a new "blank page" has been introduced for intermediate nodes that have no preferences (and is also used when the "Protocols" node itself is chosen). This prevents confusion when the user moves from a node with preferences to a node without preferences, but the page old page is still shown.

There is also a change to prevent '#' characters in a value being treated as a comment when parsing the preferences file. (There is nothing that adds comments when writing the preferences file.) 


svn path=/trunk/; revision=21066
This commit is contained in:
Graeme Lunt 2007-03-19 19:08:22 +00:00
parent 93af79c80d
commit a51f1694c9
4 changed files with 167 additions and 38 deletions

View File

@ -30,9 +30,9 @@ struct pref_module {
const char *name; /* name of module */
const char *title; /* title of module (displayed in preferences list) */
const char *description;/* Description of module (displayed in preferences notebook) */
gboolean is_subtree; /* if TRUE, this has other modules, not preferences, under it */
void (*apply_cb)(void); /* routine to call when preferences applied */
GList *prefs; /* list of its preferences or submodules */
GList *prefs; /* list of its preferences */
GList *submodules; /* list of its submodules */
int numprefs; /* number of non-obsolete preferences */
gboolean prefs_changed; /* if TRUE, a preference has changed since we last checked */
gboolean obsolete; /* if TRUE, this is a module that used to

View File

@ -51,6 +51,7 @@
#include <epan/uat-int.h>
/* Internal functions */
static module_t *find_subtree(module_t *parent, const char *name);
static module_t *prefs_register_module_or_subtree(module_t *parent,
const char *name, const char *title, const char *description, gboolean is_subtree,
void (*apply_cb)(void));
@ -166,13 +167,27 @@ prefs_register_module_or_subtree(module_t *parent, const char *name,
const char *p;
guchar c;
/* this module may have been created as a subtree item previously */
if(module = find_subtree(parent, title)) {
/* the module is currently a subtree */
module->name = name;
module->apply_cb = apply_cb;
module->description = description;
if(prefs_find_module(name) == NULL)
modules = g_list_insert_sorted(modules, module,
module_compare_name);
return module;
}
module = g_malloc(sizeof (module_t));
module->name = name;
module->title = title;
module->description = description;
module->is_subtree = is_subtree;
module->apply_cb = apply_cb;
module->prefs = NULL; /* no preferences, to start */
module->submodules = NULL; /* no submodules, to start */
module->numprefs = 0;
module->prefs_changed = FALSE;
module->obsolete = FALSE;
@ -238,7 +253,7 @@ prefs_register_module_or_subtree(module_t *parent, const char *name,
/*
* It goes into the list for this module.
*/
parent->prefs = g_list_insert_sorted(parent->prefs, module,
parent->submodules = g_list_insert_sorted(parent->submodules, module,
module_compare_title);
}
@ -271,6 +286,59 @@ prefs_register_protocol(int id, void (*apply_cb)(void))
proto_get_protocol_name(id), apply_cb);
}
module_t *
prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
{
protocol_t *protocol;
module_t *subtree_module;
module_t *new_module;
char *sep = NULL, *ptr = NULL;
char *csubtree = NULL;
/*
* Have we yet created the "Protocols" subtree?
*/
if (protocols_module == NULL) {
/*
* No. Do so.
*/
protocols_module = prefs_register_subtree(NULL, "Protocols", NULL);
}
subtree_module = protocols_module;
if(subtree) {
/* take a copy of the buffer */
ptr = csubtree = g_strdup(subtree);
while(ptr && *ptr) {
if((sep = strchr(ptr, '/')))
*sep++ = '\0';
if(!(new_module = find_subtree(subtree_module, ptr))) {
/* create it */
new_module = prefs_register_subtree(subtree_module, ptr, NULL);
}
subtree_module = new_module;
ptr = sep;
}
/* g_free(csubtree); */
}
protocol = find_protocol_by_id(id);
return prefs_register_module(subtree_module,
proto_get_protocol_filter_name(id),
proto_get_protocol_short_name(protocol),
proto_get_protocol_name(id), apply_cb);
}
/*
* Register that a protocol used to have preferences but no longer does,
* by creating an "obsolete" module for it.
@ -322,6 +390,27 @@ prefs_find_module(const char *name)
return (module_t *) list_entry->data;
}
static gint
subtree_match(gconstpointer a, gconstpointer b)
{
const module_t *module = a;
const char *title = b;
return strcmp(title, module->title);
}
static module_t *
find_subtree(module_t *parent, const char *name)
{
GList *list_entry;
list_entry = g_list_find_custom(parent ? parent->submodules : top_level_modules,
name, subtree_match);
if (list_entry == NULL)
return NULL; /* no such module */
return (module_t *) list_entry->data;
}
/*
* Call a callback function, with a specified argument, for each module
* in a list of modules. If the list is NULL, searches the top-level
@ -1306,13 +1395,7 @@ read_prefs_file(const char *pf_path, FILE *pf, pref_set_pair_cb pref_set_pair_fc
}
break;
case IN_VAL:
if (got_c != '#') {
g_string_append_c(cur_val, (gchar) got_c);
} else {
while (isspace((guchar)cur_val->str[cur_val->len]) && cur_val->len > 0)
g_string_truncate(cur_val, cur_val->len - 1);
state = IN_SKIP;
}
g_string_append_c(cur_val, (gchar) got_c);
break;
}
}

View File

@ -194,6 +194,14 @@ extern module_t *prefs_register_subtree(module_t *parent, const char *title,
*/
extern module_t *prefs_register_protocol(int id, void (*apply_cb)(void));
/*
* Register that a protocol has preferences and group it under a single
* subtree
*/
#define PREFERENCE_GROUPING
extern module_t *prefs_register_protocol_subtree(const char *subtree, int id,
void (*apply_cb)(void));
/*
* Register that a protocol used to have preferences but no longer does,
* by creating an "obsolete" module for it.

View File

@ -127,6 +127,8 @@ struct ct_struct {
gboolean is_protocol;
};
static gint blank_page = 0;
static guint
pref_exists(pref_t *pref _U_, gpointer user_data _U_)
{
@ -277,7 +279,7 @@ module_prefs_show(module_t *module, gpointer user_data)
/*
* Is this module a subtree, with modules underneath it?
*/
if (!module->is_subtree) {
if (!module->submodules) {
/*
* No.
* Does it have any preferences (other than possibly obsolete ones)?
@ -299,25 +301,24 @@ module_prefs_show(module_t *module, gpointer user_data)
strcpy(label_str, module->title);
#if GTK_MAJOR_VERSION < 2
ct_node = gtk_ctree_insert_node(GTK_CTREE(cts->tree), cts->node, NULL,
&label_ptr, 5, NULL, NULL, NULL, NULL, !module->is_subtree,
&label_ptr, 5, NULL, NULL, NULL, NULL, !module->submodules,
FALSE);
#else
model = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(cts->tree)));
if (module->is_subtree)
gtk_tree_store_append(model, &iter, NULL);
else
gtk_tree_store_append(model, &iter, &cts->iter);
if (module->submodules && !cts->iter.stamp)
gtk_tree_store_append(model, &iter, NULL);
else
gtk_tree_store_append(model, &iter, &cts->iter);
#endif
/*
* Is this a subtree?
*/
if (module->is_subtree) {
if (module->submodules) {
/*
* Yes.
*/
/* Note that there's no page attached to this item */
#if GTK_MAJOR_VERSION < 2
gtk_ctree_node_set_row_data(GTK_CTREE(cts->tree), ct_node,
GINT_TO_POINTER(-1));
@ -336,10 +337,15 @@ module_prefs_show(module_t *module, gpointer user_data)
#endif
if (module == protocols_module)
child_cts.is_protocol = TRUE;
prefs_module_list_foreach(module->prefs, module_prefs_show, &child_cts);
} else {
prefs_module_list_foreach(module->submodules, module_prefs_show, &child_cts);
/* keep the page count right */
cts->page = child_cts.page;
}
if(module->prefs) {
/*
* No. Create a notebook page for it.
* Has preferences. Create a notebook page for it.
*/
/* Scrolled window */
@ -383,10 +389,21 @@ module_prefs_show(module_t *module, gpointer user_data)
OBJECT_SET_DATA(frame, E_PAGE_ITER_KEY, gtk_tree_iter_copy(&iter));
#endif
cts->page++;
cts->page++;
/* Show 'em what we got */
gtk_widget_show_all(main_sw);
} else {
/* show the blank page */
#if GTK_MAJOR_VERSION < 2
gtk_ctree_node_set_row_data(GTK_CTREE(cts->tree), ct_node,
GINT_TO_POINTER(blank_page));
#else
gtk_tree_store_set(model, &iter, 0, label_str, 1, blank_page, -1);
#endif
}
return 0;
@ -434,8 +451,10 @@ prefs_nb_page_add(GtkWidget *notebook, const gchar *title, GtkWidget *page, cons
frame = gtk_frame_new(title);
gtk_widget_show(frame);
gtk_container_add(GTK_CONTAINER(frame), page);
OBJECT_SET_DATA(prefs_w, page_key, page);
if(page) {
gtk_container_add(GTK_CONTAINER(frame), page);
OBJECT_SET_DATA(prefs_w, page_key, page);
}
gtk_notebook_append_page (GTK_NOTEBOOK(notebook), frame, NULL);
return frame;
@ -518,6 +537,7 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
#else
store = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
cts.tree = tree_view_new(GTK_TREE_MODEL(store));
cts.iter.stamp = 0; /* mark this as the toplevel */
OBJECT_SET_DATA(prefs_w, E_PREFSW_TREE_KEY, cts.tree);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(cts.tree), FALSE);
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cts.tree));
@ -545,6 +565,11 @@ prefs_cb(GtkWidget *w _U_, gpointer dummy _U_)
cts.page = 0;
/* Blank Page */
strcpy(label_str, "(No Specific Preferences)");
prefs_nb_page_add(prefs_nb, label_str, NULL, NULL);
blank_page = cts.page++;
/* GUI prefs */
strcpy(label_str, "User Interface");
prefs_nb_page_add(prefs_nb, label_str, gui_prefs_show(), E_GUI_PAGE_KEY);
@ -1673,9 +1698,31 @@ module_search_properties(module_t *module, gpointer user_data)
p->module = module;
return 1; /* stops the search */
}
if(module->submodules)
return prefs_module_list_foreach(module->submodules, module_search_properties, p);
return 0;
}
#if GTK_MAJOR_VERSION >= 2
static void
tree_expand_row(GtkTreeModel *model, GtkTreeView *tree_view, GtkTreeIter *iter)
{
GtkTreeIter parent;
GtkTreePath *path;
/* expand the parent first */
if(gtk_tree_model_iter_parent(model, &parent, iter))
tree_expand_row(model, tree_view, &parent);
path = gtk_tree_model_get_path(model, iter);
gtk_tree_view_expand_row(tree_view, path, FALSE);
/*expand_tree(tree_view, &parent, NULL, NULL);*/
gtk_tree_path_free(path);
}
#endif
/* select a node in the tree view */
/* XXX - this is almost 100% copied from byte_view_select() in proto_draw.c,
@ -1691,8 +1738,7 @@ tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
GtkTreeIter local_iter = *iter;
GtkTreeView *tree_view = GTK_TREE_VIEW(tree);
GtkTreeModel *model;
GtkTreePath *first_path, *path;
GtkTreeIter parent;
GtkTreePath *first_path;
#endif
#if GTK_MAJOR_VERSION < 2
@ -1718,17 +1764,9 @@ tree_select_node(GtkWidget *tree, prefs_tree_iter *iter)
/* Expand our field's row */
first_path = gtk_tree_model_get_path(model, &local_iter);
gtk_tree_view_expand_row(tree_view, first_path, FALSE);
/*expand_tree(tree_view, &iter, NULL, NULL);*/
/* ... and its parents */
while (gtk_tree_model_iter_parent(model, &parent, &local_iter)) {
path = gtk_tree_model_get_path(model, &parent);
gtk_tree_view_expand_row(tree_view, path, FALSE);
/*expand_tree(tree_view, &parent, NULL, NULL);*/
local_iter = parent;
gtk_tree_path_free(path);
}
/* expand from the top down */
tree_expand_row(model, tree_view, &local_iter);
/* select our field's row */
gtk_tree_selection_select_path(gtk_tree_view_get_selection(tree_view),
@ -1774,7 +1812,7 @@ properties_cb(GtkWidget *w, gpointer dummy)
XXX - should we just associate protocols with modules directly? */
p.title = title;
p.module = NULL;
prefs_module_list_foreach(protocols_module->prefs, module_search_properties,
prefs_module_list_foreach(protocols_module->submodules, module_search_properties,
&p);
if (p.module == NULL) {
/* We didn't find it - that protocol probably has no preferences. */