From 0cea399fda44602e66fbef77da89f36a2fc5b52c Mon Sep 17 00:00:00 2001 From: Anders Broman Date: Fri, 4 May 2012 04:44:23 +0000 Subject: From Jakub Zawadzki: Use custom model in Filter Expression dialog. svn path=/trunk/; revision=42411 --- ui/gtk/Makefile.common | 2 + ui/gtk/dfilter_expr_dlg.c | 39 +--- ui/gtk/proto_hier_tree_model.c | 464 +++++++++++++++++++++++++++++++++++++++++ ui/gtk/proto_hier_tree_model.h | 50 +++++ 4 files changed, 519 insertions(+), 36 deletions(-) create mode 100644 ui/gtk/proto_hier_tree_model.c create mode 100644 ui/gtk/proto_hier_tree_model.h (limited to 'ui') diff --git a/ui/gtk/Makefile.common b/ui/gtk/Makefile.common index 82b813b855..4f6bd492ff 100644 --- a/ui/gtk/Makefile.common +++ b/ui/gtk/Makefile.common @@ -128,6 +128,7 @@ WIRESHARK_GTK_SRC = \ proto_dlg.c \ proto_help.c \ proto_hier_stats_dlg.c \ + proto_hier_tree_model.c \ range_utils.c \ rtp_player.c \ rtp_stream.c \ @@ -323,6 +324,7 @@ noinst_HEADERS = \ proto_dlg.h \ proto_help.h \ proto_hier_stats_dlg.h \ + proto_hier_tree_model.h \ range_utils.h \ remote_icons.h \ rtp_analysis.h \ diff --git a/ui/gtk/dfilter_expr_dlg.c b/ui/gtk/dfilter_expr_dlg.c index 1b8870586f..dab56b06ff 100644 --- a/ui/gtk/dfilter_expr_dlg.c +++ b/ui/gtk/dfilter_expr_dlg.c @@ -55,6 +55,7 @@ #include "ui/gtk/proto_dlg.h" #include "ui/gtk/filter_dlg.h" #include "ui/gtk/dfilter_expr_dlg.h" +#include "ui/gtk/proto_hier_tree_model.h" #include "ui/gtk/old-gtk-compat.h" @@ -945,10 +946,7 @@ dfilter_expr_dlg_new(GtkWidget *filter_te) GtkWidget *range_label, *range_entry; GtkWidget *list_bb, *ok_bt, *cancel_bt; - header_field_info *hfinfo; - int i; - protocol_t *protocol; - GtkTreeStore *store; + ProtoHierTreeModel *store; GtkTreeSelection *selection; GtkCellRenderer *renderer; GtkTreeViewColumn *column; @@ -1128,38 +1126,7 @@ dfilter_expr_dlg_new(GtkWidget *filter_te) * we're ready to cope with the selection signal. */ - store = gtk_tree_store_new(1, G_TYPE_POINTER); -{ - /* GTK2 code using two levels iterator to enumerate all protocol fields */ - - GtkTreeIter iter, child_iter; - void *cookie, *cookie2; - - for (i = proto_get_first_protocol(&cookie); i != -1; - i = proto_get_next_protocol(&cookie)) { - - protocol = find_protocol_by_id(i); - - if (!proto_is_protocol_enabled(protocol)) { - continue; - } - - hfinfo = proto_registrar_get_nth(i); - - gtk_tree_store_append(store, &iter, NULL); - gtk_tree_store_set(store, &iter, 0, hfinfo, -1); - - for (hfinfo = proto_get_first_protocol_field(i, &cookie2); hfinfo != NULL; - hfinfo = proto_get_next_protocol_field(&cookie2)) { - - if (hfinfo->same_name_prev != NULL) /* ignore duplicate names */ - continue; - - gtk_tree_store_append(store, &child_iter, &iter); - gtk_tree_store_set(store, &child_iter, 0, hfinfo, -1); - } - } -} + store = proto_hier_tree_model_new(); gtk_tree_view_set_model(GTK_TREE_VIEW(field_tree), GTK_TREE_MODEL(store)); g_object_unref(G_OBJECT(store)); diff --git a/ui/gtk/proto_hier_tree_model.c b/ui/gtk/proto_hier_tree_model.c new file mode 100644 index 0000000000..c80713277f --- /dev/null +++ b/ui/gtk/proto_hier_tree_model.c @@ -0,0 +1,464 @@ +/* proto_hier_tree_model.c + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +/* This code was originally based on the GTK+ Tree View tutorial at + * http://scentric.net/tutorial */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include "proto_hier_tree_model.h" + +#include + +static GObjectClass *parent_class = NULL; + +static GtkTreeModelFlags +proto_hier_tree_get_flags(GtkTreeModel *tree_model) +{ + g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), (GtkTreeModelFlags)0); + + return GTK_TREE_MODEL_ITERS_PERSIST; +} + +static gint +proto_hier_tree_get_n_columns(GtkTreeModel *tree_model) +{ + g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), 0); + + return 1; +} + +static GType +proto_hier_tree_get_column_type(GtkTreeModel *tree_model, gint idx) +{ + g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), G_TYPE_INVALID); + g_return_val_if_fail(idx == 0, G_TYPE_INVALID); + + return G_TYPE_POINTER; +} + +static gboolean +proto_hier_tree_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n) +{ + ProtoHierTreeModel *model; + + void *cookie; + gint proto_id; + + g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), FALSE); + model = (ProtoHierTreeModel *) tree_model; + + n = n+1; + + if (parent) { + header_field_info *hfinfo; + int p_id; + + g_return_val_if_fail(parent->stamp == model->stamp, FALSE); + + p_id = proto_get_data_protocol(parent->user_data); + + /* no child of field */ + if (parent->user_data2 != NULL) + return FALSE; + + /* get n-th field of protocol */ + hfinfo = proto_get_first_protocol_field(p_id, &cookie); + while (hfinfo) { + if (hfinfo->same_name_prev == NULL) { + n--; + if (!n) + break; + } + hfinfo = proto_get_next_protocol_field(&cookie); + } + + /* not found? */ + if (!hfinfo) + return FALSE; + + iter->stamp = model->stamp; + iter->user_data = parent->user_data; + iter->user_data2 = cookie; + iter->user_data3 = hfinfo; + return TRUE; + } + + /* get n-th enabled protocol */ + proto_id = proto_get_first_protocol(&cookie); + while (proto_id != -1 && n) { + protocol_t *p = find_protocol_by_id(proto_id); + + if (proto_is_protocol_enabled(p)) { + n--; + if (!n) + break; + } + proto_id = proto_get_next_protocol(&cookie); + } + + /* not found? */ + if (proto_id == -1) + return FALSE; + + iter->stamp = model->stamp; + iter->user_data = cookie; + iter->user_data2 = NULL; + iter->user_data3 = proto_registrar_get_nth(proto_id); + return TRUE; +} + +static gboolean +proto_hier_tree_get_iter(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path) +{ + gint *indices, depth; + + g_assert(PROTOHIER_IS_TREE(tree_model)); + g_assert(path != NULL); + + indices = gtk_tree_path_get_indices(path); + depth = gtk_tree_path_get_depth(path); + + g_assert(depth == 1 || depth == 2); + + if (!proto_hier_tree_iter_nth_child(tree_model, iter, NULL, indices[0])) + return FALSE; + + if (depth == 2) { + if (!proto_hier_tree_iter_nth_child(tree_model, iter, iter, indices[1])) + return FALSE; + } + return TRUE; +} + +static void +proto_hier_tree_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, GValue *value) +{ + header_field_info *hfinfo; + + g_return_if_fail(PROTOHIER_IS_TREE(tree_model)); + g_return_if_fail(iter != NULL); + g_return_if_fail(column == 0); + + hfinfo = iter->user_data3; + + g_value_init(value, G_TYPE_POINTER); + g_value_set_pointer(value, hfinfo); +} + +static gboolean +proto_hier_tree_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter) +{ + ProtoHierTreeModel *model; + + g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), FALSE); + model = (ProtoHierTreeModel *) tree_model; + + g_return_val_if_fail(iter->stamp == model->stamp, FALSE); + + /* protocol */ + if (iter->user_data2 == NULL) { + void *cookie = iter->user_data; + int proto_id; + + proto_id = proto_get_next_protocol(&cookie); + /* get next enabled protocol */ + while (proto_id != -1) { + protocol_t *p = find_protocol_by_id(proto_id); + + if (proto_is_protocol_enabled(p)) + break; + proto_id = proto_get_next_protocol(&cookie); + } + + if (proto_id == -1) + return FALSE; + + iter->user_data = cookie; + iter->user_data3 = proto_registrar_get_nth(proto_id); + return TRUE; + } + + /* field */ + { + void *cookie2 = iter->user_data2; + header_field_info *hfinfo; + + hfinfo = proto_get_next_protocol_field(&cookie2); + /* get next field */ + while (hfinfo) { + if (hfinfo->same_name_prev == NULL) + break; + hfinfo = proto_get_next_protocol_field(&cookie2); + } + + /* not found? */ + if (!hfinfo) + return FALSE; + + iter->user_data2 = cookie2; + iter->user_data3 = hfinfo; + return TRUE; + } +} + +static gboolean +proto_hier_tree_iter_children(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent) +{ + return proto_hier_tree_iter_nth_child(tree_model, iter, parent, 0); +} + +static gint +proto_hier_tree_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter) +{ + ProtoHierTreeModel *model; + gint count = 0; + + g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), 0); + model = (ProtoHierTreeModel *) tree_model; + + g_return_val_if_fail(iter == NULL || iter->user_data != NULL, 0); + + if (iter) { + header_field_info *hfinfo; + void *cookie; + int p_id; + + g_return_val_if_fail(iter->stamp == model->stamp, 0); + + /* field has no child */ + if (iter->user_data2 != NULL) + return 0; + + p_id = proto_get_data_protocol(iter->user_data); + + /* count not-duplicated fields */ + for (hfinfo = proto_get_first_protocol_field(p_id, &cookie); hfinfo; hfinfo = proto_get_next_protocol_field(&cookie)) { + if (hfinfo->same_name_prev) + continue; + count++; + } + + } else { + void *cookie; + int p_id; + + /* count enabled protocols */ + for (p_id = proto_get_first_protocol(&cookie); p_id != -1; p_id = proto_get_next_protocol(&cookie)) { + protocol_t *p = find_protocol_by_id(p_id); + + if (!proto_is_protocol_enabled(p)) + continue; + count++; + } + } + + return count; +} + +static GtkTreePath * +proto_hier_tree_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter) +{ + ProtoHierTreeModel *model; + GtkTreePath *path; + int pos; + + int p_id; + void *cookie; + + g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), NULL); + model = (ProtoHierTreeModel *) tree_model; + + g_return_val_if_fail(iter != NULL, NULL); + g_return_val_if_fail(iter->stamp == model->stamp, FALSE); + + p_id = proto_get_data_protocol(iter->user_data); + + path = gtk_tree_path_new(); + + /* protocol */ + { + void *cookie; + int id; + + /* XXX, assuming that protocols can't be disabled! */ + pos = 0; + for (id = proto_get_first_protocol(&cookie); id != p_id && id != -1; id = proto_get_next_protocol(&cookie)) { + protocol_t *p = find_protocol_by_id(id); + + if (!proto_is_protocol_enabled(p)) + continue; + pos++; + } + gtk_tree_path_append_index(path, pos); + } + + /* field */ + if (iter->user_data2 != NULL) { + header_field_info *hfinfo; + + pos = 0; + for (hfinfo = proto_get_first_protocol_field(p_id, &cookie); hfinfo && hfinfo != iter->user_data3; hfinfo = proto_get_next_protocol_field(&cookie)) { + if (hfinfo->same_name_prev) + continue; + pos++; + } + gtk_tree_path_append_index(path, pos); + } + + return path; +} + +static gboolean +proto_hier_tree_iter_has_child(GtkTreeModel *tree_model, GtkTreeIter *iter) +{ + /* no need to optimize? */ + return proto_hier_tree_iter_n_children(tree_model, iter) != 0; +} + +static gboolean +proto_hier_tree_iter_parent(GtkTreeModel *tree_model _U_, GtkTreeIter *iter _U_, GtkTreeIter *child _U_) +{ + ProtoHierTreeModel *model; + + g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), FALSE); + model = (ProtoHierTreeModel *) tree_model; + + g_return_val_if_fail(iter != NULL, FALSE); + g_return_val_if_fail(child->stamp == model->stamp, FALSE); + + /* from field to protocol */ + if (child->user_data2 != NULL) { + int p_id = proto_get_data_protocol(child->user_data); + protocol_t *p = find_protocol_by_id(p_id); + + iter->stamp = model->stamp; + iter->user_data = child->user_data; + iter->user_data2 = NULL; + iter->user_data3 = proto_registrar_get_nth(proto_get_id(p)); + return TRUE; + } + /* protocol has no parent */ + return FALSE; +} + +static void +proto_hier_tree_model_tree_init(GtkTreeModelIface *iface) +{ + iface->get_flags = proto_hier_tree_get_flags; + iface->get_n_columns = proto_hier_tree_get_n_columns; + iface->get_column_type = proto_hier_tree_get_column_type; + iface->get_iter = proto_hier_tree_get_iter; + iface->get_path = proto_hier_tree_get_path; + iface->get_value = proto_hier_tree_get_value; + iface->iter_next = proto_hier_tree_iter_next; + iface->iter_children = proto_hier_tree_iter_children; + iface->iter_has_child = proto_hier_tree_iter_has_child; + iface->iter_n_children = proto_hier_tree_iter_n_children; + iface->iter_nth_child = proto_hier_tree_iter_nth_child; + iface->iter_parent = proto_hier_tree_iter_parent; +} + +static void +proto_hier_tree_model_init(ProtoHierTreeModel *model) +{ + /* To check whether an iter belongs to our model. */ + model->stamp = g_random_int(); +} + +static void +_class_finalize(GObject *object) +{ + /* must chain up - finalize parent */ + (*parent_class->finalize)(object); +} + +static void +proto_hier_tree_class_init(ProtoHierTreeModelClass *klass) +{ + GObjectClass *object_class; + + parent_class = (GObjectClass*) g_type_class_peek_parent(klass); + object_class = (GObjectClass*) klass; + + object_class->finalize = _class_finalize; +} + +GType +proto_hier_tree_get_type(void) +{ + static GType proto_hier_tree_type = 0; + + if (proto_hier_tree_type == 0) { + static const GTypeInfo proto_hier_tree_info = { + sizeof(ProtoHierTreeModelClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) proto_hier_tree_class_init, + NULL, /* class finalize */ + NULL, /* class_data */ + sizeof(ProtoHierTreeModel), + 0, /* n_preallocs */ + (GInstanceInitFunc) proto_hier_tree_model_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo tree_model_info = { + (GInterfaceInitFunc) proto_hier_tree_model_tree_init, + NULL, + NULL + }; + + /* Register the new derived type with the GObject type system */ + proto_hier_tree_type = g_type_register_static(G_TYPE_OBJECT, + "ProtoHierTreeModel", + &proto_hier_tree_info, + (GTypeFlags)0); + + g_type_add_interface_static(proto_hier_tree_type, + GTK_TYPE_TREE_MODEL, + &tree_model_info); + } + return proto_hier_tree_type; +} + +ProtoHierTreeModel * +proto_hier_tree_model_new(void) +{ + ProtoHierTreeModel *model; + + model = (ProtoHierTreeModel *) g_object_new(PROTOHIER_TYPE_TREE, NULL); + + g_assert(model != NULL); + + return model; +} + diff --git a/ui/gtk/proto_hier_tree_model.h b/ui/gtk/proto_hier_tree_model.h new file mode 100644 index 0000000000..54033352f3 --- /dev/null +++ b/ui/gtk/proto_hier_tree_model.h @@ -0,0 +1,50 @@ +/* proto_hier_tree_model.h + * + * $Id$ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef __PROTO_HIER_TREE_MODEL_H__ +#define __PROTO_HIER_TREE_MODEL_H__ + +#include + +#define PROTOHIER_TYPE_TREE (proto_hier_tree_get_type()) + +#define PROTOHIER_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PROTOHIER_TYPE_TREE, ProtoHierTreeModel)) +#define PROTOHIER_IS_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PROTOHIER_TYPE_TREE)) + +typedef struct { + GObject parent; /** MUST be first */ + + /** Random integer to check whether an iter belongs to our model. */ + gint stamp; +} ProtoHierTreeModel; + +typedef struct { + GObjectClass parent_class; + +} ProtoHierTreeModelClass; + +GType proto_hier_tree_get_type(void); +ProtoHierTreeModel *proto_hier_tree_model_new(void); + +#endif /* __PROTO_HIER_TREE_MODEL_H__ */ -- cgit v1.2.3