Witness: enum witness_notifyResponse_type
[wireshark-wip.git] / ui / gtk / proto_hier_tree_model.c
blobfb71c34afd5d58e7a15c22fc182ecf17fde95503
1 /* proto_hier_tree_model.c
3 * $Id$
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,
22 * USA.
25 /* This code was originally based on the GTK+ Tree View tutorial at
26 * http://scentric.net/tutorial */
28 #include "config.h"
30 #include <string.h>
32 #include <gtk/gtk.h>
33 #include <glib.h>
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;
49 static gint
50 proto_hier_tree_get_n_columns(GtkTreeModel *tree_model)
52 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), 0);
54 return 2;
57 static GType
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);
63 switch (idx) {
64 case 0:
65 return G_TYPE_POINTER;
66 case 1:
67 return G_TYPE_STRING;
69 /* never here */
70 return G_TYPE_INVALID;
73 static gboolean
74 proto_hier_tree_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent, gint n)
76 ProtoHierTreeModel *model;
78 gint proto_id;
79 void *cookie;
81 g_return_val_if_fail(PROTOHIER_IS_TREE(tree_model), FALSE);
82 model = (ProtoHierTreeModel *) tree_model;
84 if (parent) {
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)
91 return FALSE;
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);
97 while (hfinfo) {
98 if (hfinfo->same_name_prev_id == -1) {
99 if (!n)
100 break;
101 n--;
103 hfinfo = proto_get_next_protocol_field(&cookie);
106 /* not found? */
107 if (!hfinfo)
108 return FALSE;
110 iter->stamp = model->stamp;
111 iter->user_data = parent->user_data;
112 iter->user_data2 = cookie;
113 iter->user_data3 = hfinfo;
114 return TRUE;
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)) {
123 if (!n)
124 break;
125 n--;
127 proto_id = proto_get_next_protocol(&cookie);
130 /* not found? */
131 if (proto_id == -1)
132 return FALSE;
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);
138 return TRUE;
141 static gboolean
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]))
155 return FALSE;
157 if (depth == 2) {
158 if (!proto_hier_tree_iter_nth_child(tree_model, iter, iter, indices[1]))
159 return FALSE;
161 return TRUE;
164 static char *
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);
174 else
175 return g_strdup_printf("%s - %s", hfinfo->abbrev, hfinfo->name);
178 static void
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;
193 switch (column) {
194 case 0: /* hfinfo */
195 g_value_init(value, G_TYPE_POINTER);
196 g_value_set_pointer(value, hfinfo);
197 break;
199 case 1: /* field name */
200 g_value_init(value, G_TYPE_STRING);
201 g_value_take_string(value, hfinfo_to_name(hfinfo));
202 break;
206 static gboolean
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);
216 /* protocol */
217 if (iter->user_data2 == NULL) {
218 void *cookie = iter->user_data;
219 int proto_id;
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))
227 break;
228 proto_id = proto_get_next_protocol(&cookie);
231 if (proto_id == -1)
232 return FALSE;
234 iter->user_data = cookie;
235 iter->user_data3 = proto_registrar_get_nth(proto_id);
236 return TRUE;
239 /* field */
241 void *cookie2 = iter->user_data2;
242 header_field_info *hfinfo;
244 hfinfo = proto_get_next_protocol_field(&cookie2);
245 /* get next field */
246 while (hfinfo) {
247 if (hfinfo->same_name_prev_id == -1)
248 break;
249 hfinfo = proto_get_next_protocol_field(&cookie2);
252 /* not found? */
253 if (!hfinfo)
254 return FALSE;
256 iter->user_data2 = cookie2;
257 iter->user_data3 = hfinfo;
258 return TRUE;
262 static gboolean
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);
268 static gint
269 proto_hier_tree_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter)
271 ProtoHierTreeModel *model;
272 gint count = 0;
274 int p_id;
275 void *cookie;
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);
282 if (iter) {
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)
289 return 0;
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)
296 continue;
297 count++;
300 } else {
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))
306 continue;
307 count++;
311 return count;
314 static GtkTreePath *
315 proto_hier_tree_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter)
317 ProtoHierTreeModel *model;
318 GtkTreePath *path;
319 int pos;
321 int p_id;
322 void *cookie;
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();
334 /* protocol */
336 int id;
338 /* XXX, assuming that protocols can't be disabled! */
339 pos = 0;
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))
344 continue;
345 pos++;
347 gtk_tree_path_append_index(path, pos);
350 /* field */
351 if (iter->user_data2 != NULL) {
352 header_field_info *hfinfo;
354 pos = 0;
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)
357 continue;
358 pos++;
360 gtk_tree_path_append_index(path, pos);
363 return path;
366 static gboolean
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;
373 static gboolean
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);
393 return TRUE;
395 /* protocol has no parent */
396 return FALSE;
399 static void
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;
416 static void
417 proto_hier_tree_model_init(ProtoHierTreeModel *model)
419 /* To check whether an iter belongs to our model. */
420 model->stamp = g_random_int();
423 static void
424 _class_finalize(GObject *object)
426 /* must chain up - finalize parent */
427 (*parent_class->finalize)(object);
430 static void
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;
441 GType
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),
455 0, /* n_preallocs */
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,
462 NULL,
463 NULL
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,
470 (GTypeFlags)0);
472 g_type_add_interface_static(proto_hier_tree_type,
473 GTK_TYPE_TREE_MODEL,
474 &tree_model_info);
476 return proto_hier_tree_type;
479 ProtoHierTreeModel *
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);
488 return model;