diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-02-16 22:13:47 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-02-16 22:13:47 -0500 |
commit | 39b1cdf4a8e7e256420a1dc8769d8849f185fe3b (patch) | |
tree | 0eb94a11f58a204a9c228fc07da60b146172ff1d | |
parent | ad813ef9fb16cf4510be274a04dfb37c9fadf6e3 (diff) |
trace-cmd: Add advanced filtering
Add a "Advanced event filter" option that opens a text dialog
that lets you write an advanced filter.
This is still very primitive and needs to be cleaned up.
Not only that, it needs to show previous filters.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-filter.c | 113 | ||||
-rw-r--r-- | trace-filter.h | 17 | ||||
-rw-r--r-- | trace-view-main.c | 38 | ||||
-rw-r--r-- | trace-view.c | 46 | ||||
-rw-r--r-- | trace-view.h | 4 |
5 files changed, 218 insertions, 0 deletions
diff --git a/trace-filter.c b/trace-filter.c index 7e5d37d..a431fa1 100644 --- a/trace-filter.c +++ b/trace-filter.c | |||
@@ -32,6 +32,9 @@ | |||
32 | #define DIALOG_WIDTH 400 | 32 | #define DIALOG_WIDTH 400 |
33 | #define DIALOG_HEIGHT 600 | 33 | #define DIALOG_HEIGHT 600 |
34 | 34 | ||
35 | #define TEXT_DIALOG_WIDTH 400 | ||
36 | #define TEXT_DIALOG_HEIGHT 200 | ||
37 | |||
35 | int str_cmp(const void *a, const void *b) | 38 | int str_cmp(const void *a, const void *b) |
36 | { | 39 | { |
37 | char * const * sa = a; | 40 | char * const * sa = a; |
@@ -57,6 +60,116 @@ struct dialog_helper { | |||
57 | gpointer data; | 60 | gpointer data; |
58 | }; | 61 | }; |
59 | 62 | ||
63 | struct adv_event_filter_helper { | ||
64 | trace_adv_filter_cb_func func; | ||
65 | GtkWidget *entry; | ||
66 | gpointer data; | ||
67 | }; | ||
68 | |||
69 | /* Callback for the clicked signal of the advanced filter button */ | ||
70 | static void | ||
71 | adv_filter_dialog_response (gpointer data, gint response_id) | ||
72 | { | ||
73 | struct dialog_helper *helper = data; | ||
74 | struct adv_event_filter_helper *event_helper = helper->data; | ||
75 | const gchar *text; | ||
76 | |||
77 | switch (response_id) { | ||
78 | case GTK_RESPONSE_ACCEPT: | ||
79 | text = gtk_entry_get_text(GTK_ENTRY(event_helper->entry)); | ||
80 | event_helper->func(TRUE, text, event_helper->data); | ||
81 | break; | ||
82 | case GTK_RESPONSE_REJECT: | ||
83 | event_helper->func(FALSE, NULL, event_helper->data); | ||
84 | break; | ||
85 | default: | ||
86 | break; | ||
87 | }; | ||
88 | |||
89 | gtk_widget_destroy(GTK_WIDGET(helper->dialog)); | ||
90 | |||
91 | g_free(event_helper); | ||
92 | g_free(helper); | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * trace_adv_filter_dialog - make dialog for text | ||
97 | * @handle: the handle to the tracecmd data file | ||
98 | * @event_filter: advanced filters | ||
99 | * @func: The function to call when accept or cancel is pressed | ||
100 | * @data: data to pass to the function @func | ||
101 | */ | ||
102 | void trace_adv_filter_dialog(struct tracecmd_input *handle, | ||
103 | struct event_filter *event_filter, | ||
104 | trace_adv_filter_cb_func func, | ||
105 | gpointer data) | ||
106 | { | ||
107 | struct dialog_helper *helper; | ||
108 | struct adv_event_filter_helper *event_helper; | ||
109 | GtkWidget *dialog; | ||
110 | GtkWidget *hbox; | ||
111 | GtkWidget *label; | ||
112 | GtkWidget *entry; | ||
113 | |||
114 | helper = g_malloc(sizeof(*helper)); | ||
115 | g_assert(helper); | ||
116 | |||
117 | /* --- Make dialog window --- */ | ||
118 | |||
119 | dialog = gtk_dialog_new_with_buttons("Advanced Filters", | ||
120 | NULL, | ||
121 | GTK_DIALOG_MODAL, | ||
122 | "Apply", | ||
123 | GTK_RESPONSE_ACCEPT, | ||
124 | GTK_STOCK_CANCEL, | ||
125 | GTK_RESPONSE_REJECT, | ||
126 | NULL); | ||
127 | |||
128 | event_helper = g_new0(typeof(*event_helper), 1); | ||
129 | g_assert(event_helper); | ||
130 | |||
131 | helper->dialog = dialog; | ||
132 | helper->data = event_helper; | ||
133 | |||
134 | event_helper->func = func; | ||
135 | event_helper->data = data; | ||
136 | |||
137 | /* We can attach the Quit menu item to our exit function */ | ||
138 | g_signal_connect_swapped (dialog, "response", | ||
139 | G_CALLBACK (adv_filter_dialog_response), | ||
140 | (gpointer) helper); | ||
141 | |||
142 | #if 0 | ||
143 | scrollwin = gtk_scrolled_window_new(NULL, NULL); | ||
144 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), | ||
145 | GTK_POLICY_AUTOMATIC, | ||
146 | GTK_POLICY_AUTOMATIC); | ||
147 | view = create_event_list_view(handle, all_events, systems, events); | ||
148 | event_helper->view = GTK_TREE_VIEW(view); | ||
149 | gtk_container_add(GTK_CONTAINER(scrollwin), view); | ||
150 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0); | ||
151 | #endif | ||
152 | |||
153 | hbox = gtk_hbox_new(FALSE, 0); | ||
154 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0); | ||
155 | gtk_widget_show(hbox); | ||
156 | |||
157 | label = gtk_label_new("Filter:"); | ||
158 | gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | ||
159 | gtk_widget_show(label); | ||
160 | |||
161 | entry = gtk_entry_new(); | ||
162 | gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); | ||
163 | gtk_widget_show(entry); | ||
164 | |||
165 | event_helper->entry = entry; | ||
166 | |||
167 | gtk_widget_set_size_request(GTK_WIDGET(dialog), | ||
168 | TEXT_DIALOG_WIDTH, TEXT_DIALOG_HEIGHT); | ||
169 | |||
170 | gtk_widget_show_all(dialog); | ||
171 | } | ||
172 | |||
60 | enum { | 173 | enum { |
61 | COL_EVENT, | 174 | COL_EVENT, |
62 | COL_ACTIVE, | 175 | COL_ACTIVE, |
diff --git a/trace-filter.h b/trace-filter.h index 73bdb67..80a27ed 100644 --- a/trace-filter.h +++ b/trace-filter.h | |||
@@ -29,6 +29,18 @@ struct event_filter_list { | |||
29 | }; | 29 | }; |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * trace_adv_filter_cb_func - callback type for advanced filter dialog | ||
33 | * @accept: TRUE if the accept button was pressed, otherwise FALSE | ||
34 | * @text: The text that was entered | ||
35 | * @data: The data given passed in to the event dialog function | ||
36 | * | ||
37 | * If @accept is FALSE then @text should be ignored. @data is still valid. | ||
38 | */ | ||
39 | typedef void (*trace_adv_filter_cb_func)(gboolean accept, | ||
40 | const gchar *text, | ||
41 | gpointer data); | ||
42 | |||
43 | /** | ||
32 | * trace_filter_event_cb_func - callback type for event dialog | 44 | * trace_filter_event_cb_func - callback type for event dialog |
33 | * @accept: TRUE if the accept button was pressed, otherwise FALSE | 45 | * @accept: TRUE if the accept button was pressed, otherwise FALSE |
34 | * @all_events: TRUE if "All Events" was checked | 46 | * @all_events: TRUE if "All Events" was checked |
@@ -47,6 +59,11 @@ typedef void (*trace_filter_event_cb_func)(gboolean accept, | |||
47 | gint *events, | 59 | gint *events, |
48 | gpointer data); | 60 | gpointer data); |
49 | 61 | ||
62 | void trace_adv_filter_dialog(struct tracecmd_input *handle, | ||
63 | struct event_filter *event_filter, | ||
64 | trace_adv_filter_cb_func func, | ||
65 | gpointer data); | ||
66 | |||
50 | void trace_filter_event_dialog(struct tracecmd_input *handle, | 67 | void trace_filter_event_dialog(struct tracecmd_input *handle, |
51 | gboolean all_events, | 68 | gboolean all_events, |
52 | gchar **systems, | 69 | gchar **systems, |
diff --git a/trace-view-main.c b/trace-view-main.c index 2bbfd42..268726c 100644 --- a/trace-view-main.c +++ b/trace-view-main.c | |||
@@ -126,6 +126,28 @@ events_clicked (gpointer data) | |||
126 | free(events); | 126 | free(events); |
127 | } | 127 | } |
128 | 128 | ||
129 | /* Callback for the clicked signal of the Advanced filter button */ | ||
130 | static void | ||
131 | adv_filter_clicked (gpointer data) | ||
132 | { | ||
133 | struct trace_tree_info *info = data; | ||
134 | struct event_filter *event_filter; | ||
135 | GtkTreeView *trace_tree = GTK_TREE_VIEW(info->trace_tree); | ||
136 | GtkTreeModel *model; | ||
137 | TraceViewStore *store; | ||
138 | |||
139 | model = gtk_tree_view_get_model(trace_tree); | ||
140 | if (!model) | ||
141 | return; | ||
142 | |||
143 | store = TRACE_VIEW_STORE(model); | ||
144 | |||
145 | event_filter = trace_view_store_get_event_filter(store); | ||
146 | |||
147 | trace_adv_filter_dialog(store->handle, event_filter, | ||
148 | trace_view_adv_filter_callback, trace_tree); | ||
149 | } | ||
150 | |||
129 | /* Callback for the clicked signal of the CPUs filter button */ | 151 | /* Callback for the clicked signal of the CPUs filter button */ |
130 | static void | 152 | static void |
131 | cpus_clicked (gpointer data) | 153 | cpus_clicked (gpointer data) |
@@ -293,6 +315,22 @@ void trace_view(int argc, char **argv) | |||
293 | gtk_widget_show(sub_item); | 315 | gtk_widget_show(sub_item); |
294 | 316 | ||
295 | 317 | ||
318 | /* --- Filter - Advanced Events Option --- */ | ||
319 | |||
320 | sub_item = gtk_menu_item_new_with_label("advanced event filter"); | ||
321 | |||
322 | /* Add them to the menu */ | ||
323 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); | ||
324 | |||
325 | /* We can attach the Quit menu item to our exit function */ | ||
326 | g_signal_connect_swapped (G_OBJECT (sub_item), "activate", | ||
327 | G_CALLBACK (adv_filter_clicked), | ||
328 | (gpointer) &tree_info); | ||
329 | |||
330 | /* We do need to show menu items */ | ||
331 | gtk_widget_show(sub_item); | ||
332 | |||
333 | |||
296 | /* --- Filter - CPUs Option --- */ | 334 | /* --- Filter - CPUs Option --- */ |
297 | 335 | ||
298 | sub_item = gtk_menu_item_new_with_label("CPUs"); | 336 | sub_item = gtk_menu_item_new_with_label("CPUs"); |
diff --git a/trace-view.c b/trace-view.c index 5de5f51..13fdb7e 100644 --- a/trace-view.c +++ b/trace-view.c | |||
@@ -432,6 +432,52 @@ void trace_view_event_filter_callback(gboolean accept, | |||
432 | trace_view_select(GTK_WIDGET(trace_tree), time); | 432 | trace_view_select(GTK_WIDGET(trace_tree), time); |
433 | } | 433 | } |
434 | 434 | ||
435 | void trace_view_adv_filter_callback(gboolean accept, | ||
436 | const gchar *text, | ||
437 | gpointer data) | ||
438 | { | ||
439 | struct event_filter *event_filter; | ||
440 | GtkTreeView *trace_tree = data; | ||
441 | GtkTreeModel *model; | ||
442 | TraceViewStore *store; | ||
443 | TraceViewRecord *vrec; | ||
444 | char *error_str; | ||
445 | guint64 time; | ||
446 | gint row; | ||
447 | |||
448 | if (!accept) | ||
449 | return; | ||
450 | |||
451 | model = gtk_tree_view_get_model(trace_tree); | ||
452 | if (!model) | ||
453 | return; | ||
454 | |||
455 | store = TRACE_VIEW_STORE(model); | ||
456 | |||
457 | trace_view_store_clear_all_events_enabled(store); | ||
458 | |||
459 | event_filter = trace_view_store_get_event_filter(store); | ||
460 | |||
461 | pevent_filter_add_filter_str(event_filter, text, &error_str); | ||
462 | |||
463 | /* Keep track of the currently selected row */ | ||
464 | row = trace_view_get_selected_row(GTK_WIDGET(trace_tree)); | ||
465 | if (row >= 0) { | ||
466 | vrec = trace_view_store_get_row(store, row); | ||
467 | time = vrec->timestamp; | ||
468 | } | ||
469 | |||
470 | /* Force an update */ | ||
471 | g_object_ref(store); | ||
472 | gtk_tree_view_set_model(trace_tree, NULL); | ||
473 | trace_view_store_update_filter(store); | ||
474 | gtk_tree_view_set_model(trace_tree, GTK_TREE_MODEL(store)); | ||
475 | g_object_unref(store); | ||
476 | |||
477 | if (row >= 0) | ||
478 | trace_view_select(GTK_WIDGET(trace_tree), time); | ||
479 | } | ||
480 | |||
435 | void trace_view_cpu_filter_callback(gboolean accept, | 481 | void trace_view_cpu_filter_callback(gboolean accept, |
436 | gboolean all_cpus, | 482 | gboolean all_cpus, |
437 | guint64 *selected_cpu_mask, | 483 | guint64 *selected_cpu_mask, |
diff --git a/trace-view.h b/trace-view.h index 6f1357b..f8b85ea 100644 --- a/trace-view.h +++ b/trace-view.h | |||
@@ -47,6 +47,10 @@ void trace_view_event_filter_callback(gboolean accept, | |||
47 | gint *events, | 47 | gint *events, |
48 | gpointer data); | 48 | gpointer data); |
49 | 49 | ||
50 | void trace_view_adv_filter_callback(gboolean accept, | ||
51 | const gchar *text, | ||
52 | gpointer data); | ||
53 | |||
50 | void trace_view_cpu_filter_callback(gboolean accept, | 54 | void trace_view_cpu_filter_callback(gboolean accept, |
51 | gboolean all_cpus, | 55 | gboolean all_cpus, |
52 | guint64 *selected_cpu_mask, | 56 | guint64 *selected_cpu_mask, |