implemented dlg_button_row_new to get a standard function for
[obnox/wireshark/wip.git] / gtk / proto_hier_stats_dlg.c
1 /* proto_hier_stats_dlg.c
2  *
3  * $Id: proto_hier_stats_dlg.c,v 1.14 2004/01/21 21:19:34 ulfl Exp $
4  *
5  * Ethereal - Network traffic analyzer
6  * By Gerald Combs <gerald@ethereal.com>
7  * Copyright 1998 Gerald Combs
8  *
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.
13  *
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.
18  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  */
23
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include "proto_hier_stats.h"
32 #include "dlg_utils.h"
33 #include "ui_util.h"
34 #include "main.h"
35 #include "compat_macros.h"
36
37 #if GTK_MAJOR_VERSION < 2
38 #define NUM_STAT_COLUMNS 6
39 #else
40 enum {
41     PROTOCOL_COLUMN,
42     PRCT_PKTS_COLUMN,
43     PKTS_COLUMN,
44     BYTES_COLUMN,
45     END_PKTS_COLUMN,
46     END_BYTES_COLUMN,
47     NUM_STAT_COLUMNS /* must be the last */
48 };
49 #endif
50
51 typedef struct {
52 #if GTK_MAJOR_VERSION < 2
53         GtkCTree     *tree;
54         GtkCTreeNode *parent;
55 #else
56         GtkTreeView  *tree_view;
57         GtkTreeIter  *iter;
58 #endif
59         ph_stats_t   *ps;
60 } draw_info_t;
61
62
63 #define PCT(x,y) (100.0 * (float)(x) / (float)(y))
64
65 static void
66 fill_in_tree_node(GNode *node, gpointer data)
67 {
68     ph_stats_node_t *stats = node->data;
69     draw_info_t     *di = data;
70
71 #if GTK_MAJOR_VERSION < 2
72     GtkCTree        *tree = di->tree;
73     GtkCTreeNode    *parent = di->parent;
74     gchar           *text[NUM_STAT_COLUMNS];
75     GtkCTreeNode    *new_node;
76 #else
77     GtkTreeView     *tree_view = di->tree_view;
78     GtkTreeIter     *iter = di->iter;
79     GtkTreeStore    *store;
80     gchar           *text[2];
81     GtkTreeIter      new_iter;
82 #endif
83     ph_stats_t      *ps = di->ps;
84
85     gboolean         is_leaf;
86
87     draw_info_t      child_di;
88
89     if (g_node_n_children(node) > 0) {
90         is_leaf = FALSE;
91     }
92     else {
93         is_leaf = TRUE;
94     }
95
96     text[0] = stats->hfinfo->name;
97     text[1] = g_strdup_printf("%6.2f%%",
98                               PCT(stats->num_pkts_total, ps->tot_packets));
99 #if GTK_MAJOR_VERSION < 2
100     text[2] = g_strdup_printf("%u", stats->num_pkts_total);
101     text[3] = g_strdup_printf("%u", stats->num_bytes_total);
102     text[4] = g_strdup_printf("%u", stats->num_pkts_last);
103     text[5] = g_strdup_printf("%u", stats->num_bytes_last);
104
105     new_node = gtk_ctree_insert_node(tree, parent, NULL, text,
106                                      5, NULL, NULL, NULL, NULL,
107                                      is_leaf, TRUE);
108 #else
109     store = GTK_TREE_STORE(gtk_tree_view_get_model(tree_view));
110     gtk_tree_store_append(store, &new_iter, iter);
111     gtk_tree_store_set(store, &new_iter,
112                        PROTOCOL_COLUMN, text[0],
113                        PRCT_PKTS_COLUMN, text[1],
114                        PKTS_COLUMN, stats->num_pkts_total,
115                        BYTES_COLUMN, stats->num_bytes_total,
116                        END_PKTS_COLUMN, stats->num_pkts_last,
117                        END_BYTES_COLUMN, stats->num_bytes_last,
118                        -1);
119 #endif
120
121     g_free(text[1]);
122 #if GTK_MAJOR_VERSION < 2
123     g_free(text[2]);
124     g_free(text[3]);
125     g_free(text[4]);
126     g_free(text[5]);
127
128     child_di.tree = tree;
129     child_di.parent = new_node;
130 #else
131     child_di.tree_view = tree_view;
132     child_di.iter = &new_iter;
133 #endif
134     child_di.ps = ps;
135
136     g_node_children_foreach(node, G_TRAVERSE_ALL,
137                             fill_in_tree_node, &child_di);
138 }
139
140 static void
141 fill_in_tree(GtkWidget *tree, ph_stats_t *ps)
142 {
143         draw_info_t     di;
144
145 #if GTK_MAJOR_VERSION < 2
146         di.tree = GTK_CTREE(tree);
147         di.parent = NULL;
148 #else
149         di.tree_view = GTK_TREE_VIEW(tree);
150         di.iter = NULL;
151 #endif
152         di.ps = ps;
153
154         g_node_children_foreach(ps->stats_tree, G_TRAVERSE_ALL,
155                                 fill_in_tree_node, &di);
156 }
157
158 #define MAX_DLG_HEIGHT 450
159 #define DEF_DLG_WIDTH  600
160 static void
161 create_tree(GtkWidget *container, ph_stats_t *ps)
162 {
163     GtkWidget   *sw, *tree;
164 #if GTK_MAJOR_VERSION < 2
165     int         i, height;
166     gchar               *column_titles[NUM_STAT_COLUMNS] = {
167         "Protocol",
168         "% Packets",
169         "Packets",
170         "Bytes",
171         "End Packets",
172         "End Bytes",
173     };
174 #else
175     GtkTreeView       *tree_view;
176     GtkTreeStore      *store;
177     GtkCellRenderer   *renderer;
178     GtkTreeViewColumn *column;
179 #endif
180
181     /* Scrolled Window */
182     sw = gtk_scrolled_window_new(NULL, NULL);
183     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
184                                    GTK_POLICY_AUTOMATIC,
185                                    GTK_POLICY_AUTOMATIC);
186     gtk_container_add(GTK_CONTAINER(container), sw);
187
188 #if GTK_MAJOR_VERSION < 2
189     tree = ctree_new_with_titles(NUM_STAT_COLUMNS, 0, column_titles);
190
191     /* XXX - get 'pos' to set vertical scroll-bar placement. */
192
193     /* The title bars do nothing. */
194     gtk_clist_column_titles_passive(GTK_CLIST(tree));
195
196     /* Auto Resize all columns */
197     for (i = 0; i < NUM_STAT_COLUMNS; i++) {
198         gtk_clist_set_column_auto_resize(GTK_CLIST(tree), i, TRUE);
199     }
200
201
202     /* Right justify numeric columns */
203     for (i = 1; i <= 5; i++) {
204         gtk_clist_set_column_justification(GTK_CLIST(tree), i,
205                                            GTK_JUSTIFY_RIGHT);
206     }
207 #else
208     store = gtk_tree_store_new(NUM_STAT_COLUMNS, G_TYPE_STRING,
209                                G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT,
210                                G_TYPE_UINT, G_TYPE_UINT);
211     tree = tree_view_new(GTK_TREE_MODEL(store));
212     tree_view = GTK_TREE_VIEW(tree);
213     gtk_tree_view_set_headers_visible(tree_view, TRUE);
214     gtk_tree_view_set_headers_clickable(tree_view, FALSE);
215     renderer = gtk_cell_renderer_text_new();
216     column = gtk_tree_view_column_new_with_attributes("Protocol", renderer,
217                                                       "text", PROTOCOL_COLUMN,
218                                                       NULL);
219     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
220     gtk_tree_view_append_column(tree_view, column);
221     renderer = gtk_cell_renderer_text_new();
222     column = gtk_tree_view_column_new_with_attributes("% Packets", renderer,
223                                                       "text", PRCT_PKTS_COLUMN,
224                                                       NULL);
225     g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
226     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
227     gtk_tree_view_append_column(tree_view, column);
228     renderer = gtk_cell_renderer_text_new();
229     column = gtk_tree_view_column_new_with_attributes("Packets", renderer,
230                                                       "text", PKTS_COLUMN,
231                                                       NULL);
232     g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
233     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
234     gtk_tree_view_append_column(tree_view, column);
235     renderer = gtk_cell_renderer_text_new();
236     column = gtk_tree_view_column_new_with_attributes("Bytes", renderer,
237                                                       "text", BYTES_COLUMN,
238                                                       NULL);
239     g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
240     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
241     gtk_tree_view_append_column(tree_view, column);
242     renderer = gtk_cell_renderer_text_new();
243     column = gtk_tree_view_column_new_with_attributes("End Packets",
244                                                       renderer, "text",
245                                                       END_PKTS_COLUMN, NULL);
246     g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
247     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
248     gtk_tree_view_append_column(tree_view, column);
249     renderer = gtk_cell_renderer_text_new();
250     column = gtk_tree_view_column_new_with_attributes("End Bytes", renderer,
251                                                       "text", END_BYTES_COLUMN,
252                                                       NULL);
253     g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);
254     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
255     gtk_tree_view_append_column(tree_view, column);
256 #endif
257
258     /* Fill in the data. */
259     fill_in_tree(tree, ps);
260
261 #if GTK_MAJOR_VERSION < 2
262     height = GTK_CLIST(tree)->rows * (GTK_CLIST(tree)->row_height + 5);
263     height = MIN(height, MAX_DLG_HEIGHT);
264     WIDGET_SET_SIZE(tree, DEF_DLG_WIDTH, height);
265 #else
266     WIDGET_SET_SIZE(tree, DEF_DLG_WIDTH, MAX_DLG_HEIGHT);
267 #endif
268
269     gtk_container_add(GTK_CONTAINER(sw), tree);
270     ph_stats_free(ps);
271 }
272
273 void
274 proto_hier_stats_cb(GtkWidget *w _U_, gpointer d _U_)
275 {
276         ph_stats_t      *ps;
277         GtkWidget       *dlg, *ok_bt, *vbox, *bbox;
278
279         /* Get the statistics. */
280         ps = ph_stats_new();
281         if (ps == NULL) {
282                 /* The user gave up before we finished; don't pop up
283                    a statistics window. */
284                 return;
285         }
286
287         dlg = dlg_window_new("Ethereal: Protocol Hierarchy Statistics");
288
289         vbox = gtk_vbox_new(FALSE, 5);
290         gtk_container_border_width(GTK_CONTAINER(vbox), 5);
291         gtk_container_add(GTK_CONTAINER(dlg), vbox);
292
293         /* Data section */
294         create_tree(vbox, ps);
295
296         /* Button row. */
297     bbox = dlg_button_row_new(GTK_STOCK_OK, NULL);
298     gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
299     gtk_widget_show(bbox);
300
301     ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
302         SIGNAL_CONNECT_OBJECT(ok_bt, "clicked", gtk_widget_destroy, dlg);
303     gtk_widget_grab_default(ok_bt);
304
305     /* Catch the "key_press_event" signal in the window, so that we can catch
306        the ESC key being pressed and act as if the "OK" button had
307        been selected. */
308         dlg_set_cancel(dlg, ok_bt);
309
310         gtk_widget_show_all(dlg);
311
312 }
313