1 /* proto_hier_tree_model.c
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25 /* This code was originally based on the GTK+ Tree View tutorial at
26 * http://scentric.net/tutorial */
35 #include "proto_hier_tree_model.h"
37 #include <epan/proto.h>
39 static GObjectClass
*parent_class
= NULL
;
41 static GtkTreeModelFlags
42 proto_hier_tree_get_flags(GtkTreeModel
*tree_model
)
44 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model
), (GtkTreeModelFlags
)0);
46 return GTK_TREE_MODEL_ITERS_PERSIST
;
50 proto_hier_tree_get_n_columns(GtkTreeModel
*tree_model
)
52 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model
), 0);
58 proto_hier_tree_get_column_type(GtkTreeModel
*tree_model
, gint idx
)
60 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model
), G_TYPE_INVALID
);
61 g_return_val_if_fail(idx
== 0 || idx
== 1, G_TYPE_INVALID
);
65 return G_TYPE_POINTER
;
70 return G_TYPE_INVALID
;
74 proto_hier_tree_iter_nth_child(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
, GtkTreeIter
*parent
, gint n
)
76 ProtoHierTreeModel
*model
;
81 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model
), FALSE
);
82 model
= (ProtoHierTreeModel
*) tree_model
;
85 header_field_info
*hfinfo
;
87 g_return_val_if_fail(parent
->stamp
== model
->stamp
, FALSE
);
89 /* no child of field */
90 if (parent
->user_data2
!= NULL
)
93 proto_id
= proto_get_data_protocol(parent
->user_data
);
95 /* get n-th field of protocol */
96 hfinfo
= proto_get_first_protocol_field(proto_id
, &cookie
);
98 if (hfinfo
->same_name_prev_id
== -1) {
103 hfinfo
= proto_get_next_protocol_field(&cookie
);
110 iter
->stamp
= model
->stamp
;
111 iter
->user_data
= parent
->user_data
;
112 iter
->user_data2
= cookie
;
113 iter
->user_data3
= hfinfo
;
117 /* get n-th enabled protocol */
118 proto_id
= proto_get_first_protocol(&cookie
);
119 while (proto_id
!= -1) {
120 protocol_t
*p
= find_protocol_by_id(proto_id
);
122 if (proto_is_protocol_enabled(p
)) {
127 proto_id
= proto_get_next_protocol(&cookie
);
134 iter
->stamp
= model
->stamp
;
135 iter
->user_data
= cookie
;
136 iter
->user_data2
= NULL
;
137 iter
->user_data3
= proto_registrar_get_nth(proto_id
);
142 proto_hier_tree_get_iter(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
, GtkTreePath
*path
)
144 gint
*indices
, depth
;
146 g_assert(PROTOHIER_IS_TREE(tree_model
));
147 g_assert(path
!= NULL
);
149 indices
= gtk_tree_path_get_indices(path
);
150 depth
= gtk_tree_path_get_depth(path
);
152 g_assert(depth
== 1 || depth
== 2);
154 if (!proto_hier_tree_iter_nth_child(tree_model
, iter
, NULL
, indices
[0]))
158 if (!proto_hier_tree_iter_nth_child(tree_model
, iter
, iter
, indices
[1]))
165 hfinfo_to_name(const header_field_info
*hfinfo
)
167 if (hfinfo
->parent
== -1) {
168 protocol_t
*protocol
= find_protocol_by_id(hfinfo
->id
);
170 return g_strdup_printf("%s - %s", proto_get_protocol_short_name(protocol
), proto_get_protocol_long_name(protocol
));
172 if (hfinfo
->blurb
!= NULL
&& hfinfo
->blurb
[0] != '\0')
173 return g_strdup_printf("%s - %s (%s)", hfinfo
->abbrev
, hfinfo
->name
, hfinfo
->blurb
);
175 return g_strdup_printf("%s - %s", hfinfo
->abbrev
, hfinfo
->name
);
179 proto_hier_tree_get_value(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
, gint column
, GValue
*value
)
181 ProtoHierTreeModel
*model
;
182 header_field_info
*hfinfo
;
184 g_return_if_fail(PROTOHIER_IS_TREE(tree_model
));
185 model
= (ProtoHierTreeModel
*) tree_model
;
187 g_return_if_fail(iter
!= NULL
);
188 g_return_if_fail(iter
->stamp
== model
->stamp
);
189 g_return_if_fail(column
== 0 || column
== 1);
191 hfinfo
= (header_field_info
*)iter
->user_data3
;
195 g_value_init(value
, G_TYPE_POINTER
);
196 g_value_set_pointer(value
, hfinfo
);
199 case 1: /* field name */
200 g_value_init(value
, G_TYPE_STRING
);
201 g_value_take_string(value
, hfinfo_to_name(hfinfo
));
207 proto_hier_tree_iter_next(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
)
209 ProtoHierTreeModel
*model
;
211 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model
), FALSE
);
212 model
= (ProtoHierTreeModel
*) tree_model
;
214 g_return_val_if_fail(iter
->stamp
== model
->stamp
, FALSE
);
217 if (iter
->user_data2
== NULL
) {
218 void *cookie
= iter
->user_data
;
221 proto_id
= proto_get_next_protocol(&cookie
);
222 /* get next enabled protocol */
223 while (proto_id
!= -1) {
224 protocol_t
*p
= find_protocol_by_id(proto_id
);
226 if (proto_is_protocol_enabled(p
))
228 proto_id
= proto_get_next_protocol(&cookie
);
234 iter
->user_data
= cookie
;
235 iter
->user_data3
= proto_registrar_get_nth(proto_id
);
241 void *cookie2
= iter
->user_data2
;
242 header_field_info
*hfinfo
;
244 hfinfo
= proto_get_next_protocol_field(&cookie2
);
247 if (hfinfo
->same_name_prev_id
== -1)
249 hfinfo
= proto_get_next_protocol_field(&cookie2
);
256 iter
->user_data2
= cookie2
;
257 iter
->user_data3
= hfinfo
;
263 proto_hier_tree_iter_children(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
, GtkTreeIter
*parent
)
265 return proto_hier_tree_iter_nth_child(tree_model
, iter
, parent
, 0);
269 proto_hier_tree_iter_n_children(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
)
271 ProtoHierTreeModel
*model
;
277 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model
), 0);
278 model
= (ProtoHierTreeModel
*) tree_model
;
280 g_return_val_if_fail(iter
== NULL
|| iter
->user_data
!= NULL
, 0);
283 header_field_info
*hfinfo
;
285 g_return_val_if_fail(iter
->stamp
== model
->stamp
, 0);
287 /* field has no child */
288 if (iter
->user_data2
!= NULL
)
291 p_id
= proto_get_data_protocol(iter
->user_data
);
293 /* count not-duplicated fields */
294 for (hfinfo
= proto_get_first_protocol_field(p_id
, &cookie
); hfinfo
; hfinfo
= proto_get_next_protocol_field(&cookie
)) {
295 if (hfinfo
->same_name_prev_id
!= -1)
301 /* count enabled protocols */
302 for (p_id
= proto_get_first_protocol(&cookie
); p_id
!= -1; p_id
= proto_get_next_protocol(&cookie
)) {
303 protocol_t
*p
= find_protocol_by_id(p_id
);
305 if (!proto_is_protocol_enabled(p
))
315 proto_hier_tree_get_path(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
)
317 ProtoHierTreeModel
*model
;
324 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model
), NULL
);
325 model
= (ProtoHierTreeModel
*) tree_model
;
327 g_return_val_if_fail(iter
!= NULL
, NULL
);
328 g_return_val_if_fail(iter
->stamp
== model
->stamp
, FALSE
);
330 p_id
= proto_get_data_protocol(iter
->user_data
);
332 path
= gtk_tree_path_new();
338 /* XXX, assuming that protocols can't be disabled! */
340 for (id
= proto_get_first_protocol(&cookie
); id
!= p_id
&& id
!= -1; id
= proto_get_next_protocol(&cookie
)) {
341 protocol_t
*p
= find_protocol_by_id(id
);
343 if (!proto_is_protocol_enabled(p
))
347 gtk_tree_path_append_index(path
, pos
);
351 if (iter
->user_data2
!= NULL
) {
352 header_field_info
*hfinfo
;
355 for (hfinfo
= proto_get_first_protocol_field(p_id
, &cookie
); hfinfo
&& hfinfo
!= iter
->user_data3
; hfinfo
= proto_get_next_protocol_field(&cookie
)) {
356 if (hfinfo
->same_name_prev_id
!= -1)
360 gtk_tree_path_append_index(path
, pos
);
367 proto_hier_tree_iter_has_child(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
)
369 /* no need to optimize? */
370 return proto_hier_tree_iter_n_children(tree_model
, iter
) != 0;
374 proto_hier_tree_iter_parent(GtkTreeModel
*tree_model
, GtkTreeIter
*iter
, GtkTreeIter
*child
)
376 ProtoHierTreeModel
*model
;
378 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model
), FALSE
);
379 model
= (ProtoHierTreeModel
*) tree_model
;
381 g_return_val_if_fail(iter
!= NULL
, FALSE
);
382 g_return_val_if_fail(child
->stamp
== model
->stamp
, FALSE
);
384 /* from field to protocol */
385 if (child
->user_data2
!= NULL
) {
386 int p_id
= proto_get_data_protocol(child
->user_data
);
388 iter
->stamp
= model
->stamp
;
389 iter
->user_data
= child
->user_data
;
390 iter
->user_data2
= NULL
;
391 iter
->user_data3
= proto_registrar_get_nth(p_id
);
395 /* protocol has no parent */
400 proto_hier_tree_model_tree_init(GtkTreeModelIface
*iface
)
402 iface
->get_flags
= proto_hier_tree_get_flags
;
403 iface
->get_n_columns
= proto_hier_tree_get_n_columns
;
404 iface
->get_column_type
= proto_hier_tree_get_column_type
;
405 iface
->get_iter
= proto_hier_tree_get_iter
;
406 iface
->get_path
= proto_hier_tree_get_path
;
407 iface
->get_value
= proto_hier_tree_get_value
;
408 iface
->iter_next
= proto_hier_tree_iter_next
;
409 iface
->iter_children
= proto_hier_tree_iter_children
;
410 iface
->iter_has_child
= proto_hier_tree_iter_has_child
;
411 iface
->iter_n_children
= proto_hier_tree_iter_n_children
;
412 iface
->iter_nth_child
= proto_hier_tree_iter_nth_child
;
413 iface
->iter_parent
= proto_hier_tree_iter_parent
;
417 proto_hier_tree_model_init(ProtoHierTreeModel
*model
)
419 /* To check whether an iter belongs to our model. */
420 model
->stamp
= g_random_int();
424 _class_finalize(GObject
*object
)
426 /* must chain up - finalize parent */
427 (*parent_class
->finalize
)(object
);
431 proto_hier_tree_class_init(ProtoHierTreeModelClass
*klass
)
433 GObjectClass
*object_class
;
435 parent_class
= (GObjectClass
*) g_type_class_peek_parent(klass
);
436 object_class
= (GObjectClass
*) klass
;
438 object_class
->finalize
= _class_finalize
;
442 proto_hier_tree_get_type(void)
444 static GType proto_hier_tree_type
= 0;
446 if (proto_hier_tree_type
== 0) {
447 static const GTypeInfo proto_hier_tree_info
= {
448 sizeof(ProtoHierTreeModelClass
),
449 NULL
, /* base_init */
450 NULL
, /* base_finalize */
451 (GClassInitFunc
) proto_hier_tree_class_init
,
452 NULL
, /* class finalize */
453 NULL
, /* class_data */
454 sizeof(ProtoHierTreeModel
),
456 (GInstanceInitFunc
) proto_hier_tree_model_init
,
457 NULL
/* value_table */
460 static const GInterfaceInfo tree_model_info
= {
461 (GInterfaceInitFunc
) proto_hier_tree_model_tree_init
,
466 /* Register the new derived type with the GObject type system */
467 proto_hier_tree_type
= g_type_register_static(G_TYPE_OBJECT
,
468 "ProtoHierTreeModel",
469 &proto_hier_tree_info
,
472 g_type_add_interface_static(proto_hier_tree_type
,
476 return proto_hier_tree_type
;
480 proto_hier_tree_model_new(void)
482 ProtoHierTreeModel
*model
;
484 model
= (ProtoHierTreeModel
*) g_object_new(PROTOHIER_TYPE_TREE
, NULL
);
486 g_assert(model
!= NULL
);