aboutsummaryrefslogtreecommitdiffstats
path: root/kernel-shark.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel-shark.c')
-rw-r--r--kernel-shark.c1241
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 */
74static 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
129static 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
116static void free_info(struct shark_info *info) 201static 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
226static 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
244static 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
257static 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
271static 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
137static void 284static void
138/* Callback for the clicked signal of the Load button */ 285/* Callback for the clicked signal of the Load button */
139load_clicked (gpointer data) 286load_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 */
308static void
309load_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 */
398static void
399save_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 */
191static void 465static void
192list_events_clicked (gpointer data) 466sync_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 */
216static void 551static void
217graph_events_clicked (gpointer data) 552sync_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 */ 614static void filter_list_enable_clicked (gpointer data);
615
233static void 616static void
234adv_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
652static void
653update_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
664static void
665update_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 */
677static 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 */
255static void 707static void
256adv_graph_filter_clicked (gpointer data) 708list_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
716static void
717list_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
725static 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
265static void 758static void
266sync_graph_events_to_list_clicked (gpointer data) 759update_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
771static void
772update_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 */
785static 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
806static void
807graph_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
816static void
817graph_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 */
827static void
828list_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
856static void
857graph_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
289static void 874static void
290sync_list_events_to_graph_clicked (gpointer data) 875graph_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 */
891static void
892adv_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
916static void
917graph_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 */
933static void
934adv_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 */
1007static void
1008help_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 */
1021static void
1022help_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
365static void graph_follows_tree(struct shark_info *info, 1034static 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
427filter_list_enable_clicked (gpointer data) 1096filter_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
441static void 1119static void
1120filter_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
1141static void
442filter_add_task_clicked (gpointer data) 1142filter_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
1157static void
1158filter_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
452static void 1165static 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
1180static void
1181filter_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
464static void 1188static 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
1206static void
1207filter_graph_clear_tasks_clicked (gpointer data)
1208{
1209 struct shark_info *info = data;
1210
1211 trace_graph_clear_tasks(info->ginfo);
1212}
1213
474static void graph_check_toggle(gpointer data, GtkWidget *widget) 1214static 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
1221static 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
481static gboolean 1232static gboolean
482do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) 1233do_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