From 39b1cdf4a8e7e256420a1dc8769d8849f185fe3b Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 16 Feb 2010 22:13:47 -0500 Subject: 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 --- trace-filter.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ trace-filter.h | 17 ++++++++ trace-view-main.c | 38 ++++++++++++++++++ trace-view.c | 46 ++++++++++++++++++++++ trace-view.h | 4 ++ 5 files changed, 218 insertions(+) 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 @@ #define DIALOG_WIDTH 400 #define DIALOG_HEIGHT 600 +#define TEXT_DIALOG_WIDTH 400 +#define TEXT_DIALOG_HEIGHT 200 + int str_cmp(const void *a, const void *b) { char * const * sa = a; @@ -57,6 +60,116 @@ struct dialog_helper { gpointer data; }; +struct adv_event_filter_helper { + trace_adv_filter_cb_func func; + GtkWidget *entry; + gpointer data; +}; + +/* Callback for the clicked signal of the advanced filter button */ +static void +adv_filter_dialog_response (gpointer data, gint response_id) +{ + struct dialog_helper *helper = data; + struct adv_event_filter_helper *event_helper = helper->data; + const gchar *text; + + switch (response_id) { + case GTK_RESPONSE_ACCEPT: + text = gtk_entry_get_text(GTK_ENTRY(event_helper->entry)); + event_helper->func(TRUE, text, event_helper->data); + break; + case GTK_RESPONSE_REJECT: + event_helper->func(FALSE, NULL, event_helper->data); + break; + default: + break; + }; + + gtk_widget_destroy(GTK_WIDGET(helper->dialog)); + + g_free(event_helper); + g_free(helper); +} + +/** + * trace_adv_filter_dialog - make dialog for text + * @handle: the handle to the tracecmd data file + * @event_filter: advanced filters + * @func: The function to call when accept or cancel is pressed + * @data: data to pass to the function @func + */ +void trace_adv_filter_dialog(struct tracecmd_input *handle, + struct event_filter *event_filter, + trace_adv_filter_cb_func func, + gpointer data) +{ + struct dialog_helper *helper; + struct adv_event_filter_helper *event_helper; + GtkWidget *dialog; + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *entry; + + helper = g_malloc(sizeof(*helper)); + g_assert(helper); + + /* --- Make dialog window --- */ + + dialog = gtk_dialog_new_with_buttons("Advanced Filters", + NULL, + GTK_DIALOG_MODAL, + "Apply", + GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, + NULL); + + event_helper = g_new0(typeof(*event_helper), 1); + g_assert(event_helper); + + helper->dialog = dialog; + helper->data = event_helper; + + event_helper->func = func; + event_helper->data = data; + + /* We can attach the Quit menu item to our exit function */ + g_signal_connect_swapped (dialog, "response", + G_CALLBACK (adv_filter_dialog_response), + (gpointer) helper); + +#if 0 + scrollwin = gtk_scrolled_window_new(NULL, NULL); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + view = create_event_list_view(handle, all_events, systems, events); + event_helper->view = GTK_TREE_VIEW(view); + gtk_container_add(GTK_CONTAINER(scrollwin), view); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0); +#endif + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0); + gtk_widget_show(hbox); + + label = gtk_label_new("Filter:"); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_widget_show(label); + + entry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); + gtk_widget_show(entry); + + event_helper->entry = entry; + + gtk_widget_set_size_request(GTK_WIDGET(dialog), + TEXT_DIALOG_WIDTH, TEXT_DIALOG_HEIGHT); + + gtk_widget_show_all(dialog); +} + enum { COL_EVENT, COL_ACTIVE, diff --git a/trace-filter.h b/trace-filter.h index 73bdb67..80a27ed 100644 --- a/trace-filter.h +++ b/trace-filter.h @@ -28,6 +28,18 @@ struct event_filter_list { struct event *event; }; +/** + * trace_adv_filter_cb_func - callback type for advanced filter dialog + * @accept: TRUE if the accept button was pressed, otherwise FALSE + * @text: The text that was entered + * @data: The data given passed in to the event dialog function + * + * If @accept is FALSE then @text should be ignored. @data is still valid. + */ +typedef void (*trace_adv_filter_cb_func)(gboolean accept, + const gchar *text, + gpointer data); + /** * trace_filter_event_cb_func - callback type for event dialog * @accept: TRUE if the accept button was pressed, otherwise FALSE @@ -47,6 +59,11 @@ typedef void (*trace_filter_event_cb_func)(gboolean accept, gint *events, gpointer data); +void trace_adv_filter_dialog(struct tracecmd_input *handle, + struct event_filter *event_filter, + trace_adv_filter_cb_func func, + gpointer data); + void trace_filter_event_dialog(struct tracecmd_input *handle, gboolean all_events, 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) free(events); } +/* Callback for the clicked signal of the Advanced filter button */ +static void +adv_filter_clicked (gpointer data) +{ + struct trace_tree_info *info = data; + struct event_filter *event_filter; + GtkTreeView *trace_tree = GTK_TREE_VIEW(info->trace_tree); + GtkTreeModel *model; + TraceViewStore *store; + + model = gtk_tree_view_get_model(trace_tree); + if (!model) + return; + + store = TRACE_VIEW_STORE(model); + + event_filter = trace_view_store_get_event_filter(store); + + trace_adv_filter_dialog(store->handle, event_filter, + trace_view_adv_filter_callback, trace_tree); +} + /* Callback for the clicked signal of the CPUs filter button */ static void cpus_clicked (gpointer data) @@ -293,6 +315,22 @@ void trace_view(int argc, char **argv) gtk_widget_show(sub_item); + /* --- Filter - Advanced Events Option --- */ + + sub_item = gtk_menu_item_new_with_label("advanced event filter"); + + /* Add them to the menu */ + gtk_menu_shell_append(GTK_MENU_SHELL (menu), sub_item); + + /* We can attach the Quit menu item to our exit function */ + g_signal_connect_swapped (G_OBJECT (sub_item), "activate", + G_CALLBACK (adv_filter_clicked), + (gpointer) &tree_info); + + /* We do need to show menu items */ + gtk_widget_show(sub_item); + + /* --- Filter - CPUs Option --- */ 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, trace_view_select(GTK_WIDGET(trace_tree), time); } +void trace_view_adv_filter_callback(gboolean accept, + const gchar *text, + gpointer data) +{ + struct event_filter *event_filter; + GtkTreeView *trace_tree = data; + GtkTreeModel *model; + TraceViewStore *store; + TraceViewRecord *vrec; + char *error_str; + guint64 time; + gint row; + + if (!accept) + return; + + model = gtk_tree_view_get_model(trace_tree); + if (!model) + return; + + store = TRACE_VIEW_STORE(model); + + trace_view_store_clear_all_events_enabled(store); + + event_filter = trace_view_store_get_event_filter(store); + + pevent_filter_add_filter_str(event_filter, text, &error_str); + + /* Keep track of the currently selected row */ + row = trace_view_get_selected_row(GTK_WIDGET(trace_tree)); + if (row >= 0) { + vrec = trace_view_store_get_row(store, row); + time = vrec->timestamp; + } + + /* Force an update */ + g_object_ref(store); + gtk_tree_view_set_model(trace_tree, NULL); + trace_view_store_update_filter(store); + gtk_tree_view_set_model(trace_tree, GTK_TREE_MODEL(store)); + g_object_unref(store); + + if (row >= 0) + trace_view_select(GTK_WIDGET(trace_tree), time); +} + void trace_view_cpu_filter_callback(gboolean accept, gboolean all_cpus, 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, gint *events, gpointer data); +void trace_view_adv_filter_callback(gboolean accept, + const gchar *text, + gpointer data); + void trace_view_cpu_filter_callback(gboolean accept, gboolean all_cpus, guint64 *selected_cpu_mask, -- cgit v1.2.2