/* io_stat.c
* io_stat 2002 Ronnie Sahlberg
*
- * $Id: io_stat.c,v 1.21 2003/04/23 08:20:05 guy Exp $
+ * $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
# include "config.h"
#endif
-#include <stdio.h>
-
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <ctype.h>
#include <gtk/gtk.h>
+
+#include <epan/epan_dissect.h>
+#include <epan/packet_info.h>
+
#include "gtkglobals.h"
-#include "menu.h"
-#include "epan/epan_dissect.h"
-#include "epan/packet_info.h"
-#include "../tap.h"
+#include "ui_util.h"
+#include "tap_menu.h"
+#include <epan/tap.h>
#include "../register.h"
+#include "alert_box.h"
#include "simple_dialog.h"
#include "../globals.h"
#include "../color.h"
#include "compat_macros.h"
-
-/* filter prefs dialog */
-#include "filter_prefs.h"
-/* filter prefs dialog */
+#include "dlg_utils.h"
+#include "filter_dlg.h"
void protect_thread_critical_region(void);
void unprotect_thread_critical_region(void);
#define DEFAULT_PIXELS_PER_TICK 2
static guint32 pixels_per_tick[MAX_PIXELS_PER_TICK] = {1, 2, 5, 10};
-#define MAX_COUNT_TYPES 3
+
+#define DEFAULT_PLOT_STYLE 0
+#define PLOT_STYLE_LINE 0
+#define PLOT_STYLE_IMPULSE 1
+#define PLOT_STYLE_FILLED_BAR 2
+#define MAX_PLOT_STYLES 3
+static char *plot_style_name[MAX_PLOT_STYLES] = {
+ "Line",
+ "Impulse",
+ "FBar",
+};
+
+
+#define COUNT_TYPE_FRAMES 0
+#define COUNT_TYPE_BYTES 1
#define COUNT_TYPE_ADVANCED 2
-static char *max_count_types[MAX_COUNT_TYPES] = {"frames/tick", "bytes/tick", "advanced..."};
+#define MAX_COUNT_TYPES 3
+static char *count_type_names[MAX_COUNT_TYPES] = {"Packets/Tick", "Bytes/Tick", "Advanced..."};
/* unit is in ms */
-#define MAX_TICK_VALUES 4
-#define DEFAULT_TICK_VALUE 2
-static guint max_tick_values[MAX_TICK_VALUES] = { 10, 100, 1000, 10000 };
+#define MAX_TICK_VALUES 5
+#define DEFAULT_TICK_VALUE 3
+static guint tick_interval_values[MAX_TICK_VALUES] = { 1, 10, 100, 1000, 10000 };
-#define MAX_CALC_TYPES 5
#define CALC_TYPE_SUM 0
#define CALC_TYPE_COUNT 1
#define CALC_TYPE_MAX 2
#define CALC_TYPE_MIN 3
#define CALC_TYPE_AVG 4
-static char *max_calc_types[MAX_CALC_TYPES] = {"SUM(*)", "COUNT(*)", "MAX(*)", "MIN(*)", "AVG(*)"};
+#define CALC_TYPE_LOAD 5
+#define MAX_CALC_TYPES 6
+static char *calc_type_names[MAX_CALC_TYPES] = {"SUM(*)", "COUNT(*)", "MAX(*)", "MIN(*)", "AVG(*)", "LOAD(*)"};
-typedef struct _io_stat_item_t {
- struct _io_stat_item_t *next;
- struct _io_stat_item_t *prev;
- guint32 time; /* this is number of ms since start of capture */
- guint32 frames; /* always calculated, will hold number of packets/frames*/
- guint32 bytes;
+typedef struct _io_stat_calc_type_t {
+ struct _io_stat_graph_t *gio;
+ int calc_type;
+} io_stat_calc_type_t;
+
+#define NUM_IO_ITEMS 100000
+typedef struct _io_item_t {
+ guint32 frames; /* always calculated, will hold number of frames*/
+ guint32 bytes; /* always calculated, will hold number of bytes*/
gint32 int_max;
gint32 int_min;
gint32 int_tot;
nstime_t time_max;
nstime_t time_min;
nstime_t time_tot;
-} io_stat_item_t;
-
-typedef struct _io_stat_calc_type_t {
- struct _io_stat_graph_t *gio;
- int calc_type;
-} io_stat_calc_type_t;
+} io_item_t;
typedef struct _io_stat_graph_t {
struct _io_stat_t *io;
- struct _io_stat_item_t *counts;
- int display;
+ io_item_t items[NUM_IO_ITEMS];
+ int plot_style;
+ gboolean display;
GtkWidget *display_button;
- GtkWidget *color_button;
- GtkWidget *filter_button;
+ GtkWidget *filter_field;
GtkWidget *advanced_buttons;
int calc_type;
io_stat_calc_type_t calc_types[MAX_CALC_TYPES];
GtkWidget *filter_bt;
} io_stat_graph_t;
-typedef struct _io_stat_yscale_t {
- struct _io_stat_t *io;
- int yscale;
-} io_stat_yscale_t;
-
-typedef struct _io_stat_pixels_per_tick_t {
- struct _io_stat_t *io;
- int pixels_per_tick;
-} io_stat_pixels_per_tick_t;
-
-typedef struct _io_stat_count_type_t {
- struct _io_stat_t *io;
- int count_type;
-} io_stat_count_type_t;
-
-typedef struct _io_stat_tick_interval_t {
- struct _io_stat_t *io;
- int interval;
-} io_stat_tick_interval_t;
-
typedef struct _io_stat_t {
- int needs_redraw;
+ gboolean needs_redraw;
gint32 interval; /* measurement interval in ms */
guint32 last_interval;
- guint32 max_interval;
+ guint32 max_interval; /* XXX max_interval and num_items are redundant */
+ guint32 num_items;
struct _io_stat_graph_t graphs[MAX_GRAPHS];
- struct _io_stat_yscale_t yscale[MAX_YSCALE];
- struct _io_stat_pixels_per_tick_t pixelspertick[MAX_PIXELS_PER_TICK];
- struct _io_stat_count_type_t counttype[MAX_COUNT_TYPES];
- struct _io_stat_tick_interval_t tick_val[MAX_TICK_VALUES];
GtkWidget *window;
GtkWidget *draw_area;
GdkPixmap *pixmap;
static void init_io_stat_window(io_stat_t *io);
-/* Hash table to keep track of widget to io_stat_t mappings.
- Did it this way since i could not find a clean way to associate private
- data with a widget using the API */
-static GHashTable *io_stat_widget_table=NULL;
-static guint
-io_stat_widget_hash(gconstpointer k)
+static void
+io_stat_set_title(io_stat_t *io)
{
- guint32 frame = (guint32)k;
+ char *title;
- return frame;
+ if(!io->window){
+ return;
+ }
+ title = g_strdup_printf("Ethereal IO Graphs: %s", cf_get_display_name(&cfile));
+ gtk_window_set_title(GTK_WINDOW(io->window), title);
+ g_free(title);
}
-static gint
-io_stat_widget_equal(gconstpointer k1, gconstpointer k2)
-{
- guint32 frame1 = (guint32)k1;
- guint32 frame2 = (guint32)k2;
- return frame1==frame2;
-}
+static void
+io_stat_reset(io_stat_t *io)
+{
+ int i, j;
+ io->needs_redraw=TRUE;
+ for(i=0;i<MAX_GRAPHS;i++){
+ for(j=0;j<NUM_IO_ITEMS;j++){
+ io_item_t *ioi;
+ ioi=&io->graphs[i].items[j];
+
+ ioi->frames=0;
+ ioi->bytes=0;
+ ioi->int_max=0;
+ ioi->int_min=0;
+ ioi->int_tot=0;
+ ioi->time_max.secs=0;
+ ioi->time_max.nsecs=0;
+ ioi->time_min.secs=0;
+ ioi->time_min.nsecs=0;
+ ioi->time_tot.secs=0;
+ ioi->time_tot.nsecs=0;
+ }
+ }
+ io->last_interval=0xffffffff;
+ io->max_interval=0;
+ io->num_items=0;
+ io_stat_set_title(io);
+}
static void
gtk_iostat_reset(void *g)
{
io_stat_graph_t *gio=g;
- io_stat_item_t *it;
-
- gio->io->needs_redraw=1;
-
- while(gio->counts->next){
- it=gio->counts->next;
- gio->counts->next=it->next;
- g_free(it);
- }
- gio->counts->prev=gio->counts;
- gio->counts->next=NULL;
- gio->counts->time=0;
- gio->counts->frames=0;
- gio->counts->bytes=0;
- gio->counts->int_max=0;
- gio->counts->int_min=0;
- gio->counts->int_tot=0;
-
- gio->io->last_interval=0xffffffff;
- gio->io->max_interval=0;
+ io_stat_reset(gio->io);
}
-
static int
gtk_iostat_packet(void *g, packet_info *pinfo, epan_dissect_t *edt, void *dummy _U_)
{
io_stat_graph_t *git=g;
- io_stat_item_t *it;
+ io_item_t *it;
nstime_t time_delta;
- guint32 adjusted_time;
+ int idx;
/* we sometimes get called when git is disabled.
this is a bug since the tap listener should be removed first */
return 0;
}
- git->io->needs_redraw=1;
-
- /* the prev item before the main one is always the last interval we saw packets for */
- it=git->counts->prev;
+ git->io->needs_redraw=TRUE;
- /* XXX for the time being, just ignore all frames that are in the past.
- should be fixed in the future but hopefully it is uncommon */
+ /*
+ * Find which interval this is supposed to to in and store the
+ * interval index as idx
+ */
time_delta.secs=pinfo->fd->rel_secs;
time_delta.nsecs=pinfo->fd->rel_usecs*1000;
if(time_delta.nsecs<0){
time_delta.nsecs+=1000000000;
}
if(time_delta.secs<0){
- return TRUE;
+ return FALSE;
}
- /* time since start of capture in ms */
- adjusted_time=time_delta.secs*1000+time_delta.nsecs/1000000;
+ idx=(time_delta.secs*1000+time_delta.nsecs/1000000)/git->io->interval;
- /* timestamps jumped backwards, just ignore the packet.
- if this is common someone can fix this later */
- if(adjusted_time<it->time){
- return TRUE;
+ /* some sanity checks */
+ if((idx<0)||(idx>=NUM_IO_ITEMS)){
+ return FALSE;
}
-
- /* we have moved into a new interval, we need to create a new struct */
- if(adjusted_time>=(it->time+git->io->interval)){
- it->next=g_malloc(sizeof(io_stat_item_t));
- it->next->prev=it;
- it->next->next=NULL;
- it=it->next;
- git->counts->prev=it;
-
- /* set time of new counter struct of adjusted_time rounded
- to multiple of intervals */
- it->time=(adjusted_time/git->io->interval)*git->io->interval;
- it->frames=0;
- it->bytes=0;
- it->int_max=0;
- it->int_min=0;
- it->int_tot=0;
- it->time_max.secs=0;
- it->time_max.nsecs=0;
- it->time_min.secs=0;
- it->time_min.nsecs=0;
- it->time_tot.secs=0;
- it->time_tot.nsecs=0;
- if(it->time>git->io->max_interval){
- git->io->max_interval=it->time;
- }
+ /* update num_items */
+ if((guint32)idx > git->io->num_items){
+ git->io->num_items=idx;
+ git->io->max_interval=idx*git->io->interval;
}
- /* it will now give us the current structure to use to store the data in */
+ /*
+ * Find the appropriate io_item_t structure
+ */
+ it=&git->items[idx];
+
+ /*
+ * For ADVANCED mode we need to keep track of some more stuff
+ * than just frame and byte counts
+ */
if(git->io->count_type==COUNT_TYPE_ADVANCED){
GPtrArray *gp;
guint i;
return FALSE;
}
- if(it->frames==0){
- int new_int;
- nstime_t *new_time;
-
- switch(proto_registrar_get_ftype(git->hf_index)){
- case FT_UINT8:
- case FT_UINT16:
- case FT_UINT24:
- case FT_UINT32:
- case FT_INT8:
- case FT_INT16:
- case FT_INT24:
- case FT_INT32:
- new_int=fvalue_get_integer(((field_info *)gp->pdata[0])->value);
- it->int_max=new_int;
- it->int_min=new_int;
- it->int_tot=0;
- break;
- case FT_RELATIVE_TIME:
- new_time=fvalue_get(((field_info *)gp->pdata[0])->value);
- it->time_max.secs=new_time->secs;
- it->time_max.nsecs=new_time->nsecs;
- it->time_min.secs=new_time->secs;
- it->time_min.nsecs=new_time->nsecs;
- it->time_tot.secs=0;
- it->time_tot.nsecs=0;
- }
- }
+ /* update the appropriate counters, make sure that if
+ * frames==0 then this is the first seen value so
+ * set any min/max values accordingly
+ */
for(i=0;i<gp->len;i++){
int new_int;
nstime_t *new_time;
case FT_INT16:
case FT_INT24:
case FT_INT32:
- new_int=fvalue_get_integer(((field_info *)gp->pdata[i])->value);
+ new_int=fvalue_get_integer(&((field_info *)gp->pdata[i])->value);
- if(new_int>it->int_max){
+ if((new_int>it->int_max)||(it->frames==0)){
it->int_max=new_int;
}
- if(new_int<it->int_min){
+ if((new_int<it->int_min)||(it->frames==0)){
it->int_min=new_int;
}
it->int_tot+=new_int;
break;
case FT_RELATIVE_TIME:
- new_time=fvalue_get(((field_info *)gp->pdata[0])->value);
+ new_time=fvalue_get(&((field_info *)gp->pdata[0])->value);
- if( (new_time->secs>it->time_max.secs)
- ||( (new_time->secs==it->time_max.secs)
- &&(new_time->nsecs>it->time_max.nsecs))){
- it->time_max.secs=new_time->secs;
- it->time_max.nsecs=new_time->nsecs;
- }
- if( (new_time->secs<it->time_min.secs)
- ||( (new_time->secs==it->time_min.secs)
- &&(new_time->nsecs<it->time_min.nsecs))){
- it->time_min.secs=new_time->secs;
- it->time_min.nsecs=new_time->nsecs;
- }
- it->time_tot.secs+=new_time->secs;
- it->time_tot.nsecs+=new_time->nsecs;
- if(it->time_tot.nsecs>=1000000000){
- it->time_tot.nsecs-=1000000000;
- it->time_tot.secs++;
+ switch(git->calc_type){
+#ifdef G_HAVE_UINT64
+ guint64 t, pt; /* time in us */
+#else
+ guint32 t, pt;
+#endif
+ int i;
+ case CALC_TYPE_LOAD:
+ /* it is a LOAD calculation of a relative time field.
+ * add the time this call spanned to each
+ * interval it spanned according to its contribution
+ * to that interval.
+ */
+ t=new_time->secs;
+ t=t*1000000+new_time->nsecs/1000;
+ i=idx;
+ /* handle current interval */
+ pt=pinfo->fd->rel_secs*1000000+pinfo->fd->rel_usecs;
+ pt=pt%(git->io->interval*1000);
+ if(pt>t){
+ pt=t;
+ }
+ while(t){
+ git->items[i].time_tot.nsecs+=pt*1000;
+ if(git->items[i].time_tot.nsecs>1000000000){
+ git->items[i].time_tot.secs++;
+ git->items[i].time_tot.nsecs-=1000000000;
+ }
+
+ if(i==0){
+ break;
+ }
+ i--;
+ t-=pt;
+ if(t > (guint32) (git->io->interval*1000)){
+ pt=git->io->interval*1000;
+ } else {
+ pt=t;
+ }
+ }
+ break;
+ default:
+ if( (new_time->secs>it->time_max.secs)
+ ||( (new_time->secs==it->time_max.secs)
+ &&(new_time->nsecs>it->time_max.nsecs))
+ ||(it->frames==0)){
+ it->time_max.secs=new_time->secs;
+ it->time_max.nsecs=new_time->nsecs;
+ }
+ if( (new_time->secs<it->time_min.secs)
+ ||( (new_time->secs==it->time_min.secs)
+ &&(new_time->nsecs<it->time_min.nsecs))
+ ||(it->frames==0)){
+ it->time_min.secs=new_time->secs;
+ it->time_min.nsecs=new_time->nsecs;
+ }
+ it->time_tot.secs+=new_time->secs;
+ it->time_tot.nsecs+=new_time->nsecs;
+ if(it->time_tot.nsecs>=1000000000){
+ it->time_tot.nsecs-=1000000000;
+ it->time_tot.secs++;
+ }
}
}
static guint32
-get_it_value(io_stat_t *io, io_stat_item_t *it, int adv_type, int calc_type)
+get_it_value(io_stat_t *io, int graph_id, int idx)
{
guint32 value=0;
+ int adv_type;
+ io_item_t *it;
+
+ it=&io->graphs[graph_id].items[idx];
switch(io->count_type){
- case 0:
- value=it->frames;
- break;
- case 1:
- value=it->bytes;
+ case COUNT_TYPE_FRAMES:
+ return it->frames;
+ case COUNT_TYPE_BYTES:
+ return it->bytes;
+ }
+
+
+ adv_type=proto_registrar_get_ftype(io->graphs[graph_id].hf_index);
+ switch(adv_type){
+ case FT_NONE:
+ switch(io->graphs[graph_id].calc_type){
+ case CALC_TYPE_COUNT:
+ value=it->frames;
+ break;
+ default:
+ break;
+ }
break;
- case COUNT_TYPE_ADVANCED:
- switch(adv_type){
- case FT_UINT8:
- case FT_UINT16:
- case FT_UINT24:
- case FT_UINT32:
- case FT_INT8:
- case FT_INT16:
- case FT_INT24:
- case FT_INT32:
- switch(calc_type){
- case CALC_TYPE_SUM:
- value=it->int_tot;
- break;
- case CALC_TYPE_COUNT:
- value=it->frames;
- break;
- case CALC_TYPE_MAX:
- value=it->int_max;
- break;
- case CALC_TYPE_MIN:
- value=it->int_min;
- break;
- case CALC_TYPE_AVG:
- if(it->frames){
- value=it->int_tot/it->frames;
- } else {
- value=0;
- }
- break;
- default:
- break;
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ case FT_INT8:
+ case FT_INT16:
+ case FT_INT24:
+ case FT_INT32:
+ switch(io->graphs[graph_id].calc_type){
+ case CALC_TYPE_SUM:
+ value=it->int_tot;
+ break;
+ case CALC_TYPE_COUNT:
+ value=it->frames;
+ break;
+ case CALC_TYPE_MAX:
+ value=it->int_max;
+ break;
+ case CALC_TYPE_MIN:
+ value=it->int_min;
+ break;
+ case CALC_TYPE_AVG:
+ if(it->frames){
+ value=it->int_tot/it->frames;
+ } else {
+ value=0;
}
break;
- case FT_RELATIVE_TIME:
- switch(calc_type){
- case CALC_TYPE_COUNT:
- value=it->frames;
- break;
- case CALC_TYPE_MAX:
- value=it->time_max.secs*1000000+it->time_max.nsecs/1000;
- break;
- case CALC_TYPE_MIN:
- value=it->time_min.secs*1000000+it->time_min.nsecs/1000;
- break;
- case CALC_TYPE_AVG:
- if(it->frames){
+ default:
+ break;
+ }
+ break;
+ case FT_RELATIVE_TIME:
+ switch(io->graphs[graph_id].calc_type){
+ case CALC_TYPE_COUNT:
+ value=it->frames;
+ break;
+ case CALC_TYPE_MAX:
+ value=it->time_max.secs*1000000+it->time_max.nsecs/1000;
+ break;
+ case CALC_TYPE_MIN:
+ value=it->time_min.secs*1000000+it->time_min.nsecs/1000;
+ break;
+ case CALC_TYPE_AVG:
+ if(it->frames){
#ifdef G_HAVE_UINT64
- guint64 tmp;
+ guint64 t; /* time in us */
#else
- guint32 tmp;
+ guint32 t;
#endif
- tmp=it->time_tot.secs;
- tmp=tmp*1000000+it->time_tot.nsecs/1000;
- value=tmp/it->frames;
- } else {
- value=0;
- }
- break;
- default:
- break;
+ t=it->time_tot.secs;
+ t=t*1000000+it->time_tot.nsecs/1000;
+ value=t/it->frames;
+ } else {
+ value=0;
}
break;
+ case CALC_TYPE_LOAD:
+ value=(it->time_tot.secs*1000000+it->time_tot.nsecs/1000)/io->interval;
+ break;
default:
break;
}
return value;
}
+
static void
-gtk_iostat_draw(void *g)
+print_time_scale_string(char *buf, int buf_len, guint32 t)
+{
+ if(t>=10000000){
+ g_snprintf(buf, buf_len, "%ds",t/1000000);
+ } else if(t>=1000000){
+ g_snprintf(buf, buf_len, "%d.%03ds",t/1000000,(t%1000000)/1000);
+ } else if(t>=10000){
+ g_snprintf(buf, buf_len, "%dms",t/1000);
+ } else if(t>=1000){
+ g_snprintf(buf, buf_len, "%d.%03dms",t/1000,t%1000);
+ } else {
+ g_snprintf(buf, buf_len, "%dus",t);
+ }
+}
+
+static void
+io_stat_draw(io_stat_t *io)
{
- io_stat_graph_t *git=g;
- io_stat_t *io;
- io_stat_item_t *it;
int i;
- guint32 value;
guint32 last_interval, first_interval, interval_delta, delta_multiplier;
gint32 current_interval;
- guint32 max_y;
guint32 left_x_border;
guint32 right_x_border;
guint32 top_y_border;
guint32 draw_width, draw_height;
char label_string[15];
- io=git->io;
+ /* new variables */
+ guint32 num_time_intervals;
+ guint32 max_value; /* max value of seen data */
+ guint32 max_y; /* max value of the Y scale */
+ gboolean draw_y_as_time;
+
#if GTK_MAJOR_VERSION <2
font = io->draw_area->style->font;
#endif
- if(!git->io->needs_redraw){
+ if(!io->needs_redraw){
return;
}
- git->io->needs_redraw=0;
+ io->needs_redraw=FALSE;
- /* if we havent specified the last_interval via the gui,
- then just pick the most recent one */
- if(io->last_interval==0xffffffff){
- last_interval=io->max_interval;
- } else {
- last_interval=io->last_interval;
+
+ /*
+ * Find the length of the intervals we have data for
+ * so we know how large arrays we need to malloc()
+ */
+ num_time_intervals=io->num_items;
+ /* if there isnt anything to do, just return */
+ if(num_time_intervals==0){
+ return;
+ }
+ num_time_intervals+=1;
+ /* XXX move this check to _packet() */
+ if(num_time_intervals>NUM_IO_ITEMS){
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "IO-Stat error. There are too many entries, bailing out");
+ return;
}
-
- if(io->max_y_units==AUTO_MAX_YSCALE){
- guint32 max_value=0;
- for(i=0;i<MAX_GRAPHS;i++){
- int adv_type=0;
- if( (!io->graphs[i].display) || (!io->graphs[i].counts) ){
- continue;
- }
+ /*
+ * find the max value so we can autoscale the y axis
+ */
+ max_value=0;
+ for(i=0;i<MAX_GRAPHS;i++){
+ int idx;
- if(io->count_type==COUNT_TYPE_ADVANCED){
- adv_type=proto_registrar_get_ftype(io->graphs[i].hf_index);
- }
+ if(!io->graphs[i].display){
+ continue;
+ }
+ for(idx=0;(guint32) (idx) < num_time_intervals;idx++){
+ guint32 val;
- for(it=io->graphs[i].counts;it;it=it->next){
- value=get_it_value(io, it, adv_type, io->graphs[i].calc_type);
- if(value>=max_value){
- max_value=value;
- }
+ val=get_it_value(io, i, idx);
+
+ /* keep track of the max value we have encountered */
+ if(val>max_value){
+ max_value=val;
}
}
+ }
+
+
+
+ /*
+ * Clear out old plot
+ */
+ gdk_draw_rectangle(io->pixmap,
+ io->draw_area->style->white_gc,
+ TRUE,
+ 0, 0,
+ io->draw_area->allocation.width,
+ io->draw_area->allocation.height);
+
+
+ /*
+ * Calculate the y scale we should use
+ */
+ if(io->max_y_units==AUTO_MAX_YSCALE){
max_y=yscale_max[MAX_YSCALE-1];
for(i=MAX_YSCALE-1;i>0;i--){
if(max_value<yscale_max[i]){
}
}
} else {
+ /* the user had specified an explicit y scale to use */
max_y=io->max_y_units;
}
- /* just assume that max_y will be the longest string */
- sprintf(label_string,"%d", max_y);
+ /*
+ * If we use ADVANCED and all the graphs are plotting
+ * either MIN/MAX/AVG of an FT_RELATIVE_TIME field
+ * then we will do some some special processing for the
+ * labels for the Y axis below:
+ * we will append the time unit " s" " ms" or " us"
+ * and we will present the unit in decimal
+ */
+ draw_y_as_time=FALSE;
+ if(io->count_type==COUNT_TYPE_ADVANCED){
+ draw_y_as_time=TRUE;
+ for(i=0;i<MAX_GRAPHS;i++){
+ int adv_type;
+
+ if(!io->graphs[i].display){
+ continue;
+ }
+ adv_type=proto_registrar_get_ftype(io->graphs[i].hf_index);
+ switch(adv_type){
+ case FT_RELATIVE_TIME:
+ switch(io->graphs[i].calc_type){
+ case CALC_TYPE_MAX:
+ case CALC_TYPE_MIN:
+ case CALC_TYPE_AVG:
+ break;
+ default:
+ draw_y_as_time=FALSE;
+ }
+ break;
+ default:
+ draw_y_as_time=FALSE;
+ }
+ }
+ }
+
+
+
+ /*
+ * Calculate size of borders surrounding the plot
+ * The border on the right side needs to be adjusted depending
+ * on the width of the text labels. For simplicity we assume that the
+ * top y scale label will be the widest one
+ */
+ if(draw_y_as_time){
+ print_time_scale_string(label_string, 15, max_y);
+ } else {
+ g_snprintf(label_string, 15, "%d", max_y);
+ }
#if GTK_MAJOR_VERSION < 2
label_width=gdk_string_width(font, label_string);
label_height=gdk_string_height(font, label_string);
layout = gtk_widget_create_pango_layout(io->draw_area, label_string);
pango_layout_get_pixel_size(layout, &label_width, &label_height);
#endif
-
left_x_border=10;
right_x_border=label_width+20;
top_y_border=10;
bottom_y_border=label_height+20;
+
+ /*
+ * Calculate the size of the drawing area for the actual plot
+ */
draw_width=io->pixmap_width-right_x_border-left_x_border;
draw_height=io->pixmap_height-top_y_border-bottom_y_border;
- /* clear out old plot */
- gdk_draw_rectangle(io->pixmap,
- io->draw_area->style->white_gc,
- TRUE,
- 0, 0,
- io->draw_area->allocation.width,
- io->draw_area->allocation.height);
-
- /* plot the y-scale */
+ /*
+ * Draw the y axis and labels
+ * (we always draw the y scale with 11 ticks along the axis)
+ */
gdk_draw_line(io->pixmap, io->draw_area->style->black_gc,
io->pixmap_width-right_x_border+1,
top_y_border,
xwidth=5;
if(!(i%5)){
+ /* first, middle and last tick are slightly longer */
xwidth=10;
}
+ /* draw the tick */
gdk_draw_line(io->pixmap, io->draw_area->style->black_gc,
io->pixmap_width-right_x_border+1,
io->pixmap_height-bottom_y_border-draw_height*i/10,
io->pixmap_width-right_x_border+1+xwidth,
io->pixmap_height-bottom_y_border-draw_height*i/10);
- sprintf(label_string,"%d", max_y*i/10);
+ /* draw the labels */
+ if(i==0){
+ if(draw_y_as_time){
+ print_time_scale_string(label_string, 15, (max_y*i/10));
+ } else {
+ g_snprintf(label_string, 15, "%d", max_y*i/10);
+ }
#if GTK_MAJOR_VERSION < 2
- lwidth=gdk_string_width(font, label_string);
- gdk_draw_string(io->pixmap,
- font,
- io->draw_area->style->black_gc,
- io->pixmap_width-right_x_border+15+label_width-lwidth,
- io->pixmap_height-bottom_y_border-draw_height*i/10+label_height/2,
- label_string);
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(io->pixmap,
+ font,
+ io->draw_area->style->black_gc,
+ io->pixmap_width-right_x_border+15+label_width-lwidth,
+ io->pixmap_height-bottom_y_border-draw_height*i/10+label_height/2,
+ label_string);
#else
- pango_layout_set_text(layout, label_string, -1);
- pango_layout_get_pixel_size(layout, &lwidth, NULL);
- gdk_draw_layout(io->pixmap,
- io->draw_area->style->black_gc,
- io->pixmap_width-right_x_border+15+label_width-lwidth,
- io->pixmap_height-bottom_y_border-draw_height*i/10-label_height/2,
- layout);
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(io->pixmap,
+ io->draw_area->style->black_gc,
+ io->pixmap_width-right_x_border+15+label_width-lwidth,
+ io->pixmap_height-bottom_y_border-draw_height*i/10-label_height/2,
+ layout);
#endif
+ }
+ if(i==5){
+ if(draw_y_as_time){
+ print_time_scale_string(label_string, 15, (max_y*i/10));
+ } else {
+ g_snprintf(label_string, 15, "%d", max_y*i/10);
+ }
+#if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(io->pixmap,
+ font,
+ io->draw_area->style->black_gc,
+ io->pixmap_width-right_x_border+15+label_width-lwidth,
+ io->pixmap_height-bottom_y_border-draw_height*i/10+label_height/2,
+ label_string);
+#else
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(io->pixmap,
+ io->draw_area->style->black_gc,
+ io->pixmap_width-right_x_border+15+label_width-lwidth,
+ io->pixmap_height-bottom_y_border-draw_height*i/10-label_height/2,
+ layout);
+#endif
+ }
+ if(i==10){
+ if(draw_y_as_time){
+ print_time_scale_string(label_string, 15, (max_y*i/10));
+ } else {
+ g_snprintf(label_string, 15, "%d", max_y*i/10);
+ }
+#if GTK_MAJOR_VERSION < 2
+ lwidth=gdk_string_width(font, label_string);
+ gdk_draw_string(io->pixmap,
+ font,
+ io->draw_area->style->black_gc,
+ io->pixmap_width-right_x_border+15+label_width-lwidth,
+ io->pixmap_height-bottom_y_border-draw_height*i/10+label_height/2,
+ label_string);
+#else
+ pango_layout_set_text(layout, label_string, -1);
+ pango_layout_get_pixel_size(layout, &lwidth, NULL);
+ gdk_draw_layout(io->pixmap,
+ io->draw_area->style->black_gc,
+ io->pixmap_width-right_x_border+15+label_width-lwidth,
+ io->pixmap_height-bottom_y_border-draw_height*i/10-label_height/2,
+ layout);
+#endif
+ }
+ }
+
+
+
+ /*
+ * if we have not specified the last_interval via the gui,
+ * then just pick the current end of the capture so that is scrolls
+ * nicely when doing live captures
+ */
+ if(io->last_interval==0xffffffff){
+ last_interval=io->max_interval;
+ } else {
+ last_interval=io->last_interval;
}
+
+
+
+/*XXX*/
/* plot the x-scale */
gdk_draw_line(io->pixmap, io->draw_area->style->black_gc, left_x_border, io->pixmap_height-bottom_y_border+1, io->pixmap_width-right_x_border+1, io->pixmap_height-bottom_y_border+1);
first_interval=0;
}
-
interval_delta=1;
delta_multiplier=5;
while(interval_delta<((last_interval-first_interval)/10)){
}
}
-
for(current_interval=last_interval;current_interval>(gint32)first_interval;current_interval=current_interval-io->interval){
int x, xlen;
if(xlen==10){
int lwidth;
if(io->interval>=1000){
- sprintf(label_string,"%d", current_interval/1000);
+ g_snprintf(label_string, 15, "%ds", current_interval/1000);
} else if(io->interval>=100){
- sprintf(label_string,"%d.%1d", current_interval/1000,(current_interval/100)%10);
+ g_snprintf(label_string, 15, "%d.%1ds", current_interval/1000,(current_interval/100)%10);
} else if(io->interval>=10){
- sprintf(label_string,"%d.%2d", current_interval/1000,(current_interval/10)%100);
+ g_snprintf(label_string, 15, "%d.%2ds", current_interval/1000,(current_interval/10)%100);
} else {
- sprintf(label_string,"%d.%3d", current_interval/1000,current_interval%1000);
+ g_snprintf(label_string, 15, "%d.%3ds", current_interval/1000,current_interval%1000);
}
#if GTK_MAJOR_VERSION < 2
lwidth=gdk_string_width(font, label_string);
#endif
- /* loop over all items */
+
+ /*
+ * Loop over all graphs and draw them
+ */
for(i=MAX_GRAPHS-1;i>=0;i--){
- int adv_type=0;
- int first_drawed=1;
+ guint32 interval;
+ guint32 x_pos, y_pos, prev_x_pos, prev_y_pos;
- if( (!io->graphs[i].display) || (!io->graphs[i].counts) ){
+ if(!io->graphs[i].display){
continue;
}
- if(io->count_type==COUNT_TYPE_ADVANCED){
- adv_type=proto_registrar_get_ftype(io->graphs[i].hf_index);
- }
-
- /* loop over all intervals for the item */
- for(it=io->graphs[i].counts;it;it=it->next){
- guint32 startx,starty, nexty;
- guint32 val=0;
- guint32 next_val=0;
-
- /* skip it if is outside the graph */
- if(it->time<first_interval){
- continue;
- }
- if(it->time>last_interval){
- continue;
- }
+ /* initialize prev x/y to the low left corner of the graph */
+ prev_x_pos=draw_width-1-io->pixels_per_tick*((last_interval-first_interval)/io->interval+1)+left_x_border;
+ prev_y_pos=draw_height-1+top_y_border;
- val=get_it_value(io, it, adv_type, io->graphs[i].calc_type);
- if(it->next){
- next_val=get_it_value(io, it->next, adv_type, io->graphs[i].calc_type);
- }
+ for(interval=first_interval+io->interval;interval<=last_interval;interval+=io->interval){
+ guint32 val;
+ x_pos=draw_width-1-io->pixels_per_tick*((last_interval-interval)/io->interval+1)+left_x_border;
- startx=draw_width-1-io->pixels_per_tick*((last_interval-it->time)/io->interval+1);
+ val=get_it_value(io, i, interval/io->interval);
if(val>max_y){
- starty=0;
- } else {
- starty=draw_height-1-(val*draw_height)/max_y;
- }
- if(next_val>max_y){
- nexty=0;
+ y_pos=0;
} else {
- nexty=draw_height-1-(next_val*draw_height)/max_y;
+ y_pos=draw_height-1-(val*draw_height)/max_y+top_y_border;
}
-
- /* just skip intervals that ar all or partially outside
- the draw_area */
- if(startx <=0){
- continue;
- }
-
-
- /* the first seen data for this graph might be
- * somewhere in the middle of the capture, make sure
- * we start drawing a proper line at zero from the
- * left edge of the graph up until the measurement
- * point.
+ /* dont need to draw anything if the segment
+ * is entirely above the top of the graph
*/
- if(first_drawed){
- first_drawed=0;
- gdk_draw_line(io->pixmap, io->graphs[i].gc, 10, draw_height-1+10, startx+10, draw_height-1+10);
- gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+10, draw_height-1+10, startx+10, starty+10);
- }
-
- gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+10, starty+10, startx+io->pixels_per_tick-1+10, starty+10);
-
- /* if there is no next measured interval but he have
- not reached last_interval yet, just draw 0 for the
- rest of the graph */
- if( (!it->next) && (it->time!=last_interval) ){
- gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, starty+10, startx+io->pixels_per_tick-1+10, draw_height-1+10);
- gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, draw_height-1+10, draw_width-1+10, draw_height-1+10);
- continue;
- }
-
- if(!it->next){
+ if( (prev_y_pos==0) && (y_pos==0) ){
+ prev_y_pos=y_pos;
+ prev_x_pos=x_pos;
continue;
}
- /* if there is data in next interval, connect to it */
- if((it->time+io->interval)==it->next->time){
- gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, starty+10, startx+io->pixels_per_tick-1+10, nexty+10);
- continue;
+ switch(io->graphs[i].plot_style){
+ case PLOT_STYLE_LINE:
+ gdk_draw_line(io->pixmap, io->graphs[i].gc,
+ prev_x_pos, prev_y_pos,
+ x_pos, y_pos);
+ break;
+ case PLOT_STYLE_IMPULSE:
+ if(val){
+ gdk_draw_line(io->pixmap, io->graphs[i].gc,
+ x_pos, draw_height-1+top_y_border,
+ x_pos, y_pos);
+ }
+ break;
+ case PLOT_STYLE_FILLED_BAR:
+ if(val){
+ gdk_draw_rectangle(io->pixmap,
+ io->graphs[i].gc, TRUE,
+ x_pos-io->pixels_per_tick/2,
+ draw_height-1-(val*draw_height)/max_y+top_y_border,
+ io->pixels_per_tick,
+ (val*draw_height)/max_y);
+
+ }
+ break;
}
- /* there is a gap until the next interval, we need to
- draw a bit more to connect to it. */
- if((it->time+io->interval)<it->next->time){
- int nextx;
- nextx=draw_width-1-io->pixels_per_tick*((last_interval-it->next->time)/io->interval+1);
- gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, starty+10, startx+io->pixels_per_tick-1+10, draw_height-1+10);
- gdk_draw_line(io->pixmap, io->graphs[i].gc, startx+io->pixels_per_tick-1+10, draw_height-1+10, nextx-1+10, draw_height-1+10);
- gdk_draw_line(io->pixmap, io->graphs[i].gc, nextx-1+10, draw_height-1+10, nextx-1+10, nexty+10);
- continue;
- }
-
+ prev_y_pos=y_pos;
+ prev_x_pos=x_pos;
}
}
+
+
gdk_draw_pixmap(io->draw_area->window,
io->draw_area->style->fg_gc[GTK_WIDGET_STATE(io->draw_area)],
io->pixmap,
/* update the scrollbar */
- io->scrollbar_adjustment->upper=io->max_interval;
- io->scrollbar_adjustment->step_increment=(last_interval-first_interval)/10;
- io->scrollbar_adjustment->page_increment=(last_interval-first_interval);
+ io->scrollbar_adjustment->upper=(gfloat) io->max_interval;
+ io->scrollbar_adjustment->step_increment=(gfloat) ((last_interval-first_interval)/10);
+ io->scrollbar_adjustment->page_increment=(gfloat) (last_interval-first_interval);
if((last_interval-first_interval)*100 < io->max_interval){
- io->scrollbar_adjustment->page_size=io->max_interval/100;
+ io->scrollbar_adjustment->page_size=(gfloat) (io->max_interval/100);
} else {
- io->scrollbar_adjustment->page_size=(last_interval-first_interval);
+ io->scrollbar_adjustment->page_size=(gfloat) (last_interval-first_interval);
}
io->scrollbar_adjustment->value=last_interval-io->scrollbar_adjustment->page_size;
gtk_adjustment_changed(io->scrollbar_adjustment);
gtk_adjustment_value_changed(io->scrollbar_adjustment);
+
}
+static void
+io_stat_redraw(io_stat_t *io)
+{
+ io->needs_redraw=TRUE;
+ io_stat_draw(io);
+}
+
+static void
+gtk_iostat_draw(void *g)
+{
+ io_stat_graph_t *git=g;
+
+ io_stat_draw(git->io);
+}
+
+
+/* ok we get called with both the filter and the field.
+ make sure the field is part of the filter.
+ (make sure and make sure just append it)
+ the field MUST be part of the filter or else we wont
+ be able to pick up the field values after the edt tree has been
+ pruned
+*/
+static GString *
+enable_graph(io_stat_graph_t *gio, char *filter, char *field)
+{
+ char real_filter[260];
+
+ gio->display=TRUE;
+
+ real_filter[0]=0;
+ if(filter){
+ /* skip all whitespaces */
+ while(*filter){
+ if(*filter==' '){
+ filter++;
+ continue;
+ }
+ if(*filter=='\t'){
+ filter++;
+ continue;
+ }
+ break;
+ }
+ if(*filter){
+ strncpy(real_filter, filter, 255);
+ real_filter[255]=0;
+ }
+ }
+ if(field){
+ /* skip all whitespaces */
+ while(*field){
+ if(*field==' '){
+ field++;
+ continue;
+ }
+ if(*field=='\t'){
+ field++;
+ continue;
+ }
+ break;
+ }
+ if(*field){
+ if(real_filter[0]!=0){
+ strcat(real_filter, " && ");
+ }
+ strncat(real_filter, field, 259-strlen(real_filter));
+ real_filter[259]=0;
+ }
+ }
+ return register_tap_listener("frame", gio, real_filter[0]?real_filter:NULL,
+ gtk_iostat_reset, gtk_iostat_packet, gtk_iostat_draw);
+}
+
+static void
+disable_graph(io_stat_graph_t *gio)
+{
+ if (gio->display) {
+ gio->display=FALSE;
+ protect_thread_critical_region();
+ remove_tap_listener(gio);
+ unprotect_thread_critical_region();
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button),
+ FALSE);
+ }
+}
static void
gtk_iostat_init(char *optarg _U_)
GString *error_string;
io=g_malloc(sizeof(io_stat_t));
- io->needs_redraw=1;
+ io->needs_redraw=TRUE;
io->interval=1000;
io->window=NULL;
io->draw_area=NULL;
io->scrollbar_adjustment=NULL;
io->pixmap_width=500;
io->pixmap_height=200;
- io->pixels_per_tick=5;
+ io->pixels_per_tick=pixels_per_tick[DEFAULT_PIXELS_PER_TICK];
io->max_y_units=AUTO_MAX_YSCALE;
io->count_type=0;
io->last_interval=0xffffffff;
io->max_interval=0;
+ io->num_items=0;
for(i=0;i<MAX_GRAPHS;i++){
- io->graphs[i].counts=g_malloc(sizeof(io_stat_item_t));
- io->graphs[i].counts->prev=io->graphs[i].counts;
- io->graphs[i].counts->next=NULL;
- io->graphs[i].counts->time=0;
- io->graphs[i].counts->frames=0;
- io->graphs[i].counts->bytes=0;
- io->graphs[i].counts->int_max=0;
- io->graphs[i].counts->int_min=0;
- io->graphs[i].counts->int_tot=0;
io->graphs[i].gc=NULL;
io->graphs[i].color.pixel=col[i].pixel;
io->graphs[i].color.red=col[i].red;
io->graphs[i].color.green=col[i].green;
io->graphs[i].color.blue=col[i].blue;
- io->graphs[i].display=i?0:1;
+ io->graphs[i].display=0;
io->graphs[i].display_button=NULL;
- io->graphs[i].color_button=NULL;
- io->graphs[i].filter_button=NULL;
+ io->graphs[i].filter_field=NULL;
io->graphs[i].advanced_buttons=NULL;
io->graphs[i].io=io;
io->graphs[i].filter_bt=NULL;
}
+ io_stat_reset(io);
- error_string=register_tap_listener("frame", &io->graphs[0], NULL, gtk_iostat_reset, gtk_iostat_packet, gtk_iostat_draw);
+ error_string=enable_graph(&io->graphs[0], NULL, NULL);
if(error_string){
fprintf(stderr, "ethereal: Can't attach io_stat tap: %s\n",
error_string->str);
g_string_free(error_string, TRUE);
- g_free(io->graphs[0].counts);
- io->graphs[0].counts=NULL;
io->graphs[0].display=0;
io->graphs[0].display_button=NULL;
- io->graphs[0].filter_button=NULL;
+ io->graphs[0].filter_field=NULL;
io->graphs[0].advanced_buttons=NULL;
exit(10);
}
/* build the GUI */
init_io_stat_window(io);
- redissect_packets(&cfile);
- io->needs_redraw=1;
- gtk_iostat_draw(&io->graphs[0]);
+ retap_packets(&cfile);
+ io_stat_redraw(io);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
static gint
quit(GtkWidget *widget, GdkEventExpose *event _U_)
{
int i;
io_stat_t *io;
- io=g_hash_table_lookup(io_stat_widget_table, (void*)widget);
- if(io){
- g_hash_table_remove(io_stat_widget_table, (void*)widget);
- }
+ io=(io_stat_t *)OBJECT_GET_DATA(widget, "io_stat_t");
for(i=0;i<MAX_GRAPHS;i++){
- io_stat_item_t *it;
- protect_thread_critical_region();
- remove_tap_listener(&io->graphs[i]);
- while((it=io->graphs[i].counts)){
- io->graphs[i].counts=io->graphs[i].counts->next;
- g_free(it);
- }
- unprotect_thread_critical_region();
+ if(io->graphs[i].display){
+ protect_thread_critical_region();
+ remove_tap_listener(&io->graphs[i]);
+ unprotect_thread_critical_region();
- free(io->graphs[i].args->title);
- io->graphs[i].args->title=NULL;
+ free(io->graphs[i].args->title);
+ io->graphs[i].args->title=NULL;
- g_free(io->graphs[i].args);
- io->graphs[i].args=NULL;
+ g_free(io->graphs[i].args);
+ io->graphs[i].args=NULL;
+ }
}
g_free(io);
int i;
io_stat_t *io;
- io=g_hash_table_lookup(io_stat_widget_table, (void*)widget);
+ io=(io_stat_t *)OBJECT_GET_DATA(widget, "io_stat_t");
if(!io){
exit(10);
}
}
- io->needs_redraw=1;
- gtk_iostat_draw(&io->graphs[0]);
+ io_stat_redraw(io);
return TRUE;
}
io_stat_t *io=(io_stat_t *)data;
guint32 mi;
- mi=io->scrollbar_adjustment->value+io->scrollbar_adjustment->page_size;
+ mi=(guint32) (io->scrollbar_adjustment->value+io->scrollbar_adjustment->page_size);
if(io->last_interval==mi){
return TRUE;
}
}
io->last_interval=(mi/io->interval)*io->interval;
- io->needs_redraw=1;
- gtk_iostat_draw(&io->graphs[0]);
+ io_stat_redraw(io);
return TRUE;
}
expose_event(GtkWidget *widget, GdkEventExpose *event)
{
io_stat_t *io;
- io=g_hash_table_lookup(io_stat_widget_table, (void*)widget);
+
+ io=(io_stat_t *)OBJECT_GET_DATA(widget, "io_stat_t");
if(!io){
exit(10);
}
{
io->draw_area=gtk_drawing_area_new();
SIGNAL_CONNECT(io->draw_area, "destroy", quit, io);
- g_hash_table_insert(io_stat_widget_table, (void*)io->draw_area, (void*)io);
+ OBJECT_SET_DATA(io->draw_area, "io_stat_t", io);
WIDGET_SET_SIZE(io->draw_area, io->pixmap_width, io->pixmap_height);
static void
-tick_interval_select(GtkWidget *item _U_, gpointer key)
+tick_interval_select(GtkWidget *item, gpointer key)
{
- io_stat_tick_interval_t *tiv =(io_stat_tick_interval_t *)key;
+ int val;
+ io_stat_t *io;
+
+ io=(io_stat_t *)key;
+ val=(int)OBJECT_GET_DATA(item, "tick_interval");
- tiv->io->interval=tiv->interval;
- redissect_packets(&cfile);
- tiv->io->needs_redraw=1;
- gtk_iostat_draw(&tiv->io->graphs[0]);
+ io->interval=val;
+ retap_packets(&cfile);
+ io_stat_redraw(io);
}
static void
-pixels_per_tick_select(GtkWidget *item _U_, gpointer key)
+pixels_per_tick_select(GtkWidget *item, gpointer key)
{
- io_stat_pixels_per_tick_t *ppt=(io_stat_pixels_per_tick_t *)key;
+ int val;
+ io_stat_t *io;
+
+ io=(io_stat_t *)key;
+ val=(int)OBJECT_GET_DATA(item, "pixels_per_tick");
+ io->pixels_per_tick=val;
+ io_stat_redraw(io);
+}
+
+static void
+plot_style_select(GtkWidget *item, gpointer key)
+{
+ int val;
+ io_stat_graph_t *ppt;
+
+ ppt=(io_stat_graph_t *)key;
+ val=(int)OBJECT_GET_DATA(item, "plot_style");
- ppt->io->pixels_per_tick=ppt->pixels_per_tick;
- ppt->io->needs_redraw=1;
- gtk_iostat_draw(&ppt->io->graphs[0]);
+ ppt->plot_style=val;
+
+ io_stat_redraw(ppt->io);
}
static void
int i;
for(i=0;i<MAX_PIXELS_PER_TICK;i++){
- sprintf(str,"%d", pixels_per_tick[i]);
+ g_snprintf(str, 5, "%d", pixels_per_tick[i]);
menu_item=gtk_menu_item_new_with_label(str);
- io->pixelspertick[i].io=io;
- io->pixelspertick[i].pixels_per_tick=pixels_per_tick[i];
- SIGNAL_CONNECT(menu_item, "activate", pixels_per_tick_select, &io->pixelspertick[i]);
+
+ OBJECT_SET_DATA(menu_item, "pixels_per_tick",
+ pixels_per_tick[i]);
+ SIGNAL_CONNECT(menu_item, "activate", pixels_per_tick_select, io);
gtk_widget_show(menu_item);
gtk_menu_append(GTK_MENU(menu), menu_item);
}
static void
-yscale_select(GtkWidget *item _U_, gpointer key)
+yscale_select(GtkWidget *item, gpointer key)
{
- io_stat_yscale_t *ys=(io_stat_yscale_t *)key;
+ int val;
+ io_stat_t *io;
+
+ io=(io_stat_t *)key;
+ val=(int)OBJECT_GET_DATA(item, "yscale_max");
- ys->io->max_y_units=ys->yscale;
- ys->io->needs_redraw=1;
- gtk_iostat_draw(&ys->io->graphs[0]);
+ io->max_y_units=val;
+ io_stat_redraw(io);
}
static void
int i;
for(i=0;i<MAX_TICK_VALUES;i++){
- if(max_tick_values[i]>=1000){
- sprintf(str,"%d sec", max_tick_values[i]/1000);
- } else if(max_tick_values[i]>=100){
- sprintf(str,"0.%1d sec", (max_tick_values[i]/100)%10);
- } else if(max_tick_values[i]>=10){
- sprintf(str,"0.%02d sec", (max_tick_values[i]/10)%10);
+ if(tick_interval_values[i]>=1000){
+ g_snprintf(str, 15, "%d sec", tick_interval_values[i]/1000);
+ } else if(tick_interval_values[i]>=100){
+ g_snprintf(str, 15, "0.%1d sec", (tick_interval_values[i]/100)%10);
+ } else if(tick_interval_values[i]>=10){
+ g_snprintf(str, 15, "0.%02d sec", (tick_interval_values[i]/10)%10);
} else {
- sprintf(str,"0.%03d sec", (max_tick_values[i])%10);
+ g_snprintf(str, 15, "0.%03d sec", (tick_interval_values[i])%10);
}
menu_item=gtk_menu_item_new_with_label(str);
- io->tick_val[i].io=io;
- io->tick_val[i].interval=max_tick_values[i];
- SIGNAL_CONNECT(menu_item, "activate", tick_interval_select, &io->tick_val[i]);
+ OBJECT_SET_DATA(menu_item, "tick_interval",
+ tick_interval_values[i]);
+ SIGNAL_CONNECT(menu_item, "activate", tick_interval_select, (gpointer)io);
gtk_widget_show(menu_item);
gtk_menu_append(GTK_MENU(menu), menu_item);
}
if(yscale_max[i]==AUTO_MAX_YSCALE){
strcpy(str,"Auto");
} else {
- sprintf(str,"%d", yscale_max[i]);
+ g_snprintf(str, 15, "%d", yscale_max[i]);
}
menu_item=gtk_menu_item_new_with_label(str);
- io->yscale[i].io=io;
- io->yscale[i].yscale=yscale_max[i];
- SIGNAL_CONNECT(menu_item, "activate", yscale_select, &io->yscale[i]);
+ OBJECT_SET_DATA(menu_item, "yscale_max", yscale_max[i]);
+ SIGNAL_CONNECT(menu_item, "activate", yscale_select, io);
gtk_widget_show(menu_item);
gtk_menu_append(GTK_MENU(menu), menu_item);
}
}
static void
-count_type_select(GtkWidget *item _U_, gpointer key)
+count_type_select(GtkWidget *item, gpointer key)
{
- io_stat_count_type_t *ct=(io_stat_count_type_t *)key;
+ int val;
+ io_stat_t *io;
+
+ io=(io_stat_t *)key;
+ val=(int)OBJECT_GET_DATA(item, "count_type");
- ct->io->count_type=ct->count_type;
+ io->count_type=val;
- if(ct->io->count_type==COUNT_TYPE_ADVANCED){
+ if(io->count_type==COUNT_TYPE_ADVANCED){
int i;
for(i=0;i<MAX_GRAPHS;i++){
- ct->io->graphs[i].display=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ct->io->graphs[i].display_button), ct->io->graphs[i].display);
- gtk_widget_show(ct->io->graphs[i].advanced_buttons);
-/* redraw the entire window so teh unhidden widgets show up, hopefully */
+ disable_graph(&io->graphs[i]);
+ gtk_widget_show(io->graphs[i].advanced_buttons);
+/* redraw the entire window so the unhidden widgets show up, hopefully */
{GdkRectangle update_rect;
update_rect.x=0;
update_rect.y=0;
-update_rect.width=ct->io->window->allocation.width;
-update_rect.height=ct->io->window->allocation.height;
-gtk_widget_draw(ct->io->window, &update_rect);
+update_rect.width=io->window->allocation.width;
+update_rect.height=io->window->allocation.height;
+gtk_widget_draw(io->window, &update_rect);
}
}
} else {
int i;
for(i=0;i<MAX_GRAPHS;i++){
- gtk_widget_hide(ct->io->graphs[i].advanced_buttons);
+ gtk_widget_hide(io->graphs[i].advanced_buttons);
}
}
- ct->io->needs_redraw=1;
- gtk_iostat_draw(&ct->io->graphs[0]);
+ io_stat_redraw(io);
}
static void
int i;
for(i=0;i<MAX_COUNT_TYPES;i++){
- menu_item=gtk_menu_item_new_with_label(max_count_types[i]);
- io->counttype[i].io=io;
- io->counttype[i].count_type=i;
- SIGNAL_CONNECT(menu_item, "activate", count_type_select, &io->counttype[i]);
+ menu_item=gtk_menu_item_new_with_label(count_type_names[i]);
+ OBJECT_SET_DATA(menu_item, "count_type", i);
+ SIGNAL_CONNECT(menu_item, "activate", count_type_select, io);
gtk_widget_show(menu_item);
gtk_menu_append(GTK_MENU(menu), menu_item);
}
static void
create_ctrl_area(io_stat_t *io, GtkWidget *box)
{
+ GtkWidget *frame_vbox;
+ GtkWidget *frame;
GtkWidget *vbox;
+ frame_vbox=gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(box), frame_vbox);
+ gtk_widget_show(frame_vbox);
+
+ frame = gtk_frame_new("X Axis");
+ gtk_container_add(GTK_CONTAINER(frame_vbox), frame);
+ gtk_widget_show(frame);
+
+ vbox=gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 3);
+ gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_END);
+ gtk_widget_show(vbox);
+
+ create_ctrl_menu(io, vbox, "Tick interval:", create_tick_interval_menu_items);
+ create_ctrl_menu(io, vbox, "Pixels per tick:", create_pixels_per_tick_menu_items);
+
+ frame = gtk_frame_new("Y Axis");
+ gtk_container_add(GTK_CONTAINER(frame_vbox), frame);
+ gtk_widget_show(frame);
+
vbox=gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(box), vbox);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 3);
gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_END);
gtk_widget_show(vbox);
- create_ctrl_menu(io, vbox, "Unit:", create_frames_or_bytes_menu_items);
- create_ctrl_menu(io, vbox, "Tick Interval:", create_tick_interval_menu_items);
- create_ctrl_menu(io, vbox, "Pixels Per Tick:", create_pixels_per_tick_menu_items);
- create_ctrl_menu(io, vbox, "Y-scale:", create_yscale_max_menu_items);
+ create_ctrl_menu(io, vbox, "Unit:", create_frames_or_bytes_menu_items);
+ create_ctrl_menu(io, vbox, "Scale:", create_yscale_max_menu_items);
return;
}
filter_callback(GtkWidget *widget _U_, io_stat_graph_t *gio)
{
char *filter;
- int i;
+ char *field;
header_field_info *hfi;
+ dfilter_t *dfilter;
+
+ field=(char *)gtk_entry_get_text(GTK_ENTRY(gio->calc_field));
+
+ /* this graph is not active, just update display and redraw */
+ if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gio->display_button))){
+ disable_graph(gio);
+ io_stat_redraw(gio->io);
+ return 0;
+ }
/* first check if the field string is valid */
if(gio->io->count_type==COUNT_TYPE_ADVANCED){
- char *field;
- field=(char *)gtk_entry_get_text(GTK_ENTRY(gio->calc_field));
/* warn and bail out if there was no field specified */
if(field==NULL || field[0]==0){
- simple_dialog(ESD_TYPE_WARN, NULL, "'%s' is not a valid field name", field);
- gio->display=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
- gio->io->needs_redraw=1;
- gtk_iostat_draw(gio);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "You did not specify a field name.");
+ disable_graph(gio);
+ io_stat_redraw(gio->io);
return 0;
}
/* warn and bail out if the field could not be found */
hfi=proto_registrar_get_byname(field);
if(hfi==NULL){
- simple_dialog(ESD_TYPE_WARN, NULL, "'%s' is not a valid field name", field);
- gio->display=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
- gio->io->needs_redraw=1;
- gtk_iostat_draw(gio);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "'%s' is not a valid field name.", field);
+ disable_graph(gio);
+ io_stat_redraw(gio->io);
return 0;
}
gio->hf_index=hfi->id;
case FT_INT16:
case FT_INT24:
case FT_INT32:
+ /* these values support all calculations except LOAD */
+ switch(gio->calc_type){
+ case CALC_TYPE_LOAD:
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "LOAD(*) is only supported for relative-time fields.");
+ disable_graph(gio);
+ io_stat_redraw(gio->io);
+ return 0;
+ }
/* these types support all calculations */
break;
case FT_RELATIVE_TIME:
- /* this type only support COUNT, MAX, MIN, AVG */
+ /* this type only supports COUNT, MAX, MIN, AVG */
switch(gio->calc_type){
case CALC_TYPE_COUNT:
case CALC_TYPE_MAX:
case CALC_TYPE_MIN:
case CALC_TYPE_AVG:
+ case CALC_TYPE_LOAD:
break;
default:
- simple_dialog(ESD_TYPE_WARN, NULL, "%s is not supported for %s's type", max_calc_types[gio->calc_type], field);
- gio->display=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
- gio->io->needs_redraw=1;
- gtk_iostat_draw(gio);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "%s is a relative-time field, so %s calculations are not supported on it.",
+ field,
+ calc_type_names[gio->calc_type]);
+ disable_graph(gio);
+ io_stat_redraw(gio->io);
+ return 0;
+ }
+ break;
+ case FT_UINT64:
+ case FT_INT64:
+ /*
+ * XXX - support this if gint64/guint64 are
+ * available?
+ */
+ if(gio->calc_type!=CALC_TYPE_COUNT){
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "%s is a 64-bit integer, so %s calculations are not supported on it.",
+ field,
+ calc_type_names[gio->calc_type]);
+ disable_graph(gio);
+ io_stat_redraw(gio->io);
return 0;
}
break;
default:
+ /*
+ * XXX - support all operations on floating-point
+ * numbers?
+ */
if(gio->calc_type!=CALC_TYPE_COUNT){
- simple_dialog(ESD_TYPE_WARN, NULL, "Stat calculations is not supported for %s's type", field);
- gio->display=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
- gio->io->needs_redraw=1;
- gtk_iostat_draw(gio);
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+ "%s doesn't have integral values, so %s calculations are not supported on it.",
+ field,
+ calc_type_names[gio->calc_type]);
+ disable_graph(gio);
+ io_stat_redraw(gio->io);
return 0;
}
+ break;
}
-
-
- }
-
- /* first check if the filter string is valid. Do this by just trying
- to register, deregister a dummy listener. */
- filter=(char *)gtk_entry_get_text(GTK_ENTRY(gio->filter_button));
- if(register_tap_listener("frame", &filter, filter, NULL, NULL, NULL)){
- simple_dialog(ESD_TYPE_WARN, NULL, "%s is not a valid filter string", filter);
- if(gio->display){
- gio->display=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
- }
- protect_thread_critical_region();
- remove_tap_listener(gio);
- unprotect_thread_critical_region();
-
- gio->io->needs_redraw=1;
- gtk_iostat_draw(gio);
-
- return 0;
}
- /* just remove the dummy again */
- protect_thread_critical_region();
- remove_tap_listener(&filter);
- unprotect_thread_critical_region();
- /* this graph is not active, just update display and redraw */
- if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gio->display_button))){
- gio->display=0;
- gio->io->needs_redraw=1;
- gtk_iostat_draw(gio);
+ /* first check if the filter string is valid. */
+ filter=(char *)gtk_entry_get_text(GTK_ENTRY(gio->filter_field));
+ if(!dfilter_compile(filter, &dfilter)) {
+ bad_dfilter_alert_box(filter);
+ disable_graph(gio);
+ io_stat_redraw(gio->io);
return 0;
}
+ if (dfilter != NULL)
+ dfilter_free(dfilter);
/* ok, we have a valid filter and the graph is active.
first just try to delete any previous settings and then apply
remove_tap_listener(gio);
unprotect_thread_critical_region();
- gio->display=1;
-
- /* only register the draw routine for the first gio. */
- for(i=0;i<MAX_GRAPHS;i++){
- gtk_iostat_reset(&gio->io->graphs[i]);
- }
- register_tap_listener("frame", gio, filter, gtk_iostat_reset, gtk_iostat_packet, gtk_iostat_draw);
- redissect_packets(&cfile);
- gio->io->needs_redraw=1;
- gtk_iostat_draw(gio);
+ io_stat_reset(gio->io);
+ enable_graph(gio, filter, field);
+ retap_packets(&cfile);
+ io_stat_redraw(gio->io);
return 0;
}
ct->gio->calc_type=ct->calc_type;
/* disable the graph */
- ct->gio->display=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ct->gio->display_button), ct->gio->display);
-
- ct->gio->io->needs_redraw=1;
- gtk_iostat_draw(&ct->gio->io->graphs[0]);
+ disable_graph(ct->gio);
+ io_stat_redraw(ct->gio->io);
}
for(i=0;i<MAX_CALC_TYPES;i++){
gio->calc_types[i].gio=gio;
gio->calc_types[i].calc_type=i;
- menu_item=gtk_menu_item_new_with_label(max_calc_types[i]);
+ menu_item=gtk_menu_item_new_with_label(calc_type_names[i]);
SIGNAL_CONNECT(menu_item, "activate", calc_type_select, &gio->calc_types[i]);
gtk_widget_show(menu_item);
gtk_menu_append(GTK_MENU(menu), menu_item);
gtk_widget_show(option_menu);
}
-
-static gint
-field_callback(GtkWidget *widget _U_, io_stat_graph_t *gio)
-{
- gio->display=0;
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
- gio->io->needs_redraw=1;
- gtk_iostat_draw(gio);
- return 0;
-}
-
-
static void
create_advanced_field(io_stat_graph_t *gio, GtkWidget *box)
{
gio->calc_field=gtk_entry_new_with_max_length(30);
gtk_box_pack_start(GTK_BOX(box), gio->calc_field, FALSE, FALSE, 0);
gtk_widget_show(gio->calc_field);
- SIGNAL_CONNECT(gio->filter_button, "activate", field_callback, gio);
+ SIGNAL_CONNECT(gio->calc_field, "activate", filter_callback, gio);
}
gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
gtk_widget_hide(hbox);
+ gio->calc_type=CALC_TYPE_SUM;
create_advanced_menu(gio, hbox, "Calc:", create_calc_types_menu_items);
create_advanced_field(gio, hbox);
}
static void
create_filter_box(io_stat_graph_t *gio, GtkWidget *box, int num)
{
+ GtkWidget *option_menu;
+ GtkWidget *menu;
+ GtkWidget *menu_item;
GtkWidget *hbox;
GtkWidget *label;
char str[256];
+ int i;
- hbox=gtk_hbox_new(FALSE, 0);
+ hbox=gtk_hbox_new(FALSE, 3);
gtk_container_add(GTK_CONTAINER(box), hbox);
gtk_box_set_child_packing(GTK_BOX(box), hbox, FALSE, FALSE, 0, GTK_PACK_START);
gtk_widget_show(hbox);
-
- sprintf(str, "Filter:%d", num);
- label=gtk_label_new(str);
- gtk_widget_show(label);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- gio->display_button=gtk_toggle_button_new();
+ g_snprintf(str, 256, "Graph %d", num);
+ gio->display_button=gtk_toggle_button_new_with_label(str);
gtk_box_pack_start(GTK_BOX(hbox), gio->display_button, FALSE, FALSE, 0);
gtk_widget_show(gio->display_button);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gio->display_button), gio->display);
SIGNAL_CONNECT(gio->display_button, "toggled", filter_callback, gio);
-
-
- label=gtk_label_new(" Color:");
+ label=gtk_label_new("Color");
gtk_widget_show(label);
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
- gio->color_button=gtk_toggle_button_new();
- gtk_box_pack_start(GTK_BOX(hbox), gio->color_button, FALSE, FALSE, 0);
- gtk_widget_show(gio->color_button);
-
#if GTK_MAJOR_VERSION < 2
+ /* setting the color of the display button doesn't work */
rc_style = gtk_rc_style_new ();
- rc_style->bg[GTK_STATE_NORMAL] = gio->color;
- rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_BG;
- rc_style->bg[GTK_STATE_ACTIVE] = gio->color;
- rc_style->color_flags[GTK_STATE_ACTIVE] |= GTK_RC_BG;
- rc_style->bg[GTK_STATE_PRELIGHT] = gio->color;
- rc_style->color_flags[GTK_STATE_PRELIGHT] |= GTK_RC_BG;
- rc_style->bg[GTK_STATE_SELECTED] = gio->color;
- rc_style->color_flags[GTK_STATE_SELECTED] |= GTK_RC_BG;
- rc_style->bg[GTK_STATE_INSENSITIVE] = gio->color;
- rc_style->color_flags[GTK_STATE_INSENSITIVE] |= GTK_RC_BG;
- gtk_widget_modify_style (gio->color_button, rc_style);
+ rc_style->fg[GTK_STATE_NORMAL] = gio->color;
+ rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_FG;
+ rc_style->fg[GTK_STATE_ACTIVE] = gio->color;
+ rc_style->color_flags[GTK_STATE_ACTIVE] |= GTK_RC_FG;
+ rc_style->fg[GTK_STATE_PRELIGHT] = gio->color;
+ rc_style->color_flags[GTK_STATE_PRELIGHT] |= GTK_RC_FG;
+ rc_style->fg[GTK_STATE_SELECTED] = gio->color;
+ rc_style->color_flags[GTK_STATE_SELECTED] |= GTK_RC_FG;
+ rc_style->fg[GTK_STATE_INSENSITIVE] = gio->color;
+ rc_style->color_flags[GTK_STATE_INSENSITIVE] |= GTK_RC_FG;
+ gtk_widget_modify_style (label, rc_style);
gtk_rc_style_unref (rc_style);
#else
- gtk_widget_modify_bg(gio->color_button, GTK_STATE_NORMAL, &gio->color);
- gtk_widget_modify_bg(gio->color_button, GTK_STATE_ACTIVE, &gio->color);
- gtk_widget_modify_bg(gio->color_button, GTK_STATE_PRELIGHT, &gio->color);
- gtk_widget_modify_bg(gio->color_button, GTK_STATE_SELECTED, &gio->color);
- gtk_widget_modify_bg(gio->color_button, GTK_STATE_INSENSITIVE, &gio->color);
+ gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &gio->color);
+ gtk_widget_modify_fg(label, GTK_STATE_ACTIVE, &gio->color);
+ gtk_widget_modify_fg(label, GTK_STATE_PRELIGHT, &gio->color);
+ gtk_widget_modify_fg(label, GTK_STATE_SELECTED, &gio->color);
+ gtk_widget_modify_fg(label, GTK_STATE_INSENSITIVE, &gio->color);
#endif
/* gtk_signal_connect(GTK_OBJECT(gio->display_button), "toggled", GTK_SIGNAL_FUNC(filter_callback), gio);*/
- /* filter prefs dialog --- comment out static label */
- /* label=gtk_label_new(" Filter:"); */
-
/* filter prefs dialog */
- label=gtk_label_new(" ");
- gtk_widget_show(label);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
- gio->filter_bt = gtk_button_new_with_label("Filter:");
+ gio->filter_bt=BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
- sprintf(str, "Ethereal: Display Filter IO-Stat (Filter:%d)", num);
+ g_snprintf(str, 256, "Ethereal: Display Filter IO-Stat (Filter:%d)", num);
if(gio->args->title){
free(gio->args->title);
}
gtk_box_pack_start(GTK_BOX(hbox), gio->filter_bt, FALSE, TRUE, 0);
gtk_widget_show(gio->filter_bt);
- gio->filter_button=gtk_entry_new_with_max_length(256);
+ gio->filter_field=gtk_entry_new_with_max_length(256);
/* filter prefs dialog */
- OBJECT_SET_DATA(gio->filter_bt, E_FILT_TE_PTR_KEY, gio->filter_button);
+ OBJECT_SET_DATA(gio->filter_bt, E_FILT_TE_PTR_KEY, gio->filter_field);
/* filter prefs dialog */
- gtk_box_pack_start(GTK_BOX(hbox), gio->filter_button, FALSE, FALSE, 0);
- gtk_widget_show(gio->filter_button);
- SIGNAL_CONNECT(gio->filter_button, "activate", filter_callback, gio);
+ gtk_box_pack_start(GTK_BOX(hbox), gio->filter_field, FALSE, FALSE, 0);
+ gtk_widget_show(gio->filter_field);
+ SIGNAL_CONNECT(gio->filter_field, "activate", filter_callback, gio);
+ SIGNAL_CONNECT(gio->filter_field, "changed", filter_te_syntax_check_cb, NULL);
create_advanced_box(gio, hbox);
+
+ /*
+ * create PlotStyle menu
+ */
+ g_snprintf(str, 256, " Style:");
+ label=gtk_label_new(str);
+ gtk_widget_show(label);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ option_menu=gtk_option_menu_new();
+ menu=gtk_menu_new();
+ for(i=0;i<MAX_PLOT_STYLES;i++){
+ menu_item=gtk_menu_item_new_with_label(plot_style_name[i]);
+ OBJECT_SET_DATA(menu_item, "plot_style", i);
+ SIGNAL_CONNECT(menu_item, "activate", plot_style_select, &gio->io->graphs[num-1]);
+ gtk_widget_show(menu_item);
+ gtk_menu_append(GTK_MENU(menu), menu_item);
+ }
+ gtk_menu_set_active(GTK_MENU(menu), DEFAULT_PLOT_STYLE);
+
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
+ gtk_box_pack_end(GTK_BOX(hbox), option_menu, FALSE, FALSE, 0);
+ gtk_widget_show(option_menu);
+
+
return;
}
static void
create_filter_area(io_stat_t *io, GtkWidget *box)
{
+ GtkWidget *frame;
GtkWidget *vbox;
int i;
- vbox=gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(box), vbox);
+ frame=gtk_frame_new("Graphs");
+ gtk_container_add(GTK_CONTAINER(box), frame);
+ gtk_widget_show(frame);
+
+ vbox=gtk_vbox_new(FALSE, 1);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ gtk_container_border_width(GTK_CONTAINER(vbox), 3);
gtk_box_set_child_packing(GTK_BOX(box), vbox, FALSE, FALSE, 0, GTK_PACK_START);
gtk_widget_show(vbox);
{
GtkWidget *vbox;
GtkWidget *hbox;
+ GtkWidget *bt_close;
/* create the main window */
- io->window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- gtk_widget_set_name(io->window, "I/O Statistics");
+ io->window=window_new(GTK_WINDOW_TOPLEVEL, "I/O Graphs");
vbox=gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(io->window), vbox);
create_draw_area(io, vbox);
- hbox=gtk_hbox_new(FALSE, 0);
+ hbox=gtk_hbox_new(FALSE, 3);
gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+ gtk_container_border_width(GTK_CONTAINER(hbox), 3);
gtk_box_set_child_packing(GTK_BOX(vbox), hbox, FALSE, FALSE, 0, GTK_PACK_START);
gtk_widget_show(hbox);
create_filter_area(io, hbox);
create_ctrl_area(io, hbox);
- gtk_widget_show(io->window);
- gtk_window_set_title(GTK_WINDOW(io->window),"IO-Stat");
+ io_stat_set_title(io);
+
+ hbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_widget_show(hbox);
+
+ bt_close = OBJECT_GET_DATA(hbox, GTK_STOCK_CLOSE);
+ window_set_cancel_button(io->window, bt_close, window_cancel_button_cb);
+
+ SIGNAL_CONNECT(io->window, "delete_event", window_delete_event_cb, NULL);
+
+ gtk_widget_show(io->window);
+ window_present(io->window);
}
void
register_tap_listener_gtk_iostat(void)
{
- io_stat_widget_table = g_hash_table_new(io_stat_widget_hash,
- io_stat_widget_equal);
register_ethereal_tap("io,stat", gtk_iostat_init);
-}
-void
-register_tap_menu_gtkiostat(void)
-{
- register_tap_menu_item("IO/IO-Stat", gtk_iostat_cb);
+ register_tap_menu_item("_IO Graphs", REGISTER_TAP_GROUP_GENERIC,
+ gtk_iostat_cb, NULL, NULL, NULL);
}