aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-01-07 23:02:50 -0500
committerSteven Rostedt <rostedt@goodmis.org>2010-01-07 23:02:50 -0500
commit3c6228066478232d696fc7da7db2e1c7a3e29329 (patch)
tree1d16951cb1774dab2d4ace773b509595723162e0
parent7b0139ebb1cfd673189c82ed565619480c1c3cf2 (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.c16
-rw-r--r--trace-view-main.c13
-rw-r--r--trace-view.c301
-rw-r--r--trace-view.h2
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
310static 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
309void trace_view_select(GtkWidget *treeview, guint64 time) 321void 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
471static 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
499struct 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
514static gchar *select_names[] = { SELECTION_NAMES, NULL };
515
516#undef C
517#define C(a, b) SEL_##b
518
519enum select_options { SELECTION_NAMES };
520
521static 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
546static 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
566static void search_tree(gpointer data)
567{
568 struct search_info *info = data;
569 GtkTreePath *path;
570 GtkTreeViewColumn *col;
571 GtkTreeModel *model;
572 TraceViewStore *store;
573 GtkTreeIter iter;
574 GtkEntry *entry = GTK_ENTRY(info->entry);
575 GtkComboBox *col_combo = GTK_COMBO_BOX(info->column);
576 GtkComboBox *sel_combo = GTK_COMBO_BOX(info->selection);
577 const gchar *title;
578 gint val;
579 gchar *text = NULL;
580 const gchar *search_text;
581 gint col_num;
582 gint sel;
583 gint search_val;
584 gint start_row;
585 gboolean found = FALSE;
586
587 col_num = gtk_combo_box_get_active(col_combo);
588 sel = gtk_combo_box_get_active(sel_combo);
589
590 if (col_num >= TRACE_VIEW_STORE_N_COLUMNS)
591 return;
592
593 search_text = gtk_entry_get_text(entry);
594 if (!search_text || !strlen(search_text))
595 return;
596
597 col = gtk_tree_view_get_column(info->treeview, col_num);
598 if (!col)
599 return;
600
601 title = gtk_tree_view_column_get_title(col);
602 if (!title)
603 return;
604
605 model = gtk_tree_view_get_model(info->treeview);
606 store = TRACE_VIEW_STORE(model);
607
608 if (!trace_view_store_visible_rows(store))
609 return;
610
611 start_row = trace_view_get_selected_row(GTK_WIDGET(info->treeview));
612 if (start_row < 0)
613 start_row = 0;
614
615 if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, start_row))
616 return;
617
618 search_val = atoi(search_text);
619 while (gtk_tree_model_iter_next(model, &iter)) {
620 switch (col_num) {
621 case TRACE_VIEW_STORE_COL_INDEX:
622 case TRACE_VIEW_STORE_COL_CPU:
623 case TRACE_VIEW_STORE_COL_PID:
624 /* integers */
625
626 gtk_tree_model_get(model, &iter,
627 col_num, &val,
628 -1);
629 if (test_int(val, search_val, sel))
630 found = TRUE;
631 break;
632
633 case TRACE_VIEW_STORE_COL_TS:
634 case TRACE_VIEW_STORE_COL_COMM:
635 case TRACE_VIEW_STORE_COL_LAT:
636 case TRACE_VIEW_STORE_COL_EVENT:
637 case TRACE_VIEW_STORE_COL_INFO:
638 /* strings */
639
640 gtk_tree_model_get(model, &iter,
641 col_num, &text,
642 -1);
643
644 if (test_text(text, search_text, sel))
645 found = TRUE;
646 break;
647 }
648
649 if (found)
650 break;
651 }
652
653
654 if (!found) {
655 printf("NOT FOUND!\n");
656 /* show pop up */
657 return;
658 }
659
660 path = gtk_tree_model_get_path(model, &iter);
661 select_row_from_path(info->treeview, path);
662 gtk_tree_path_free(path);
663}
664
665void trace_view_search_setup(GtkBox *box, GtkTreeView *treeview)
666{
667 GtkCellRenderer *renderer;
668 GtkListStore *store;
669 GtkTreeModel *model;
670 GtkTreeIter iter;
671 GtkWidget *label;
672 GtkWidget *col_combo;
673 GtkWidget *sel_combo;
674 GtkWidget *entry;
675 gchar **selects = select_names;
676 int i;
677 struct search_info *info;
678
679 renderer = gtk_cell_renderer_text_new();
680
681 info = g_new0(typeof(*info), 1);
682 info->treeview = treeview;
683
684 label = gtk_label_new("Column: ");
685 gtk_box_pack_start(box, label, FALSE, FALSE, 0);
686 gtk_widget_show(label);
687
688 /* --- Set up the column selection combo box --- */
689
690 model = create_col_model(treeview);
691
692 col_combo = gtk_combo_box_new_with_model(model);
693 gtk_box_pack_start(box, col_combo, FALSE, FALSE, 0);
694 gtk_widget_show(col_combo);
695
696 /* Free model with combobox */
697 g_object_unref(model);
698
699 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(col_combo),
700 renderer,
701 TRUE);
702 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(col_combo),
703 renderer,
704 "text", 0,
705 NULL);
706
707 gtk_combo_box_set_active(GTK_COMBO_BOX(col_combo), 0);
708
709 info->column = col_combo;
710
711 /* --- Set up the column selection combo box --- */
712
713 store = gtk_list_store_new(1, G_TYPE_STRING);
714 model = GTK_TREE_MODEL(store);
715
716 sel_combo = gtk_combo_box_new_with_model(model);
717 gtk_box_pack_start(box, sel_combo, FALSE, FALSE, 0);
718 gtk_widget_show(sel_combo);
719
720 info->selection = sel_combo;
721
722 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(sel_combo),
723 renderer,
724 TRUE);
725 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(sel_combo),
726 renderer,
727 "text", 0,
728 NULL);
729
730 for (i = 0; selects[i]; i++ ) {
731 gtk_list_store_append(store, &iter);
732 gtk_list_store_set(store, &iter,
733 0, selects[i],
734 -1);
735 }
736
737 gtk_combo_box_set_active(GTK_COMBO_BOX(sel_combo), 0);
738
739 /* --- The text entry --- */
740
741 entry = gtk_entry_new();
742 gtk_box_pack_start(box, entry, FALSE, FALSE, 0);
743 gtk_widget_show(entry);
744
745 info->entry = entry;
746
747 g_signal_connect_swapped (entry, "activate",
748 G_CALLBACK (search_tree),
749 (gpointer) info);
750}
diff --git a/trace-view.h b/trace-view.h
index b637d82..291fa0d 100644
--- a/trace-view.h
+++ b/trace-view.h
@@ -29,4 +29,6 @@ void trace_view_cpu_filter_callback(gboolean accept,
29 guint64 *selected_cpu_mask, 29 guint64 *selected_cpu_mask,
30 gpointer data); 30 gpointer data);
31 31
32void trace_view_search_setup(GtkBox *box, GtkTreeView *treeview);
33
32#endif /* _TRACE_VIEW_H */ 34#endif /* _TRACE_VIEW_H */