diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-02-17 11:18:44 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-02-17 11:18:44 -0500 |
commit | ca3d47c45d871007f734510748b660bd7d432a12 (patch) | |
tree | 5fd6abaac85a82ab215ce335fbdae7895572f618 | |
parent | 9c029f42a9a21654e27d612d614abd8d9866a317 (diff) |
trace-view: Add ability to show and delete advance filters
Add to the filter dialog the list of filters defined and a way
to delete those filters.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-filter.c | 223 | ||||
-rw-r--r-- | trace-filter.h | 8 | ||||
-rw-r--r-- | trace-view.c | 28 | ||||
-rw-r--r-- | trace-view.h | 1 | ||||
-rw-r--r-- | util.h | 14 |
5 files changed, 260 insertions, 14 deletions
diff --git a/trace-filter.c b/trace-filter.c index a431fa1..38ca58c 100644 --- a/trace-filter.c +++ b/trace-filter.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <gtk/gtk.h> | 21 | #include <gtk/gtk.h> |
22 | #include <stdlib.h> | 22 | #include <stdlib.h> |
23 | #include <string.h> | 23 | #include <string.h> |
24 | #include <ctype.h> | ||
24 | 25 | ||
25 | #include "trace-cmd.h" | 26 | #include "trace-cmd.h" |
26 | #include "trace-local.h" | 27 | #include "trace-local.h" |
@@ -28,12 +29,13 @@ | |||
28 | #include "trace-view.h" | 29 | #include "trace-view.h" |
29 | 30 | ||
30 | #include "cpu.h" | 31 | #include "cpu.h" |
32 | #include "util.h" | ||
31 | 33 | ||
32 | #define DIALOG_WIDTH 400 | 34 | #define DIALOG_WIDTH 400 |
33 | #define DIALOG_HEIGHT 600 | 35 | #define DIALOG_HEIGHT 600 |
34 | 36 | ||
35 | #define TEXT_DIALOG_WIDTH 400 | 37 | #define TEXT_DIALOG_WIDTH 400 |
36 | #define TEXT_DIALOG_HEIGHT 200 | 38 | #define TEXT_DIALOG_HEIGHT 400 |
37 | 39 | ||
38 | int str_cmp(const void *a, const void *b) | 40 | int str_cmp(const void *a, const void *b) |
39 | { | 41 | { |
@@ -62,10 +64,58 @@ struct dialog_helper { | |||
62 | 64 | ||
63 | struct adv_event_filter_helper { | 65 | struct adv_event_filter_helper { |
64 | trace_adv_filter_cb_func func; | 66 | trace_adv_filter_cb_func func; |
67 | GtkTreeView *view; | ||
65 | GtkWidget *entry; | 68 | GtkWidget *entry; |
66 | gpointer data; | 69 | gpointer data; |
67 | }; | 70 | }; |
68 | 71 | ||
72 | enum { | ||
73 | ADV_COL_DELETE, | ||
74 | ADV_COL_EVENT, | ||
75 | ADV_COL_FILTER, | ||
76 | ADV_COL_ID, | ||
77 | NUM_ADV_FILTER_COLS, | ||
78 | }; | ||
79 | |||
80 | static gint *get_event_ids(GtkTreeView *treeview) | ||
81 | { | ||
82 | GtkTreeModel *model; | ||
83 | GtkTreeIter iter; | ||
84 | gboolean active; | ||
85 | gint *ids = NULL; | ||
86 | gint id; | ||
87 | int count = 0; | ||
88 | |||
89 | model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); | ||
90 | if (!model) | ||
91 | return NULL; | ||
92 | |||
93 | if (!gtk_tree_model_iter_children(model, &iter, NULL)) | ||
94 | return NULL; | ||
95 | |||
96 | for (;;) { | ||
97 | gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, | ||
98 | ADV_COL_DELETE, &active, | ||
99 | ADV_COL_ID, &id, | ||
100 | -1); | ||
101 | |||
102 | if (active) { | ||
103 | if (count) | ||
104 | ids = realloc(ids, sizeof(*ids) * (count + 2)); | ||
105 | else | ||
106 | ids = malloc(sizeof(*ids) * 2); | ||
107 | ids[count] = id; | ||
108 | count++; | ||
109 | ids[count] = -1; | ||
110 | } | ||
111 | |||
112 | if (!gtk_tree_model_iter_next(model, &iter)) | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | return ids; | ||
117 | } | ||
118 | |||
69 | /* Callback for the clicked signal of the advanced filter button */ | 119 | /* Callback for the clicked signal of the advanced filter button */ |
70 | static void | 120 | static void |
71 | adv_filter_dialog_response (gpointer data, gint response_id) | 121 | adv_filter_dialog_response (gpointer data, gint response_id) |
@@ -73,14 +123,17 @@ adv_filter_dialog_response (gpointer data, gint response_id) | |||
73 | struct dialog_helper *helper = data; | 123 | struct dialog_helper *helper = data; |
74 | struct adv_event_filter_helper *event_helper = helper->data; | 124 | struct adv_event_filter_helper *event_helper = helper->data; |
75 | const gchar *text; | 125 | const gchar *text; |
126 | gint *event_ids; | ||
76 | 127 | ||
77 | switch (response_id) { | 128 | switch (response_id) { |
78 | case GTK_RESPONSE_ACCEPT: | 129 | case GTK_RESPONSE_ACCEPT: |
79 | text = gtk_entry_get_text(GTK_ENTRY(event_helper->entry)); | 130 | text = gtk_entry_get_text(GTK_ENTRY(event_helper->entry)); |
80 | event_helper->func(TRUE, text, event_helper->data); | 131 | event_ids = get_event_ids(event_helper->view); |
132 | event_helper->func(TRUE, text, event_ids, event_helper->data); | ||
133 | free(event_ids); | ||
81 | break; | 134 | break; |
82 | case GTK_RESPONSE_REJECT: | 135 | case GTK_RESPONSE_REJECT: |
83 | event_helper->func(FALSE, NULL, event_helper->data); | 136 | event_helper->func(FALSE, NULL, NULL, event_helper->data); |
84 | break; | 137 | break; |
85 | default: | 138 | default: |
86 | break; | 139 | break; |
@@ -92,6 +145,164 @@ adv_filter_dialog_response (gpointer data, gint response_id) | |||
92 | g_free(helper); | 145 | g_free(helper); |
93 | } | 146 | } |
94 | 147 | ||
148 | static GtkTreeModel * | ||
149 | create_tree_filter_model(struct tracecmd_input *handle, | ||
150 | struct event_filter *event_filter) | ||
151 | { | ||
152 | GtkTreeStore *treestore; | ||
153 | GtkTreeIter iter_events; | ||
154 | struct pevent *pevent; | ||
155 | struct event_format **events; | ||
156 | char *str; | ||
157 | gint i; | ||
158 | |||
159 | pevent = tracecmd_get_pevent(handle); | ||
160 | |||
161 | treestore = gtk_tree_store_new(NUM_ADV_FILTER_COLS, G_TYPE_BOOLEAN, | ||
162 | G_TYPE_STRING, G_TYPE_STRING, | ||
163 | G_TYPE_INT); | ||
164 | |||
165 | events = pevent_list_events(pevent, EVENT_SORT_SYSTEM); | ||
166 | if (!events) | ||
167 | return GTK_TREE_MODEL(treestore); | ||
168 | |||
169 | for (i = 0; events[i]; i++) { | ||
170 | str = pevent_filter_make_string(event_filter, events[i]->id); | ||
171 | if (!str) | ||
172 | continue; | ||
173 | |||
174 | /* We only want to show advanced filters */ | ||
175 | if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) { | ||
176 | free(str); | ||
177 | continue; | ||
178 | } | ||
179 | |||
180 | gtk_tree_store_append(treestore, &iter_events, NULL); | ||
181 | gtk_tree_store_set(treestore, &iter_events, | ||
182 | ADV_COL_DELETE, FALSE, | ||
183 | ADV_COL_EVENT, events[i]->name, | ||
184 | ADV_COL_FILTER, str, | ||
185 | ADV_COL_ID, events[i]->id, | ||
186 | -1); | ||
187 | free(str); | ||
188 | } | ||
189 | |||
190 | return GTK_TREE_MODEL(treestore); | ||
191 | } | ||
192 | |||
193 | #define DELETE_FILTER "Delete Filter" | ||
194 | |||
195 | static void adv_filter_cursor_changed(GtkTreeView *treeview, gpointer data) | ||
196 | { | ||
197 | GtkTreeViewColumn *col; | ||
198 | GtkTreeModel *model; | ||
199 | GtkTreePath *path; | ||
200 | GtkTreeIter iter; | ||
201 | gboolean active; | ||
202 | const gchar *title; | ||
203 | |||
204 | model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); | ||
205 | if (!model) | ||
206 | return; | ||
207 | |||
208 | gtk_tree_view_get_cursor(treeview, &path, &col); | ||
209 | if (!path) | ||
210 | return; | ||
211 | |||
212 | if (!col) | ||
213 | goto free; | ||
214 | |||
215 | title = gtk_tree_view_column_get_title(col); | ||
216 | |||
217 | if (strcmp(title, DELETE_FILTER) != 0) | ||
218 | goto free; | ||
219 | |||
220 | if (!gtk_tree_model_get_iter(model, &iter, path)) | ||
221 | goto free; | ||
222 | |||
223 | gtk_tree_model_get(model, &iter, | ||
224 | ADV_COL_DELETE, &active, | ||
225 | -1); | ||
226 | |||
227 | active = active ? FALSE : TRUE; | ||
228 | |||
229 | gtk_tree_store_set(GTK_TREE_STORE(model), &iter, | ||
230 | ADV_COL_DELETE, active, | ||
231 | -1); | ||
232 | |||
233 | free: | ||
234 | gtk_tree_path_free(path); | ||
235 | } | ||
236 | |||
237 | static GtkWidget * | ||
238 | create_adv_filter_view(struct tracecmd_input *handle, | ||
239 | struct event_filter *event_filter) | ||
240 | { | ||
241 | GtkTreeViewColumn *col; | ||
242 | GtkCellRenderer *renderer; | ||
243 | GtkCellRenderer *togrend; | ||
244 | GtkWidget *view; | ||
245 | GtkTreeModel *model; | ||
246 | |||
247 | view = gtk_tree_view_new(); | ||
248 | |||
249 | renderer = gtk_cell_renderer_text_new(); | ||
250 | |||
251 | togrend = gtk_cell_renderer_toggle_new(); | ||
252 | |||
253 | /* --- delete column --- */ | ||
254 | |||
255 | col = gtk_tree_view_column_new(); | ||
256 | |||
257 | gtk_tree_view_column_set_title(col, DELETE_FILTER); | ||
258 | |||
259 | gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); | ||
260 | |||
261 | gtk_tree_view_column_pack_start(col, togrend, FALSE); | ||
262 | gtk_tree_view_column_add_attribute(col, togrend, "active", ADV_COL_DELETE); | ||
263 | |||
264 | /* --- events column --- */ | ||
265 | |||
266 | col = gtk_tree_view_column_new(); | ||
267 | |||
268 | gtk_tree_view_column_set_title(col, "Event"); | ||
269 | |||
270 | gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); | ||
271 | |||
272 | gtk_tree_view_column_pack_start(col, renderer, FALSE); | ||
273 | |||
274 | gtk_tree_view_column_add_attribute(col, renderer, "text", ADV_COL_EVENT); | ||
275 | |||
276 | /* --- filter column --- */ | ||
277 | |||
278 | col = gtk_tree_view_column_new(); | ||
279 | |||
280 | gtk_tree_view_column_set_title(col, "Filter"); | ||
281 | |||
282 | gtk_tree_view_append_column(GTK_TREE_VIEW(view), col); | ||
283 | |||
284 | gtk_tree_view_column_pack_start(col, renderer, FALSE); | ||
285 | |||
286 | gtk_tree_view_column_add_attribute(col, renderer, "text", ADV_COL_FILTER); | ||
287 | |||
288 | |||
289 | model = create_tree_filter_model(handle, event_filter); | ||
290 | |||
291 | gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); | ||
292 | |||
293 | g_object_unref(model); | ||
294 | |||
295 | gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), | ||
296 | GTK_SELECTION_NONE); | ||
297 | |||
298 | |||
299 | g_signal_connect_swapped (view, "cursor-changed", | ||
300 | G_CALLBACK (adv_filter_cursor_changed), | ||
301 | (gpointer) view); | ||
302 | |||
303 | return view; | ||
304 | } | ||
305 | |||
95 | /** | 306 | /** |
96 | * trace_adv_filter_dialog - make dialog for text | 307 | * trace_adv_filter_dialog - make dialog for text |
97 | * @handle: the handle to the tracecmd data file | 308 | * @handle: the handle to the tracecmd data file |
@@ -110,6 +321,8 @@ void trace_adv_filter_dialog(struct tracecmd_input *handle, | |||
110 | GtkWidget *hbox; | 321 | GtkWidget *hbox; |
111 | GtkWidget *label; | 322 | GtkWidget *label; |
112 | GtkWidget *entry; | 323 | GtkWidget *entry; |
324 | GtkWidget *scrollwin; | ||
325 | GtkWidget *view; | ||
113 | 326 | ||
114 | helper = g_malloc(sizeof(*helper)); | 327 | helper = g_malloc(sizeof(*helper)); |
115 | g_assert(helper); | 328 | g_assert(helper); |
@@ -139,16 +352,14 @@ void trace_adv_filter_dialog(struct tracecmd_input *handle, | |||
139 | G_CALLBACK (adv_filter_dialog_response), | 352 | G_CALLBACK (adv_filter_dialog_response), |
140 | (gpointer) helper); | 353 | (gpointer) helper); |
141 | 354 | ||
142 | #if 0 | ||
143 | scrollwin = gtk_scrolled_window_new(NULL, NULL); | 355 | scrollwin = gtk_scrolled_window_new(NULL, NULL); |
144 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), | 356 | gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin), |
145 | GTK_POLICY_AUTOMATIC, | 357 | GTK_POLICY_AUTOMATIC, |
146 | GTK_POLICY_AUTOMATIC); | 358 | GTK_POLICY_AUTOMATIC); |
147 | view = create_event_list_view(handle, all_events, systems, events); | 359 | view = create_adv_filter_view(handle, event_filter); |
148 | event_helper->view = GTK_TREE_VIEW(view); | 360 | event_helper->view = GTK_TREE_VIEW(view); |
149 | gtk_container_add(GTK_CONTAINER(scrollwin), view); | 361 | gtk_container_add(GTK_CONTAINER(scrollwin), view); |
150 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0); | 362 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), scrollwin, TRUE, TRUE, 0); |
151 | #endif | ||
152 | 363 | ||
153 | hbox = gtk_hbox_new(FALSE, 0); | 364 | hbox = gtk_hbox_new(FALSE, 0); |
154 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0); | 365 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0); |
diff --git a/trace-filter.h b/trace-filter.h index 80a27ed..f4ee26d 100644 --- a/trace-filter.h +++ b/trace-filter.h | |||
@@ -32,12 +32,18 @@ struct event_filter_list { | |||
32 | * trace_adv_filter_cb_func - callback type for advanced filter dialog | 32 | * trace_adv_filter_cb_func - callback type for advanced filter dialog |
33 | * @accept: TRUE if the accept button was pressed, otherwise FALSE | 33 | * @accept: TRUE if the accept button was pressed, otherwise FALSE |
34 | * @text: The text that was entered | 34 | * @text: The text that was entered |
35 | * @delete_event_filters: The list of event ids for filters to remove | ||
35 | * @data: The data given passed in to the event dialog function | 36 | * @data: The data given passed in to the event dialog function |
36 | * | 37 | * |
37 | * If @accept is FALSE then @text should be ignored. @data is still valid. | 38 | * If @accept is FALSE then @text and @delete_event_filters |
39 | * should be ignored. @data is still valid. | ||
40 | * | ||
41 | * @text may be NULL or empty, and @delete_event_ids may also be NULL. | ||
42 | * @delete_event_ids if not NULL, then ends with -1 | ||
38 | */ | 43 | */ |
39 | typedef void (*trace_adv_filter_cb_func)(gboolean accept, | 44 | typedef void (*trace_adv_filter_cb_func)(gboolean accept, |
40 | const gchar *text, | 45 | const gchar *text, |
46 | gint *delete_event_filters, | ||
41 | gpointer data); | 47 | gpointer data); |
42 | 48 | ||
43 | /** | 49 | /** |
diff --git a/trace-view.c b/trace-view.c index 052160f..bcba484 100644 --- a/trace-view.c +++ b/trace-view.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "trace-view.h" | 30 | #include "trace-view.h" |
31 | #include "trace-compat.h" | 31 | #include "trace-compat.h" |
32 | #include "cpu.h" | 32 | #include "cpu.h" |
33 | #include "util.h" | ||
33 | 34 | ||
34 | enum { | 35 | enum { |
35 | COL_INDEX, | 36 | COL_INDEX, |
@@ -434,6 +435,7 @@ void trace_view_event_filter_callback(gboolean accept, | |||
434 | 435 | ||
435 | void trace_view_adv_filter_callback(gboolean accept, | 436 | void trace_view_adv_filter_callback(gboolean accept, |
436 | const gchar *text, | 437 | const gchar *text, |
438 | gint *event_ids, | ||
437 | gpointer data) | 439 | gpointer data) |
438 | { | 440 | { |
439 | struct event_filter *event_filter; | 441 | struct event_filter *event_filter; |
@@ -445,6 +447,7 @@ void trace_view_adv_filter_callback(gboolean accept, | |||
445 | guint64 time; | 447 | guint64 time; |
446 | gint row; | 448 | gint row; |
447 | int ret; | 449 | int ret; |
450 | int i; | ||
448 | 451 | ||
449 | if (!accept) | 452 | if (!accept) |
450 | return; | 453 | return; |
@@ -453,17 +456,28 @@ void trace_view_adv_filter_callback(gboolean accept, | |||
453 | if (!model) | 456 | if (!model) |
454 | return; | 457 | return; |
455 | 458 | ||
456 | store = TRACE_VIEW_STORE(model); | 459 | if (!has_text(text) && !event_ids) |
460 | return; | ||
457 | 461 | ||
458 | trace_view_store_clear_all_events_enabled(store); | 462 | store = TRACE_VIEW_STORE(model); |
459 | 463 | ||
460 | event_filter = trace_view_store_get_event_filter(store); | 464 | event_filter = trace_view_store_get_event_filter(store); |
461 | 465 | ||
462 | ret = pevent_filter_add_filter_str(event_filter, text, &error_str); | 466 | if (event_ids) { |
463 | if (ret < 0) { | 467 | for (i = 0; event_ids[i] >= 0; i++) |
464 | warning("filter failed due to: %s", error_str); | 468 | pevent_filter_remove_event(event_filter, event_ids[i]); |
465 | free(error_str); | 469 | } |
466 | return; | 470 | |
471 | if (has_text(text)) { | ||
472 | |||
473 | trace_view_store_clear_all_events_enabled(store); | ||
474 | |||
475 | ret = pevent_filter_add_filter_str(event_filter, text, &error_str); | ||
476 | if (ret < 0) { | ||
477 | warning("filter failed due to: %s", error_str); | ||
478 | free(error_str); | ||
479 | return; | ||
480 | } | ||
467 | } | 481 | } |
468 | 482 | ||
469 | /* Keep track of the currently selected row */ | 483 | /* Keep track of the currently selected row */ |
diff --git a/trace-view.h b/trace-view.h index f8b85ea..bbc05ce 100644 --- a/trace-view.h +++ b/trace-view.h | |||
@@ -49,6 +49,7 @@ void trace_view_event_filter_callback(gboolean accept, | |||
49 | 49 | ||
50 | void trace_view_adv_filter_callback(gboolean accept, | 50 | void trace_view_adv_filter_callback(gboolean accept, |
51 | const gchar *text, | 51 | const gchar *text, |
52 | gint *event_ids, | ||
52 | gpointer data); | 53 | gpointer data); |
53 | 54 | ||
54 | void trace_view_cpu_filter_callback(gboolean accept, | 55 | void trace_view_cpu_filter_callback(gboolean accept, |
@@ -47,4 +47,18 @@ static inline char *strim(char *string) | |||
47 | return ret; | 47 | return ret; |
48 | } | 48 | } |
49 | 49 | ||
50 | static inline int has_text(const char *text) | ||
51 | { | ||
52 | if (!text) | ||
53 | return 0; | ||
54 | |||
55 | while (*text) { | ||
56 | if (!isspace(*text)) | ||
57 | return 1; | ||
58 | text++; | ||
59 | } | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
50 | #endif | 64 | #endif |