2 * expert_comp_table 2005 Greg Morris
3 * Portions copied from service_response_time_table.c by Ronnie Sahlberg
4 * Helper routines common to all composite expert statistics
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 #include "epan/packet_info.h"
38 #include "epan/strutil.h"
40 #include <epan/expert.h>
42 #include "ui/simple_dialog.h"
43 #include "ui/utf8_entities.h"
45 #include "ui/gtk/expert_comp_table.h"
46 #include "ui/gtk/filter_utils.h"
47 #include "ui/gtk/find_dlg.h"
48 #include "ui/gtk/color_dlg.h"
49 #include "ui/gtk/main.h"
50 #include "ui/gtk/gui_utils.h"
51 #include "ui/gtk/gtkglobals.h"
52 #include "ui/gtk/webbrowser.h"
53 #include "ui/gtk/stock_icons.h"
55 #include "ui/gtk/old-gtk-compat.h"
57 const char *packet
= "Packet:";
69 proto_data_func (GtkTreeViewColumn
*column _U_
,
70 GtkCellRenderer
*renderer
,
76 gchar
*grp
= NULL
; /* type pointer, don't free */
78 /* The col to get data from is in userdata */
79 gint data_column
= GPOINTER_TO_INT(user_data
);
81 gtk_tree_model_get(model
, iter
, data_column
, &str
, -1);
82 gtk_tree_model_get(model
, iter
, GROUP_COLUMN
, &grp
, -1);
83 /* XXX should we check that str is non NULL and print a warning or do assert? */
85 g_object_set(renderer
, "text", str
, NULL
);
87 /* it's a number right align */
88 g_object_set(renderer
, "xalign", 1.0, NULL
);
91 g_object_set(renderer
, "xalign", 0.0, NULL
);
97 proto_sort_func(GtkTreeModel
*model
,
104 gchar
*grp
= NULL
; /* type pointer, don't free */
107 /* The col to get data from is in userdata */
108 gint data_column
= GPOINTER_TO_INT(user_data
);
110 gtk_tree_model_get(model
, a
, data_column
, &str_a
, -1);
111 gtk_tree_model_get(model
, b
, data_column
, &str_b
, -1);
112 gtk_tree_model_get(model
, a
, GROUP_COLUMN
, &grp
, -1);
114 if (str_a
== str_b
) {
117 else if (str_a
== NULL
|| str_b
== NULL
) {
118 ret
= (str_a
== NULL
) ? -1 : 1;
122 gint int_a
= atoi(str_a
);
123 gint int_b
= atoi(str_b
);
126 else if (int_a
< int_b
)
132 ret
= g_ascii_strcasecmp(str_a
,str_b
);
139 static gint
find_summary_data(error_equiv_table
*err
, const expert_info_t
*expert_data
)
142 error_procedure_t
*procedure
;
144 /* First time thru values will be 0 */
145 if (err
->num_procs
==0) {
148 for (i
=0;i
<err
->num_procs
;i
++) {
149 procedure
= &g_array_index(err
->procs_array
, error_procedure_t
, i
);
150 if (strcmp(procedure
->entries
[0], expert_data
->protocol
) == 0 &&
151 strcmp(procedure
->entries
[1], expert_data
->summary
) == 0) {
159 error_select_filter_cb(GtkWidget
*widget _U_
, gpointer callback_data
, guint callback_action
)
161 int action
, type
, selection
;
162 error_equiv_table
*err
= (error_equiv_table
*)callback_data
;
164 const char *current_filter
;
165 error_procedure_t
*procedure
;
169 expert_info_t expert_data
;
172 action
=FILTER_ACTION(callback_action
);
173 type
=FILTER_ACTYPE(callback_action
);
176 if(!gtk_tree_selection_get_selected(err
->select
, &model
, &iter
)){
177 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "No selection made or the table is empty");
181 gtk_tree_model_get (model
, &iter
,
183 PROTOCOL_COLUMN
, &expert_data
.protocol
,
184 SUMMARY_COLUMN
, &expert_data
.summary
,
187 if (strcmp(grp
, packet
)==0) {
188 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "You cannot filter or search for packet number. Click on a valid item header.");
189 g_free(expert_data
.summary
);
193 /* XXX: find_summary_data doesn't (currently) reference expert_data.group. */
194 /* If "group" is required, then the message from GROUP_COLUMN will need */
195 /* to be translated to the group number (or the actual group number */
196 /* will also need to be stored in the TreeModel). */
197 selection
= find_summary_data(err
, &expert_data
);
198 /* g_free(expert_data.protocol); - const */
199 g_free(expert_data
.summary
);
201 if(selection
>=(int)err
->num_procs
){
202 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "No items are selected");
205 current_filter
=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget
));
207 /* Some expert data doesn't pass an expert item. Without this we cannot create a filter */
208 /* But allow for searching of internet for error string */
209 procedure
= &g_array_index(err
->procs_array
, error_procedure_t
, selection
);
211 if (action
!= ACTION_WEB_LOOKUP
&& action
!= ACTION_COPY
) {
213 if (0 /*procedure->fvalue_value==NULL*/) {
214 if (action
!= ACTION_FIND_FRAME
&& action
!= ACTION_FIND_NEXT
&& action
!= ACTION_FIND_PREVIOUS
) {
215 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "Wireshark cannot create a filter on this item - %s, try using find instead.",
216 procedure
->entries
[1]);
220 msg
= (char *)g_malloc(escape_string_len(procedure
->entries
[1]));
221 escape_string(msg
, procedure
->entries
[1]);
223 case ACTYPE_SELECTED
:
224 /* if no expert item was passed */
225 if (procedure
->fvalue_value
==NULL
) {
226 g_snprintf(str
, sizeof(str
), "expert.message==%s", msg
);
230 /* expert item exists. Use it. */
231 g_strlcpy(str
, procedure
->fvalue_value
, sizeof(str
));
234 case ACTYPE_NOT_SELECTED
:
235 /* if no expert item was passed */
236 if (procedure
->fvalue_value
==NULL
) {
237 g_snprintf(str
, sizeof(str
), "!(expert.message==%s)", msg
);
241 /* expert item exists. Use it. */
242 g_snprintf(str
, sizeof(str
), "!(%s)", procedure
->fvalue_value
);
245 /* the remaining cases will only exist if the expert item exists so no need to check */
246 case ACTYPE_AND_SELECTED
:
247 if ((!current_filter
) || (0 == strlen(current_filter
)))
248 g_snprintf(str
, sizeof(str
), "expert.message==%s", msg
);
250 g_snprintf(str
, sizeof(str
), "(%s) && (expert.message==%s)", current_filter
, msg
);
252 case ACTYPE_OR_SELECTED
:
253 if ((!current_filter
) || (0 == strlen(current_filter
)))
254 g_snprintf(str
, sizeof(str
), "expert.message==%s", msg
);
256 g_snprintf(str
, sizeof(str
), "(%s) || (expert.message==%s)", current_filter
, msg
);
258 case ACTYPE_AND_NOT_SELECTED
:
259 if ((!current_filter
) || (0 == strlen(current_filter
)))
260 g_snprintf(str
, sizeof(str
), "!(expert.message==%s)", msg
);
262 g_snprintf(str
, sizeof(str
), "(%s) && !(expert.message==%s)", current_filter
, msg
);
264 case ACTYPE_OR_NOT_SELECTED
:
265 if ((!current_filter
) || (0 == strlen(current_filter
)))
266 g_snprintf(str
, sizeof(str
), "!(expert.message==%s)", msg
);
268 g_snprintf(str
, sizeof(str
), "(%s) || !(expert.message==%s)", current_filter
, msg
);
271 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "Can't find menu type - %u", type
);
278 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget
), str
);
279 main_filter_packets(&cfile
, str
, FALSE
);
280 gdk_window_raise(gtk_widget_get_window(top_level
));
283 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget
), str
);
285 case ACTION_FIND_FRAME
:
286 /* When trying to perform a find without expert item, we must pass
287 * the expert string to the find window. The user might need to modify
288 * the string and click on the text search to locate the packet in question.
289 * So regardless of the type we will just bring up the find window and allow
290 * the user to modify the search criteria and options.
292 find_frame_with_filter(str
);
294 case ACTION_FIND_NEXT
:
295 /* In the case of find next, if there was no expert item, then most likely the expert
296 * string was modified to locate the text inside the message. So we can't just perform
297 * a find with the expert string or we will not really be performing a find next.
298 * In an effort to allow the user to modify the string and/or continue searching, we
299 * will just present the user with the find window again with the default expert string.
300 * A better aproach would be to attempt in capturing the last find string and utilize this
301 * with a find next/previous. Also a better approach might be to just send a <Ctl-N> keystroke.
304 case ACTION_FIND_PREVIOUS
:
305 /* In the case of find previous, if there was no expert item, then most likely the expert
306 * string was modified to locate the text inside the message. So we can't just perform
307 * a find with the expert string or we will not really be performing a find previous.
308 * In an effort to allow the user to modify the string and/or continue searching, we
309 * will just present the user with the find window again with the default expert string.
310 * A better aproach would be to attempt in capturing the last find string and utilize this
311 * with a find next/previous. Also a better approach might be to just send a <Ctl-B> keystroke.
313 if (procedure
->fvalue_value
==NULL
) {
314 find_frame_with_filter(str
);
318 /* We have an expert item so just continue search without find dialog. */
319 cf_find_packet_dfilter_string(&cfile
, str
, SD_FORWARD
);
322 case ACTION_COLORIZE
:
323 color_display_with_filter(str
);
325 case ACTION_WEB_LOOKUP
:
326 /* Lookup expert string on internet. Default search via www.google.com */
327 g_snprintf(str
, sizeof(str
), "http://www.google.com/search?hl=en&q=%s+'%s'", procedure
->entries
[0], procedure
->entries
[1]);
328 browser_open_url(str
);
332 GString
*copyString
= g_string_sized_new(0);
333 g_string_printf(copyString
, "%s: %s",
334 procedure
->entries
[0], procedure
->entries
[1]);
335 copy_to_clipboard(copyString
);
336 g_string_free(copyString
, TRUE
);
341 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "Can't find menu action - %u", action
);
346 error_show_popup_menu_cb(void *widg _U_
, GdkEvent
*event
, gpointer user_data
)
348 error_equiv_table
*err
= (error_equiv_table
*)user_data
;
349 GdkEventButton
*bevent
= (GdkEventButton
*)event
;
351 if(event
->type
==GDK_BUTTON_PRESS
&& bevent
->button
==3){
352 gtk_menu_popup(GTK_MENU(err
->menu
), NULL
, NULL
, NULL
, NULL
,
353 bevent
->button
, bevent
->time
);
360 apply_as_selected_cb(GtkWidget
*widget
, gpointer user_data
)
362 error_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_SELECTED
, 0));
365 apply_as_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
367 error_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_NOT_SELECTED
, 0));
370 apply_as_and_selected_cb(GtkWidget
*widget
, gpointer user_data
)
372 error_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_AND_SELECTED
, 0));
375 apply_as_or_selected_cb(GtkWidget
*widget
, gpointer user_data
)
377 error_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_OR_SELECTED
, 0));
380 apply_as_and_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
382 error_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED
, 0));
385 apply_as_or_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
387 error_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED
, 0));
391 prep_as_selected_cb(GtkWidget
*widget
, gpointer user_data
)
393 error_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_SELECTED
, 0));
396 prep_as_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
398 error_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED
, 0));
401 prep_as_and_selected_cb(GtkWidget
*widget
, gpointer user_data
)
403 error_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_AND_SELECTED
, 0));
406 prep_as_or_selected_cb(GtkWidget
*widget
, gpointer user_data
)
408 error_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_OR_SELECTED
, 0));
411 prep_as_and_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
413 error_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED
, 0));
416 prep_as_or_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
418 error_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED
, 0));
422 find_selected_cb(GtkWidget
*widget
, gpointer user_data
)
424 error_select_filter_cb( widget
, user_data
, CALLBACK_FIND_FRAME(ACTYPE_SELECTED
, 0));
427 find_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
429 error_select_filter_cb( widget
, user_data
, CALLBACK_FIND_FRAME(ACTYPE_NOT_SELECTED
, 0));
432 find_prev_selected_cb(GtkWidget
*widget
, gpointer user_data
)
434 error_select_filter_cb( widget
, user_data
, CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED
, 0));
437 find_prev_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
439 error_select_filter_cb( widget
, user_data
, CALLBACK_FIND_PREVIOUS(ACTYPE_NOT_SELECTED
, 0));
442 find_next_selected_cb(GtkWidget
*widget
, gpointer user_data
)
444 error_select_filter_cb( widget
, user_data
, CALLBACK_FIND_NEXT(ACTYPE_SELECTED
, 0));
447 find_next_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
449 error_select_filter_cb( widget
, user_data
, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED
, 0));
452 color_selected_cb(GtkWidget
*widget
, gpointer user_data
)
454 error_select_filter_cb( widget
, user_data
, CALLBACK_COLORIZE(ACTYPE_SELECTED
, 0));
457 color_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
459 error_select_filter_cb( widget
, user_data
, CALLBACK_COLORIZE(ACTYPE_SELECTED
, 0));
462 internet_search_cb(GtkWidget
*widget
, gpointer user_data
)
464 error_select_filter_cb( widget
, user_data
, CALLBACK_WEB_LOOKUP
);
467 copy_cb(GtkWidget
*widget
, gpointer user_data
)
469 error_select_filter_cb( widget
, user_data
, CALLBACK_COPY
);
472 static const char *ui_desc_expert_filter_popup
=
474 " <popup name='ExpertFilterPopup'>\n"
475 " <menu action='/Apply as Filter'>\n"
476 " <menuitem action='/Apply as Filter/Selected'/>\n"
477 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" not Selected'/>\n"
478 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and Selected'/>\n"
479 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or Selected'/>\n"
480 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and not Selected'/>\n"
481 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or not Selected'/>\n"
483 " <menu action='/Prepare a Filter'>\n"
484 " <menuitem action='/Prepare a Filter/Selected'/>\n"
485 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" not Selected'/>\n"
486 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and Selected'/>\n"
487 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or Selected'/>\n"
488 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and not Selected'/>\n"
489 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or not Selected'/>\n"
491 " <menu action='/Find Frame'>\n"
492 " <menu action='/Find Frame/Find Frame'>\n"
493 " <menuitem action='/Find Frame/Selected'/>\n"
494 " <menuitem action='/Find Frame/Not Selected'/>\n"
496 " <menu action='/Find Frame/Find Next'>\n"
497 " <menuitem action='/Find Next/Selected'/>\n"
498 " <menuitem action='/Find Next/Not Selected'/>\n"
500 " <menu action='/Find Frame/Find Previous'>\n"
501 " <menuitem action='/Find Previous/Selected'/>\n"
502 " <menuitem action='/Find Previous/Not Selected'/>\n"
505 " <menu action='/Colorize Procedure'>\n"
506 " <menuitem action='/Colorize Procedure/Selected'/>\n"
507 " <menuitem action='/Colorize Procedure/Not Selected'/>\n"
509 " <menu action='/Internet Search'>\n"
510 " <menuitem action='/For Info Text'/>\n"
512 " <menu action='/Copy'>\n"
513 " <menuitem action='/Copy/Protocol Plus Summary'/>\n"
523 * const gchar *stock_id;
524 * const gchar *label;
525 * const gchar *accelerator;
526 * const gchar *tooltip;
527 * GCallback callback;
529 * const gchar *name; The name of the action.
530 * const gchar *stock_id; The stock id for the action, or the name of an icon from the icon theme.
531 * const gchar *label; The label for the action. This field should typically be marked for translation,
532 * see gtk_action_group_set_translation_domain().
533 * If label is NULL, the label of the stock item with id stock_id is used.
534 * const gchar *accelerator; The accelerator for the action, in the format understood by gtk_accelerator_parse().
535 * const gchar *tooltip; The tooltip for the action. This field should typically be marked for translation,
536 * see gtk_action_group_set_translation_domain().
537 * GCallback callback; The function to call when the action is activated.
540 static const GtkActionEntry expert_popup_entries
[] = {
541 { "/Apply as Filter", NULL
, "Apply as Filter", NULL
, NULL
, NULL
},
542 { "/Prepare a Filter", NULL
, "Prepare a Filter", NULL
, NULL
, NULL
},
543 { "/Find Frame", NULL
, "Find Frame", NULL
, NULL
, NULL
},
544 { "/Find Frame/Find Frame", NULL
, "Find Frame", NULL
, NULL
, NULL
},
545 { "/Find Frame/Find Next", NULL
, "Find Next" , NULL
, NULL
, NULL
},
546 { "/Find Frame/Find Previous", NULL
, "Find Previous", NULL
, NULL
, NULL
},
547 { "/Colorize Procedure", NULL
, "Colorize Procedure", NULL
, NULL
, NULL
},
548 { "/Apply as Filter/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(apply_as_selected_cb
) },
549 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" not Selected", G_CALLBACK(apply_as_not_selected_cb
) },
550 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and Selected", G_CALLBACK(apply_as_and_selected_cb
) },
551 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or Selected", G_CALLBACK(apply_as_or_selected_cb
) },
552 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", G_CALLBACK(apply_as_and_not_selected_cb
) },
553 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", G_CALLBACK(apply_as_or_not_selected_cb
) },
554 { "/Prepare a Filter/Selected", NULL
, "Selected", NULL
, "selcted", G_CALLBACK(prep_as_selected_cb
) },
555 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" not Selected", G_CALLBACK(prep_as_not_selected_cb
) },
556 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and Selected", G_CALLBACK(prep_as_and_selected_cb
) },
557 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or Selected", G_CALLBACK(prep_as_or_selected_cb
) },
558 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", G_CALLBACK(prep_as_and_not_selected_cb
) },
559 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", G_CALLBACK(prep_as_or_not_selected_cb
) },
560 { "/Find Frame/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(find_selected_cb
) },
561 { "/Find Frame/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(find_not_selected_cb
) },
562 { "/Find Previous/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(find_prev_selected_cb
) },
563 { "/Find Previous/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(find_prev_not_selected_cb
) },
564 { "/Find Next/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(find_next_selected_cb
) },
565 { "/Find Next/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(find_next_not_selected_cb
) },
566 { "/Colorize Procedure/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(color_selected_cb
) },
567 { "/Colorize Procedure/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(color_not_selected_cb
) },
568 { "/Internet Search", WIRESHARK_STOCK_INTERNET
, "Internet Search", NULL
, "Internet Search", NULL
},
569 { "/For Info Text", NULL
, "For Info Text", NULL
, "For Info Text", G_CALLBACK(internet_search_cb
) },
570 { "/Copy", NULL
, "Copy", NULL
, "Copy", NULL
},
571 { "/Copy/Protocol Plus Summary", NULL
, "Protocol Plus Summary", NULL
, "Protocol Plus Summary", G_CALLBACK(copy_cb
) },
575 expert_goto_pkt_cb (GtkTreeSelection
*selection
, gpointer data _U_
)
582 if (gtk_tree_selection_get_selected (selection
, &model
, &iter
))
584 gtk_tree_model_get (model
, &iter
,
585 PROTOCOL_COLUMN
, &pkt
,
589 if (strcmp(grp
, packet
)==0) {
590 cf_goto_frame(&cfile
, atoi(pkt
));
597 error_create_popup_menu(error_equiv_table
*err
)
599 GtkUIManager
*ui_manager
;
600 GtkActionGroup
*action_group
;
601 GError
*error
= NULL
;
603 err
->select
= gtk_tree_view_get_selection (GTK_TREE_VIEW (err
->tree_view
));
604 gtk_tree_selection_set_mode (err
->select
, GTK_SELECTION_SINGLE
);
605 g_signal_connect (G_OBJECT (err
->select
), "changed", G_CALLBACK(expert_goto_pkt_cb
), NULL
);
607 action_group
= gtk_action_group_new ("ExpertFilterPopupActionGroup");
608 gtk_action_group_add_actions (action_group
, /* the action group */
609 (GtkActionEntry
*)expert_popup_entries
, /* an array of action descriptions */
610 G_N_ELEMENTS(expert_popup_entries
), /* the number of entries */
611 err
); /* data to pass to the action callbacks */
613 ui_manager
= gtk_ui_manager_new ();
614 gtk_ui_manager_insert_action_group (ui_manager
, action_group
, 0);
615 gtk_ui_manager_add_ui_from_string (ui_manager
,ui_desc_expert_filter_popup
, -1, &error
);
618 fprintf (stderr
, "Warning: building expert filter popup failed: %s\n",
620 g_error_free (error
);
623 err
->menu
= gtk_ui_manager_get_widget(ui_manager
, "/ExpertFilterPopup");
624 g_signal_connect(err
->tree_view
, "button_press_event", G_CALLBACK(error_show_popup_menu_cb
), err
);
628 init_error_table(error_equiv_table
*err
, guint num_procs
, GtkWidget
*vbox
)
632 GtkTreeViewColumn
*column
;
633 GtkCellRenderer
*renderer
;
634 GtkTreeSortable
*sortable
;
636 /* Create the store */
637 store
= gtk_tree_store_new (4, /* Total number of columns */
638 G_TYPE_POINTER
, /* Group */
639 G_TYPE_STRING
, /* Protocol */
640 G_TYPE_STRING
, /* Summary */
641 G_TYPE_INT
); /* Count */
644 tree
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
645 err
->tree_view
= GTK_TREE_VIEW(tree
);
646 sortable
= GTK_TREE_SORTABLE(store
);
648 /* Speed up the list display */
649 gtk_tree_view_set_fixed_height_mode(err
->tree_view
, TRUE
);
651 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW (tree
), FALSE
);
653 /* The view now holds a reference. We can get rid of our own reference */
654 g_object_unref (G_OBJECT (store
));
656 /* Create a cell renderer */
657 renderer
= gtk_cell_renderer_text_new ();
659 /* Create the first column, associating the "text" attribute of the
660 * cell_renderer to the first column of the model
662 column
= gtk_tree_view_column_new_with_attributes ("Group", renderer
, NULL
);
663 gtk_tree_view_column_set_sort_column_id(column
, GROUP_COLUMN
);
664 gtk_tree_view_column_set_resizable(column
, TRUE
);
665 gtk_tree_view_column_set_cell_data_func(column
, renderer
, str_ptr_data_func
,
666 GINT_TO_POINTER(GROUP_COLUMN
), NULL
);
668 gtk_tree_sortable_set_sort_func(sortable
, GROUP_COLUMN
, str_ptr_sort_func
,
669 GINT_TO_POINTER(GROUP_COLUMN
), NULL
);
671 gtk_tree_view_column_set_sizing(column
, GTK_TREE_VIEW_COLUMN_FIXED
);
672 gtk_tree_view_column_set_min_width(column
, 80);
673 gtk_tree_view_column_set_fixed_width(column
, 80);
674 /* Add the column to the view. */
675 gtk_tree_view_append_column (GTK_TREE_VIEW (err
->tree_view
), column
);
677 /* Second column.. Protocol. */
678 renderer
= gtk_cell_renderer_text_new ();
679 column
= gtk_tree_view_column_new_with_attributes ("Protocol", renderer
, "text", PROTOCOL_COLUMN
, NULL
);
680 gtk_tree_view_column_set_sort_column_id(column
, PROTOCOL_COLUMN
);
681 gtk_tree_view_column_set_resizable(column
, TRUE
);
682 gtk_tree_view_column_set_cell_data_func(column
, renderer
, proto_data_func
,
683 GINT_TO_POINTER(PROTOCOL_COLUMN
), NULL
);
685 gtk_tree_sortable_set_sort_func(sortable
, PROTOCOL_COLUMN
, proto_sort_func
,
686 GINT_TO_POINTER(PROTOCOL_COLUMN
), NULL
);
688 gtk_tree_view_column_set_sizing(column
, GTK_TREE_VIEW_COLUMN_FIXED
);
689 gtk_tree_view_column_set_min_width(column
, 80);
690 gtk_tree_view_column_set_fixed_width(column
, 100);
691 gtk_tree_view_append_column (GTK_TREE_VIEW (err
->tree_view
), column
);
693 /* Third column.. Summary. */
694 renderer
= gtk_cell_renderer_text_new ();
695 column
= gtk_tree_view_column_new_with_attributes ("Summary", renderer
, "text", SUMMARY_COLUMN
, NULL
);
696 gtk_tree_view_column_set_sort_column_id(column
, SUMMARY_COLUMN
);
697 gtk_tree_view_column_set_resizable(column
, TRUE
);
698 gtk_tree_view_column_set_sizing(column
, GTK_TREE_VIEW_COLUMN_FIXED
);
699 gtk_tree_view_column_set_min_width(column
, 300);
700 gtk_tree_view_column_set_fixed_width(column
,
701 700 /* window size */ -
702 (80 /* group */ + 100 /* protocol */ + 80 /* count */ +
703 24 /* border */ + 22 /* vbar */));
704 gtk_tree_view_append_column (GTK_TREE_VIEW (err
->tree_view
), column
);
706 /* Last column.. Count. */
707 renderer
= gtk_cell_renderer_text_new ();
709 g_object_set(G_OBJECT(renderer
), "xalign", 1.0, NULL
);
710 column
= gtk_tree_view_column_new_with_attributes ("Count", renderer
, "text", COUNT_COLUMN
, NULL
);
711 gtk_tree_view_column_set_sort_column_id(column
, COUNT_COLUMN
);
712 gtk_tree_view_column_set_resizable(column
, TRUE
);
713 gtk_tree_view_column_set_sizing(column
, GTK_TREE_VIEW_COLUMN_FIXED
);
714 gtk_tree_view_column_set_min_width(column
, 80);
715 gtk_tree_view_append_column (GTK_TREE_VIEW (err
->tree_view
), column
);
717 err
->scrolled_window
=scrolled_window_new(NULL
, NULL
);
719 gtk_container_add(GTK_CONTAINER(err
->scrolled_window
), GTK_WIDGET (err
->tree_view
));
721 gtk_box_pack_start(GTK_BOX(vbox
), err
->scrolled_window
, TRUE
, TRUE
, 0);
723 gtk_tree_view_set_search_column (err
->tree_view
, SUMMARY_COLUMN
); /* Allow searching the summary */
724 gtk_tree_view_set_reorderable (err
->tree_view
, TRUE
); /* Allow user to reorder data with drag n drop */
726 /* Now enable the sorting of each column */
727 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(err
->tree_view
), TRUE
);
728 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(err
->tree_view
), TRUE
);
730 gtk_widget_show(err
->scrolled_window
);
732 err
->num_procs
=num_procs
;
734 err
->text
= g_string_chunk_new(100);
735 err
->procs_array
= g_array_sized_new(FALSE
, FALSE
, sizeof(error_procedure_t
), num_procs
);
737 /* create popup menu for this table */
738 error_create_popup_menu(err
);
742 init_error_table_row(error_equiv_table
*err
, const expert_info_t
*expert_data
)
744 guint old_num_procs
=err
->num_procs
;
746 error_procedure_t
*procedure
;
748 GtkTreeIter new_iter
;
751 /* we have discovered a new procedure. Extend the table accordingly */
752 row
= find_summary_data(err
, expert_data
);
754 error_procedure_t new_procedure
;
755 /* First time we have seen this event so initialize memory table */
756 row
= old_num_procs
; /* Number of expert events since this is a new event */
758 new_procedure
.count
=0; /* count of events for this item */
759 new_procedure
.fvalue_value
= NULL
; /* Filter string value */
761 g_array_append_val(err
->procs_array
, new_procedure
);
762 procedure
= &g_array_index(err
->procs_array
, error_procedure_t
, row
);
764 /* Create the item in our memory table */
765 procedure
->entries
[0]=(char *)g_string_chunk_insert_const(err
->text
, expert_data
->protocol
); /* Protocol */
766 procedure
->entries
[1]=(char *)g_string_chunk_insert_const(err
->text
, expert_data
->summary
); /* Summary */
768 /* Create a new item in our tree view */
769 store
= GTK_TREE_STORE(gtk_tree_view_get_model(err
->tree_view
)); /* Get store */
770 gtk_tree_store_append (store
, &procedure
->iter
, NULL
); /* Acquire an iterator */
772 /* try_val_to_str return a static constant or null */
773 gtk_tree_store_set (store
, &procedure
->iter
,
774 GROUP_COLUMN
, try_val_to_str(expert_data
->group
, expert_group_vals
),
775 PROTOCOL_COLUMN
, procedure
->entries
[0],
776 SUMMARY_COLUMN
, procedure
->entries
[1], -1);
778 /* If an expert item was passed then build the filter string */
779 if (expert_data
->pitem
) {
782 g_assert(PITEM_FINFO(expert_data
->pitem
));
783 filter
= proto_construct_match_selected_string(PITEM_FINFO(expert_data
->pitem
), NULL
);
785 procedure
->fvalue_value
= g_string_chunk_insert_const(err
->text
, filter
);
787 /* Store the updated count of events */
788 err
->num_procs
= ++old_num_procs
;
791 /* Update our memory table with event data */
792 procedure
= &g_array_index(err
->procs_array
, error_procedure_t
, row
);
793 procedure
->count
++; /* increment the count of events for this item */
795 /* Update the tree with new count for this event */
796 store
= GTK_TREE_STORE(gtk_tree_view_get_model(err
->tree_view
));
797 gtk_tree_store_set(store
, &procedure
->iter
,
798 COUNT_COLUMN
, procedure
->count
,
801 g_snprintf(num
, sizeof(num
), "%d", expert_data
->packet_num
);
803 This does
not have a big performance improvment
:(
804 gtk_tree_store_insert_with_values (store
,
805 &new_iter
, /* *iter */
806 &procedure
->iter
, /* *parent*/
807 G_MAXINT
, /* position */
811 /* FIXME gtk is plagued with slow algorithms
812 gtk_tree_store_append call new_path and its nice recursive linear search....
814 if (procedure
->count
> 1000) {
815 /* If there's more than 1000 sub rows give up and prepend new rows, at least
816 it will end in a reasonable time. Anyway with so many rows it's not
817 very useful and if sorted the right order is restored.
819 gtk_tree_store_prepend(store
, &new_iter
, &procedure
->iter
);
822 gtk_tree_store_append(store
, &new_iter
, &procedure
->iter
);
824 gtk_tree_store_set(store
, &new_iter
,
826 GROUP_COLUMN
, packet
,
827 PROTOCOL_COLUMN
, num
,
833 reset_error_table_data(error_equiv_table
*err
)
837 store
= GTK_TREE_STORE(gtk_tree_view_get_model(err
->tree_view
));
838 gtk_tree_store_clear(store
);
840 /* g_string_chunk_clear() is introduced in glib 2.14 */
841 g_string_chunk_free(err
->text
);
842 err
->text
= g_string_chunk_new(100);
844 g_array_set_size(err
->procs_array
, 0);
848 free_error_table_data(error_equiv_table
*err
)
851 g_string_chunk_free(err
->text
);
852 g_array_free(err
->procs_array
, TRUE
);