forked from osmocom/wireshark
98b0812341
value in a human-readable format. Use it in the welcome screen, status bar, and Win32 interface details. Note that in the welcome screen and status bar we've switched from customary binary prefixes to strict SI. svn path=/trunk/; revision=45453
1101 lines
33 KiB
C
1101 lines
33 KiB
C
/* main_statusbar.c
|
|
*
|
|
* $Id$
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <epan/epan.h>
|
|
#include <epan/filesystem.h>
|
|
#include <epan/epan_dissect.h>
|
|
#include <epan/expert.h>
|
|
#include <epan/prefs.h>
|
|
|
|
#include "../cfile.h"
|
|
#include "../file.h"
|
|
#ifdef HAVE_LIBPCAP
|
|
#include "../capture_opts.h"
|
|
#include "../capture_ui_utils.h"
|
|
#include "../capture.h"
|
|
#endif
|
|
|
|
#include <wsutil/str_util.h>
|
|
|
|
#include "ui/main_statusbar.h"
|
|
#include "ui/recent.h"
|
|
#include "ui/utf8_entities.h"
|
|
|
|
#include "ui/gtk/main.h"
|
|
#include "ui/gtk/main_statusbar_private.h"
|
|
#include "ui/gtk/gui_utils.h"
|
|
#include "ui/gtk/gtkglobals.h"
|
|
#include "ui/gtk/expert_comp_dlg.h"
|
|
#include "ui/gtk/profile_dlg.h"
|
|
#include "ui/gtk/main_welcome.h"
|
|
#include "ui/gtk/expert_indicators.h"
|
|
#include "ui/gtk/capture_comment_icons.h"
|
|
#include "ui/gtk/keys.h"
|
|
#include "ui/gtk/menus.h"
|
|
#include "ui/gtk/edit_packet_comment_dlg.h"
|
|
|
|
/*
|
|
* The order below defines the priority of info bar contexts.
|
|
*/
|
|
typedef enum {
|
|
STATUS_LEVEL_MAIN,
|
|
STATUS_LEVEL_FILE,
|
|
STATUS_LEVEL_FILTER,
|
|
STATUS_LEVEL_HELP,
|
|
NUM_STATUS_LEVELS
|
|
} status_level_e;
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
#define DEF_READY_MESSAGE " Ready to load or capture"
|
|
#else
|
|
#define DEF_READY_MESSAGE " Ready to load file"
|
|
#endif
|
|
|
|
|
|
static GtkWidget *status_pane_left, *status_pane_right;
|
|
static GtkWidget *info_bar, *info_bar_event, *packets_bar, *profile_bar, *profile_bar_event;
|
|
static GtkWidget *expert_info_error, *expert_info_warn, *expert_info_note;
|
|
static GtkWidget *expert_info_chat, *expert_info_comment, *expert_info_none;
|
|
|
|
static GtkWidget *capture_comment_none, *capture_comment;
|
|
|
|
static guint main_ctx, file_ctx, help_ctx, filter_ctx, packets_ctx, profile_ctx;
|
|
static guint status_levels[NUM_STATUS_LEVELS];
|
|
static GString *packets_str = NULL;
|
|
static gchar *profile_str = NULL;
|
|
|
|
|
|
static void info_bar_new(void);
|
|
static void packets_bar_new(void);
|
|
static void profile_bar_new(void);
|
|
static void status_expert_new(void);
|
|
static void status_capture_comment_new(void);
|
|
|
|
/* Temporary message timeouts */
|
|
#define TEMPORARY_MSG_TIMEOUT (7 * 1000)
|
|
#define TEMPORARY_FLASH_TIMEOUT (1 * 1000)
|
|
#define TEMPORARY_FLASH_INTERVAL (TEMPORARY_FLASH_TIMEOUT / 4)
|
|
static gint flash_time;
|
|
static gboolean flash_highlight = FALSE;
|
|
|
|
static void
|
|
statusbar_push_file_msg(const gchar *msg_format, ...)
|
|
G_GNUC_PRINTF(1, 2);
|
|
|
|
/*
|
|
* Return TRUE if there are any higher priority status level messages pushed.
|
|
* Return FALSE otherwise.
|
|
*/
|
|
static gboolean
|
|
higher_priority_status_level(int level)
|
|
{
|
|
int i;
|
|
|
|
for (i = level + 1; i < NUM_STATUS_LEVELS; i++) {
|
|
if (status_levels[i])
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Push a formatted message referring to file access onto the statusbar.
|
|
*/
|
|
static void
|
|
statusbar_push_file_msg(const gchar *msg_format, ...)
|
|
{
|
|
va_list ap;
|
|
gchar *msg;
|
|
|
|
/*g_warning("statusbar_push: %s", msg);*/
|
|
if (higher_priority_status_level(STATUS_LEVEL_FILE))
|
|
return;
|
|
status_levels[STATUS_LEVEL_FILE]++;
|
|
|
|
va_start(ap, msg_format);
|
|
msg = g_strdup_vprintf(msg_format, ap);
|
|
va_end(ap);
|
|
|
|
gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
|
|
g_free(msg);
|
|
}
|
|
|
|
/*
|
|
* Pop a message referring to file access off the statusbar.
|
|
*/
|
|
static void
|
|
statusbar_pop_file_msg(void)
|
|
{
|
|
/*g_warning("statusbar_pop");*/
|
|
if (status_levels[STATUS_LEVEL_FILE] > 0) {
|
|
status_levels[STATUS_LEVEL_FILE]--;
|
|
}
|
|
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
|
|
}
|
|
|
|
/*
|
|
* Push a formatted message referring to the currently-selected field onto
|
|
* the statusbar.
|
|
*/
|
|
void
|
|
statusbar_push_field_msg(const gchar *msg_format, ...)
|
|
{
|
|
va_list ap;
|
|
gchar *msg;
|
|
|
|
if (higher_priority_status_level(STATUS_LEVEL_HELP))
|
|
return;
|
|
status_levels[STATUS_LEVEL_HELP]++;
|
|
|
|
va_start(ap, msg_format);
|
|
msg = g_strdup_vprintf(msg_format, ap);
|
|
va_end(ap);
|
|
|
|
gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
|
|
g_free(msg);
|
|
}
|
|
|
|
/*
|
|
* Pop a message referring to the currently-selected field off the statusbar.
|
|
*/
|
|
void
|
|
statusbar_pop_field_msg(void)
|
|
{
|
|
if (status_levels[STATUS_LEVEL_HELP] > 0) {
|
|
status_levels[STATUS_LEVEL_HELP]--;
|
|
}
|
|
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
|
|
}
|
|
|
|
/*
|
|
* Push a formatted message referring to the current filter onto the statusbar.
|
|
*/
|
|
void
|
|
statusbar_push_filter_msg(const gchar *msg_format, ...)
|
|
{
|
|
va_list ap;
|
|
gchar *msg;
|
|
|
|
if (higher_priority_status_level(STATUS_LEVEL_FILTER))
|
|
return;
|
|
status_levels[STATUS_LEVEL_FILTER]++;
|
|
|
|
va_start(ap, msg_format);
|
|
msg = g_strdup_vprintf(msg_format, ap);
|
|
va_end(ap);
|
|
|
|
gtk_statusbar_push(GTK_STATUSBAR(info_bar), filter_ctx, msg);
|
|
g_free(msg);
|
|
}
|
|
|
|
/*
|
|
* Pop a message referring to the current filter off the statusbar.
|
|
*/
|
|
void
|
|
statusbar_pop_filter_msg(void)
|
|
{
|
|
if (status_levels[STATUS_LEVEL_FILTER] > 0) {
|
|
status_levels[STATUS_LEVEL_FILTER]--;
|
|
}
|
|
gtk_statusbar_pop(GTK_STATUSBAR(info_bar), filter_ctx);
|
|
}
|
|
|
|
/*
|
|
* Timeout callbacks for statusbar_push_temporary_msg
|
|
*/
|
|
static gboolean
|
|
statusbar_remove_temporary_msg(gpointer data)
|
|
{
|
|
guint msg_id = GPOINTER_TO_UINT(data);
|
|
|
|
gtk_statusbar_remove(GTK_STATUSBAR(info_bar), main_ctx, msg_id);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
statusbar_flash_temporary_msg(gpointer data _U_)
|
|
{
|
|
gboolean retval = TRUE;
|
|
|
|
if (flash_time > 0) {
|
|
flash_highlight = !flash_highlight;
|
|
} else {
|
|
flash_highlight = FALSE;
|
|
retval = FALSE;
|
|
}
|
|
|
|
/*
|
|
* As of 2.18.3 gtk_drag_highlight just draws a border around the widget
|
|
* so we can abuse it here.
|
|
*/
|
|
if (flash_highlight) {
|
|
gtk_drag_highlight(info_bar);
|
|
} else {
|
|
gtk_drag_unhighlight(info_bar);
|
|
}
|
|
|
|
flash_time -= TEMPORARY_FLASH_INTERVAL;
|
|
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* Push a formatted temporary message onto the statusbar.
|
|
*/
|
|
void
|
|
statusbar_push_temporary_msg(const gchar *msg_format, ...)
|
|
{
|
|
va_list ap;
|
|
gchar *msg;
|
|
guint msg_id;
|
|
|
|
va_start(ap, msg_format);
|
|
msg = g_strdup_vprintf(msg_format, ap);
|
|
va_end(ap);
|
|
|
|
msg_id = gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, msg);
|
|
g_free(msg);
|
|
|
|
flash_time = TEMPORARY_FLASH_TIMEOUT - 1;
|
|
g_timeout_add(TEMPORARY_FLASH_INTERVAL, statusbar_flash_temporary_msg, NULL);
|
|
|
|
g_timeout_add(TEMPORARY_MSG_TIMEOUT, statusbar_remove_temporary_msg, GUINT_TO_POINTER(msg_id));
|
|
}
|
|
|
|
|
|
GtkWidget *
|
|
statusbar_new(void)
|
|
{
|
|
GtkWidget *status_hbox;
|
|
|
|
/* Status hbox */
|
|
status_hbox = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1, FALSE);
|
|
gtk_container_set_border_width(GTK_CONTAINER(status_hbox), 0);
|
|
|
|
/* info (main) statusbar */
|
|
info_bar_new();
|
|
|
|
/* packets statusbar */
|
|
packets_bar_new();
|
|
|
|
/* profile statusbar */
|
|
profile_bar_new();
|
|
|
|
/* expert info indicator */
|
|
status_expert_new();
|
|
|
|
/* Capture comments indicator */
|
|
status_capture_comment_new();
|
|
|
|
/* Pane for the statusbar */
|
|
status_pane_left = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
|
|
gtk_widget_show(status_pane_left);
|
|
status_pane_right = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
|
|
gtk_widget_show(status_pane_right);
|
|
|
|
return status_hbox;
|
|
}
|
|
|
|
void
|
|
statusbar_load_window_geometry(void)
|
|
{
|
|
if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_left)
|
|
gtk_paned_set_position(GTK_PANED(status_pane_left), recent.gui_geometry_status_pane_left);
|
|
if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_right)
|
|
gtk_paned_set_position(GTK_PANED(status_pane_right), recent.gui_geometry_status_pane_right);
|
|
}
|
|
|
|
void
|
|
statusbar_save_window_geometry(void)
|
|
{
|
|
recent.gui_geometry_status_pane_left = gtk_paned_get_position(GTK_PANED(status_pane_left));
|
|
recent.gui_geometry_status_pane_right = gtk_paned_get_position(GTK_PANED(status_pane_right));
|
|
}
|
|
|
|
|
|
/*
|
|
* Helper for statusbar_widgets_emptying()
|
|
*/
|
|
static void
|
|
foreach_remove_a_child(GtkWidget *widget, gpointer data) {
|
|
gtk_container_remove(GTK_CONTAINER(data), widget);
|
|
}
|
|
|
|
void
|
|
statusbar_widgets_emptying(GtkWidget *statusbar)
|
|
{
|
|
g_object_ref(G_OBJECT(info_bar));
|
|
g_object_ref(G_OBJECT(info_bar_event));
|
|
g_object_ref(G_OBJECT(packets_bar));
|
|
g_object_ref(G_OBJECT(profile_bar));
|
|
g_object_ref(G_OBJECT(profile_bar_event));
|
|
g_object_ref(G_OBJECT(status_pane_left));
|
|
g_object_ref(G_OBJECT(status_pane_right));
|
|
g_object_ref(G_OBJECT(expert_info_error));
|
|
g_object_ref(G_OBJECT(expert_info_warn));
|
|
g_object_ref(G_OBJECT(expert_info_note));
|
|
g_object_ref(G_OBJECT(expert_info_chat));
|
|
g_object_ref(G_OBJECT(expert_info_comment));
|
|
g_object_ref(G_OBJECT(expert_info_none));
|
|
g_object_ref(G_OBJECT(capture_comment));
|
|
g_object_ref(G_OBJECT(capture_comment_none));
|
|
|
|
|
|
/* empty all containers participating */
|
|
gtk_container_foreach(GTK_CONTAINER(statusbar), foreach_remove_a_child, statusbar);
|
|
gtk_container_foreach(GTK_CONTAINER(status_pane_left), foreach_remove_a_child, status_pane_left);
|
|
gtk_container_foreach(GTK_CONTAINER(status_pane_right), foreach_remove_a_child, status_pane_right);
|
|
}
|
|
|
|
void
|
|
statusbar_widgets_pack(GtkWidget *statusbar)
|
|
{
|
|
gtk_box_pack_start(GTK_BOX(statusbar), expert_info_error, FALSE, FALSE, 2);
|
|
gtk_box_pack_start(GTK_BOX(statusbar), expert_info_warn, FALSE, FALSE, 2);
|
|
gtk_box_pack_start(GTK_BOX(statusbar), expert_info_note, FALSE, FALSE, 2);
|
|
gtk_box_pack_start(GTK_BOX(statusbar), expert_info_chat, FALSE, FALSE, 2);
|
|
gtk_box_pack_start(GTK_BOX(statusbar), expert_info_comment, FALSE, FALSE, 2);
|
|
gtk_box_pack_start(GTK_BOX(statusbar), expert_info_none, FALSE, FALSE, 2);
|
|
gtk_box_pack_start(GTK_BOX(statusbar), capture_comment, FALSE, FALSE, 2);
|
|
gtk_box_pack_start(GTK_BOX(statusbar), capture_comment_none, FALSE, FALSE, 2);
|
|
gtk_box_pack_start(GTK_BOX(statusbar), status_pane_left, TRUE, TRUE, 0);
|
|
gtk_paned_pack1(GTK_PANED(status_pane_left), info_bar_event, FALSE, FALSE);
|
|
gtk_paned_pack2(GTK_PANED(status_pane_left), status_pane_right, TRUE, FALSE);
|
|
gtk_paned_pack1(GTK_PANED(status_pane_right), packets_bar, TRUE, FALSE);
|
|
gtk_paned_pack2(GTK_PANED(status_pane_right), profile_bar_event, FALSE, FALSE);
|
|
}
|
|
|
|
void
|
|
statusbar_widgets_show_or_hide(GtkWidget *statusbar)
|
|
{
|
|
/*
|
|
* Show the status hbox if either:
|
|
*
|
|
* 1) we're showing the filter toolbar and we want it in the status
|
|
* line
|
|
*
|
|
* or
|
|
*
|
|
* 2) we're showing the status bar.
|
|
*/
|
|
if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
|
|
recent.statusbar_show) {
|
|
gtk_widget_show(statusbar);
|
|
} else {
|
|
gtk_widget_hide(statusbar);
|
|
}
|
|
|
|
if (recent.statusbar_show) {
|
|
gtk_widget_show(status_pane_left);
|
|
} else {
|
|
gtk_widget_hide(status_pane_left);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
info_bar_new(void)
|
|
{
|
|
info_bar_event = gtk_event_box_new();
|
|
info_bar = gtk_statusbar_new();
|
|
gtk_container_add(GTK_CONTAINER(info_bar_event), info_bar);
|
|
main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
|
|
file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
|
|
help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
|
|
filter_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "filter");
|
|
#if !GTK_CHECK_VERSION(3,0,0)
|
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
|
|
#endif
|
|
gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
|
|
|
|
memset(status_levels, 0, sizeof(status_levels));
|
|
|
|
gtk_widget_show(info_bar);
|
|
gtk_widget_show(info_bar_event);
|
|
}
|
|
|
|
static void
|
|
packets_bar_new(void)
|
|
{
|
|
/* tip: tooltips don't work on statusbars! */
|
|
packets_bar = gtk_statusbar_new();
|
|
packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
|
|
packets_bar_update();
|
|
#if !GTK_CHECK_VERSION(3,0,0)
|
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(packets_bar), FALSE);
|
|
#endif
|
|
|
|
gtk_widget_show(packets_bar);
|
|
}
|
|
|
|
static void
|
|
profile_bar_new(void)
|
|
{
|
|
profile_bar_event = gtk_event_box_new();
|
|
profile_bar = gtk_statusbar_new();
|
|
gtk_container_add(GTK_CONTAINER(profile_bar_event), profile_bar);
|
|
g_signal_connect(profile_bar_event, "button_press_event", G_CALLBACK(profile_show_popup_cb), NULL);
|
|
g_signal_connect(profile_bar_event, "button_press_event", G_CALLBACK(popup_menu_handler),
|
|
g_object_get_data(G_OBJECT(popup_menu_object), PM_STATUSBAR_PROFILES_KEY));
|
|
profile_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(profile_bar), "profile");
|
|
gtk_widget_set_tooltip_text(profile_bar_event, "Click to change configuration profile");
|
|
profile_bar_update();
|
|
#if !GTK_CHECK_VERSION(3,0,0)
|
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(profile_bar), FALSE);
|
|
#endif
|
|
|
|
gtk_widget_show(profile_bar);
|
|
gtk_widget_show(profile_bar_event);
|
|
}
|
|
|
|
|
|
/*
|
|
* Update the packets statusbar to the current values
|
|
*/
|
|
void
|
|
packets_bar_update(void)
|
|
{
|
|
if(packets_bar) {
|
|
/* Remove old status */
|
|
if(packets_str) {
|
|
gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
|
|
} else {
|
|
packets_str = g_string_new ("");
|
|
}
|
|
|
|
/* Do we have any packets? */
|
|
if(cfile.count) {
|
|
g_string_printf(packets_str, " Packets: %u " UTF8_MIDDLE_DOT
|
|
" Displayed: %u (%.1f%%) ",
|
|
cfile.count,
|
|
cfile.displayed_count,
|
|
(100.0 * cfile.displayed_count)/cfile.count);
|
|
if(cfile.marked_count) {
|
|
g_string_append_printf(packets_str, " " UTF8_MIDDLE_DOT " Marked: %u (%.1f%%)",
|
|
cfile.marked_count, (100.0 * cfile.marked_count)/cfile.count);
|
|
}
|
|
if(cfile.drops_known) {
|
|
g_string_append_printf(packets_str, " " UTF8_MIDDLE_DOT " Dropped: %u (%.1f%%)",
|
|
cfile.drops, (100.0 * cfile.drops)/cfile.count);
|
|
}
|
|
if(cfile.ignored_count) {
|
|
g_string_append_printf(packets_str, " " UTF8_MIDDLE_DOT " Ignored: %u (%.1f%%)",
|
|
cfile.ignored_count, (100.0 * cfile.ignored_count)/cfile.count);
|
|
}
|
|
if(!cfile.is_tempfile){
|
|
/* Loading an existing file */
|
|
gulong computed_elapsed = cf_get_computed_elapsed();
|
|
g_string_append_printf(packets_str, " " UTF8_MIDDLE_DOT " Load time: %lu:%02lu.%03lu",
|
|
computed_elapsed/60000,
|
|
computed_elapsed%60000/1000,
|
|
computed_elapsed%1000);
|
|
}
|
|
} else {
|
|
g_string_printf(packets_str, " No Packets");
|
|
}
|
|
gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str->str);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Update the packets statusbar to the current values
|
|
*/
|
|
void
|
|
profile_bar_update(void)
|
|
{
|
|
if (profile_bar) {
|
|
/* remove old status */
|
|
if(profile_str) {
|
|
g_free(profile_str);
|
|
gtk_statusbar_pop(GTK_STATUSBAR(profile_bar), profile_ctx);
|
|
}
|
|
|
|
profile_str = g_strdup_printf (" Profile: %s", get_profile_name ());
|
|
gtk_statusbar_push(GTK_STATUSBAR(profile_bar), profile_ctx, profile_str);
|
|
|
|
set_menus_for_profiles(is_default_profile());
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
expert_comp_dlg_event_cb(GtkWidget *w _U_, GdkEventButton *event _U_, gpointer user_data _U_)
|
|
{
|
|
expert_comp_dlg_launch();
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
edit_capture_comment_dlg_event_cb(GtkWidget *w _U_, GdkEventButton *event _U_, gpointer user_data _U_)
|
|
{
|
|
edit_capture_dlg_launch();
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
status_expert_new(void)
|
|
{
|
|
GtkWidget *expert_image;
|
|
|
|
expert_image = pixbuf_to_widget(expert_error_pb_data);
|
|
gtk_widget_set_tooltip_text(expert_image, "ERROR is the highest expert info level");
|
|
gtk_widget_show(expert_image);
|
|
expert_info_error = gtk_event_box_new();
|
|
gtk_container_add(GTK_CONTAINER(expert_info_error), expert_image);
|
|
g_signal_connect(expert_info_error, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
|
|
|
|
expert_image = pixbuf_to_widget(expert_warn_pb_data);
|
|
gtk_widget_set_tooltip_text(expert_image, "WARNING is the highest expert info level");
|
|
gtk_widget_show(expert_image);
|
|
expert_info_warn = gtk_event_box_new();
|
|
gtk_container_add(GTK_CONTAINER(expert_info_warn), expert_image);
|
|
g_signal_connect(expert_info_warn, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
|
|
|
|
expert_image = pixbuf_to_widget(expert_note_pb_data);
|
|
gtk_widget_set_tooltip_text(expert_image, "NOTE is the highest expert info level");
|
|
gtk_widget_show(expert_image);
|
|
expert_info_note = gtk_event_box_new();
|
|
gtk_container_add(GTK_CONTAINER(expert_info_note), expert_image);
|
|
g_signal_connect(expert_info_note, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
|
|
|
|
expert_image = pixbuf_to_widget(expert_chat_pb_data);
|
|
gtk_widget_set_tooltip_text(expert_image, "CHAT is the highest expert info level");
|
|
gtk_widget_show(expert_image);
|
|
expert_info_chat = gtk_event_box_new();
|
|
gtk_container_add(GTK_CONTAINER(expert_info_chat), expert_image);
|
|
g_signal_connect(expert_info_chat, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
|
|
|
|
expert_image = gtk_image_new_from_stock(GTK_STOCK_YES, GTK_ICON_SIZE_MENU);
|
|
gtk_widget_set_tooltip_text(expert_image, "COMMENT is the highest expert info level");
|
|
gtk_widget_show(expert_image);
|
|
expert_info_comment = gtk_event_box_new();
|
|
gtk_container_add(GTK_CONTAINER(expert_info_comment), expert_image);
|
|
g_signal_connect(expert_info_comment, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
|
|
|
|
expert_image = pixbuf_to_widget(expert_none_pb_data);
|
|
gtk_widget_set_tooltip_text(expert_image, "No expert info");
|
|
gtk_widget_show(expert_image);
|
|
expert_info_none = gtk_event_box_new();
|
|
gtk_container_add(GTK_CONTAINER(expert_info_none), expert_image);
|
|
g_signal_connect(expert_info_none, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
|
|
}
|
|
|
|
static void
|
|
status_expert_hide(void)
|
|
{
|
|
/* reset expert info indicator */
|
|
gtk_widget_hide(expert_info_error);
|
|
gtk_widget_hide(expert_info_warn);
|
|
gtk_widget_hide(expert_info_note);
|
|
gtk_widget_hide(expert_info_chat);
|
|
gtk_widget_hide(expert_info_comment);
|
|
gtk_widget_hide(expert_info_none);
|
|
}
|
|
|
|
void
|
|
status_expert_update(void)
|
|
{
|
|
status_expert_hide();
|
|
|
|
switch(expert_get_highest_severity()) {
|
|
case(PI_ERROR):
|
|
gtk_widget_show(expert_info_error);
|
|
break;
|
|
case(PI_WARN):
|
|
gtk_widget_show(expert_info_warn);
|
|
break;
|
|
case(PI_NOTE):
|
|
gtk_widget_show(expert_info_note);
|
|
break;
|
|
case(PI_CHAT):
|
|
gtk_widget_show(expert_info_chat);
|
|
break;
|
|
case(PI_COMMENT):
|
|
gtk_widget_show(expert_info_comment);
|
|
break;
|
|
default:
|
|
gtk_widget_show(expert_info_none);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
status_capture_comment_new(void)
|
|
{
|
|
GtkWidget *comment_image;
|
|
|
|
comment_image = pixbuf_to_widget(capture_comment_update_pb_data);
|
|
gtk_widget_set_tooltip_text(comment_image, "Read or edit the comment for this capture file");
|
|
gtk_widget_show(comment_image);
|
|
capture_comment = gtk_event_box_new();
|
|
gtk_container_add(GTK_CONTAINER(capture_comment), comment_image);
|
|
g_signal_connect(capture_comment, "button_press_event", G_CALLBACK(edit_capture_comment_dlg_event_cb), NULL);
|
|
|
|
comment_image = pixbuf_to_widget(capture_comment_add_pb_data);
|
|
gtk_widget_set_tooltip_text(comment_image, "Add a comment to this capture file");
|
|
gtk_widget_show(comment_image);
|
|
capture_comment_none = gtk_event_box_new();
|
|
gtk_container_add(GTK_CONTAINER(capture_comment_none), comment_image);
|
|
g_signal_connect(capture_comment_none, "button_press_event", G_CALLBACK(edit_capture_comment_dlg_event_cb), NULL);
|
|
|
|
/* comment_image = pixbuf_to_widget(capture_comment_disabled_pb_data); ... */
|
|
|
|
}
|
|
|
|
static void
|
|
status_capture_comment_hide(void)
|
|
{
|
|
/* reset capture coment info indicator */
|
|
gtk_widget_hide(capture_comment);
|
|
gtk_widget_hide(capture_comment_none);
|
|
}
|
|
|
|
void
|
|
status_capture_comment_update(void)
|
|
{
|
|
const gchar *comment_str;
|
|
|
|
status_capture_comment_hide();
|
|
|
|
comment_str = cf_read_shb_comment(&cfile);
|
|
|
|
/* *comment_str==0x0 -> comment exists, but it's empty */
|
|
if(comment_str!=NULL && *comment_str!=0x0){
|
|
gtk_widget_show(capture_comment);
|
|
}else{
|
|
gtk_widget_show(capture_comment_none);
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
statusbar_set_filename(const char *file_name, gint64 file_length, nstime_t *file_elapsed_time)
|
|
{
|
|
gchar *size_str;
|
|
|
|
/* expert info indicator */
|
|
status_expert_update();
|
|
|
|
/* statusbar */
|
|
size_str = format_size(file_length, format_size_unit_bytes|format_size_prefix_si);
|
|
|
|
statusbar_push_file_msg(" File: \"%s\" %s %02lu:%02lu:%02lu",
|
|
(file_name) ? file_name : "", size_str,
|
|
(long)file_elapsed_time->secs/3600,
|
|
(long)file_elapsed_time->secs%3600/60,
|
|
(long)file_elapsed_time->secs%60);
|
|
g_free(size_str);
|
|
}
|
|
|
|
|
|
static void
|
|
statusbar_cf_file_closing_cb(capture_file *cf _U_)
|
|
{
|
|
/* Clear any file-related status bar messages.
|
|
XXX - should be "clear *ALL* file-related status bar messages;
|
|
will there ever be more than one on the stack? */
|
|
statusbar_pop_file_msg();
|
|
|
|
/* reset expert info indicator */
|
|
status_expert_hide();
|
|
gtk_widget_show(expert_info_none);
|
|
}
|
|
|
|
|
|
static void
|
|
statusbar_cf_file_closed_cb(capture_file *cf _U_)
|
|
{
|
|
/* go back to "No packets" */
|
|
packets_bar_update();
|
|
/* Remove comments icon */
|
|
status_capture_comment_hide();
|
|
/* Remove experts icon */
|
|
status_expert_hide();
|
|
}
|
|
|
|
|
|
static void
|
|
statusbar_cf_file_read_started_cb(capture_file *cf, const char *action)
|
|
{
|
|
gchar *name_ptr;
|
|
|
|
/* Ensure we pop any previous loaded filename */
|
|
statusbar_pop_file_msg();
|
|
|
|
name_ptr = g_filename_display_basename(cf->filename);
|
|
statusbar_push_file_msg(" %s: %s", action, name_ptr);
|
|
g_free(name_ptr);
|
|
}
|
|
|
|
|
|
static void
|
|
statusbar_cf_file_read_finished_cb(capture_file *cf)
|
|
{
|
|
statusbar_pop_file_msg();
|
|
statusbar_set_filename(cf->filename, cf->f_datalen, &(cf->elapsed_time));
|
|
status_capture_comment_update();
|
|
}
|
|
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
static void
|
|
statusbar_capture_prepared_cb(capture_options *capture_opts _U_)
|
|
{
|
|
static const gchar msg[] = " Waiting for capture input data ...";
|
|
statusbar_push_file_msg(msg);
|
|
welcome_header_push_msg(msg);
|
|
}
|
|
|
|
static GString *
|
|
statusbar_get_interface_names(capture_options *capture_opts)
|
|
{
|
|
guint i;
|
|
GString *interface_names;
|
|
|
|
interface_names = g_string_new("");
|
|
|
|
#ifdef _WIN32
|
|
if (capture_opts->ifaces->len < 2) {
|
|
#else
|
|
if (capture_opts->ifaces->len < 4) {
|
|
#endif
|
|
for (i = 0; i < capture_opts->ifaces->len; i++) {
|
|
if (i > 0) {
|
|
g_string_append_printf(interface_names, ", ");
|
|
}
|
|
g_string_append_printf(interface_names, "%s", get_iface_description_for_interface(capture_opts, i));
|
|
}
|
|
} else {
|
|
g_string_append_printf(interface_names, "%u interfaces", capture_opts->ifaces->len);
|
|
}
|
|
if (strlen (interface_names->str) > 0) {
|
|
g_string_append(interface_names, ":");
|
|
}
|
|
g_string_append(interface_names, " ");
|
|
return (interface_names);
|
|
}
|
|
|
|
static void
|
|
statusbar_capture_update_started_cb(capture_options *capture_opts)
|
|
{
|
|
GString *interface_names;
|
|
|
|
statusbar_pop_file_msg();
|
|
welcome_header_pop_msg();
|
|
|
|
interface_names = statusbar_get_interface_names(capture_opts);
|
|
statusbar_push_file_msg("%s<live capture in progress> to file: %s",
|
|
interface_names->str,
|
|
(capture_opts->save_file) ? capture_opts->save_file : "");
|
|
g_string_free(interface_names, TRUE);
|
|
|
|
status_capture_comment_update();
|
|
}
|
|
|
|
static void
|
|
statusbar_capture_update_continue_cb(capture_options *capture_opts)
|
|
{
|
|
GString *interface_names;
|
|
capture_file *cf = capture_opts->cf;
|
|
|
|
status_expert_update();
|
|
|
|
statusbar_pop_file_msg();
|
|
|
|
interface_names = statusbar_get_interface_names(capture_opts);
|
|
if (cf->f_datalen/1024/1024 > 10) {
|
|
statusbar_push_file_msg("%s<live capture in progress> File: %s %" G_GINT64_MODIFIER "d MB",
|
|
interface_names->str,
|
|
capture_opts->save_file,
|
|
cf->f_datalen/1024/1024);
|
|
} else if (cf->f_datalen/1024 > 10) {
|
|
statusbar_push_file_msg("%s<live capture in progress> File: %s %" G_GINT64_MODIFIER "d KB",
|
|
interface_names->str,
|
|
capture_opts->save_file,
|
|
cf->f_datalen/1024);
|
|
} else {
|
|
statusbar_push_file_msg("%s<live capture in progress> File: %s %" G_GINT64_MODIFIER "d Bytes",
|
|
interface_names->str,
|
|
capture_opts->save_file,
|
|
cf->f_datalen);
|
|
}
|
|
g_string_free(interface_names, TRUE);
|
|
}
|
|
|
|
static void
|
|
statusbar_capture_update_finished_cb(capture_options *capture_opts)
|
|
{
|
|
capture_file *cf = capture_opts->cf;
|
|
|
|
/* Pop the "<live capture in progress>" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
statusbar_set_filename(cf->filename, cf->f_datalen, &(cf->elapsed_time));
|
|
packets_bar_update();
|
|
}
|
|
|
|
static void
|
|
statusbar_capture_fixed_started_cb(capture_options *capture_opts)
|
|
{
|
|
GString *interface_names;
|
|
|
|
statusbar_pop_file_msg();
|
|
|
|
interface_names = statusbar_get_interface_names(capture_opts);
|
|
statusbar_push_file_msg("%s<live capture in progress> to file: %s",
|
|
interface_names->str,
|
|
(capture_opts->save_file) ? capture_opts->save_file : "");
|
|
|
|
gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, " Packets: 0");
|
|
g_string_free(interface_names, TRUE);
|
|
}
|
|
|
|
static void
|
|
statusbar_capture_fixed_continue_cb(capture_options *capture_opts)
|
|
{
|
|
capture_file *cf = capture_opts->cf;
|
|
gchar *capture_msg;
|
|
|
|
|
|
gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
|
|
capture_msg = g_strdup_printf(" Packets: %u", cf_get_packet_count(cf));
|
|
gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, capture_msg);
|
|
g_free(capture_msg);
|
|
}
|
|
|
|
|
|
static void
|
|
statusbar_capture_fixed_finished_cb(capture_options *capture_opts _U_)
|
|
{
|
|
#if 0
|
|
capture_file *cf = capture_opts->cf;
|
|
#endif
|
|
|
|
/* Pop the "<live capture in progress>" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
welcome_header_pop_msg();
|
|
|
|
/* Pop the "<capturing>" message off the status bar */
|
|
gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
|
|
}
|
|
|
|
static void
|
|
statusbar_capture_failed_cb(capture_options *capture_opts _U_)
|
|
{
|
|
#if 0
|
|
capture_file *cf = capture_opts->cf;
|
|
#endif
|
|
|
|
/* Pop the "<live capture in progress>" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
welcome_header_pop_msg();
|
|
|
|
/* Pop the "<capturing>" message off the status bar */
|
|
gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
|
|
}
|
|
#endif /* HAVE_LIBPCAP */
|
|
|
|
|
|
static void
|
|
statusbar_cf_field_unselected_cb(capture_file *cf _U_)
|
|
{
|
|
statusbar_pop_field_msg();
|
|
}
|
|
|
|
static void
|
|
statusbar_cf_file_save_started_cb(gchar *filename)
|
|
{
|
|
statusbar_pop_file_msg();
|
|
statusbar_push_file_msg(" Saving: %s...", g_filename_display_basename(filename));
|
|
}
|
|
|
|
static void
|
|
statusbar_cf_file_save_finished_cb(gpointer data _U_)
|
|
{
|
|
/* Pop the "Saving:" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
}
|
|
|
|
static void
|
|
statusbar_cf_file_save_failed_cb(gpointer data _U_)
|
|
{
|
|
/* Pop the "Saving:" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
}
|
|
|
|
static void
|
|
statusbar_cf_file_save_stopped_cb(gpointer data _U_)
|
|
{
|
|
/* Pop the "Saving:" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
}
|
|
|
|
static void
|
|
statusbar_cf_file_export_specified_packets_started_cb(gchar *filename)
|
|
{
|
|
statusbar_pop_file_msg();
|
|
statusbar_push_file_msg(" Exporting to: %s...", g_filename_display_basename(filename));
|
|
}
|
|
|
|
static void
|
|
statusbar_cf_file_export_specified_packets_finished_cb(gpointer data _U_)
|
|
{
|
|
/* Pop the "Exporting to:" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
}
|
|
|
|
static void
|
|
statusbar_cf_file_export_specified_packets_failed_cb(gpointer data _U_)
|
|
{
|
|
/* Pop the "Exporting to:" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
}
|
|
|
|
static void
|
|
statusbar_cf_file_export_specified_packets_stopped_cb(gpointer data _U_)
|
|
{
|
|
/* Pop the "Saving:" message off the status bar. */
|
|
statusbar_pop_file_msg();
|
|
}
|
|
|
|
|
|
|
|
void
|
|
statusbar_cf_callback(gint event, gpointer data, gpointer user_data _U_)
|
|
{
|
|
switch(event) {
|
|
case(cf_cb_file_opened):
|
|
break;
|
|
case(cf_cb_file_closing):
|
|
statusbar_cf_file_closing_cb(data);
|
|
break;
|
|
case(cf_cb_file_closed):
|
|
statusbar_cf_file_closed_cb(data);
|
|
break;
|
|
case(cf_cb_file_read_started):
|
|
statusbar_cf_file_read_started_cb(data, "Loading");
|
|
break;
|
|
case(cf_cb_file_read_finished):
|
|
statusbar_cf_file_read_finished_cb(data);
|
|
break;
|
|
case(cf_cb_file_reload_started):
|
|
statusbar_cf_file_read_started_cb(data, "Reloading");
|
|
break;
|
|
case(cf_cb_file_reload_finished):
|
|
statusbar_cf_file_read_finished_cb(data);
|
|
break;
|
|
case(cf_cb_file_rescan_started):
|
|
statusbar_cf_file_read_started_cb(data, "Rescanning");
|
|
break;
|
|
case(cf_cb_file_rescan_finished):
|
|
statusbar_cf_file_read_finished_cb(data);
|
|
break;
|
|
case(cf_cb_file_fast_save_finished):
|
|
break;
|
|
case(cf_cb_packet_selected):
|
|
break;
|
|
case(cf_cb_packet_unselected):
|
|
break;
|
|
case(cf_cb_field_unselected):
|
|
statusbar_cf_field_unselected_cb(data);
|
|
break;
|
|
case(cf_cb_file_save_started):
|
|
statusbar_cf_file_save_started_cb(data);
|
|
break;
|
|
case(cf_cb_file_save_finished):
|
|
statusbar_cf_file_save_finished_cb(data);
|
|
break;
|
|
case(cf_cb_file_save_failed):
|
|
statusbar_cf_file_save_failed_cb(data);
|
|
break;
|
|
case(cf_cb_file_save_stopped):
|
|
statusbar_cf_file_save_stopped_cb(data);
|
|
break;
|
|
case(cf_cb_file_export_specified_packets_started):
|
|
statusbar_cf_file_export_specified_packets_started_cb(data);
|
|
break;
|
|
case(cf_cb_file_export_specified_packets_finished):
|
|
statusbar_cf_file_export_specified_packets_finished_cb(data);
|
|
break;
|
|
case(cf_cb_file_export_specified_packets_failed):
|
|
statusbar_cf_file_export_specified_packets_failed_cb(data);
|
|
break;
|
|
case(cf_cb_file_export_specified_packets_stopped):
|
|
statusbar_cf_file_export_specified_packets_stopped_cb(data);
|
|
break;
|
|
default:
|
|
g_warning("statusbar_cf_callback: event %u unknown", event);
|
|
g_assert_not_reached();
|
|
}
|
|
}
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
void
|
|
statusbar_capture_callback(gint event, capture_options *capture_opts,
|
|
gpointer user_data _U_)
|
|
{
|
|
switch(event) {
|
|
case(capture_cb_capture_prepared):
|
|
statusbar_capture_prepared_cb(capture_opts);
|
|
break;
|
|
case(capture_cb_capture_update_started):
|
|
statusbar_capture_update_started_cb(capture_opts);
|
|
break;
|
|
case(capture_cb_capture_update_continue):
|
|
statusbar_capture_update_continue_cb(capture_opts);
|
|
break;
|
|
case(capture_cb_capture_update_finished):
|
|
statusbar_capture_update_finished_cb(capture_opts);
|
|
break;
|
|
case(capture_cb_capture_fixed_started):
|
|
statusbar_capture_fixed_started_cb(capture_opts);
|
|
break;
|
|
case(capture_cb_capture_fixed_continue):
|
|
statusbar_capture_fixed_continue_cb(capture_opts);
|
|
break;
|
|
case(capture_cb_capture_fixed_finished):
|
|
statusbar_capture_fixed_finished_cb(capture_opts);
|
|
break;
|
|
case(capture_cb_capture_stopping):
|
|
/* Beware: this state won't be called, if the capture child
|
|
* closes the capturing on it's own! */
|
|
break;
|
|
case(capture_cb_capture_failed):
|
|
statusbar_capture_failed_cb(capture_opts);
|
|
break;
|
|
default:
|
|
g_warning("statusbar_capture_callback: event %u unknown", event);
|
|
g_assert_not_reached();
|
|
}
|
|
}
|
|
#endif
|