diff options
Diffstat (limited to 'kernel-shark.c')
-rw-r--r-- | kernel-shark.c | 1241 |
1 files changed, 1122 insertions, 119 deletions
diff --git a/kernel-shark.c b/kernel-shark.c index fcb0f54..9ca3942 100644 --- a/kernel-shark.c +++ b/kernel-shark.c | |||
@@ -27,13 +27,18 @@ | |||
27 | #include <sys/stat.h> | 27 | #include <sys/stat.h> |
28 | #include <unistd.h> | 28 | #include <unistd.h> |
29 | #include <gtk/gtk.h> | 29 | #include <gtk/gtk.h> |
30 | #include <errno.h> | ||
30 | #include <getopt.h> | 31 | #include <getopt.h> |
31 | 32 | ||
32 | #include "trace-compat.h" | 33 | #include "trace-compat.h" |
33 | #include "trace-cmd.h" | 34 | #include "trace-cmd.h" |
35 | #include "trace-gui.h" | ||
34 | #include "kernel-shark.h" | 36 | #include "kernel-shark.h" |
35 | #include "version.h" | 37 | #include "version.h" |
36 | 38 | ||
39 | #define ___stringify(X) #X | ||
40 | #define __stringify(X) ___stringify(X) | ||
41 | |||
37 | #define DEBUG_LEVEL 0 | 42 | #define DEBUG_LEVEL 0 |
38 | #if DEBUG_LEVEL > 0 | 43 | #if DEBUG_LEVEL > 0 |
39 | # define dprintf(l, x...) \ | 44 | # define dprintf(l, x...) \ |
@@ -59,6 +64,85 @@ void usage(char *prog) | |||
59 | printf(" -i input_file, default is %s\n", default_input_file); | 64 | printf(" -i input_file, default is %s\n", default_input_file); |
60 | } | 65 | } |
61 | 66 | ||
67 | /* | ||
68 | * trace_sync_select_menu - helper function to the syncing of list and graph filters | ||
69 | * | ||
70 | * Creates a pop up dialog with the selections given. The selections will be | ||
71 | * radio buttons to the user. The keep is a value that will be set to the check | ||
72 | * box (default on) if the user wants to keep the selection persistant. | ||
73 | */ | ||
74 | static int trace_sync_select_menu(const gchar *title, | ||
75 | gchar **selections, gboolean *keep) | ||
76 | { | ||
77 | GtkWidget *dialog; | ||
78 | GtkWidget *radio; | ||
79 | GtkWidget *check; | ||
80 | GSList *group; | ||
81 | int result; | ||
82 | int i; | ||
83 | |||
84 | dialog = gtk_dialog_new_with_buttons(title, | ||
85 | NULL, | ||
86 | GTK_DIALOG_MODAL, | ||
87 | "OK", GTK_RESPONSE_ACCEPT, | ||
88 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | ||
89 | NULL); | ||
90 | |||
91 | radio = gtk_radio_button_new_with_label(NULL, selections[0]); | ||
92 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), radio, TRUE, TRUE, 0); | ||
93 | gtk_widget_show(radio); | ||
94 | |||
95 | group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio)); | ||
96 | |||
97 | for (i = 1; selections[i]; i++) { | ||
98 | radio = gtk_radio_button_new_with_label(group, selections[i]); | ||
99 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), radio, TRUE, TRUE, 0); | ||
100 | gtk_widget_show(radio); | ||
101 | } | ||
102 | |||
103 | check = gtk_check_button_new_with_label("Keep the filters in sync?"); | ||
104 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), check, TRUE, TRUE, 0); | ||
105 | gtk_widget_show(check); | ||
106 | |||
107 | gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); | ||
108 | |||
109 | result = gtk_dialog_run(GTK_DIALOG(dialog)); | ||
110 | switch (result) { | ||
111 | case GTK_RESPONSE_ACCEPT: | ||
112 | i = 0; | ||
113 | for (i = 0; group; i++, group = g_slist_next(group)) { | ||
114 | radio = group->data; | ||
115 | if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio))) | ||
116 | break; | ||
117 | } | ||
118 | result = i; | ||
119 | *keep = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check)); | ||
120 | break; | ||
121 | default: | ||
122 | result = -1; | ||
123 | } | ||
124 | |||
125 | gtk_widget_destroy(dialog); | ||
126 | return result; | ||
127 | } | ||
128 | |||
129 | static void update_tree_view_filters(struct shark_info *info, | ||
130 | struct filter_task *task_filter, | ||
131 | struct filter_task *hide_tasks) | ||
132 | { | ||
133 | if (info->list_filter_enabled) | ||
134 | trace_view_update_filters(info->treeview, | ||
135 | task_filter, hide_tasks); | ||
136 | |||
137 | if (filter_task_count(task_filter) || | ||
138 | filter_task_count(hide_tasks)) | ||
139 | info->list_filter_available = 1; | ||
140 | else { | ||
141 | info->list_filter_enabled = 0; | ||
142 | info->list_filter_available = 0; | ||
143 | } | ||
144 | } | ||
145 | |||
62 | /* graph callbacks */ | 146 | /* graph callbacks */ |
63 | 147 | ||
64 | /* convert_nano() and print_time() are copied from trace-graph.c for debugging | 148 | /* convert_nano() and print_time() are copied from trace-graph.c for debugging |
@@ -108,15 +192,20 @@ static void ks_graph_filter(struct graph_info *ginfo, | |||
108 | cbs = trace_graph_get_callbacks(ginfo); | 192 | cbs = trace_graph_get_callbacks(ginfo); |
109 | info = container_of(cbs, struct shark_info, graph_cbs); | 193 | info = container_of(cbs, struct shark_info, graph_cbs); |
110 | 194 | ||
111 | if (info->list_filter_enabled) | 195 | if (!info->sync_task_filters) |
112 | trace_view_update_filters(info->treeview, | 196 | return; |
113 | task_filter, hide_tasks); | 197 | |
198 | update_tree_view_filters(info, task_filter, hide_tasks); | ||
114 | } | 199 | } |
115 | 200 | ||
116 | static void free_info(struct shark_info *info) | 201 | static void free_info(struct shark_info *info) |
117 | { | 202 | { |
118 | tracecmd_close(info->handle); | 203 | tracecmd_close(info->handle); |
119 | trace_graph_free_info(info->ginfo); | 204 | trace_graph_free_info(info->ginfo); |
205 | |||
206 | filter_task_hash_free(info->list_task_filter); | ||
207 | filter_task_hash_free(info->list_hide_tasks); | ||
208 | |||
120 | free(info->ginfo); | 209 | free(info->ginfo); |
121 | free(info); | 210 | free(info); |
122 | } | 211 | } |
@@ -134,34 +223,219 @@ static void update_title(GtkWidget *window, const gchar *file) | |||
134 | g_free(str); | 223 | g_free(str); |
135 | } | 224 | } |
136 | 225 | ||
226 | static void unsync_task_filters(struct shark_info *info) | ||
227 | { | ||
228 | info->sync_task_filters = 0; | ||
229 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu), | ||
230 | "Sync Graph and List Task Filters"); | ||
231 | |||
232 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu), | ||
233 | "graph tasks"); | ||
234 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_hide_task_menu), | ||
235 | "graph hide tasks"); | ||
236 | gtk_widget_show(info->list_task_menu); | ||
237 | gtk_widget_show(info->list_hide_task_menu); | ||
238 | |||
239 | /* The list now uses its own hash */ | ||
240 | info->list_task_filter = filter_task_hash_copy(info->ginfo->task_filter); | ||
241 | info->list_hide_tasks = filter_task_hash_copy(info->ginfo->hide_tasks); | ||
242 | } | ||
243 | |||
244 | static void sync_task_filters(struct shark_info *info) | ||
245 | { | ||
246 | info->sync_task_filters = 1; | ||
247 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu), | ||
248 | "Unsync Graph and List Task Filters"); | ||
249 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_task_menu), | ||
250 | "tasks"); | ||
251 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_hide_task_menu), | ||
252 | "hide tasks"); | ||
253 | gtk_widget_hide(info->list_task_menu); | ||
254 | gtk_widget_hide(info->list_hide_task_menu); | ||
255 | } | ||
256 | |||
257 | static void unsync_event_filters(struct shark_info *info) | ||
258 | { | ||
259 | info->sync_event_filters = 0; | ||
260 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->events_sync_menu), | ||
261 | "Sync Graph and List Event Filters"); | ||
262 | |||
263 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_events_menu), | ||
264 | "graph events"); | ||
265 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_adv_events_menu), | ||
266 | "graph advanced events"); | ||
267 | gtk_widget_show(info->list_events_menu); | ||
268 | gtk_widget_show(info->list_adv_events_menu); | ||
269 | } | ||
270 | |||
271 | static void sync_event_filters(struct shark_info *info) | ||
272 | { | ||
273 | info->sync_event_filters = 1; | ||
274 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->events_sync_menu), | ||
275 | "Unsync Graph and List Event Filters"); | ||
276 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_events_menu), | ||
277 | "events"); | ||
278 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->graph_adv_events_menu), | ||
279 | "advanced events"); | ||
280 | gtk_widget_hide(info->list_events_menu); | ||
281 | gtk_widget_hide(info->list_adv_events_menu); | ||
282 | } | ||
283 | |||
137 | static void | 284 | static void |
138 | /* Callback for the clicked signal of the Load button */ | 285 | /* Callback for the clicked signal of the Load button */ |
139 | load_clicked (gpointer data) | 286 | load_clicked (gpointer data) |
140 | { | 287 | { |
141 | struct shark_info *info = data; | 288 | struct shark_info *info = data; |
142 | struct tracecmd_input *handle; | 289 | struct tracecmd_input *handle; |
143 | GtkWidget *dialog; | ||
144 | gchar *filename; | 290 | gchar *filename; |
145 | 291 | ||
146 | dialog = gtk_file_chooser_dialog_new("Load File", | 292 | filename = trace_get_file_dialog("Load File"); |
147 | NULL, | 293 | if (!filename) |
148 | GTK_FILE_CHOOSER_ACTION_OPEN, | 294 | return; |
149 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | 295 | |
150 | GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | 296 | handle = tracecmd_open(filename); |
151 | NULL); | 297 | if (handle) { |
152 | if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { | 298 | tracecmd_close(info->handle); |
153 | filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); | 299 | info->handle = handle; |
154 | handle = tracecmd_open(filename); | 300 | trace_graph_load_handle(info->ginfo, handle); |
155 | if (handle) { | 301 | trace_view_reload(info->treeview, handle, info->spin); |
156 | tracecmd_close(info->handle); | 302 | update_title(info->window, filename); |
157 | info->handle = handle; | ||
158 | trace_graph_load_handle(info->ginfo, handle); | ||
159 | trace_view_reload(info->treeview, handle, info->spin); | ||
160 | update_title(info->window, filename); | ||
161 | } | ||
162 | g_free(filename); | ||
163 | } | 303 | } |
164 | gtk_widget_destroy(dialog); | 304 | g_free(filename); |
305 | } | ||
306 | |||
307 | /* Callback for the clicked signal of the Load Filters button */ | ||
308 | static void | ||
309 | load_filters_clicked (gpointer data) | ||
310 | { | ||
311 | struct shark_info *info = data; | ||
312 | struct graph_info *ginfo = info->ginfo; | ||
313 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); | ||
314 | GtkTreeModel *model; | ||
315 | TraceViewStore *store; | ||
316 | struct tracecmd_xml_handle *handle; | ||
317 | struct filter_task *task_filter; | ||
318 | struct filter_task *hide_tasks; | ||
319 | struct event_filter *event_filter; | ||
320 | gchar *filename; | ||
321 | int ret; | ||
322 | |||
323 | filename = trace_get_file_dialog("Load Filters"); | ||
324 | if (!filename) | ||
325 | return; | ||
326 | |||
327 | handle = tracecmd_xml_open(filename); | ||
328 | if (!handle) { | ||
329 | warning("Could not open %s", filename); | ||
330 | goto out; | ||
331 | } | ||
332 | |||
333 | /* Unsync the list and graph filters */ | ||
334 | if (info->sync_task_filters) | ||
335 | unsync_task_filters(info); | ||
336 | if (info->sync_event_filters) | ||
337 | unsync_event_filters(info); | ||
338 | |||
339 | ret = tracecmd_xml_system_exists(handle, | ||
340 | "GraphTaskFilter"); | ||
341 | if (ret) { | ||
342 | filter_task_clear(ginfo->task_filter); | ||
343 | filter_task_clear(ginfo->hide_tasks); | ||
344 | |||
345 | trace_filter_load_filters(handle, | ||
346 | "GraphTaskFilter", | ||
347 | ginfo->task_filter, | ||
348 | ginfo->hide_tasks); | ||
349 | trace_graph_refresh_filters(ginfo); | ||
350 | } | ||
351 | |||
352 | ret = tracecmd_xml_system_exists(handle, | ||
353 | "ListTaskFilter"); | ||
354 | if (ret) { | ||
355 | task_filter = info->list_task_filter; | ||
356 | hide_tasks = info->list_hide_tasks; | ||
357 | filter_task_clear(task_filter); | ||
358 | filter_task_clear(hide_tasks); | ||
359 | |||
360 | trace_filter_load_filters(handle, | ||
361 | "ListTaskFilter", | ||
362 | task_filter, | ||
363 | hide_tasks); | ||
364 | update_tree_view_filters(info, task_filter, hide_tasks); | ||
365 | } | ||
366 | |||
367 | trace_graph_load_filters(ginfo, handle); | ||
368 | ret = trace_view_load_filters(handle, trace_tree); | ||
369 | |||
370 | tracecmd_xml_close(handle); | ||
371 | |||
372 | /* | ||
373 | * If the events or tasks filters are the same for both | ||
374 | * the list and graph, then sync them back. | ||
375 | */ | ||
376 | if (filter_task_compare(ginfo->task_filter, | ||
377 | info->list_task_filter) && | ||
378 | filter_task_compare(ginfo->hide_tasks, | ||
379 | info->list_hide_tasks)) | ||
380 | sync_task_filters(info); | ||
381 | |||
382 | model = gtk_tree_view_get_model(trace_tree); | ||
383 | if (!model) | ||
384 | goto out; | ||
385 | |||
386 | store = TRACE_VIEW_STORE(model); | ||
387 | event_filter = trace_view_store_get_event_filter(store); | ||
388 | |||
389 | if (pevent_filter_compare(event_filter, ginfo->event_filter)) | ||
390 | sync_event_filters(info); | ||
391 | |||
392 | out: | ||
393 | g_free(filename); | ||
394 | |||
395 | } | ||
396 | |||
397 | /* Callback for the clicked signal of the Save Filters button */ | ||
398 | static void | ||
399 | save_filters_clicked (gpointer data) | ||
400 | { | ||
401 | struct shark_info *info = data; | ||
402 | struct graph_info *ginfo = info->ginfo; | ||
403 | struct tracecmd_xml_handle *handle; | ||
404 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); | ||
405 | struct filter_task *task_filter; | ||
406 | struct filter_task *hide_tasks; | ||
407 | gchar *filename; | ||
408 | |||
409 | filename = trace_get_file_dialog("Save Filters"); | ||
410 | if (!filename) | ||
411 | return; | ||
412 | |||
413 | handle = tracecmd_xml_create(filename, VERSION_STRING); | ||
414 | if (!handle) | ||
415 | warning("Could not create %s", filename); | ||
416 | g_free(filename); | ||
417 | |||
418 | trace_view_save_filters(handle, trace_tree); | ||
419 | trace_graph_save_filters(ginfo, handle); | ||
420 | |||
421 | trace_filter_save_filters(handle, | ||
422 | "GraphTaskFilter", | ||
423 | ginfo->task_filter, | ||
424 | ginfo->hide_tasks); | ||
425 | |||
426 | if (info->sync_task_filters) { | ||
427 | task_filter = ginfo->task_filter; | ||
428 | hide_tasks = ginfo->hide_tasks; | ||
429 | } else { | ||
430 | task_filter = info->list_task_filter; | ||
431 | hide_tasks = info->list_hide_tasks; | ||
432 | } | ||
433 | |||
434 | trace_filter_save_filters(handle, | ||
435 | "ListTaskFilter", | ||
436 | task_filter, hide_tasks); | ||
437 | |||
438 | tracecmd_xml_close(handle); | ||
165 | } | 439 | } |
166 | 440 | ||
167 | /* Callback for the clicked signal of the Exit button */ | 441 | /* Callback for the clicked signal of the Exit button */ |
@@ -187,16 +461,28 @@ delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) | |||
187 | return TRUE; | 461 | return TRUE; |
188 | } | 462 | } |
189 | 463 | ||
190 | /* Callback for the clicked signal of the Events filter button */ | 464 | /* Callback for the clicked signal of the tasks sync filter button */ |
191 | static void | 465 | static void |
192 | list_events_clicked (gpointer data) | 466 | sync_task_filter_clicked (GtkWidget *subitem, gpointer data) |
193 | { | 467 | { |
194 | struct shark_info *info = data; | 468 | struct shark_info *info = data; |
195 | struct event_filter *event_filter; | 469 | struct filter_task *task_filter; |
470 | struct filter_task *hide_tasks; | ||
196 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); | 471 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); |
197 | GtkTreeModel *model; | 472 | GtkTreeModel *model; |
198 | TraceViewStore *store; | 473 | TraceViewStore *store; |
199 | gboolean all_events; | 474 | gboolean keep; |
475 | gchar *selections[] = { "Sync List Filter with Graph Filter", | ||
476 | "Sync Graph Filter with List Filter", | ||
477 | NULL }; | ||
478 | int result; | ||
479 | |||
480 | if (info->sync_task_filters) { | ||
481 | /* Separate the List and Graph filters */ | ||
482 | |||
483 | unsync_task_filters(info); | ||
484 | return; | ||
485 | } | ||
200 | 486 | ||
201 | model = gtk_tree_view_get_model(trace_tree); | 487 | model = gtk_tree_view_get_model(trace_tree); |
202 | if (!model) | 488 | if (!model) |
@@ -204,40 +490,204 @@ list_events_clicked (gpointer data) | |||
204 | 490 | ||
205 | store = TRACE_VIEW_STORE(model); | 491 | store = TRACE_VIEW_STORE(model); |
206 | 492 | ||
207 | all_events = trace_view_store_get_all_events_enabled(store); | 493 | /* If they are already equal, then just perminently sync them */ |
208 | event_filter = trace_view_store_get_event_filter(store); | 494 | if (filter_task_compare(info->ginfo->task_filter, |
495 | info->list_task_filter) && | ||
496 | filter_task_compare(info->ginfo->hide_tasks, | ||
497 | info->list_hide_tasks)) | ||
498 | result = 2; | ||
209 | 499 | ||
210 | trace_filter_event_filter_dialog(store->handle, event_filter, | 500 | else |
211 | all_events, | 501 | /* Ask user which way to sync */ |
212 | trace_view_event_filter_callback, | 502 | result = trace_sync_select_menu("Sync Task Filters", |
213 | info->treeview); | 503 | selections, &keep); |
504 | |||
505 | switch (result) { | ||
506 | case 0: | ||
507 | /* Sync List Filter with Graph Filter */ | ||
508 | filter_task_hash_free(info->list_task_filter); | ||
509 | filter_task_hash_free(info->list_hide_tasks); | ||
510 | |||
511 | info->list_task_filter = NULL; | ||
512 | info->list_hide_tasks = NULL; | ||
513 | |||
514 | task_filter = info->ginfo->task_filter; | ||
515 | hide_tasks = info->ginfo->hide_tasks; | ||
516 | |||
517 | if (!keep) { | ||
518 | info->list_task_filter = filter_task_hash_copy(task_filter); | ||
519 | info->list_hide_tasks = filter_task_hash_copy(hide_tasks); | ||
520 | } | ||
521 | |||
522 | update_tree_view_filters(info, task_filter, hide_tasks); | ||
523 | |||
524 | break; | ||
525 | case 1: | ||
526 | /* Sync Graph Filter with List Filter */ | ||
527 | trace_graph_update_filters(info->ginfo, | ||
528 | info->list_task_filter, | ||
529 | info->list_hide_tasks); | ||
530 | |||
531 | if (keep) { | ||
532 | filter_task_hash_free(info->list_task_filter); | ||
533 | filter_task_hash_free(info->list_hide_tasks); | ||
534 | |||
535 | info->list_task_filter = NULL; | ||
536 | info->list_hide_tasks = NULL; | ||
537 | } | ||
538 | break; | ||
539 | case 2: | ||
540 | keep = 1; | ||
541 | break; | ||
542 | default: | ||
543 | keep = 0; | ||
544 | } | ||
545 | |||
546 | if (keep) | ||
547 | sync_task_filters(info); | ||
214 | } | 548 | } |
215 | 549 | ||
550 | /* Callback for the clicked signal of the events sync filter button */ | ||
216 | static void | 551 | static void |
217 | graph_events_clicked (gpointer data) | 552 | sync_events_filter_clicked (GtkWidget *subitem, gpointer data) |
218 | { | 553 | { |
219 | struct shark_info *info = data; | 554 | struct shark_info *info = data; |
220 | struct graph_info *ginfo = info->ginfo; | 555 | struct graph_info *ginfo = info->ginfo; |
556 | struct event_filter *event_filter; | ||
557 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); | ||
558 | GtkTreeModel *model; | ||
559 | TraceViewStore *store; | ||
560 | gboolean keep; | ||
221 | gboolean all_events; | 561 | gboolean all_events; |
562 | gchar *selections[] = { "Sync List Filter with Graph Filter", | ||
563 | "Sync Graph Filter with List Filter", | ||
564 | NULL }; | ||
565 | int result; | ||
566 | |||
567 | if (info->sync_event_filters) { | ||
568 | /* Separate the List and Graph filters */ | ||
569 | unsync_event_filters(info); | ||
570 | return; | ||
571 | } | ||
222 | 572 | ||
223 | all_events = ginfo->all_events; | 573 | model = gtk_tree_view_get_model(trace_tree); |
574 | if (!model) | ||
575 | return; | ||
224 | 576 | ||
225 | trace_filter_event_filter_dialog(info->handle, | 577 | store = TRACE_VIEW_STORE(model); |
226 | ginfo->event_filter, | 578 | event_filter = trace_view_store_get_event_filter(store); |
227 | all_events, | 579 | |
228 | trace_graph_event_filter_callback, | 580 | /* If they are already equal, then just perminently sync them */ |
229 | ginfo); | 581 | if (pevent_filter_compare(event_filter, ginfo->event_filter)) |
582 | result = 2; | ||
583 | else | ||
584 | /* Ask user which way to sync */ | ||
585 | result = trace_sync_select_menu("Sync Event Filters", | ||
586 | selections, &keep); | ||
587 | |||
588 | switch (result) { | ||
589 | case 0: | ||
590 | /* Sync List Filter with Graph Filter */ | ||
591 | all_events = ginfo->all_events; | ||
592 | |||
593 | trace_view_copy_filter(info->treeview, all_events, | ||
594 | ginfo->event_filter); | ||
595 | break; | ||
596 | case 1: | ||
597 | /* Sync Graph Filter with List Filter */ | ||
598 | all_events = trace_view_store_get_all_events_enabled(store); | ||
599 | |||
600 | trace_graph_copy_filter(info->ginfo, all_events, | ||
601 | event_filter); | ||
602 | break; | ||
603 | case 2: | ||
604 | keep = 1; | ||
605 | break; | ||
606 | default: | ||
607 | keep = 0; | ||
608 | } | ||
609 | |||
610 | if (keep) | ||
611 | sync_event_filters(info); | ||
230 | } | 612 | } |
231 | 613 | ||
232 | /* Callback for the clicked signal of the List advanced filter button */ | 614 | static void filter_list_enable_clicked (gpointer data); |
615 | |||
233 | static void | 616 | static void |
234 | adv_list_filter_clicked (gpointer data) | 617 | __update_list_task_filter_callback(struct shark_info *info, |
618 | gboolean accept, | ||
619 | gint *selected, | ||
620 | struct filter_task *task_filter) | ||
621 | { | ||
622 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); | ||
623 | GtkTreeModel *model; | ||
624 | TraceViewStore *store; | ||
625 | int i; | ||
626 | |||
627 | if (!accept) | ||
628 | return; | ||
629 | |||
630 | model = gtk_tree_view_get_model(trace_tree); | ||
631 | if (!model) | ||
632 | return; | ||
633 | |||
634 | store = TRACE_VIEW_STORE(model); | ||
635 | |||
636 | filter_task_clear(task_filter); | ||
637 | |||
638 | if (selected) { | ||
639 | for (i = 0; selected[i] >= 0; i++) | ||
640 | filter_task_add_pid(task_filter, selected[i]); | ||
641 | } | ||
642 | |||
643 | update_tree_view_filters(info, info->list_task_filter, info->list_hide_tasks); | ||
644 | |||
645 | /* | ||
646 | * The menu filters always enable the filters. | ||
647 | */ | ||
648 | if (info->list_filter_available && !info->list_filter_enabled) | ||
649 | filter_list_enable_clicked(info); | ||
650 | } | ||
651 | |||
652 | static void | ||
653 | update_list_task_filter_callback(gboolean accept, | ||
654 | gint *selected, | ||
655 | gint *non_select, | ||
656 | gpointer data) | ||
235 | { | 657 | { |
236 | struct shark_info *info = data; | 658 | struct shark_info *info = data; |
237 | struct event_filter *event_filter; | 659 | |
660 | __update_list_task_filter_callback(info, accept, selected, | ||
661 | info->list_task_filter); | ||
662 | } | ||
663 | |||
664 | static void | ||
665 | update_list_hide_task_filter_callback(gboolean accept, | ||
666 | gint *selected, | ||
667 | gint *non_select, | ||
668 | gpointer data) | ||
669 | { | ||
670 | struct shark_info *info = data; | ||
671 | |||
672 | __update_list_task_filter_callback(info, accept, selected, | ||
673 | info->list_hide_tasks); | ||
674 | } | ||
675 | |||
676 | /* Callback for the clicked signal of the List Tasks filter button */ | ||
677 | static void | ||
678 | __list_tasks_clicked (struct shark_info *info, | ||
679 | struct filter_task *task_filter, | ||
680 | trace_task_cb_func func) | ||
681 | { | ||
238 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); | 682 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); |
683 | struct graph_info *ginfo = info->ginfo; | ||
239 | GtkTreeModel *model; | 684 | GtkTreeModel *model; |
240 | TraceViewStore *store; | 685 | TraceViewStore *store; |
686 | gint *selected; | ||
687 | gint *tasks; | ||
688 | |||
689 | if (!ginfo->handle) | ||
690 | return; | ||
241 | 691 | ||
242 | model = gtk_tree_view_get_model(trace_tree); | 692 | model = gtk_tree_view_get_model(trace_tree); |
243 | if (!model) | 693 | if (!model) |
@@ -245,25 +695,137 @@ adv_list_filter_clicked (gpointer data) | |||
245 | 695 | ||
246 | store = TRACE_VIEW_STORE(model); | 696 | store = TRACE_VIEW_STORE(model); |
247 | 697 | ||
248 | event_filter = trace_view_store_get_event_filter(store); | 698 | tasks = trace_graph_task_list(ginfo); |
699 | selected = filter_task_pids(task_filter); | ||
249 | 700 | ||
250 | trace_adv_filter_dialog(store->handle, event_filter, | 701 | trace_task_dialog(info->handle, tasks, selected, func, info); |
251 | trace_view_adv_filter_callback, trace_tree); | 702 | |
703 | free(tasks); | ||
704 | free(selected); | ||
252 | } | 705 | } |
253 | 706 | ||
254 | /* Callback for the clicked signal of the Graph advanced filter button */ | ||
255 | static void | 707 | static void |
256 | adv_graph_filter_clicked (gpointer data) | 708 | list_tasks_clicked (gpointer data) |
257 | { | 709 | { |
258 | struct shark_info *info = data; | 710 | struct shark_info *info = data; |
711 | |||
712 | __list_tasks_clicked(info, info->list_task_filter, | ||
713 | update_list_task_filter_callback); | ||
714 | } | ||
715 | |||
716 | static void | ||
717 | list_hide_tasks_clicked (gpointer data) | ||
718 | { | ||
719 | struct shark_info *info = data; | ||
720 | |||
721 | __list_tasks_clicked(info, info->list_hide_tasks, | ||
722 | update_list_hide_task_filter_callback); | ||
723 | } | ||
724 | |||
725 | static void | ||
726 | __update_graph_task_filter_callback(struct shark_info *info, | ||
727 | gboolean accept, | ||
728 | gint *selected, | ||
729 | struct filter_task *task_filter) | ||
730 | { | ||
259 | struct graph_info *ginfo = info->ginfo; | 731 | struct graph_info *ginfo = info->ginfo; |
732 | int i; | ||
260 | 733 | ||
261 | trace_adv_filter_dialog(ginfo->handle, ginfo->event_filter, | 734 | if (!accept) |
262 | trace_graph_adv_filter_callback, ginfo); | 735 | return; |
736 | |||
737 | filter_task_clear(task_filter); | ||
738 | |||
739 | if (selected) { | ||
740 | for (i = 0; selected[i] >= 0; i++) | ||
741 | filter_task_add_pid(task_filter, selected[i]); | ||
742 | } | ||
743 | |||
744 | trace_graph_refresh_filters(ginfo); | ||
745 | |||
746 | /* | ||
747 | * The menu filters always enable the filters. | ||
748 | */ | ||
749 | if (ginfo->filter_available) { | ||
750 | if (!ginfo->filter_enabled) | ||
751 | trace_graph_filter_toggle(info->ginfo); | ||
752 | |||
753 | if (info->sync_task_filters && !info->list_filter_enabled) | ||
754 | filter_list_enable_clicked(info); | ||
755 | } | ||
263 | } | 756 | } |
264 | 757 | ||
265 | static void | 758 | static void |
266 | sync_graph_events_to_list_clicked (gpointer data) | 759 | update_graph_task_filter_callback(gboolean accept, |
760 | gint *selected, | ||
761 | gint *non_select, | ||
762 | gpointer data) | ||
763 | { | ||
764 | struct shark_info *info = data; | ||
765 | struct graph_info *ginfo = info->ginfo; | ||
766 | |||
767 | __update_graph_task_filter_callback(info, accept, selected, | ||
768 | ginfo->task_filter); | ||
769 | } | ||
770 | |||
771 | static void | ||
772 | update_graph_hide_task_filter_callback(gboolean accept, | ||
773 | gint *selected, | ||
774 | gint *non_select, | ||
775 | gpointer data) | ||
776 | { | ||
777 | struct shark_info *info = data; | ||
778 | struct graph_info *ginfo = info->ginfo; | ||
779 | |||
780 | __update_graph_task_filter_callback(info, accept, selected, | ||
781 | ginfo->hide_tasks); | ||
782 | } | ||
783 | |||
784 | /* Callback for the clicked signal of the Tasks filter button */ | ||
785 | static void | ||
786 | __graph_tasks_clicked (struct shark_info *info, | ||
787 | struct filter_task *task_filter, | ||
788 | trace_task_cb_func func) | ||
789 | { | ||
790 | struct graph_info *ginfo = info->ginfo; | ||
791 | gint *selected; | ||
792 | gint *tasks; | ||
793 | |||
794 | if (!ginfo->handle) | ||
795 | return; | ||
796 | |||
797 | tasks = trace_graph_task_list(ginfo); | ||
798 | selected = filter_task_pids(task_filter); | ||
799 | |||
800 | trace_task_dialog(ginfo->handle, tasks, selected, func, info); | ||
801 | |||
802 | free(tasks); | ||
803 | free(selected); | ||
804 | } | ||
805 | |||
806 | static void | ||
807 | graph_tasks_clicked (gpointer data) | ||
808 | { | ||
809 | struct shark_info *info = data; | ||
810 | struct graph_info *ginfo = info->ginfo; | ||
811 | |||
812 | __graph_tasks_clicked(info, ginfo->task_filter, | ||
813 | update_graph_task_filter_callback); | ||
814 | } | ||
815 | |||
816 | static void | ||
817 | graph_hide_tasks_clicked (gpointer data) | ||
818 | { | ||
819 | struct shark_info *info = data; | ||
820 | struct graph_info *ginfo = info->ginfo; | ||
821 | |||
822 | __graph_tasks_clicked(info, ginfo->hide_tasks, | ||
823 | update_graph_hide_task_filter_callback); | ||
824 | } | ||
825 | |||
826 | /* Callback for the clicked signal of the Events filter button */ | ||
827 | static void | ||
828 | list_events_clicked (gpointer data) | ||
267 | { | 829 | { |
268 | struct shark_info *info = data; | 830 | struct shark_info *info = data; |
269 | struct event_filter *event_filter; | 831 | struct event_filter *event_filter; |
@@ -281,13 +843,36 @@ sync_graph_events_to_list_clicked (gpointer data) | |||
281 | all_events = trace_view_store_get_all_events_enabled(store); | 843 | all_events = trace_view_store_get_all_events_enabled(store); |
282 | event_filter = trace_view_store_get_event_filter(store); | 844 | event_filter = trace_view_store_get_event_filter(store); |
283 | 845 | ||
284 | trace_graph_copy_filter(info->ginfo, all_events, | 846 | /* |
285 | event_filter); | 847 | * This menu is not available when in sync, so we |
848 | * can call the treeview callback directly. | ||
849 | */ | ||
850 | trace_filter_event_filter_dialog(store->handle, event_filter, | ||
851 | all_events, | ||
852 | trace_view_event_filter_callback, | ||
853 | info->treeview); | ||
286 | } | 854 | } |
287 | 855 | ||
856 | static void | ||
857 | graph_event_filter_callback(gboolean accept, | ||
858 | gboolean all_events, | ||
859 | gchar **systems, | ||
860 | gint *events, | ||
861 | gpointer data) | ||
862 | { | ||
863 | struct shark_info *info = data; | ||
864 | |||
865 | trace_graph_event_filter_callback(accept, all_events, | ||
866 | systems, events, | ||
867 | info->ginfo); | ||
868 | |||
869 | if (info->sync_event_filters) | ||
870 | trace_view_event_filter_callback(accept, all_events, systems, | ||
871 | events, info->treeview); | ||
872 | } | ||
288 | 873 | ||
289 | static void | 874 | static void |
290 | sync_list_events_to_graph_clicked (gpointer data) | 875 | graph_events_clicked (gpointer data) |
291 | { | 876 | { |
292 | struct shark_info *info = data; | 877 | struct shark_info *info = data; |
293 | struct graph_info *ginfo = info->ginfo; | 878 | struct graph_info *ginfo = info->ginfo; |
@@ -295,8 +880,64 @@ sync_list_events_to_graph_clicked (gpointer data) | |||
295 | 880 | ||
296 | all_events = ginfo->all_events; | 881 | all_events = ginfo->all_events; |
297 | 882 | ||
298 | trace_view_copy_filter(info->treeview, all_events, | 883 | trace_filter_event_filter_dialog(info->handle, |
299 | ginfo->event_filter); | 884 | ginfo->event_filter, |
885 | all_events, | ||
886 | graph_event_filter_callback, | ||
887 | info); | ||
888 | } | ||
889 | |||
890 | /* Callback for the clicked signal of the List advanced filter button */ | ||
891 | static void | ||
892 | adv_list_filter_clicked (gpointer data) | ||
893 | { | ||
894 | struct shark_info *info = data; | ||
895 | struct event_filter *event_filter; | ||
896 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); | ||
897 | GtkTreeModel *model; | ||
898 | TraceViewStore *store; | ||
899 | |||
900 | model = gtk_tree_view_get_model(trace_tree); | ||
901 | if (!model) | ||
902 | return; | ||
903 | |||
904 | store = TRACE_VIEW_STORE(model); | ||
905 | |||
906 | event_filter = trace_view_store_get_event_filter(store); | ||
907 | |||
908 | /* | ||
909 | * This menu is not available when in sync, so we | ||
910 | * can call the treeview callback directly. | ||
911 | */ | ||
912 | trace_adv_filter_dialog(store->handle, event_filter, | ||
913 | trace_view_adv_filter_callback, trace_tree); | ||
914 | } | ||
915 | |||
916 | static void | ||
917 | graph_adv_filter_callback(gboolean accept, | ||
918 | const gchar *text, | ||
919 | gint *event_ids, | ||
920 | gpointer data) | ||
921 | { | ||
922 | struct shark_info *info = data; | ||
923 | struct graph_info *ginfo = info->ginfo; | ||
924 | |||
925 | trace_graph_adv_filter_callback(accept, text, event_ids, ginfo); | ||
926 | |||
927 | if (info->sync_event_filters) | ||
928 | trace_view_adv_filter_callback(accept, text, event_ids, | ||
929 | info->treeview); | ||
930 | } | ||
931 | |||
932 | /* Callback for the clicked signal of the Graph advanced filter button */ | ||
933 | static void | ||
934 | adv_graph_filter_clicked (gpointer data) | ||
935 | { | ||
936 | struct shark_info *info = data; | ||
937 | struct graph_info *ginfo = info->ginfo; | ||
938 | |||
939 | trace_adv_filter_dialog(ginfo->handle, ginfo->event_filter, | ||
940 | graph_adv_filter_callback, info); | ||
300 | } | 941 | } |
301 | 942 | ||
302 | /* Callback for the clicked signal of the CPUs filter button */ | 943 | /* Callback for the clicked signal of the CPUs filter button */ |
@@ -362,6 +1003,34 @@ plot_tasks_clicked (gpointer data) | |||
362 | free(selected); | 1003 | free(selected); |
363 | } | 1004 | } |
364 | 1005 | ||
1006 | /* Callback for the clicked signal of the help contents button */ | ||
1007 | static void | ||
1008 | help_content_clicked (gpointer data) | ||
1009 | { | ||
1010 | struct shark_info *info = data; | ||
1011 | GError *error = NULL; | ||
1012 | gchar *link; | ||
1013 | |||
1014 | link = "file://" __stringify(HELP_DIR) "/index.html"; | ||
1015 | |||
1016 | trace_show_help(info->window, link, &error); | ||
1017 | } | ||
1018 | |||
1019 | |||
1020 | /* Callback for the clicked signal of the help about button */ | ||
1021 | static void | ||
1022 | help_about_clicked (gpointer data) | ||
1023 | { | ||
1024 | struct shark_info *info = data; | ||
1025 | |||
1026 | trace_dialog(GTK_WINDOW(info->window), TRACE_GUI_INFO, | ||
1027 | "KernelShark\n\n" | ||
1028 | "version %s\n\n" | ||
1029 | "Copyright (C) 2009, 2010 Red Hat Inc\n\n" | ||
1030 | " Author: Steven Rostedt <srostedt@redhat.com>", | ||
1031 | VERSION_STRING); | ||
1032 | } | ||
1033 | |||
365 | static void graph_follows_tree(struct shark_info *info, | 1034 | static void graph_follows_tree(struct shark_info *info, |
366 | GtkTreeView *treeview, | 1035 | GtkTreeView *treeview, |
367 | GtkTreePath *path) | 1036 | GtkTreePath *path) |
@@ -427,26 +1096,70 @@ static void | |||
427 | filter_list_enable_clicked (gpointer data) | 1096 | filter_list_enable_clicked (gpointer data) |
428 | { | 1097 | { |
429 | struct shark_info *info = data; | 1098 | struct shark_info *info = data; |
1099 | struct filter_task *task_filter; | ||
1100 | struct filter_task *hide_tasks; | ||
430 | 1101 | ||
431 | info->list_filter_enabled ^= 1; | 1102 | info->list_filter_enabled ^= 1; |
432 | 1103 | ||
1104 | if (info->sync_task_filters) { | ||
1105 | task_filter = info->ginfo->task_filter; | ||
1106 | hide_tasks = info->ginfo->hide_tasks; | ||
1107 | } else { | ||
1108 | task_filter = info->list_task_filter; | ||
1109 | hide_tasks = info->list_hide_tasks; | ||
1110 | } | ||
1111 | |||
433 | if (info->list_filter_enabled) | 1112 | if (info->list_filter_enabled) |
434 | trace_view_update_filters(info->treeview, | 1113 | trace_view_update_filters(info->treeview, |
435 | info->ginfo->task_filter, | 1114 | task_filter, hide_tasks); |
436 | info->ginfo->hide_tasks); | ||
437 | else | 1115 | else |
438 | trace_view_update_filters(info->treeview, NULL, NULL); | 1116 | trace_view_update_filters(info->treeview, NULL, NULL); |
439 | } | 1117 | } |
440 | 1118 | ||
441 | static void | 1119 | static void |
1120 | filter_update_list_filter(struct shark_info *info, | ||
1121 | struct filter_task *filter, | ||
1122 | struct filter_task *other_filter) | ||
1123 | { | ||
1124 | struct filter_task_item *task; | ||
1125 | int pid = info->selected_task; | ||
1126 | |||
1127 | task = filter_task_find_pid(filter, pid); | ||
1128 | if (task) { | ||
1129 | filter_task_remove_pid(filter, pid); | ||
1130 | if (!filter_task_count(filter) && | ||
1131 | !filter_task_count(other_filter)) { | ||
1132 | info->list_filter_enabled = 0; | ||
1133 | info->list_filter_available = 0; | ||
1134 | } | ||
1135 | } else { | ||
1136 | filter_task_add_pid(filter, pid); | ||
1137 | info->list_filter_available = 1; | ||
1138 | } | ||
1139 | } | ||
1140 | |||
1141 | static void | ||
442 | filter_add_task_clicked (gpointer data) | 1142 | filter_add_task_clicked (gpointer data) |
443 | { | 1143 | { |
444 | struct shark_info *info = data; | 1144 | struct shark_info *info = data; |
1145 | int pid = info->selected_task; | ||
445 | 1146 | ||
446 | trace_graph_filter_add_remove_task(info->ginfo, info->selected_task); | 1147 | if (info->sync_task_filters) { |
1148 | trace_graph_filter_add_remove_task(info->ginfo, pid); | ||
1149 | return; | ||
1150 | } | ||
447 | 1151 | ||
448 | if (!filter_task_count(info->ginfo->task_filter)) | 1152 | filter_update_list_filter(info, info->list_task_filter, info->list_hide_tasks); |
449 | info->list_filter_enabled = 0; | 1153 | trace_view_update_filters(info->treeview, |
1154 | info->list_task_filter, info->list_hide_tasks); | ||
1155 | } | ||
1156 | |||
1157 | static void | ||
1158 | filter_graph_add_task_clicked (gpointer data) | ||
1159 | { | ||
1160 | struct shark_info *info = data; | ||
1161 | |||
1162 | trace_graph_filter_add_remove_task(info->ginfo, info->selected_task); | ||
450 | } | 1163 | } |
451 | 1164 | ||
452 | static void | 1165 | static void |
@@ -454,11 +1167,22 @@ filter_hide_task_clicked (gpointer data) | |||
454 | { | 1167 | { |
455 | struct shark_info *info = data; | 1168 | struct shark_info *info = data; |
456 | 1169 | ||
457 | trace_graph_filter_hide_show_task(info->ginfo, info->selected_task); | 1170 | if (info->sync_task_filters) { |
1171 | trace_graph_filter_hide_show_task(info->ginfo, info->selected_task); | ||
1172 | return; | ||
1173 | } | ||
458 | 1174 | ||
459 | if (!filter_task_count(info->ginfo->task_filter) && | 1175 | filter_update_list_filter(info, info->list_hide_tasks, info->list_task_filter); |
460 | !filter_task_count(info->ginfo->hide_tasks)) | 1176 | trace_view_update_filters(info->treeview, |
461 | info->list_filter_enabled = 0; | 1177 | info->list_task_filter, info->list_hide_tasks); |
1178 | } | ||
1179 | |||
1180 | static void | ||
1181 | filter_graph_hide_task_clicked (gpointer data) | ||
1182 | { | ||
1183 | struct shark_info *info = data; | ||
1184 | |||
1185 | trace_graph_filter_hide_show_task(info->ginfo, info->selected_task); | ||
462 | } | 1186 | } |
463 | 1187 | ||
464 | static void | 1188 | static void |
@@ -466,11 +1190,27 @@ filter_clear_tasks_clicked (gpointer data) | |||
466 | { | 1190 | { |
467 | struct shark_info *info = data; | 1191 | struct shark_info *info = data; |
468 | 1192 | ||
469 | trace_graph_clear_tasks(info->ginfo); | 1193 | if (info->sync_task_filters) { |
1194 | trace_graph_clear_tasks(info->ginfo); | ||
1195 | return; | ||
1196 | } | ||
1197 | |||
1198 | filter_task_clear(info->list_task_filter); | ||
1199 | filter_task_clear(info->list_hide_tasks); | ||
1200 | trace_view_update_filters(info->treeview, NULL, NULL); | ||
470 | 1201 | ||
1202 | info->list_filter_available = 0; | ||
471 | info->list_filter_enabled = 0; | 1203 | info->list_filter_enabled = 0; |
472 | } | 1204 | } |
473 | 1205 | ||
1206 | static void | ||
1207 | filter_graph_clear_tasks_clicked (gpointer data) | ||
1208 | { | ||
1209 | struct shark_info *info = data; | ||
1210 | |||
1211 | trace_graph_clear_tasks(info->ginfo); | ||
1212 | } | ||
1213 | |||
474 | static void graph_check_toggle(gpointer data, GtkWidget *widget) | 1214 | static void graph_check_toggle(gpointer data, GtkWidget *widget) |
475 | { | 1215 | { |
476 | struct shark_info *info = data; | 1216 | struct shark_info *info = data; |
@@ -478,6 +1218,17 @@ static void graph_check_toggle(gpointer data, GtkWidget *widget) | |||
478 | info->graph_follows = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | 1218 | info->graph_follows = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); |
479 | } | 1219 | } |
480 | 1220 | ||
1221 | static void set_menu_label(GtkWidget *menu, const char *comm, int pid, | ||
1222 | const char *fmt) | ||
1223 | { | ||
1224 | int len = strlen(comm) + strlen(fmt) + 50; | ||
1225 | char text[len]; | ||
1226 | |||
1227 | snprintf(text, len, fmt, comm, pid); | ||
1228 | |||
1229 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu), text); | ||
1230 | } | ||
1231 | |||
481 | static gboolean | 1232 | static gboolean |
482 | do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | 1233 | do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) |
483 | { | 1234 | { |
@@ -489,11 +1240,13 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
489 | static GtkWidget *menu_filter_add_task; | 1240 | static GtkWidget *menu_filter_add_task; |
490 | static GtkWidget *menu_filter_hide_task; | 1241 | static GtkWidget *menu_filter_hide_task; |
491 | static GtkWidget *menu_filter_clear_tasks; | 1242 | static GtkWidget *menu_filter_clear_tasks; |
1243 | static GtkWidget *menu_filter_graph_add_task; | ||
1244 | static GtkWidget *menu_filter_graph_hide_task; | ||
1245 | static GtkWidget *menu_filter_graph_clear_tasks; | ||
492 | struct record *record; | 1246 | struct record *record; |
493 | TraceViewRecord *vrec; | 1247 | TraceViewRecord *vrec; |
494 | GtkTreeModel *model; | 1248 | GtkTreeModel *model; |
495 | const char *comm; | 1249 | const char *comm; |
496 | gchar *text; | ||
497 | gint pid; | 1250 | gint pid; |
498 | gint len; | 1251 | gint len; |
499 | guint64 offset; | 1252 | guint64 offset; |
@@ -502,7 +1255,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
502 | 1255 | ||
503 | if (!menu) { | 1256 | if (!menu) { |
504 | menu = gtk_menu_new(); | 1257 | menu = gtk_menu_new(); |
505 | menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Filter"); | 1258 | menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Task Filter"); |
506 | gtk_widget_show(menu_filter_graph_enable); | 1259 | gtk_widget_show(menu_filter_graph_enable); |
507 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_enable); | 1260 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_enable); |
508 | 1261 | ||
@@ -510,7 +1263,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
510 | G_CALLBACK (filter_graph_enable_clicked), | 1263 | G_CALLBACK (filter_graph_enable_clicked), |
511 | data); | 1264 | data); |
512 | 1265 | ||
513 | menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Filter"); | 1266 | menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Task Filter"); |
514 | gtk_widget_show(menu_filter_list_enable); | 1267 | gtk_widget_show(menu_filter_list_enable); |
515 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_list_enable); | 1268 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_list_enable); |
516 | 1269 | ||
@@ -526,6 +1279,14 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
526 | G_CALLBACK (filter_add_task_clicked), | 1279 | G_CALLBACK (filter_add_task_clicked), |
527 | data); | 1280 | data); |
528 | 1281 | ||
1282 | menu_filter_graph_add_task = gtk_menu_item_new_with_label("Add Task to Graph"); | ||
1283 | gtk_widget_show(menu_filter_graph_add_task); | ||
1284 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_add_task); | ||
1285 | |||
1286 | g_signal_connect_swapped (G_OBJECT (menu_filter_graph_add_task), "activate", | ||
1287 | G_CALLBACK (filter_graph_add_task_clicked), | ||
1288 | data); | ||
1289 | |||
529 | menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task"); | 1290 | menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task"); |
530 | gtk_widget_show(menu_filter_hide_task); | 1291 | gtk_widget_show(menu_filter_hide_task); |
531 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task); | 1292 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task); |
@@ -534,6 +1295,14 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
534 | G_CALLBACK (filter_hide_task_clicked), | 1295 | G_CALLBACK (filter_hide_task_clicked), |
535 | data); | 1296 | data); |
536 | 1297 | ||
1298 | menu_filter_graph_hide_task = gtk_menu_item_new_with_label("Hide Task from Graph"); | ||
1299 | gtk_widget_show(menu_filter_graph_hide_task); | ||
1300 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_hide_task); | ||
1301 | |||
1302 | g_signal_connect_swapped (G_OBJECT (menu_filter_graph_hide_task), "activate", | ||
1303 | G_CALLBACK (filter_graph_hide_task_clicked), | ||
1304 | data); | ||
1305 | |||
537 | menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter"); | 1306 | menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter"); |
538 | gtk_widget_show(menu_filter_clear_tasks); | 1307 | gtk_widget_show(menu_filter_clear_tasks); |
539 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks); | 1308 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks); |
@@ -542,6 +1311,15 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
542 | G_CALLBACK (filter_clear_tasks_clicked), | 1311 | G_CALLBACK (filter_clear_tasks_clicked), |
543 | data); | 1312 | data); |
544 | 1313 | ||
1314 | menu_filter_graph_clear_tasks = | ||
1315 | gtk_menu_item_new_with_label("Clear Graph Task Filter"); | ||
1316 | gtk_widget_show(menu_filter_graph_clear_tasks); | ||
1317 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_clear_tasks); | ||
1318 | |||
1319 | g_signal_connect_swapped (G_OBJECT (menu_filter_graph_clear_tasks), "activate", | ||
1320 | G_CALLBACK (filter_graph_clear_tasks_clicked), | ||
1321 | data); | ||
1322 | |||
545 | } | 1323 | } |
546 | 1324 | ||
547 | row = trace_view_get_selected_row(GTK_WIDGET(info->treeview)); | 1325 | row = trace_view_get_selected_row(GTK_WIDGET(info->treeview)); |
@@ -559,29 +1337,59 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
559 | 1337 | ||
560 | len = strlen(comm) + 50; | 1338 | len = strlen(comm) + 50; |
561 | 1339 | ||
562 | text = g_malloc(len); | 1340 | if (info->sync_task_filters) { |
563 | g_assert(text); | 1341 | if (trace_graph_filter_task_find_pid(ginfo, pid)) |
564 | 1342 | set_menu_label(menu_filter_add_task, comm, pid, | |
565 | if (trace_graph_filter_task_find_pid(ginfo, pid)) | 1343 | "Remove %s-%d from filters"); |
566 | snprintf(text, len, "Remove %s-%d to filter", comm, pid); | 1344 | else |
567 | else | 1345 | set_menu_label(menu_filter_add_task, comm, pid, |
568 | snprintf(text, len, "Add %s-%d to filter", comm, pid); | 1346 | "Add %s-%d to filters"); |
1347 | |||
1348 | if (trace_graph_hide_task_find_pid(ginfo, pid)) | ||
1349 | set_menu_label(menu_filter_hide_task, comm, pid, | ||
1350 | "Show %s-%d"); | ||
1351 | else | ||
1352 | set_menu_label(menu_filter_hide_task, comm, pid, | ||
1353 | "Hide %s-%d"); | ||
1354 | |||
1355 | gtk_widget_hide(menu_filter_graph_add_task); | ||
1356 | gtk_widget_hide(menu_filter_graph_hide_task); | ||
1357 | |||
1358 | } else { | ||
1359 | if (filter_task_find_pid(info->list_task_filter, pid)) | ||
1360 | set_menu_label(menu_filter_add_task, comm, pid, | ||
1361 | "Remove %s-%d from List filter"); | ||
1362 | else | ||
1363 | set_menu_label(menu_filter_add_task, comm, pid, | ||
1364 | "Add %s-%d to List filter"); | ||
1365 | |||
1366 | if (filter_task_find_pid(info->list_hide_tasks, pid)) | ||
1367 | set_menu_label(menu_filter_hide_task, comm, pid, | ||
1368 | "Show %s-%d in List"); | ||
1369 | else | ||
1370 | set_menu_label(menu_filter_hide_task, comm, pid, | ||
1371 | "Hide %s-%d from List"); | ||
1372 | |||
1373 | if (trace_graph_filter_task_find_pid(ginfo, pid)) | ||
1374 | set_menu_label(menu_filter_graph_add_task, comm, pid, | ||
1375 | "Remove %s-%d from Graph filter"); | ||
1376 | else | ||
1377 | set_menu_label(menu_filter_graph_add_task, comm, pid, | ||
1378 | "Add %s-%d to Graph filter"); | ||
1379 | |||
1380 | if (trace_graph_hide_task_find_pid(ginfo, pid)) | ||
1381 | set_menu_label(menu_filter_graph_hide_task, comm, pid, | ||
1382 | "Show %s-%d in Graph"); | ||
1383 | else | ||
1384 | set_menu_label(menu_filter_graph_hide_task, comm, pid, | ||
1385 | "Hide %s-%d from Graph"); | ||
1386 | |||
1387 | gtk_widget_show(menu_filter_graph_add_task); | ||
1388 | gtk_widget_show(menu_filter_graph_hide_task); | ||
1389 | } | ||
569 | 1390 | ||
570 | ginfo->filter_task_selected = pid; | 1391 | ginfo->filter_task_selected = pid; |
571 | 1392 | ||
572 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_add_task), | ||
573 | text); | ||
574 | |||
575 | if (trace_graph_hide_task_find_pid(ginfo, pid)) | ||
576 | snprintf(text, len, "Show %s-%d", comm, pid); | ||
577 | else | ||
578 | snprintf(text, len, "Hide %s-%d", comm, pid); | ||
579 | |||
580 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_hide_task), | ||
581 | text); | ||
582 | |||
583 | g_free(text); | ||
584 | |||
585 | info->selected_task = pid; | 1393 | info->selected_task = pid; |
586 | 1394 | ||
587 | gtk_widget_show(menu_filter_add_task); | 1395 | gtk_widget_show(menu_filter_add_task); |
@@ -591,35 +1399,62 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
591 | } else { | 1399 | } else { |
592 | gtk_widget_hide(menu_filter_add_task); | 1400 | gtk_widget_hide(menu_filter_add_task); |
593 | gtk_widget_hide(menu_filter_hide_task); | 1401 | gtk_widget_hide(menu_filter_hide_task); |
1402 | gtk_widget_hide(menu_filter_graph_add_task); | ||
1403 | gtk_widget_hide(menu_filter_graph_hide_task); | ||
594 | } | 1404 | } |
595 | 1405 | ||
596 | if (ginfo->filter_enabled) | 1406 | if (ginfo->filter_enabled) |
597 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), | 1407 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), |
598 | "Disable Graph Filter"); | 1408 | "Disable Graph Task Filter"); |
599 | else | 1409 | else |
600 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), | 1410 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), |
601 | "Enable Graph Filter"); | 1411 | "Enable Graph Task Filter"); |
602 | 1412 | ||
603 | if (info->list_filter_enabled) | 1413 | if (info->list_filter_enabled) |
604 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), | 1414 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), |
605 | "Disable List Filter"); | 1415 | "Disable List Task Filter"); |
606 | else | 1416 | else |
607 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), | 1417 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), |
608 | "Enable List Filter"); | 1418 | "Enable List Task Filter"); |
609 | 1419 | ||
610 | if (ginfo->filter_available) { | 1420 | if (ginfo->filter_available) |
611 | gtk_widget_set_sensitive(menu_filter_graph_enable, TRUE); | 1421 | gtk_widget_set_sensitive(menu_filter_graph_enable, TRUE); |
612 | gtk_widget_set_sensitive(menu_filter_list_enable, TRUE); | 1422 | else |
613 | } else { | ||
614 | gtk_widget_set_sensitive(menu_filter_graph_enable, FALSE); | 1423 | gtk_widget_set_sensitive(menu_filter_graph_enable, FALSE); |
615 | gtk_widget_set_sensitive(menu_filter_list_enable, FALSE); | ||
616 | } | ||
617 | 1424 | ||
618 | if (filter_task_count(ginfo->task_filter) || | 1425 | if ((info->sync_task_filters && ginfo->filter_available) || |
619 | filter_task_count(ginfo->hide_tasks)) | 1426 | (!info->sync_task_filters && info->list_filter_available)) |
620 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | 1427 | gtk_widget_set_sensitive(menu_filter_list_enable, TRUE); |
621 | else | 1428 | else |
622 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | 1429 | gtk_widget_set_sensitive(menu_filter_list_enable, FALSE); |
1430 | |||
1431 | if (info->sync_task_filters) { | ||
1432 | if (filter_task_count(ginfo->task_filter) || | ||
1433 | filter_task_count(ginfo->hide_tasks)) | ||
1434 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | ||
1435 | else | ||
1436 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | ||
1437 | |||
1438 | set_menu_label(menu_filter_clear_tasks, comm, pid, | ||
1439 | "Clear Task Filter"); | ||
1440 | gtk_widget_hide(menu_filter_graph_clear_tasks); | ||
1441 | } else { | ||
1442 | if (filter_task_count(ginfo->task_filter) || | ||
1443 | filter_task_count(ginfo->hide_tasks)) | ||
1444 | gtk_widget_set_sensitive(menu_filter_graph_clear_tasks, TRUE); | ||
1445 | else | ||
1446 | gtk_widget_set_sensitive(menu_filter_graph_clear_tasks, FALSE); | ||
1447 | |||
1448 | if (filter_task_count(info->list_task_filter) || | ||
1449 | filter_task_count(info->list_hide_tasks)) | ||
1450 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | ||
1451 | else | ||
1452 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | ||
1453 | |||
1454 | set_menu_label(menu_filter_clear_tasks, comm, pid, | ||
1455 | "Clear List Task Filter"); | ||
1456 | gtk_widget_show(menu_filter_graph_clear_tasks); | ||
1457 | } | ||
623 | 1458 | ||
624 | gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, | 1459 | gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, |
625 | gtk_get_current_event_time()); | 1460 | gtk_get_current_event_time()); |
@@ -655,6 +1490,7 @@ void kernel_shark(int argc, char **argv) | |||
655 | GtkWidget *label; | 1490 | GtkWidget *label; |
656 | GtkWidget *spin; | 1491 | GtkWidget *spin; |
657 | GtkWidget *check; | 1492 | GtkWidget *check; |
1493 | GtkWidget *statusbar; | ||
658 | int ret; | 1494 | int ret; |
659 | int c; | 1495 | int c; |
660 | 1496 | ||
@@ -701,12 +1537,16 @@ void kernel_shark(int argc, char **argv) | |||
701 | handle = NULL; | 1537 | handle = NULL; |
702 | 1538 | ||
703 | info->handle = handle; | 1539 | info->handle = handle; |
1540 | info->sync_task_filters = TRUE; | ||
1541 | info->sync_event_filters = TRUE; | ||
704 | 1542 | ||
705 | /* --- Main window --- */ | 1543 | /* --- Main window --- */ |
706 | 1544 | ||
707 | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | 1545 | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
708 | info->window = window; | 1546 | info->window = window; |
709 | 1547 | ||
1548 | trace_dialog_register_window(window); | ||
1549 | |||
710 | if (input_file) | 1550 | if (input_file) |
711 | update_title(window, input_file); | 1551 | update_title(window, input_file); |
712 | 1552 | ||
@@ -734,12 +1574,11 @@ void kernel_shark(int argc, char **argv) | |||
734 | 1574 | ||
735 | /* --- File - Load Option --- */ | 1575 | /* --- File - Load Option --- */ |
736 | 1576 | ||
737 | sub_item = gtk_menu_item_new_with_label("Load info"); | 1577 | sub_item = gtk_menu_item_new_with_label("Load data"); |
738 | 1578 | ||
739 | /* Add them to the menu */ | 1579 | /* Add them to the menu */ |
740 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | 1580 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); |
741 | 1581 | ||
742 | /* We can attach the Quit menu item to our exit function */ | ||
743 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | 1582 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", |
744 | G_CALLBACK (load_clicked), | 1583 | G_CALLBACK (load_clicked), |
745 | (gpointer) info); | 1584 | (gpointer) info); |
@@ -748,6 +1587,35 @@ void kernel_shark(int argc, char **argv) | |||
748 | gtk_widget_show(sub_item); | 1587 | gtk_widget_show(sub_item); |
749 | 1588 | ||
750 | 1589 | ||
1590 | /* --- File - Load Filter Option --- */ | ||
1591 | |||
1592 | sub_item = gtk_menu_item_new_with_label("Load filters"); | ||
1593 | |||
1594 | /* Add them to the menu */ | ||
1595 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
1596 | |||
1597 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
1598 | G_CALLBACK (load_filters_clicked), | ||
1599 | (gpointer) info); | ||
1600 | |||
1601 | /* We do need to show menu items */ | ||
1602 | gtk_widget_show(sub_item); | ||
1603 | |||
1604 | |||
1605 | /* --- File - Save Filter Option --- */ | ||
1606 | |||
1607 | sub_item = gtk_menu_item_new_with_label("Save filters"); | ||
1608 | |||
1609 | /* Add them to the menu */ | ||
1610 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
1611 | |||
1612 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
1613 | G_CALLBACK (save_filters_clicked), | ||
1614 | (gpointer) info); | ||
1615 | |||
1616 | /* We do need to show menu items */ | ||
1617 | gtk_widget_show(sub_item); | ||
1618 | |||
751 | /* --- File - Quit Option --- */ | 1619 | /* --- File - Quit Option --- */ |
752 | 1620 | ||
753 | sub_item = gtk_menu_item_new_with_label("Quit"); | 1621 | sub_item = gtk_menu_item_new_with_label("Quit"); |
@@ -777,66 +1645,145 @@ void kernel_shark(int argc, char **argv) | |||
777 | menu = gtk_menu_new(); /* Don't need to show menus */ | 1645 | menu = gtk_menu_new(); /* Don't need to show menus */ |
778 | 1646 | ||
779 | 1647 | ||
780 | /* --- Filter - List Events Option --- */ | ||
781 | 1648 | ||
782 | sub_item = gtk_menu_item_new_with_label("list events"); | 1649 | /* --- Filter - Sync task Option --- */ |
1650 | |||
1651 | sub_item = gtk_menu_item_new_with_label("Unsync Graph and List Task Filters"); | ||
1652 | |||
1653 | info->task_sync_menu = sub_item; | ||
783 | 1654 | ||
784 | /* Add them to the menu */ | 1655 | /* Add them to the menu */ |
785 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | 1656 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); |
786 | 1657 | ||
787 | /* We can attach the Quit menu item to our exit function */ | 1658 | /* We can attach the Quit menu item to our exit function */ |
788 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | 1659 | g_signal_connect (G_OBJECT (sub_item), "activate", |
789 | G_CALLBACK (list_events_clicked), | 1660 | G_CALLBACK (sync_task_filter_clicked), |
790 | (gpointer) info); | 1661 | (gpointer) info); |
791 | 1662 | ||
792 | /* We do need to show menu items */ | 1663 | /* We do need to show menu items */ |
793 | gtk_widget_show(sub_item); | 1664 | gtk_widget_show(sub_item); |
794 | 1665 | ||
795 | 1666 | ||
796 | /* --- Filter - Events Option --- */ | 1667 | /* --- Filter - Sync events Option --- */ |
1668 | |||
1669 | sub_item = gtk_menu_item_new_with_label("Unsync Graph and List Event Filters"); | ||
797 | 1670 | ||
798 | sub_item = gtk_menu_item_new_with_label("graph events"); | 1671 | info->events_sync_menu = sub_item; |
1672 | |||
1673 | /* Add them to the menu */ | ||
1674 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
1675 | |||
1676 | /* We can attach the Quit menu item to our exit function */ | ||
1677 | g_signal_connect (G_OBJECT (sub_item), "activate", | ||
1678 | G_CALLBACK (sync_events_filter_clicked), | ||
1679 | (gpointer) info); | ||
1680 | |||
1681 | /* We do need to show menu items */ | ||
1682 | gtk_widget_show(sub_item); | ||
1683 | |||
1684 | |||
1685 | /* --- Filter - List Tasks Option --- */ | ||
1686 | |||
1687 | sub_item = gtk_menu_item_new_with_label("list tasks"); | ||
799 | 1688 | ||
800 | /* Add them to the menu */ | 1689 | /* Add them to the menu */ |
801 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | 1690 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); |
802 | 1691 | ||
803 | /* We can attach the Quit menu item to our exit function */ | 1692 | /* We can attach the Quit menu item to our exit function */ |
804 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | 1693 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", |
805 | G_CALLBACK (graph_events_clicked), | 1694 | G_CALLBACK (list_tasks_clicked), |
1695 | (gpointer) info); | ||
1696 | |||
1697 | info->list_task_menu = sub_item; | ||
1698 | |||
1699 | /* Only show this item when list and graph tasks are not synced */ | ||
1700 | |||
1701 | |||
1702 | /* --- Filter - Graph Tasks Option --- */ | ||
1703 | |||
1704 | sub_item = gtk_menu_item_new_with_label("tasks"); | ||
1705 | |||
1706 | /* Add them to the menu */ | ||
1707 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
1708 | |||
1709 | /* We can attach the Quit menu item to our exit function */ | ||
1710 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
1711 | G_CALLBACK (graph_tasks_clicked), | ||
806 | (gpointer) info); | 1712 | (gpointer) info); |
807 | 1713 | ||
1714 | info->graph_task_menu = sub_item; | ||
1715 | |||
808 | /* We do need to show menu items */ | 1716 | /* We do need to show menu items */ |
809 | gtk_widget_show(sub_item); | 1717 | gtk_widget_show(sub_item); |
810 | 1718 | ||
811 | 1719 | ||
812 | /* --- Filter - Events Option --- */ | 1720 | /* --- Filter - List Hide Tasks Option --- */ |
813 | 1721 | ||
814 | sub_item = gtk_menu_item_new_with_label("sync graph events with list"); | 1722 | sub_item = gtk_menu_item_new_with_label("list hide tasks"); |
815 | 1723 | ||
816 | /* Add them to the menu */ | 1724 | /* Add them to the menu */ |
817 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | 1725 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); |
818 | 1726 | ||
819 | /* We can attach the Quit menu item to our exit function */ | 1727 | /* We can attach the Quit menu item to our exit function */ |
820 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | 1728 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", |
821 | G_CALLBACK (sync_graph_events_to_list_clicked), | 1729 | G_CALLBACK (list_hide_tasks_clicked), |
822 | (gpointer) info); | 1730 | (gpointer) info); |
823 | 1731 | ||
1732 | info->list_hide_task_menu = sub_item; | ||
1733 | |||
1734 | /* Only show this item when list and graph tasks are not synced */ | ||
1735 | |||
1736 | |||
1737 | /* --- Filter - Graph Hide Tasks Option --- */ | ||
1738 | |||
1739 | sub_item = gtk_menu_item_new_with_label("hide tasks"); | ||
1740 | |||
1741 | /* Add them to the menu */ | ||
1742 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
1743 | |||
1744 | /* We can attach the Quit menu item to our exit function */ | ||
1745 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
1746 | G_CALLBACK (graph_hide_tasks_clicked), | ||
1747 | (gpointer) info); | ||
1748 | |||
1749 | info->graph_hide_task_menu = sub_item; | ||
1750 | |||
824 | /* We do need to show menu items */ | 1751 | /* We do need to show menu items */ |
825 | gtk_widget_show(sub_item); | 1752 | gtk_widget_show(sub_item); |
826 | 1753 | ||
827 | 1754 | ||
1755 | /* --- Filter - List Events Option --- */ | ||
1756 | |||
1757 | sub_item = gtk_menu_item_new_with_label("list events"); | ||
1758 | |||
1759 | /* Add them to the menu */ | ||
1760 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
1761 | |||
1762 | /* We can attach the Quit menu item to our exit function */ | ||
1763 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
1764 | G_CALLBACK (list_events_clicked), | ||
1765 | (gpointer) info); | ||
1766 | |||
1767 | info->list_events_menu = sub_item; | ||
1768 | |||
1769 | /* We do not show this menu (yet) */ | ||
1770 | |||
1771 | |||
828 | /* --- Filter - Events Option --- */ | 1772 | /* --- Filter - Events Option --- */ |
829 | 1773 | ||
830 | sub_item = gtk_menu_item_new_with_label("sync list events with graph"); | 1774 | /* The list and graph events start off insync */ |
1775 | sub_item = gtk_menu_item_new_with_label("events"); | ||
831 | 1776 | ||
832 | /* Add them to the menu */ | 1777 | /* Add them to the menu */ |
833 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | 1778 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); |
834 | 1779 | ||
835 | /* We can attach the Quit menu item to our exit function */ | 1780 | /* We can attach the Quit menu item to our exit function */ |
836 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | 1781 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", |
837 | G_CALLBACK (sync_list_events_to_graph_clicked), | 1782 | G_CALLBACK (graph_events_clicked), |
838 | (gpointer) info); | 1783 | (gpointer) info); |
839 | 1784 | ||
1785 | info->graph_events_menu = sub_item; | ||
1786 | |||
840 | /* We do need to show menu items */ | 1787 | /* We do need to show menu items */ |
841 | gtk_widget_show(sub_item); | 1788 | gtk_widget_show(sub_item); |
842 | 1789 | ||
@@ -853,13 +1800,14 @@ void kernel_shark(int argc, char **argv) | |||
853 | G_CALLBACK (adv_list_filter_clicked), | 1800 | G_CALLBACK (adv_list_filter_clicked), |
854 | (gpointer) info); | 1801 | (gpointer) info); |
855 | 1802 | ||
856 | /* We do need to show menu items */ | 1803 | info->list_adv_events_menu = sub_item; |
857 | gtk_widget_show(sub_item); | 1804 | /* We do not show this menu (yet) */ |
858 | 1805 | ||
859 | 1806 | ||
860 | /* --- Filter - Graph Advanced Events Option --- */ | 1807 | /* --- Filter - Graph Advanced Events Option --- */ |
861 | 1808 | ||
862 | sub_item = gtk_menu_item_new_with_label("graph advanced event"); | 1809 | /* The list and graph events start off in sync */ |
1810 | sub_item = gtk_menu_item_new_with_label("advanced events"); | ||
863 | 1811 | ||
864 | /* Add them to the menu */ | 1812 | /* Add them to the menu */ |
865 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | 1813 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); |
@@ -869,6 +1817,8 @@ void kernel_shark(int argc, char **argv) | |||
869 | G_CALLBACK (adv_graph_filter_clicked), | 1817 | G_CALLBACK (adv_graph_filter_clicked), |
870 | (gpointer) info); | 1818 | (gpointer) info); |
871 | 1819 | ||
1820 | info->graph_adv_events_menu = sub_item; | ||
1821 | |||
872 | /* We do need to show menu items */ | 1822 | /* We do need to show menu items */ |
873 | gtk_widget_show(sub_item); | 1823 | gtk_widget_show(sub_item); |
874 | 1824 | ||
@@ -939,6 +1889,53 @@ void kernel_shark(int argc, char **argv) | |||
939 | gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu); | 1889 | gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu); |
940 | 1890 | ||
941 | 1891 | ||
1892 | |||
1893 | /* --- Help Option --- */ | ||
1894 | |||
1895 | menu_item = gtk_menu_item_new_with_label("Help"); | ||
1896 | gtk_widget_show(menu_item); | ||
1897 | |||
1898 | gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), menu_item); | ||
1899 | |||
1900 | menu = gtk_menu_new(); /* Don't need to show menus */ | ||
1901 | |||
1902 | |||
1903 | /* --- Help - Contents Option --- */ | ||
1904 | |||
1905 | sub_item = gtk_menu_item_new_with_label("Contents"); | ||
1906 | |||
1907 | /* Add them to the menu */ | ||
1908 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
1909 | |||
1910 | /* We can attach the Quit menu item to our exit function */ | ||
1911 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
1912 | G_CALLBACK (help_content_clicked), | ||
1913 | (gpointer) info); | ||
1914 | |||
1915 | /* We do need to show menu items */ | ||
1916 | gtk_widget_show(sub_item); | ||
1917 | |||
1918 | |||
1919 | /* --- Help - About Option --- */ | ||
1920 | |||
1921 | sub_item = gtk_menu_item_new_with_label("About"); | ||
1922 | |||
1923 | /* Add them to the menu */ | ||
1924 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
1925 | |||
1926 | /* We can attach the Quit menu item to our exit function */ | ||
1927 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
1928 | G_CALLBACK (help_about_clicked), | ||
1929 | (gpointer) info); | ||
1930 | |||
1931 | /* We do need to show menu items */ | ||
1932 | gtk_widget_show(sub_item); | ||
1933 | |||
1934 | |||
1935 | /* --- End Help Options --- */ | ||
1936 | gtk_menu_item_set_submenu(GTK_MENU_ITEM (menu_item), menu); | ||
1937 | |||
1938 | |||
942 | /* --- Top Level Vpaned --- */ | 1939 | /* --- Top Level Vpaned --- */ |
943 | 1940 | ||
944 | vpaned = gtk_vpaned_new(); | 1941 | vpaned = gtk_vpaned_new(); |
@@ -1033,6 +2030,12 @@ void kernel_shark(int argc, char **argv) | |||
1033 | 2030 | ||
1034 | gtk_widget_show(info->treeview); | 2031 | gtk_widget_show(info->treeview); |
1035 | 2032 | ||
2033 | /* --- Set up Status Bar --- */ | ||
2034 | |||
2035 | statusbar = trace_status_bar_new(); | ||
2036 | |||
2037 | gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 0); | ||
2038 | gtk_widget_show(statusbar); | ||
1036 | 2039 | ||
1037 | /********************************************** | 2040 | /********************************************** |
1038 | * Main Window | 2041 | * Main Window |