diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2010-01-07 23:02:50 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2010-01-07 23:02:50 -0500 |
| commit | 3c6228066478232d696fc7da7db2e1c7a3e29329 (patch) | |
| tree | 1d16951cb1774dab2d4ace773b509595723162e0 | |
| parent | 7b0139ebb1cfd673189c82ed565619480c1c3cf2 (diff) | |
trace-view: Add search feature
Add a search feature to search for matches in the list rows.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
| -rw-r--r-- | kernel-shark.c | 16 | ||||
| -rw-r--r-- | trace-view-main.c | 13 | ||||
| -rw-r--r-- | trace-view.c | 301 | ||||
| -rw-r--r-- | trace-view.h | 2 |
4 files changed, 319 insertions, 13 deletions
diff --git a/kernel-shark.c b/kernel-shark.c index 720833b..b0d2a19 100644 --- a/kernel-shark.c +++ b/kernel-shark.c | |||
| @@ -718,6 +718,18 @@ void kernel_shark(int argc, char **argv) | |||
| 718 | gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0); | 718 | gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0); |
| 719 | gtk_widget_show(spin); | 719 | gtk_widget_show(spin); |
| 720 | 720 | ||
| 721 | /* --- Search --- */ | ||
| 722 | |||
| 723 | /* The tree needs its columns loaded now */ | ||
| 724 | info->treeview = gtk_tree_view_new(); | ||
| 725 | trace_view_load(info->treeview, handle, spin); | ||
| 726 | |||
| 727 | label = gtk_label_new(" Search: "); | ||
| 728 | gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | ||
| 729 | gtk_widget_show(label); | ||
| 730 | |||
| 731 | trace_view_search_setup(GTK_BOX(hbox), GTK_TREE_VIEW(info->treeview)); | ||
| 732 | |||
| 721 | /* --- Top Level Trace View Paging Hbox --- */ | 733 | /* --- Top Level Trace View Paging Hbox --- */ |
| 722 | 734 | ||
| 723 | hbox = gtk_hbox_new(FALSE, 0); | 735 | hbox = gtk_hbox_new(FALSE, 0); |
| @@ -734,13 +746,9 @@ void kernel_shark(int argc, char **argv) | |||
| 734 | 746 | ||
| 735 | /* --- Set up Trace Tree --- */ | 747 | /* --- Set up Trace Tree --- */ |
| 736 | 748 | ||
| 737 | info->treeview = gtk_tree_view_new(); | ||
| 738 | |||
| 739 | g_signal_connect(info->treeview, "row-activated", | 749 | g_signal_connect(info->treeview, "row-activated", |
| 740 | (GCallback)row_double_clicked, info); | 750 | (GCallback)row_double_clicked, info); |
| 741 | 751 | ||
| 742 | trace_view_load(info->treeview, handle, spin); | ||
| 743 | |||
| 744 | gtk_container_add(GTK_CONTAINER(scrollwin), info->treeview); | 752 | gtk_container_add(GTK_CONTAINER(scrollwin), info->treeview); |
| 745 | 753 | ||
| 746 | gtk_signal_connect(GTK_OBJECT(info->treeview), "button_press_event", | 754 | gtk_signal_connect(GTK_OBJECT(info->treeview), "button_press_event", |
diff --git a/trace-view-main.c b/trace-view-main.c index 122cda8..c728646 100644 --- a/trace-view-main.c +++ b/trace-view-main.c | |||
| @@ -257,6 +257,17 @@ void trace_view(int argc, char **argv) | |||
| 257 | gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0); | 257 | gtk_box_pack_start(GTK_BOX(hbox), spin, FALSE, FALSE, 0); |
| 258 | gtk_widget_show(spin); | 258 | gtk_widget_show(spin); |
| 259 | 259 | ||
| 260 | /* --- Search --- */ | ||
| 261 | |||
| 262 | /* The tree needs its columns loaded now */ | ||
| 263 | trace_view_load(trace_tree, handle, spin); | ||
| 264 | |||
| 265 | label = gtk_label_new(" Search: "); | ||
| 266 | gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | ||
| 267 | gtk_widget_show(label); | ||
| 268 | |||
| 269 | trace_view_search_setup(GTK_BOX(hbox), GTK_TREE_VIEW(trace_tree)); | ||
| 270 | |||
| 260 | /* --- Top Level Hbox --- */ | 271 | /* --- Top Level Hbox --- */ |
| 261 | 272 | ||
| 262 | hbox = gtk_hbox_new(FALSE, 0); | 273 | hbox = gtk_hbox_new(FALSE, 0); |
| @@ -273,8 +284,6 @@ void trace_view(int argc, char **argv) | |||
| 273 | 284 | ||
| 274 | /* --- Set up Trace Tree --- */ | 285 | /* --- Set up Trace Tree --- */ |
| 275 | 286 | ||
| 276 | trace_view_load(trace_tree, handle, spin); | ||
| 277 | |||
| 278 | gtk_container_add(GTK_CONTAINER(scrollwin), trace_tree); | 287 | gtk_container_add(GTK_CONTAINER(scrollwin), trace_tree); |
| 279 | gtk_widget_show(trace_tree); | 288 | gtk_widget_show(trace_tree); |
| 280 | 289 | ||
diff --git a/trace-view.c b/trace-view.c index 8b98e48..90c01c7 100644 --- a/trace-view.c +++ b/trace-view.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | * | 18 | * |
| 19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 19 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 20 | */ | 20 | */ |
| 21 | #define _GNU_SOURCE | ||
| 21 | #include <stdio.h> | 22 | #include <stdio.h> |
| 22 | #include <string.h> | 23 | #include <string.h> |
| 23 | #include <stdarg.h> | 24 | #include <stdarg.h> |
| @@ -306,10 +307,20 @@ void trace_view_update_filters(GtkWidget *treeview, | |||
| 306 | trace_view_select(treeview, time); | 307 | trace_view_select(treeview, time); |
| 307 | } | 308 | } |
| 308 | 309 | ||
| 310 | static void select_row_from_path(GtkTreeView *tree, GtkTreePath *path) | ||
| 311 | { | ||
| 312 | GtkTreeSelection *selection; | ||
| 313 | |||
| 314 | selection = gtk_tree_view_get_selection(tree); | ||
| 315 | gtk_tree_selection_select_path(selection, path); | ||
| 316 | |||
| 317 | /* finally, make it visible */ | ||
| 318 | gtk_tree_view_scroll_to_cell(tree, path, NULL, TRUE, 0.5, 0.0); | ||
| 319 | } | ||
| 320 | |||
| 309 | void trace_view_select(GtkWidget *treeview, guint64 time) | 321 | void trace_view_select(GtkWidget *treeview, guint64 time) |
| 310 | { | 322 | { |
| 311 | GtkTreeView *tree = GTK_TREE_VIEW(treeview); | 323 | GtkTreeView *tree = GTK_TREE_VIEW(treeview); |
| 312 | GtkTreeSelection *selection; | ||
| 313 | GtkTreeModel *model; | 324 | GtkTreeModel *model; |
| 314 | GtkTreePath *path; | 325 | GtkTreePath *path; |
| 315 | gint select_page, page; | 326 | gint select_page, page; |
| @@ -351,12 +362,7 @@ void trace_view_select(GtkWidget *treeview, guint64 time) | |||
| 351 | snprintf(buf, 100, "%d", row); | 362 | snprintf(buf, 100, "%d", row); |
| 352 | printf("row = %s\n", buf); | 363 | printf("row = %s\n", buf); |
| 353 | path = gtk_tree_path_new_from_string(buf); | 364 | path = gtk_tree_path_new_from_string(buf); |
| 354 | 365 | select_row_from_path(tree, path); | |
| 355 | selection = gtk_tree_view_get_selection(tree); | ||
| 356 | gtk_tree_selection_select_path(selection, path); | ||
| 357 | |||
| 358 | /* finally, make it visible */ | ||
| 359 | gtk_tree_view_scroll_to_cell(tree, path, NULL, TRUE, 0.5, 0.0); | ||
| 360 | gtk_tree_path_free(path); | 366 | gtk_tree_path_free(path); |
| 361 | } | 367 | } |
| 362 | 368 | ||
| @@ -461,3 +467,284 @@ void trace_view_cpu_filter_callback(gboolean accept, | |||
| 461 | gtk_tree_view_set_model(trace_tree, GTK_TREE_MODEL(store)); | 467 | gtk_tree_view_set_model(trace_tree, GTK_TREE_MODEL(store)); |
| 462 | g_object_unref(store); | 468 | g_object_unref(store); |
| 463 | } | 469 | } |
| 470 | |||
| 471 | static GtkTreeModel *create_col_model(GtkTreeView *treeview) | ||
| 472 | { | ||
| 473 | GtkListStore *store; | ||
| 474 | GtkTreeViewColumn *col; | ||
| 475 | GtkTreeIter iter; | ||
| 476 | const gchar *title; | ||
| 477 | int i; | ||
| 478 | |||
| 479 | store = gtk_list_store_new(1, G_TYPE_STRING); | ||
| 480 | |||
| 481 | i = 0; | ||
| 482 | col = gtk_tree_view_get_column(treeview, i++); | ||
| 483 | while (col) { | ||
| 484 | title = gtk_tree_view_column_get_title(col); | ||
| 485 | if (!title) | ||
| 486 | break; | ||
| 487 | |||
| 488 | gtk_list_store_append(store, &iter); | ||
| 489 | gtk_list_store_set(store, &iter, | ||
| 490 | 0, title, | ||
| 491 | -1); | ||
| 492 | |||
| 493 | col = gtk_tree_view_get_column(treeview, i++); | ||
| 494 | } | ||
| 495 | |||
| 496 | return GTK_TREE_MODEL(store); | ||
| 497 | } | ||
| 498 | |||
| 499 | struct search_info { | ||
| 500 | GtkTreeView *treeview; | ||
| 501 | GtkWidget *entry; | ||
| 502 | GtkWidget *selection; | ||
| 503 | GtkWidget *column; | ||
| 504 | }; | ||
| 505 | |||
| 506 | #define SELECTION_NAMES \ | ||
| 507 | C( contains, CONTAINS ), \ | ||
| 508 | C( full match, FULL_MATCH ), \ | ||
| 509 | C( does not have, NOT_IN ) | ||
| 510 | |||
| 511 | #undef C | ||
| 512 | #define C(a, b) #a | ||
| 513 | |||
| 514 | static gchar *select_names[] = { SELECTION_NAMES, NULL }; | ||
| 515 | |||
| 516 | #undef C | ||
| 517 | #define C(a, b) SEL_##b | ||
| 518 | |||
| 519 | enum select_options { SELECTION_NAMES }; | ||
| 520 | |||
| 521 | static gboolean test_int(gint val, gint search_val, enum select_options sel) | ||
| 522 | { | ||
| 523 | gint tens; | ||
| 524 | gboolean match = TRUE; | ||
| 525 | |||
| 526 | switch (sel) { | ||
| 527 | case SEL_NOT_IN: | ||
| 528 | match = FALSE; | ||
| 529 | case SEL_CONTAINS: | ||
| 530 | for (tens = 1; search_val / tens; tens *= 10) | ||
| 531 | ; | ||
| 532 | |||
| 533 | while (val) { | ||
| 534 | if (val - search_val == (val / tens) * tens) | ||
| 535 | return match; | ||
| 536 | val /= 10; | ||
| 537 | } | ||
| 538 | return !match; | ||
| 539 | |||
| 540 | case SEL_FULL_MATCH: | ||
| 541 | return search_val == val; | ||
| 542 | } | ||
| 543 | return FALSE; | ||
| 544 | } | ||
| 545 | |||
| 546 | static gboolean test_text(const gchar *text, const gchar *search_text, enum select_options sel) | ||
| 547 | { | ||
| 548 | gboolean match = TRUE; | ||
| 549 | |||
| 550 | switch (sel) { | ||
| 551 | case SEL_NOT_IN: | ||
| 552 | match = FALSE; | ||
| 553 | case SEL_CONTAINS: | ||
| 554 | |||
| 555 | text = strcasestr(text, search_text); | ||
| 556 | if (text) | ||
| 557 | return match; | ||
| 558 | return !match; | ||
| 559 | |||
| 560 | case SEL_FULL_MATCH: | ||
| 561 | return strcmp(text, search_text) == 0; | ||
| 562 | } | ||
| 563 | return FALSE; | ||
| 564 | } | ||
| 565 | |||
| 566 | static void search_tree(gpointer dat | ||
