1 #include "../evlist.h" 2 #include "../cache.h" 3 #include "../evsel.h" 4 #include "../sort.h" 5 #include "../hist.h" 6 #include "gtk.h" 7 8 #include <signal.h> 9 10 #define MAX_COLUMNS 32 11 12 static void perf_gtk__signal(int sig) 13 { 14 psignal(sig, "perf"); 15 gtk_main_quit(); 16 } 17 18 static void perf_gtk__resize_window(GtkWidget *window) 19 { 20 GdkRectangle rect; 21 GdkScreen *screen; 22 int monitor; 23 int height; 24 int width; 25 26 screen = gtk_widget_get_screen(window); 27 28 monitor = gdk_screen_get_monitor_at_window(screen, window->window); 29 30 gdk_screen_get_monitor_geometry(screen, monitor, &rect); 31 32 width = rect.width * 3 / 4; 33 height = rect.height * 3 / 4; 34 35 gtk_window_resize(GTK_WINDOW(window), width, height); 36 } 37 38 static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) 39 { 40 GType col_types[MAX_COLUMNS]; 41 GtkCellRenderer *renderer; 42 struct sort_entry *se; 43 GtkListStore *store; 44 struct rb_node *nd; 45 u64 total_period; 46 GtkWidget *view; 47 int col_idx; 48 int nr_cols; 49 50 nr_cols = 0; 51 52 /* The percentage column */ 53 col_types[nr_cols++] = G_TYPE_STRING; 54 55 list_for_each_entry(se, &hist_entry__sort_list, list) { 56 if (se->elide) 57 continue; 58 59 col_types[nr_cols++] = G_TYPE_STRING; 60 } 61 62 store = gtk_list_store_newv(nr_cols, col_types); 63 64 view = gtk_tree_view_new(); 65 66 renderer = gtk_cell_renderer_text_new(); 67 68 col_idx = 0; 69 70 /* The percentage column */ 71 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), 72 -1, "Overhead (%)", 73 renderer, "text", 74 col_idx++, NULL); 75 76 list_for_each_entry(se, &hist_entry__sort_list, list) { 77 if (se->elide) 78 continue; 79 80 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), 81 -1, se->se_header, 82 renderer, "text", 83 col_idx++, NULL); 84 } 85 86 gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store)); 87 88 g_object_unref(GTK_TREE_MODEL(store)); 89 90 total_period = hists->stats.total_period; 91 92 for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { 93 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 94 GtkTreeIter iter; 95 double percent; 96 char s[512]; 97 98 if (h->filtered) 99 continue; 100 101 gtk_list_store_append(store, &iter); 102 103 col_idx = 0; 104 105 percent = (h->period * 100.0) / total_period; 106 107 snprintf(s, ARRAY_SIZE(s), "%.2f", percent); 108 109 gtk_list_store_set(store, &iter, col_idx++, s, -1); 110 111 list_for_each_entry(se, &hist_entry__sort_list, list) { 112 if (se->elide) 113 continue; 114 115 se->se_snprintf(h, s, ARRAY_SIZE(s), 116 hists__col_len(hists, se->se_width_idx)); 117 118 gtk_list_store_set(store, &iter, col_idx++, s, -1); 119 } 120 } 121 122 gtk_container_add(GTK_CONTAINER(window), view); 123 } 124 125 int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, 126 const char *help __used, 127 void (*timer) (void *arg)__used, 128 void *arg __used, int delay_secs __used) 129 { 130 struct perf_evsel *pos; 131 GtkWidget *notebook; 132 GtkWidget *window; 133 134 signal(SIGSEGV, perf_gtk__signal); 135 signal(SIGFPE, perf_gtk__signal); 136 signal(SIGINT, perf_gtk__signal); 137 signal(SIGQUIT, perf_gtk__signal); 138 signal(SIGTERM, perf_gtk__signal); 139 140 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 141 142 gtk_window_set_title(GTK_WINDOW(window), "perf report"); 143 144 g_signal_connect(window, "delete_event", gtk_main_quit, NULL); 145 146 notebook = gtk_notebook_new(); 147 148 list_for_each_entry(pos, &evlist->entries, node) { 149 struct hists *hists = &pos->hists; 150 const char *evname = event_name(pos); 151 GtkWidget *scrolled_window; 152 GtkWidget *tab_label; 153 154 scrolled_window = gtk_scrolled_window_new(NULL, NULL); 155 156 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), 157 GTK_POLICY_AUTOMATIC, 158 GTK_POLICY_AUTOMATIC); 159 160 perf_gtk__show_hists(scrolled_window, hists); 161 162 tab_label = gtk_label_new(evname); 163 164 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label); 165 } 166 167 gtk_container_add(GTK_CONTAINER(window), notebook); 168 169 gtk_widget_show_all(window); 170 171 perf_gtk__resize_window(window); 172 173 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 174 175 gtk_main(); 176 177 return 0; 178 } 179