2012-03-19 15:13:29 -03:00
# include "../evlist.h"
# include "../cache.h"
# include "../evsel.h"
# include "../sort.h"
# include "../hist.h"
2012-08-16 17:14:53 +09:00
# include "../helpline.h"
2012-03-19 15:13:29 -03:00
# include "gtk.h"
# include <signal.h>
# define MAX_COLUMNS 32
2012-04-30 13:55:07 +09:00
static void perf_gtk__signal ( int sig )
2012-03-19 15:13:29 -03:00
{
2012-05-29 13:22:59 +09:00
perf_gtk__exit ( false ) ;
2012-03-19 15:13:29 -03:00
psignal ( sig , " perf " ) ;
}
2012-04-30 13:55:07 +09:00
static void perf_gtk__resize_window ( GtkWidget * window )
2012-03-19 15:13:29 -03:00
{
GdkRectangle rect ;
GdkScreen * screen ;
int monitor ;
int height ;
int width ;
screen = gtk_widget_get_screen ( window ) ;
monitor = gdk_screen_get_monitor_at_window ( screen , window - > window ) ;
gdk_screen_get_monitor_geometry ( screen , monitor , & rect ) ;
width = rect . width * 3 / 4 ;
height = rect . height * 3 / 4 ;
gtk_window_resize ( GTK_WINDOW ( window ) , width , height ) ;
}
2012-09-03 11:53:10 +09:00
static const char * perf_gtk__get_percent_color ( double percent )
{
if ( percent > = MIN_RED )
return " <span fgcolor='red'> " ;
if ( percent > = MIN_GREEN )
return " <span fgcolor='dark green'> " ;
return NULL ;
}
# define HPP__COLOR_FN(_name, _field) \
static int perf_gtk__hpp_color_ # # _name ( struct perf_hpp * hpp , \
struct hist_entry * he ) \
{ \
2012-10-04 21:49:40 +09:00
struct hists * hists = he - > hists ; \
2012-10-04 21:49:41 +09:00
double percent = 100.0 * he - > stat . _field / hists - > stats . total_period ; \
2012-09-03 11:53:10 +09:00
const char * markup ; \
int ret = 0 ; \
\
markup = perf_gtk__get_percent_color ( percent ) ; \
if ( markup ) \
ret + = scnprintf ( hpp - > buf , hpp - > size , " %s " , markup ) ; \
2012-09-12 15:35:05 +09:00
ret + = scnprintf ( hpp - > buf + ret , hpp - > size - ret , " %6.2f%% " , percent ) ; \
2012-09-03 11:53:10 +09:00
if ( markup ) \
ret + = scnprintf ( hpp - > buf + ret , hpp - > size - ret , " </span> " ) ; \
\
return ret ; \
}
HPP__COLOR_FN ( overhead , period )
HPP__COLOR_FN ( overhead_sys , period_sys )
HPP__COLOR_FN ( overhead_us , period_us )
HPP__COLOR_FN ( overhead_guest_sys , period_guest_sys )
HPP__COLOR_FN ( overhead_guest_us , period_guest_us )
# undef HPP__COLOR_FN
void perf_gtk__init_hpp ( void )
{
2012-10-04 21:49:39 +09:00
perf_hpp__init ( ) ;
2012-09-03 11:53:10 +09:00
perf_hpp__format [ PERF_HPP__OVERHEAD ] . color =
perf_gtk__hpp_color_overhead ;
perf_hpp__format [ PERF_HPP__OVERHEAD_SYS ] . color =
perf_gtk__hpp_color_overhead_sys ;
perf_hpp__format [ PERF_HPP__OVERHEAD_US ] . color =
perf_gtk__hpp_color_overhead_us ;
perf_hpp__format [ PERF_HPP__OVERHEAD_GUEST_SYS ] . color =
perf_gtk__hpp_color_overhead_guest_sys ;
perf_hpp__format [ PERF_HPP__OVERHEAD_GUEST_US ] . color =
perf_gtk__hpp_color_overhead_guest_us ;
}
2012-04-30 13:55:07 +09:00
static void perf_gtk__show_hists ( GtkWidget * window , struct hists * hists )
2012-03-19 15:13:29 -03:00
{
GType col_types [ MAX_COLUMNS ] ;
GtkCellRenderer * renderer ;
struct sort_entry * se ;
GtkListStore * store ;
struct rb_node * nd ;
GtkWidget * view ;
2012-09-03 11:53:10 +09:00
int i , col_idx ;
2012-03-19 15:13:29 -03:00
int nr_cols ;
2012-09-03 11:53:10 +09:00
char s [ 512 ] ;
struct perf_hpp hpp = {
. buf = s ,
. size = sizeof ( s ) ,
} ;
2012-03-19 15:13:29 -03:00
nr_cols = 0 ;
2012-09-03 11:53:10 +09:00
for ( i = 0 ; i < PERF_HPP__MAX_INDEX ; i + + ) {
if ( ! perf_hpp__format [ i ] . cond )
continue ;
col_types [ nr_cols + + ] = G_TYPE_STRING ;
}
2012-03-19 15:13:29 -03:00
list_for_each_entry ( se , & hist_entry__sort_list , list ) {
if ( se - > elide )
continue ;
col_types [ nr_cols + + ] = G_TYPE_STRING ;
}
store = gtk_list_store_newv ( nr_cols , col_types ) ;
view = gtk_tree_view_new ( ) ;
renderer = gtk_cell_renderer_text_new ( ) ;
col_idx = 0 ;
2012-09-03 11:53:10 +09:00
for ( i = 0 ; i < PERF_HPP__MAX_INDEX ; i + + ) {
if ( ! perf_hpp__format [ i ] . cond )
continue ;
perf_hpp__format [ i ] . header ( & hpp ) ;
gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW ( view ) ,
- 1 , s ,
renderer , " markup " ,
col_idx + + , NULL ) ;
}
2012-03-19 15:13:29 -03:00
list_for_each_entry ( se , & hist_entry__sort_list , list ) {
if ( se - > elide )
continue ;
gtk_tree_view_insert_column_with_attributes ( GTK_TREE_VIEW ( view ) ,
- 1 , se - > se_header ,
renderer , " text " ,
col_idx + + , NULL ) ;
}
gtk_tree_view_set_model ( GTK_TREE_VIEW ( view ) , GTK_TREE_MODEL ( store ) ) ;
g_object_unref ( GTK_TREE_MODEL ( store ) ) ;
for ( nd = rb_first ( & hists - > entries ) ; nd ; nd = rb_next ( nd ) ) {
struct hist_entry * h = rb_entry ( nd , struct hist_entry , rb_node ) ;
GtkTreeIter iter ;
if ( h - > filtered )
continue ;
gtk_list_store_append ( store , & iter ) ;
col_idx = 0 ;
2012-09-03 11:53:10 +09:00
for ( i = 0 ; i < PERF_HPP__MAX_INDEX ; i + + ) {
if ( ! perf_hpp__format [ i ] . cond )
continue ;
2012-03-19 15:13:29 -03:00
2012-09-03 11:53:10 +09:00
if ( perf_hpp__format [ i ] . color )
perf_hpp__format [ i ] . color ( & hpp , h ) ;
else
perf_hpp__format [ i ] . entry ( & hpp , h ) ;
2012-03-19 15:13:29 -03:00
2012-09-03 11:53:10 +09:00
gtk_list_store_set ( store , & iter , col_idx + + , s , - 1 ) ;
}
2012-03-19 15:13:29 -03:00
list_for_each_entry ( se , & hist_entry__sort_list , list ) {
if ( se - > elide )
continue ;
se - > se_snprintf ( h , s , ARRAY_SIZE ( s ) ,
hists__col_len ( hists , se - > se_width_idx ) ) ;
gtk_list_store_set ( store , & iter , col_idx + + , s , - 1 ) ;
}
}
gtk_container_add ( GTK_CONTAINER ( window ) , view ) ;
}
2012-05-29 13:23:01 +09:00
# ifdef HAVE_GTK_INFO_BAR
static GtkWidget * perf_gtk__setup_info_bar ( void )
{
GtkWidget * info_bar ;
GtkWidget * label ;
GtkWidget * content_area ;
info_bar = gtk_info_bar_new ( ) ;
gtk_widget_set_no_show_all ( info_bar , TRUE ) ;
label = gtk_label_new ( " " ) ;
gtk_widget_show ( label ) ;
content_area = gtk_info_bar_get_content_area ( GTK_INFO_BAR ( info_bar ) ) ;
gtk_container_add ( GTK_CONTAINER ( content_area ) , label ) ;
gtk_info_bar_add_button ( GTK_INFO_BAR ( info_bar ) , GTK_STOCK_OK ,
GTK_RESPONSE_OK ) ;
g_signal_connect ( info_bar , " response " ,
G_CALLBACK ( gtk_widget_hide ) , NULL ) ;
pgctx - > info_bar = info_bar ;
pgctx - > message_label = label ;
return info_bar ;
}
# endif
2012-05-29 13:23:00 +09:00
static GtkWidget * perf_gtk__setup_statusbar ( void )
{
GtkWidget * stbar ;
unsigned ctxid ;
stbar = gtk_statusbar_new ( ) ;
ctxid = gtk_statusbar_get_context_id ( GTK_STATUSBAR ( stbar ) ,
" perf report " ) ;
pgctx - > statbar = stbar ;
pgctx - > statbar_ctx_id = ctxid ;
return stbar ;
}
2012-03-19 15:13:29 -03:00
int perf_evlist__gtk_browse_hists ( struct perf_evlist * evlist ,
2012-08-16 17:14:53 +09:00
const char * help ,
2012-11-02 14:50:05 +09:00
struct hist_browser_timer * hbt __maybe_unused )
2012-03-19 15:13:29 -03:00
{
struct perf_evsel * pos ;
2012-05-29 13:23:00 +09:00
GtkWidget * vbox ;
2012-03-19 15:13:29 -03:00
GtkWidget * notebook ;
2012-05-29 13:23:01 +09:00
GtkWidget * info_bar ;
2012-05-29 13:23:00 +09:00
GtkWidget * statbar ;
2012-03-19 15:13:29 -03:00
GtkWidget * window ;
2012-04-30 13:55:07 +09:00
signal ( SIGSEGV , perf_gtk__signal ) ;
signal ( SIGFPE , perf_gtk__signal ) ;
signal ( SIGINT , perf_gtk__signal ) ;
signal ( SIGQUIT , perf_gtk__signal ) ;
signal ( SIGTERM , perf_gtk__signal ) ;
2012-03-19 15:13:29 -03:00
window = gtk_window_new ( GTK_WINDOW_TOPLEVEL ) ;
gtk_window_set_title ( GTK_WINDOW ( window ) , " perf report " ) ;
g_signal_connect ( window , " delete_event " , gtk_main_quit , NULL ) ;
2012-05-29 13:22:59 +09:00
pgctx = perf_gtk__activate_context ( window ) ;
if ( ! pgctx )
return - 1 ;
2012-05-29 13:23:00 +09:00
vbox = gtk_vbox_new ( FALSE , 0 ) ;
2012-03-19 15:13:29 -03:00
notebook = gtk_notebook_new ( ) ;
list_for_each_entry ( pos , & evlist - > entries , node ) {
struct hists * hists = & pos - > hists ;
2012-06-12 12:34:58 -03:00
const char * evname = perf_evsel__name ( pos ) ;
2012-03-19 15:13:29 -03:00
GtkWidget * scrolled_window ;
GtkWidget * tab_label ;
scrolled_window = gtk_scrolled_window_new ( NULL , NULL ) ;
gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_window ) ,
GTK_POLICY_AUTOMATIC ,
GTK_POLICY_AUTOMATIC ) ;
2012-04-30 13:55:07 +09:00
perf_gtk__show_hists ( scrolled_window , hists ) ;
2012-03-19 15:13:29 -03:00
tab_label = gtk_label_new ( evname ) ;
gtk_notebook_append_page ( GTK_NOTEBOOK ( notebook ) , scrolled_window , tab_label ) ;
}
2012-05-29 13:23:00 +09:00
gtk_box_pack_start ( GTK_BOX ( vbox ) , notebook , TRUE , TRUE , 0 ) ;
2012-05-29 13:23:01 +09:00
info_bar = perf_gtk__setup_info_bar ( ) ;
if ( info_bar )
gtk_box_pack_start ( GTK_BOX ( vbox ) , info_bar , FALSE , FALSE , 0 ) ;
2012-05-29 13:23:00 +09:00
statbar = perf_gtk__setup_statusbar ( ) ;
gtk_box_pack_start ( GTK_BOX ( vbox ) , statbar , FALSE , FALSE , 0 ) ;
gtk_container_add ( GTK_CONTAINER ( window ) , vbox ) ;
2012-03-19 15:13:29 -03:00
gtk_widget_show_all ( window ) ;
2012-04-30 13:55:07 +09:00
perf_gtk__resize_window ( window ) ;
2012-03-19 15:13:29 -03:00
gtk_window_set_position ( GTK_WINDOW ( window ) , GTK_WIN_POS_CENTER ) ;
2012-08-16 17:14:53 +09:00
ui_helpline__push ( help ) ;
2012-03-19 15:13:29 -03:00
gtk_main ( ) ;
2012-05-29 13:22:59 +09:00
perf_gtk__deactivate_context ( & pgctx ) ;
2012-03-19 15:13:29 -03:00
return 0 ;
}