diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2010-06-01 11:09:01 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2010-06-08 22:53:10 -0400 |
| commit | 19c146cbf37c95cf77319569d1beff35fd8d544b (patch) | |
| tree | 86861cda5f182aa9d7f6b45795cff11b657dc1b0 | |
| parent | 7327b8f423f55873d30d523e882bb8fd9338e1ac (diff) | |
kernelshark: Allow for separate list and graph task filters
To make the task filters more like the event filters, allow the
list and graph to have their own filtering.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
| -rw-r--r-- | kernel-shark.c | 448 | ||||
| -rw-r--r-- | kernel-shark.h | 5 | ||||
| -rw-r--r-- | trace-graph.c | 14 | ||||
| -rw-r--r-- | trace-graph.h | 3 | ||||
| -rw-r--r-- | trace-view-store.c | 1 |
5 files changed, 424 insertions, 47 deletions
diff --git a/kernel-shark.c b/kernel-shark.c index b056420..e591657 100644 --- a/kernel-shark.c +++ b/kernel-shark.c | |||
| @@ -64,6 +64,68 @@ void usage(char *prog) | |||
| 64 | printf(" -i input_file, default is %s\n", default_input_file); | 64 | printf(" -i input_file, default is %s\n", default_input_file); |
| 65 | } | 65 | } |
| 66 | 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 | |||
| 67 | /* graph callbacks */ | 129 | /* graph callbacks */ |
| 68 | 130 | ||
| 69 | /* convert_nano() and print_time() are copied from trace-graph.c for debugging | 131 | /* convert_nano() and print_time() are copied from trace-graph.c for debugging |
| @@ -113,15 +175,30 @@ static void ks_graph_filter(struct graph_info *ginfo, | |||
| 113 | cbs = trace_graph_get_callbacks(ginfo); | 175 | cbs = trace_graph_get_callbacks(ginfo); |
| 114 | info = container_of(cbs, struct shark_info, graph_cbs); | 176 | info = container_of(cbs, struct shark_info, graph_cbs); |
| 115 | 177 | ||
| 178 | if (!info->sync_task_filters) | ||
| 179 | return; | ||
| 180 | |||
| 116 | if (info->list_filter_enabled) | 181 | if (info->list_filter_enabled) |
| 117 | trace_view_update_filters(info->treeview, | 182 | trace_view_update_filters(info->treeview, |
| 118 | task_filter, hide_tasks); | 183 | task_filter, hide_tasks); |
| 184 | |||
| 185 | if (filter_task_count(task_filter) || | ||
| 186 | filter_task_count(hide_tasks)) | ||
| 187 | info->list_filter_available = 1; | ||
| 188 | else { | ||
| 189 | info->list_filter_enabled = 0; | ||
| 190 | info->list_filter_available = 0; | ||
| 191 | } | ||
| 119 | } | 192 | } |
| 120 | 193 | ||
| 121 | static void free_info(struct shark_info *info) | 194 | static void free_info(struct shark_info *info) |
| 122 | { | 195 | { |
| 123 | tracecmd_close(info->handle); | 196 | tracecmd_close(info->handle); |
| 124 | trace_graph_free_info(info->ginfo); | 197 | trace_graph_free_info(info->ginfo); |
| 198 | |||
| 199 | filter_task_hash_free(info->list_task_filter); | ||
| 200 | filter_task_hash_free(info->list_hide_tasks); | ||
| 201 | |||
| 125 | free(info->ginfo); | 202 | free(info->ginfo); |
| 126 | free(info); | 203 | free(info); |
| 127 | } | 204 | } |
| @@ -244,6 +321,99 @@ delete_event (GtkWidget *widget, GdkEvent *event, gpointer data) | |||
| 244 | 321 | ||
| 245 | /* Callback for the clicked signal of the Events filter button */ | 322 | /* Callback for the clicked signal of the Events filter button */ |
| 246 | static void | 323 | static void |
| 324 | sync_task_filter_clicked (GtkWidget *subitem, gpointer data) | ||
| 325 | { | ||
| 326 | struct shark_info *info = data; | ||
| 327 | struct filter_task *task_filter; | ||
| 328 | struct filter_task *hide_tasks; | ||
| 329 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->treeview); | ||
| 330 | GtkTreeModel *model; | ||
| 331 | TraceViewStore *store; | ||
| 332 | gboolean keep; | ||
| 333 | gchar *selections[] = { "Sync List Filter with Graph Filter", | ||
| 334 | "Sync Graph Filter with List Filter", | ||
| 335 | NULL }; | ||
| 336 | int result; | ||
| 337 | |||
| 338 | if (info->sync_task_filters) { | ||
| 339 | /* Separate the List and Graph filters */ | ||
| 340 | |||
| 341 | info->sync_task_filters = 0; | ||
| 342 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu), | ||
| 343 | "Sync Graph and List Task Filters"); | ||
| 344 | |||
| 345 | /* The list now uses its own hash */ | ||
| 346 | info->list_task_filter = filter_task_hash_copy(info->ginfo->task_filter); | ||
| 347 | info->list_hide_tasks = filter_task_hash_copy(info->ginfo->hide_tasks); | ||
| 348 | return; | ||
| 349 | } | ||
| 350 | |||
| 351 | model = gtk_tree_view_get_model(trace_tree); | ||
| 352 | if (!model) | ||
| 353 | return; | ||
| 354 | |||
| 355 | store = TRACE_VIEW_STORE(model); | ||
| 356 | |||
| 357 | /* Ask user which way to sync */ | ||
| 358 | result = trace_sync_select_menu("Sync Task Filters", | ||
| 359 | selections, &keep); | ||
| 360 | |||
| 361 | switch (result) { | ||
| 362 | case 0: | ||
| 363 | /* Sync List Filter with Graph Filter */ | ||
| 364 | filter_task_hash_free(info->list_task_filter); | ||
| 365 | filter_task_hash_free(info->list_hide_tasks); | ||
| 366 | |||
| 367 | info->list_task_filter = NULL; | ||
| 368 | info->list_hide_tasks = NULL; | ||
| 369 | |||
| 370 | task_filter = info->ginfo->task_filter; | ||
| 371 | hide_tasks = info->ginfo->hide_tasks; | ||
| 372 | |||
| 373 | if (!keep) { | ||
| 374 | info->list_task_filter = filter_task_hash_copy(task_filter); | ||
| 375 | info->list_hide_tasks = filter_task_hash_copy(hide_tasks); | ||
| 376 | } | ||
| 377 | |||
| 378 | if (info->list_filter_enabled) | ||
| 379 | trace_view_update_filters(info->treeview, | ||
| 380 | task_filter, hide_tasks); | ||
| 381 | |||
| 382 | if (!filter_task_count(task_filter) && | ||
| 383 | !filter_task_count(hide_tasks)) { | ||
| 384 | info->list_filter_enabled = 0; | ||
| 385 | info->list_filter_available = 0; | ||
| 386 | } else | ||
| 387 | info->list_filter_available = 1; | ||
| 388 | |||
| 389 | break; | ||
| 390 | case 1: | ||
| 391 | /* Sync Graph Filter with List Filter */ | ||
| 392 | trace_graph_update_filters(info->ginfo, | ||
| 393 | info->list_task_filter, | ||
| 394 | info->list_hide_tasks); | ||
| 395 | |||
| 396 | if (keep) { | ||
| 397 | filter_task_hash_free(info->list_task_filter); | ||
| 398 | filter_task_hash_free(info->list_hide_tasks); | ||
| 399 | |||
| 400 | info->list_task_filter = NULL; | ||
| 401 | info->list_hide_tasks = NULL; | ||
| 402 | } | ||
| 403 | break; | ||
| 404 | default: | ||
| 405 | keep = 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | if (keep) { | ||
| 409 | info->sync_task_filters = 1; | ||
| 410 | gtk_menu_item_set_label(GTK_MENU_ITEM(info->task_sync_menu), | ||
| 411 | "Unsync Graph and List Task Filters"); | ||
| 412 | } | ||
| 413 | } | ||
| 414 | |||
| 415 | /* Callback for the clicked signal of the Events filter button */ | ||
| 416 | static void | ||
| 247 | list_events_clicked (gpointer data) | 417 | list_events_clicked (gpointer data) |
| 248 | { | 418 | { |
| 249 | struct shark_info *info = data; | 419 | struct shark_info *info = data; |
| @@ -510,26 +680,70 @@ static void | |||
| 510 | filter_list_enable_clicked (gpointer data) | 680 | filter_list_enable_clicked (gpointer data) |
| 511 | { | 681 | { |
| 512 | struct shark_info *info = data; | 682 | struct shark_info *info = data; |
| 683 | struct filter_task *task_filter; | ||
| 684 | struct filter_task *hide_tasks; | ||
| 513 | 685 | ||
| 514 | info->list_filter_enabled ^= 1; | 686 | info->list_filter_enabled ^= 1; |
| 515 | 687 | ||
| 688 | if (info->sync_task_filters) { | ||
| 689 | task_filter = info->ginfo->task_filter; | ||
| 690 | hide_tasks = info->ginfo->hide_tasks; | ||
| 691 | } else { | ||
| 692 | task_filter = info->list_task_filter; | ||
| 693 | hide_tasks = info->list_hide_tasks; | ||
| 694 | } | ||
| 695 | |||
| 516 | if (info->list_filter_enabled) | 696 | if (info->list_filter_enabled) |
| 517 | trace_view_update_filters(info->treeview, | 697 | trace_view_update_filters(info->treeview, |
| 518 | info->ginfo->task_filter, | 698 | task_filter, hide_tasks); |
| 519 | info->ginfo->hide_tasks); | ||
| 520 | else | 699 | else |
| 521 | trace_view_update_filters(info->treeview, NULL, NULL); | 700 | trace_view_update_filters(info->treeview, NULL, NULL); |
| 522 | } | 701 | } |
| 523 | 702 | ||
| 524 | static void | 703 | static void |
| 704 | filter_update_list_filter(struct shark_info *info, | ||
| 705 | struct filter_task *filter, | ||
| 706 | struct filter_task *other_filter) | ||
| 707 | { | ||
| 708 | struct filter_task_item *task; | ||
| 709 | int pid = info->selected_task; | ||
| 710 | |||
| 711 | task = filter_task_find_pid(filter, pid); | ||
| 712 | if (task) { | ||
| 713 | filter_task_remove_pid(filter, pid); | ||
| 714 | if (!filter_task_count(filter) && | ||
| 715 | !filter_task_count(other_filter)) { | ||
| 716 | info->list_filter_enabled = 0; | ||
| 717 | info->list_filter_available = 0; | ||
| 718 | } | ||
| 719 | } else { | ||
| 720 | filter_task_add_pid(filter, pid); | ||
| 721 | info->list_filter_available = 1; | ||
| 722 | } | ||
| 723 | } | ||
| 724 | |||
| 725 | static void | ||
| 525 | filter_add_task_clicked (gpointer data) | 726 | filter_add_task_clicked (gpointer data) |
| 526 | { | 727 | { |
| 527 | struct shark_info *info = data; | 728 | struct shark_info *info = data; |
| 729 | int pid = info->selected_task; | ||
| 528 | 730 | ||
| 529 | trace_graph_filter_add_remove_task(info->ginfo, info->selected_task); | 731 | if (info->sync_task_filters) { |
| 732 | trace_graph_filter_add_remove_task(info->ginfo, pid); | ||
| 733 | return; | ||
| 734 | } | ||
| 530 | 735 | ||
| 531 | if (!filter_task_count(info->ginfo->task_filter)) | 736 | filter_update_list_filter(info, info->list_task_filter, info->list_hide_tasks); |
| 532 | info->list_filter_enabled = 0; | 737 | trace_view_update_filters(info->treeview, |
| 738 | info->list_task_filter, info->list_hide_tasks); | ||
| 739 | } | ||
| 740 | |||
| 741 | static void | ||
| 742 | filter_graph_add_task_clicked (gpointer data) | ||
| 743 | { | ||
| 744 | struct shark_info *info = data; | ||
| 745 | |||
| 746 | trace_graph_filter_add_remove_task(info->ginfo, info->selected_task); | ||
| 533 | } | 747 | } |
| 534 | 748 | ||
| 535 | static void | 749 | static void |
| @@ -537,11 +751,22 @@ filter_hide_task_clicked (gpointer data) | |||
| 537 | { | 751 | { |
| 538 | struct shark_info *info = data; | 752 | struct shark_info *info = data; |
| 539 | 753 | ||
| 540 | trace_graph_filter_hide_show_task(info->ginfo, info->selected_task); | 754 | if (info->sync_task_filters) { |
| 755 | trace_graph_filter_hide_show_task(info->ginfo, info->selected_task); | ||
| 756 | return; | ||
| 757 | } | ||
| 541 | 758 | ||
| 542 | if (!filter_task_count(info->ginfo->task_filter) && | 759 | filter_update_list_filter(info, info->list_hide_tasks, info->list_task_filter); |
| 543 | !filter_task_count(info->ginfo->hide_tasks)) | 760 | trace_view_update_filters(info->treeview, |
| 544 | info->list_filter_enabled = 0; | 761 | info->list_task_filter, info->list_hide_tasks); |
| 762 | } | ||
| 763 | |||
| 764 | static void | ||
| 765 | filter_graph_hide_task_clicked (gpointer data) | ||
| 766 | { | ||
| 767 | struct shark_info *info = data; | ||
| 768 | |||
| 769 | trace_graph_filter_hide_show_task(info->ginfo, info->selected_task); | ||
| 545 | } | 770 | } |
| 546 | 771 | ||
| 547 | static void | 772 | static void |
| @@ -549,11 +774,27 @@ filter_clear_tasks_clicked (gpointer data) | |||
| 549 | { | 774 | { |
| 550 | struct shark_info *info = data; | 775 | struct shark_info *info = data; |
| 551 | 776 | ||
| 552 | trace_graph_clear_tasks(info->ginfo); | 777 | if (info->sync_task_filters) { |
| 778 | trace_graph_clear_tasks(info->ginfo); | ||
| 779 | return; | ||
| 780 | } | ||
| 553 | 781 | ||
| 782 | filter_task_clear(info->list_task_filter); | ||
| 783 | filter_task_clear(info->list_hide_tasks); | ||
| 784 | trace_view_update_filters(info->treeview, NULL, NULL); | ||
| 785 | |||
| 786 | info->list_filter_available = 0; | ||
| 554 | info->list_filter_enabled = 0; | 787 | info->list_filter_enabled = 0; |
| 555 | } | 788 | } |
| 556 | 789 | ||
| 790 | static void | ||
| 791 | filter_graph_clear_tasks_clicked (gpointer data) | ||
| 792 | { | ||
| 793 | struct shark_info *info = data; | ||
| 794 | |||
| 795 | trace_graph_clear_tasks(info->ginfo); | ||
| 796 | } | ||
| 797 | |||
| 557 | static void graph_check_toggle(gpointer data, GtkWidget *widget) | 798 | static void graph_check_toggle(gpointer data, GtkWidget *widget) |
| 558 | { | 799 | { |
| 559 | struct shark_info *info = data; | 800 | struct shark_info *info = data; |
| @@ -561,6 +802,17 @@ static void graph_check_toggle(gpointer data, GtkWidget *widget) | |||
| 561 | info->graph_follows = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); | 802 | info->graph_follows = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); |
| 562 | } | 803 | } |
| 563 | 804 | ||
| 805 | static void set_menu_label(GtkWidget *menu, const char *comm, int pid, | ||
| 806 | const char *fmt) | ||
| 807 | { | ||
| 808 | int len = strlen(comm) + strlen(fmt) + 50; | ||
| 809 | char text[len]; | ||
| 810 | |||
| 811 | snprintf(text, len, fmt, comm, pid); | ||
| 812 | |||
| 813 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu), text); | ||
| 814 | } | ||
| 815 | |||
| 564 | static gboolean | 816 | static gboolean |
| 565 | do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | 817 | do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) |
| 566 | { | 818 | { |
| @@ -572,11 +824,13 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 572 | static GtkWidget *menu_filter_add_task; | 824 | static GtkWidget *menu_filter_add_task; |
| 573 | static GtkWidget *menu_filter_hide_task; | 825 | static GtkWidget *menu_filter_hide_task; |
| 574 | static GtkWidget *menu_filter_clear_tasks; | 826 | static GtkWidget *menu_filter_clear_tasks; |
| 827 | static GtkWidget *menu_filter_graph_add_task; | ||
| 828 | static GtkWidget *menu_filter_graph_hide_task; | ||
| 829 | static GtkWidget *menu_filter_graph_clear_tasks; | ||
| 575 | struct record *record; | 830 | struct record *record; |
| 576 | TraceViewRecord *vrec; | 831 | TraceViewRecord *vrec; |
| 577 | GtkTreeModel *model; | 832 | GtkTreeModel *model; |
| 578 | const char *comm; | 833 | const char *comm; |
| 579 | gchar *text; | ||
| 580 | gint pid; | 834 | gint pid; |
| 581 | gint len; | 835 | gint len; |
| 582 | guint64 offset; | 836 | guint64 offset; |
| @@ -585,7 +839,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 585 | 839 | ||
| 586 | if (!menu) { | 840 | if (!menu) { |
| 587 | menu = gtk_menu_new(); | 841 | menu = gtk_menu_new(); |
| 588 | menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Filter"); | 842 | menu_filter_graph_enable = gtk_menu_item_new_with_label("Enable Graph Task Filter"); |
| 589 | gtk_widget_show(menu_filter_graph_enable); | 843 | gtk_widget_show(menu_filter_graph_enable); |
| 590 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_enable); | 844 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_enable); |
| 591 | 845 | ||
| @@ -593,7 +847,7 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 593 | G_CALLBACK (filter_graph_enable_clicked), | 847 | G_CALLBACK (filter_graph_enable_clicked), |
| 594 | data); | 848 | data); |
| 595 | 849 | ||
| 596 | menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Filter"); | 850 | menu_filter_list_enable = gtk_menu_item_new_with_label("Enable List Task Filter"); |
| 597 | gtk_widget_show(menu_filter_list_enable); | 851 | gtk_widget_show(menu_filter_list_enable); |
| 598 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_list_enable); | 852 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_list_enable); |
| 599 | 853 | ||
| @@ -609,6 +863,14 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 609 | G_CALLBACK (filter_add_task_clicked), | 863 | G_CALLBACK (filter_add_task_clicked), |
| 610 | data); | 864 | data); |
| 611 | 865 | ||
| 866 | menu_filter_graph_add_task = gtk_menu_item_new_with_label("Add Task to Graph"); | ||
| 867 | gtk_widget_show(menu_filter_graph_add_task); | ||
| 868 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_add_task); | ||
| 869 | |||
| 870 | g_signal_connect_swapped (G_OBJECT (menu_filter_graph_add_task), "activate", | ||
| 871 | G_CALLBACK (filter_graph_add_task_clicked), | ||
| 872 | data); | ||
| 873 | |||
| 612 | menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task"); | 874 | menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task"); |
| 613 | gtk_widget_show(menu_filter_hide_task); | 875 | gtk_widget_show(menu_filter_hide_task); |
| 614 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task); | 876 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task); |
| @@ -617,6 +879,14 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 617 | G_CALLBACK (filter_hide_task_clicked), | 879 | G_CALLBACK (filter_hide_task_clicked), |
| 618 | data); | 880 | data); |
| 619 | 881 | ||
| 882 | menu_filter_graph_hide_task = gtk_menu_item_new_with_label("Hide Task from Graph"); | ||
| 883 | gtk_widget_show(menu_filter_graph_hide_task); | ||
| 884 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_hide_task); | ||
| 885 | |||
| 886 | g_signal_connect_swapped (G_OBJECT (menu_filter_graph_hide_task), "activate", | ||
| 887 | G_CALLBACK (filter_graph_hide_task_clicked), | ||
| 888 | data); | ||
| 889 | |||
| 620 | menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter"); | 890 | menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter"); |
| 621 | gtk_widget_show(menu_filter_clear_tasks); | 891 | gtk_widget_show(menu_filter_clear_tasks); |
| 622 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks); | 892 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks); |
| @@ -625,6 +895,15 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 625 | G_CALLBACK (filter_clear_tasks_clicked), | 895 | G_CALLBACK (filter_clear_tasks_clicked), |
| 626 | data); | 896 | data); |
| 627 | 897 | ||
| 898 | menu_filter_graph_clear_tasks = | ||
| 899 | gtk_menu_item_new_with_label("Clear Graph Task Filter"); | ||
| 900 | gtk_widget_show(menu_filter_graph_clear_tasks); | ||
| 901 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_graph_clear_tasks); | ||
| 902 | |||
| 903 | g_signal_connect_swapped (G_OBJECT (menu_filter_graph_clear_tasks), "activate", | ||
| 904 | G_CALLBACK (filter_graph_clear_tasks_clicked), | ||
| 905 | data); | ||
| 906 | |||
| 628 | } | 907 | } |
| 629 | 908 | ||
| 630 | row = trace_view_get_selected_row(GTK_WIDGET(info->treeview)); | 909 | row = trace_view_get_selected_row(GTK_WIDGET(info->treeview)); |
| @@ -642,29 +921,59 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 642 | 921 | ||
| 643 | len = strlen(comm) + 50; | 922 | len = strlen(comm) + 50; |
| 644 | 923 | ||
| 645 | text = g_malloc(len); | 924 | if (info->sync_task_filters) { |
| 646 | g_assert(text); | 925 | if (trace_graph_filter_task_find_pid(ginfo, pid)) |
| 647 | 926 | set_menu_label(menu_filter_add_task, comm, pid, | |
| 648 | if (trace_graph_filter_task_find_pid(ginfo, pid)) | 927 | "Remove %s-%d from filters"); |
| 649 | snprintf(text, len, "Remove %s-%d from filter", comm, pid); | 928 | else |
| 650 | else | 929 | set_menu_label(menu_filter_add_task, comm, pid, |
| 651 | snprintf(text, len, "Add %s-%d to filter", comm, pid); | 930 | "Add %s-%d to filters"); |
| 931 | |||
| 932 | if (trace_graph_hide_task_find_pid(ginfo, pid)) | ||
| 933 | set_menu_label(menu_filter_hide_task, comm, pid, | ||
| 934 | "Show %s-%d"); | ||
| 935 | else | ||
| 936 | set_menu_label(menu_filter_hide_task, comm, pid, | ||
| 937 | "Hide %s-%d"); | ||
| 938 | |||
| 939 | gtk_widget_hide(menu_filter_graph_add_task); | ||
| 940 | gtk_widget_hide(menu_filter_graph_hide_task); | ||
| 941 | |||
| 942 | } else { | ||
| 943 | if (filter_task_find_pid(info->list_task_filter, pid)) | ||
| 944 | set_menu_label(menu_filter_add_task, comm, pid, | ||
| 945 | "Remove %s-%d from List filter"); | ||
| 946 | else | ||
| 947 | set_menu_label(menu_filter_add_task, comm, pid, | ||
| 948 | "Add %s-%d to List filter"); | ||
| 949 | |||
| 950 | if (filter_task_find_pid(info->list_hide_tasks, pid)) | ||
| 951 | set_menu_label(menu_filter_hide_task, comm, pid, | ||
| 952 | "Show %s-%d in List"); | ||
| 953 | else | ||
| 954 | set_menu_label(menu_filter_hide_task, comm, pid, | ||
| 955 | "Hide %s-%d from List"); | ||
| 956 | |||
| 957 | if (trace_graph_filter_task_find_pid(ginfo, pid)) | ||
| 958 | set_menu_label(menu_filter_graph_add_task, comm, pid, | ||
| 959 | "Remove %s-%d from Graph filter"); | ||
| 960 | else | ||
| 961 | set_menu_label(menu_filter_graph_add_task, comm, pid, | ||
| 962 | "Add %s-%d to Graph filter"); | ||
| 963 | |||
| 964 | if (trace_graph_hide_task_find_pid(ginfo, pid)) | ||
| 965 | set_menu_label(menu_filter_graph_hide_task, comm, pid, | ||
| 966 | "Show %s-%d in Graph"); | ||
| 967 | else | ||
| 968 | set_menu_label(menu_filter_graph_hide_task, comm, pid, | ||
| 969 | "Hide %s-%d from Graph"); | ||
| 970 | |||
| 971 | gtk_widget_show(menu_filter_graph_add_task); | ||
| 972 | gtk_widget_show(menu_filter_graph_hide_task); | ||
| 973 | } | ||
| 652 | 974 | ||
| 653 | ginfo->filter_task_selected = pid; | 975 | ginfo->filter_task_selected = pid; |
| 654 | 976 | ||
| 655 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_add_task), | ||
| 656 | text); | ||
| 657 | |||
| 658 | if (trace_graph_hide_task_find_pid(ginfo, pid)) | ||
| 659 | snprintf(text, len, "Show %s-%d", comm, pid); | ||
| 660 | else | ||
| 661 | snprintf(text, len, "Hide %s-%d", comm, pid); | ||
| 662 | |||
| 663 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_hide_task), | ||
| 664 | text); | ||
| 665 | |||
| 666 | g_free(text); | ||
| 667 | |||
| 668 | info->selected_task = pid; | 977 | info->selected_task = pid; |
| 669 | 978 | ||
| 670 | gtk_widget_show(menu_filter_add_task); | 979 | gtk_widget_show(menu_filter_add_task); |
| @@ -674,35 +983,62 @@ do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | |||
| 674 | } else { | 983 | } else { |
| 675 | gtk_widget_hide(menu_filter_add_task); | 984 | gtk_widget_hide(menu_filter_add_task); |
| 676 | gtk_widget_hide(menu_filter_hide_task); | 985 | gtk_widget_hide(menu_filter_hide_task); |
| 986 | gtk_widget_hide(menu_filter_graph_add_task); | ||
| 987 | gtk_widget_hide(menu_filter_graph_hide_task); | ||
| 677 | } | 988 | } |
| 678 | 989 | ||
| 679 | if (ginfo->filter_enabled) | 990 | if (ginfo->filter_enabled) |
| 680 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), | 991 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), |
| 681 | "Disable Graph Filter"); | 992 | "Disable Graph Task Filter"); |
| 682 | else | 993 | else |
| 683 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), | 994 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_graph_enable), |
| 684 | "Enable Graph Filter"); | 995 | "Enable Graph Task Filter"); |
| 685 | 996 | ||
| 686 | if (info->list_filter_enabled) | 997 | if (info->list_filter_enabled) |
| 687 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), | 998 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), |
| 688 | "Disable List Filter"); | 999 | "Disable List Task Filter"); |
| 689 | else | 1000 | else |
| 690 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), | 1001 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_list_enable), |
| 691 | "Enable List Filter"); | 1002 | "Enable List Task Filter"); |
| 692 | 1003 | ||
| 693 | if (ginfo->filter_available) { | 1004 | if (ginfo->filter_available) |
| 694 | gtk_widget_set_sensitive(menu_filter_graph_enable, TRUE); | 1005 | gtk_widget_set_sensitive(menu_filter_graph_enable, TRUE); |
| 695 | gtk_widget_set_sensitive(menu_filter_list_enable, TRUE); | 1006 | else |
| 696 | } else { | ||
| 697 | gtk_widget_set_sensitive(menu_filter_graph_enable, FALSE); | 1007 | gtk_widget_set_sensitive(menu_filter_graph_enable, FALSE); |
| 698 | gtk_widget_set_sensitive(menu_filter_list_enable, FALSE); | ||
| 699 | } | ||
| 700 | 1008 | ||
| 701 | if (filter_task_count(ginfo->task_filter) || | 1009 | if ((info->sync_task_filters && ginfo->filter_available) || |
| 702 | filter_task_count(ginfo->hide_tasks)) | 1010 | (!info->sync_task_filters && info->list_filter_available)) |
| 703 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | 1011 | gtk_widget_set_sensitive(menu_filter_list_enable, TRUE); |
| 704 | else | 1012 | else |
| 705 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | 1013 | gtk_widget_set_sensitive(menu_filter_list_enable, FALSE); |
| 1014 | |||
| 1015 | if (info->sync_task_filters) { | ||
| 1016 | if (filter_task_count(ginfo->task_filter) || | ||
| 1017 | filter_task_count(ginfo->hide_tasks)) | ||
| 1018 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | ||
| 1019 | else | ||
| 1020 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | ||
| 1021 | |||
| 1022 | set_menu_label(menu_filter_clear_tasks, comm, pid, | ||
| 1023 | "Clear Task Filter"); | ||
| 1024 | gtk_widget_hide(menu_filter_graph_clear_tasks); | ||
| 1025 | } else { | ||
| 1026 | if (filter_task_count(ginfo->task_filter) || | ||
| 1027 | filter_task_count(ginfo->hide_tasks)) | ||
| 1028 | gtk_widget_set_sensitive(menu_filter_graph_clear_tasks, TRUE); | ||
| 1029 | else | ||
| 1030 | gtk_widget_set_sensitive(menu_filter_graph_clear_tasks, FALSE); | ||
| 1031 | |||
| 1032 | if (filter_task_count(info->list_task_filter) || | ||
| 1033 | filter_task_count(info->list_hide_tasks)) | ||
| 1034 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | ||
| 1035 | else | ||
| 1036 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | ||
| 1037 | |||
| 1038 | set_menu_label(menu_filter_clear_tasks, comm, pid, | ||
| 1039 | "Clear List Task Filter"); | ||
| 1040 | gtk_widget_show(menu_filter_graph_clear_tasks); | ||
| 1041 | } | ||
| 706 | 1042 | ||
| 707 | gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, | 1043 | gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, |
| 708 | gtk_get_current_event_time()); | 1044 | gtk_get_current_event_time()); |
| @@ -785,6 +1121,7 @@ void kernel_shark(int argc, char **argv) | |||
| 785 | handle = NULL; | 1121 | handle = NULL; |
| 786 | 1122 | ||
| 787 | info->handle = handle; | 1123 | info->handle = handle; |
| 1124 | info->sync_task_filters = TRUE; | ||
| 788 | 1125 | ||
| 789 | /* --- Main window --- */ | 1126 | /* --- Main window --- */ |
| 790 | 1127 | ||
| @@ -891,6 +1228,25 @@ void kernel_shark(int argc, char **argv) | |||
| 891 | menu = gtk_menu_new(); /* Don't need to show menus */ | 1228 | menu = gtk_menu_new(); /* Don't need to show menus */ |
| 892 | 1229 | ||
| 893 | 1230 | ||
| 1231 | |||
| 1232 | /* --- Filter - Sync task Option --- */ | ||
| 1233 | |||
| 1234 | sub_item = gtk_menu_item_new_with_label("Unsync Graph and List Task Filters"); | ||
| 1235 | |||
| 1236 | info->task_sync_menu = sub_item; | ||
| 1237 | |||
| 1238 | /* Add them to the menu */ | ||
| 1239 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
| 1240 | |||
| 1241 | /* We can attach the Quit menu item to our exit function */ | ||
| 1242 | g_signal_connect (G_OBJECT (sub_item), "activate", | ||
| 1243 | G_CALLBACK (sync_task_filter_clicked), | ||
| 1244 | (gpointer) info); | ||
| 1245 | |||
| 1246 | /* We do need to show menu items */ | ||
| 1247 | gtk_widget_show(sub_item); | ||
| 1248 | |||
| 1249 | |||
| 894 | /* --- Filter - List Events Option --- */ | 1250 | /* --- Filter - List Events Option --- */ |
| 895 | 1251 | ||
| 896 | sub_item = gtk_menu_item_new_with_label("list events"); | 1252 | sub_item = gtk_menu_item_new_with_label("list events"); |
diff --git a/kernel-shark.h b/kernel-shark.h index edb3787..f931406 100644 --- a/kernel-shark.h +++ b/kernel-shark.h | |||
| @@ -30,10 +30,15 @@ struct shark_info { | |||
| 30 | struct tracecmd_input *handle; | 30 | struct tracecmd_input *handle; |
| 31 | GtkWidget *treeview; | 31 | GtkWidget *treeview; |
| 32 | GtkWidget *spin; | 32 | GtkWidget *spin; |
| 33 | GtkWidget *task_sync_menu; | ||
| 33 | struct graph_callbacks graph_cbs; | 34 | struct graph_callbacks graph_cbs; |
| 34 | gint selected_task; | 35 | gint selected_task; |
| 35 | gboolean list_filter_enabled; | 36 | gboolean list_filter_enabled; |
| 37 | gboolean list_filter_available; | ||
| 36 | gboolean graph_follows; | 38 | gboolean graph_follows; |
| 39 | gboolean sync_task_filters; | ||
| 40 | struct filter_task *list_task_filter; | ||
| 41 | struct filter_task *list_hide_tasks; | ||
| 37 | }; | 42 | }; |
| 38 | 43 | ||
| 39 | #define offset_of(type, field) (long)(&((type *)0)->field) | 44 | #define offset_of(type, field) (long)(&((type *)0)->field) |
diff --git a/trace-graph.c b/trace-graph.c index 9e5cd19..2bbe73f 100644 --- a/trace-graph.c +++ b/trace-graph.c | |||
| @@ -548,6 +548,20 @@ void trace_graph_clear_tasks(struct graph_info *ginfo) | |||
| 548 | redraw_graph(ginfo); | 548 | redraw_graph(ginfo); |
| 549 | } | 549 | } |
| 550 | 550 | ||
| 551 | void trace_graph_update_filters(struct graph_info *ginfo, | ||
| 552 | struct filter_task *task_filter, | ||
| 553 | struct filter_task *hide_tasks) | ||
| 554 | { | ||
| 555 | filter_task_hash_free(ginfo->task_filter); | ||
| 556 | filter_task_hash_free(ginfo->hide_tasks); | ||
| 557 | |||
| 558 | ginfo->task_filter = filter_task_hash_copy(task_filter); | ||
| 559 | ginfo->hide_tasks = filter_task_hash_copy(hide_tasks); | ||
| 560 | |||
| 561 | if (ginfo->filter_enabled) | ||
| 562 | redraw_graph(ginfo); | ||
| 563 | } | ||
| 564 | |||
| 551 | static void | 565 | static void |
| 552 | filter_clear_tasks_clicked (gpointer data) | 566 | filter_clear_tasks_clicked (gpointer data) |
| 553 | { | 567 | { |
diff --git a/trace-graph.h b/trace-graph.h index 916ad50..91194c1 100644 --- a/trace-graph.h +++ b/trace-graph.h | |||
| @@ -311,6 +311,9 @@ int trace_graph_load_filters(struct graph_info *ginfo, | |||
| 311 | struct tracecmd_xml_handle *handle); | 311 | struct tracecmd_xml_handle *handle); |
| 312 | int trace_graph_save_filters(struct graph_info *ginfo, | 312 | int trace_graph_save_filters(struct graph_info *ginfo, |
| 313 | struct tracecmd_xml_handle *handle); | 313 | struct tracecmd_xml_handle *handle); |
| 314 | void trace_graph_update_filters(struct graph_info *ginfo, | ||
| 315 | struct filter_task *task_filter, | ||
| 316 | struct filter_task *hide_tasks); | ||
| 314 | 317 | ||
| 315 | /* plots */ | 318 | /* plots */ |
| 316 | void trace_graph_plot_free(struct graph_info *ginfo); | 319 | void trace_graph_plot_free(struct graph_info *ginfo); |
diff --git a/trace-view-store.c b/trace-view-store.c index ba40aad..6f70ca5 100644 --- a/trace-view-store.c +++ b/trace-view-store.c | |||
| @@ -1330,7 +1330,6 @@ void trace_view_store_assign_filters(TraceViewStore *store, | |||
| 1330 | 1330 | ||
| 1331 | if (store->task_filter != task_filter) | 1331 | if (store->task_filter != task_filter) |
| 1332 | store->task_filter = filter_task_hash_copy(task_filter); | 1332 | store->task_filter = filter_task_hash_copy(task_filter); |
| 1333 | |||
| 1334 | } | 1333 | } |
| 1335 | 1334 | ||
| 1336 | 1335 | ||
