Fix the wireless settings button for AirPCap devices in the
[obnox/wireshark/wip.git] / gtk / ansi_map_stat.c
1 /* ansi_map_stat.c
2  *
3  * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
4  * In association with Telos Technology Inc.
5  *
6  * MUCH code modified from service_response_time_table.c.
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 /*
30  * This TAP provides statistics for ANSI MAP:
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <gtk/gtk.h>
38 #include <string.h>
39
40 #include <epan/packet_info.h>
41 #include <epan/epan.h>
42 #include <epan/value_string.h>
43 #include <epan/stat_cmd_args.h>
44 #include <epan/tap.h>
45 #include <epan/dissectors/packet-ansi_map.h>
46
47 #include "../stat_menu.h"
48 #include "../simple_dialog.h"
49
50 #include "gtk/gui_stat_menu.h"
51 #include "gtk/dlg_utils.h"
52 #include "gtk/filter_dlg.h"
53 #include "gtk/gui_utils.h"
54
55 #include "gtk/old-gtk-compat.h"
56
57 enum
58 {
59     OP_CODE_COLUMN,
60     OP_CODE_NAME_COLUMN,
61     COUNT_COLUMN,
62     TOT_BYTES_COLUMN,
63     AVG_BYTES_COLUMN,
64     N_COLUMN /* The number of columns */
65 };
66
67 typedef struct _ansi_map_stat_dlg_t {
68     GtkWidget       *win;
69     GtkWidget       *scrolled_win;
70     GtkWidget       *table;
71 } ansi_map_stat_dlg_t;
72
73 typedef struct _ansi_map_stat_t {
74     int         message_type[ANSI_MAP_MAX_NUM_MESSAGE_TYPES];
75     double      size[ANSI_MAP_MAX_NUM_MESSAGE_TYPES];
76 } ansi_map_stat_t;
77
78 static ansi_map_stat_dlg_t  dlg;
79 static ansi_map_stat_t      ansi_a_stat;
80
81 /* Create list */
82 static
83 GtkWidget* create_list(void)
84 {
85
86     GtkListStore *list_store;
87     GtkWidget *list;
88     GtkTreeViewColumn *column;
89     GtkCellRenderer *renderer;
90     GtkTreeSortable *sortable;
91     GtkTreeView     *list_view;
92     GtkTreeSelection  *selection;
93
94     /* Create the store */
95     list_store = gtk_list_store_new(N_COLUMN,   /* Total number of columns XXX*/
96                                     G_TYPE_UINT,     /* Op Code          */
97                                     G_TYPE_STRING,   /* Operation Name   */
98                                     G_TYPE_UINT,     /* Count            */
99                                     G_TYPE_UINT,     /* Total Bytes      */
100                                     G_TYPE_FLOAT);   /* Avg Bytes        */
101
102     /* Create a view */
103     list = gtk_tree_view_new_with_model (GTK_TREE_MODEL (list_store));
104
105     list_view = GTK_TREE_VIEW(list);
106     sortable = GTK_TREE_SORTABLE(list_store);
107
108     /* Speed up the list display */
109     gtk_tree_view_set_fixed_height_mode(list_view, TRUE);
110
111     /* Setup the sortable columns */
112     gtk_tree_sortable_set_sort_column_id(sortable, OP_CODE_COLUMN, GTK_SORT_ASCENDING);
113     gtk_tree_view_set_headers_clickable(list_view, FALSE);
114
115     /* The view now holds a reference.  We can get rid of our own reference */
116     g_object_unref (G_OBJECT (list_store));
117
118     /*
119      * Create the first column packet, associating the "text" attribute of the
120      * cell_renderer to the first column of the model
121      */
122     /* 1:st column */
123     renderer = gtk_cell_renderer_text_new ();
124     column = gtk_tree_view_column_new_with_attributes ("Op Code", renderer,
125         "text", OP_CODE_COLUMN,
126         NULL);
127
128     gtk_tree_view_column_set_cell_data_func(column, renderer, present_as_hex_func,
129         GINT_TO_POINTER(OP_CODE_COLUMN), NULL);
130
131     gtk_tree_view_column_set_sort_column_id(column, OP_CODE_COLUMN);
132     gtk_tree_view_column_set_resizable(column, TRUE);
133     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
134     gtk_tree_view_column_set_min_width(column, 60);
135
136     /* Add the column to the view. */
137     gtk_tree_view_append_column (list_view, column);
138
139     /* 2:nd column... */
140     renderer = gtk_cell_renderer_text_new ();
141     column = gtk_tree_view_column_new_with_attributes ("Operation Name", renderer,
142         "text", OP_CODE_NAME_COLUMN,
143         NULL);
144     gtk_tree_view_column_set_sort_column_id(column, OP_CODE_NAME_COLUMN);
145     gtk_tree_view_column_set_resizable(column, TRUE);
146     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
147     gtk_tree_view_column_set_min_width(column, 290);
148     gtk_tree_view_append_column (list_view, column);
149
150     /* 3:d column... */
151     renderer = gtk_cell_renderer_text_new ();
152     column = gtk_tree_view_column_new_with_attributes ("Count", renderer,
153         "text", COUNT_COLUMN,
154         NULL);
155     gtk_tree_view_column_set_sort_column_id(column, COUNT_COLUMN);
156     gtk_tree_view_column_set_resizable(column, TRUE);
157     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
158     gtk_tree_view_column_set_min_width(column, 50);
159     gtk_tree_view_append_column (list_view, column);
160
161     /* 4:th column... */
162     renderer = gtk_cell_renderer_text_new ();
163     column = gtk_tree_view_column_new_with_attributes ("Total Bytes", renderer,
164         "text", TOT_BYTES_COLUMN,
165         NULL);
166
167
168     gtk_tree_view_column_set_sort_column_id(column, TOT_BYTES_COLUMN);
169     gtk_tree_view_column_set_resizable(column, TRUE);
170     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
171     gtk_tree_view_column_set_min_width(column, 100);
172     gtk_tree_view_append_column (list_view, column);
173
174     /* 10:th column.. Avg Bytes. */
175     renderer = gtk_cell_renderer_text_new ();
176     column = gtk_tree_view_column_new_with_attributes ("Avg Bytes", renderer,
177         "text", AVG_BYTES_COLUMN,
178         NULL);
179     gtk_tree_view_column_set_cell_data_func(column, renderer, float_data_func,
180         GINT_TO_POINTER(AVG_BYTES_COLUMN), NULL);
181
182     gtk_tree_view_column_set_sort_column_id(column, AVG_BYTES_COLUMN);
183     gtk_tree_view_column_set_resizable(column, TRUE);
184     gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
185     gtk_tree_view_column_set_min_width(column, 50);
186     gtk_tree_view_append_column (list_view, column);
187
188     /* Now enable the sorting of each column */
189     gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(list_view), TRUE);
190     gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list_view), TRUE);
191
192     /* Setup the selection handler */
193     selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
194     gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
195
196     return list;
197
198 }
199
200 static void
201 ansi_map_stat_reset(
202     void        *tapdata)
203 {
204     ansi_map_stat_t *stat_p = tapdata;
205
206     memset(stat_p, 0, sizeof(ansi_map_stat_t));
207 }
208
209
210 static gboolean
211 ansi_map_stat_packet(
212     void        *tapdata,
213     packet_info     *pinfo _U_,
214     epan_dissect_t  *edt _U_,
215     const void      *data)
216 {
217     ansi_map_stat_t *stat_p = tapdata;
218     const ansi_map_tap_rec_t    *data_p = data;
219
220 #if 0   /* always false because message_type is 8 bit value */
221     if (data_p->message_type >= ANSI_MAP_MAX_NUM_MESSAGE_TYPES)
222     {
223     /*
224      * unknown PDU type !!!
225      */
226     return(FALSE);
227     }
228 #endif
229
230     stat_p->message_type[data_p->message_type]++;
231     stat_p->size[data_p->message_type] += data_p->size;
232
233     return(TRUE);
234 }
235
236
237 static void
238 ansi_map_stat_draw(
239     void        *tapdata)
240 {
241     ansi_map_stat_t *stat_p = tapdata;
242     int         i;
243     float       avg;
244     GtkListStore *list_store;
245     GtkTreeIter  iter;
246
247     if (dlg.win && tapdata)
248     {
249         i = 0;
250         list_store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW (dlg.table))); /* Get store */
251         while (ansi_map_opr_code_strings[i].strptr)
252         {
253             avg = 0.0f;
254             if (stat_p->message_type[ansi_map_opr_code_strings[i].value] !=0 ){
255                 avg = (float)stat_p->size[ansi_map_opr_code_strings[i].value]/(float)stat_p->message_type[ansi_map_opr_code_strings[i].value];
256             }
257             /* Creates a new row at position. iter will be changed to point to this new row.
258              * If position is larger than the number of rows on the list, then the new row will be appended to the list.
259              * The row will be filled with the values given to this function.
260              * :
261              * should generally be preferred when inserting rows in a sorted list store.
262              */
263             gtk_list_store_insert_with_values( list_store , &iter, G_MAXINT,
264                OP_CODE_COLUMN,      ansi_map_opr_code_strings[i].value,
265                OP_CODE_NAME_COLUMN, ansi_map_opr_code_strings[i].strptr,
266                COUNT_COLUMN,        (guint)stat_p->message_type[ansi_map_opr_code_strings[i].value],
267                TOT_BYTES_COLUMN,    (guint)stat_p->size[ansi_map_opr_code_strings[i].value],
268                AVG_BYTES_COLUMN,    avg,
269                -1);
270             i++;
271         }
272     }
273 }
274
275
276
277
278 static void
279 ansi_map_stat_gtk_win_destroy_cb(
280     GtkWindow       *win _U_,
281     gpointer        user_data)
282 {
283     memset((void *) user_data, 0, sizeof(ansi_map_stat_dlg_t));
284 }
285
286
287 static void
288 ansi_map_stat_gtk_win_create(
289     ansi_map_stat_dlg_t *dlg_p,
290     const char      *title)
291 {
292     GtkWidget       *vbox;
293     GtkWidget       *bt_close;
294     GtkWidget       *bbox;
295
296
297     dlg_p->win= dlg_window_new(title);  /* transient_for top_level */
298     gtk_window_set_destroy_with_parent (GTK_WINDOW(dlg_p->win), TRUE);
299
300     gtk_window_set_default_size(GTK_WINDOW(dlg_p->win), 500, 450);
301
302     vbox = gtk_vbox_new(FALSE, 3);
303     gtk_container_add(GTK_CONTAINER(dlg_p->win), vbox);
304     gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
305
306     dlg_p->scrolled_win = scrolled_window_new(NULL, NULL);
307     gtk_box_pack_start(GTK_BOX(vbox), dlg_p->scrolled_win, TRUE, TRUE, 0);
308
309     dlg_p->table = create_list();
310
311     gtk_container_add(GTK_CONTAINER(dlg_p->scrolled_win), dlg_p->table);
312
313     /* Button row. */
314     bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
315     gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
316
317     bt_close = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
318
319     window_set_cancel_button(dlg_p->win, bt_close, window_cancel_button_cb);
320
321     g_signal_connect(dlg_p->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
322     g_signal_connect(dlg_p->win, "destroy", G_CALLBACK(ansi_map_stat_gtk_win_destroy_cb), dlg_p);
323
324     gtk_widget_show_all(dlg_p->win);
325     window_present(dlg_p->win);
326 }
327
328 #ifdef MAIN_MENU_USE_UIMANAGER
329 void
330 ansi_map_stat_gtk_cb(GtkAction *action _U_, gpointer user_data _U_)
331 #else
332 static void
333 ansi_map_stat_gtk_cb(
334     GtkWidget       *w _U_,
335     gpointer        d _U_)
336 #endif
337 {
338     /*
339      * if the window is already open, bring it to front
340      */
341     if (dlg.win){
342         gdk_window_raise(gtk_widget_get_window(dlg.win));
343         return;
344     }
345
346     ansi_map_stat_gtk_win_create(&dlg, "ANSI MAP Operation Statistics");
347     ansi_map_stat_draw(&ansi_a_stat);
348 }
349
350
351 static void
352 ansi_map_stat_gtk_init(
353     const char      *optarg _U_,
354     void* userdata _U_ )
355 {
356     ansi_map_stat_gtk_cb(NULL, NULL);
357 }
358
359
360 void
361 register_tap_listener_gtkansi_map_stat(void)
362 {
363     GString     *err_p;
364
365
366     memset((void *) &ansi_a_stat, 0, sizeof(ansi_map_stat_t));
367
368     err_p =
369     register_tap_listener("ansi_map", &ansi_a_stat, NULL, 0,
370         ansi_map_stat_reset,
371         ansi_map_stat_packet,
372         ansi_map_stat_draw);
373
374     if (err_p != NULL)
375     {
376         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_p->str);
377         g_string_free(err_p, TRUE);
378
379         exit(1);
380     }
381 #ifdef MAIN_MENU_USE_UIMANAGER
382 #else
383     register_stat_menu_item("_ANSI/MAP Operation", REGISTER_STAT_GROUP_TELEPHONY,
384         ansi_map_stat_gtk_cb, NULL, NULL, NULL);
385 #endif
386     register_stat_cmd_arg("ansi_map", ansi_map_stat_gtk_init,NULL);
387 }