diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-04-05 17:28:12 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-04-09 11:56:18 -0400 |
commit | 81b404df1d425f146527dc3da253365071e68bea (patch) | |
tree | b5d1c23d118f41505e7c896837ef27bf489c5e9c | |
parent | b2a9cd2f38f6c3c30e9ef4c47eb004b41b50fe5e (diff) |
trace-view: Add pop-up task menu for filtering tasks
Add pop-up menu over the rows that will allow to filter on tasks
in trace-view.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-view-main.c | 227 |
1 files changed, 214 insertions, 13 deletions
diff --git a/trace-view-main.c b/trace-view-main.c index 22b9e32..74922fb 100644 --- a/trace-view-main.c +++ b/trace-view-main.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "trace-view.h" | 30 | #include "trace-view.h" |
31 | #include "trace-xml.h" | 31 | #include "trace-xml.h" |
32 | #include "trace-gui.h" | 32 | #include "trace-gui.h" |
33 | #include "trace-compat.h" | ||
33 | 34 | ||
34 | #define version "0.1.1" | 35 | #define version "0.1.1" |
35 | 36 | ||
@@ -40,8 +41,13 @@ | |||
40 | static char *input_file; | 41 | static char *input_file; |
41 | 42 | ||
42 | struct trace_tree_info { | 43 | struct trace_tree_info { |
43 | GtkWidget *trace_tree; | 44 | struct tracecmd_input *handle; |
44 | GtkWidget *spin; | 45 | GtkWidget *trace_tree; |
46 | GtkWidget *spin; | ||
47 | gint filter_enabled; | ||
48 | gint filter_task_selected; | ||
49 | struct filter_task *task_filter; | ||
50 | struct filter_task *hide_tasks; | ||
45 | }; | 51 | }; |
46 | 52 | ||
47 | void usage(char *prog) | 53 | void usage(char *prog) |
@@ -68,6 +74,7 @@ load_clicked (gpointer data) | |||
68 | trace_view_reload(info->trace_tree, handle, info->spin); | 74 | trace_view_reload(info->trace_tree, handle, info->spin); |
69 | /* Free handle when freeing the trace tree */ | 75 | /* Free handle when freeing the trace tree */ |
70 | tracecmd_close(handle); | 76 | tracecmd_close(handle); |
77 | info->handle = handle; | ||
71 | } | 78 | } |
72 | g_free(filename); | 79 | g_free(filename); |
73 | } | 80 | } |
@@ -203,24 +210,209 @@ cpus_clicked (gpointer data) | |||
203 | trace_view_cpu_filter_callback, trace_tree); | 210 | trace_view_cpu_filter_callback, trace_tree); |
204 | } | 211 | } |
205 | 212 | ||
206 | #if 0 | 213 | static void |
207 | static GtkTreeModel * | 214 | filter_list_clicked (gpointer data) |
208 | create_combo_box_model(void) | 215 | { |
216 | struct trace_tree_info *info = data; | ||
217 | |||
218 | if (!filter_task_count(info->task_filter) && | ||
219 | !filter_task_count(info->hide_tasks)) | ||
220 | return; | ||
221 | |||
222 | info->filter_enabled ^= 1; | ||
223 | |||
224 | if (info->filter_enabled) | ||
225 | trace_view_update_filters(info->trace_tree, | ||
226 | info->task_filter, | ||
227 | info->hide_tasks); | ||
228 | else | ||
229 | trace_view_update_filters(info->trace_tree, NULL, NULL); | ||
230 | } | ||
231 | |||
232 | static void update_task_filter(struct trace_tree_info *info, | ||
233 | struct filter_task *filter) | ||
234 | { | ||
235 | struct filter_task_item *task; | ||
236 | gint pid = info->filter_task_selected; | ||
237 | |||
238 | task = filter_task_find_pid(filter, pid); | ||
239 | |||
240 | if (task) | ||
241 | filter_task_remove_pid(filter, pid); | ||
242 | else | ||
243 | filter_task_add_pid(filter, pid); | ||
244 | |||
245 | if (info->filter_enabled) | ||
246 | trace_view_update_filters(info->trace_tree, | ||
247 | info->task_filter, | ||
248 | info->hide_tasks); | ||
249 | } | ||
250 | |||
251 | static void filter_add_task_clicked(gpointer data) | ||
252 | { | ||
253 | struct trace_tree_info *info = data; | ||
254 | |||
255 | update_task_filter(info, info->task_filter); | ||
256 | } | ||
257 | |||
258 | static void filter_hide_task_clicked(gpointer data) | ||
209 | { | 259 | { |
210 | GtkListStore *store; | 260 | struct trace_tree_info *info = data; |
211 | GtkTreeIter iter; | ||
212 | 261 | ||
213 | store = gtk_list_store_new(1, G_TYPE_STRING); | 262 | update_task_filter(info, info->hide_tasks); |
214 | gtk_list_store_append(store, &iter); | 263 | } |
215 | gtk_list_store_set(store, &iter, 0, "1", -1); | 264 | |
265 | static void | ||
266 | filter_clear_tasks_clicked (gpointer data) | ||
267 | { | ||
268 | struct trace_tree_info *info = data; | ||
216 | 269 | ||
217 | return GTK_TREE_MODEL(store); | 270 | trace_view_update_filters(info->trace_tree, NULL, NULL); |
271 | info->filter_enabled = 0; | ||
272 | } | ||
273 | |||
274 | static gboolean | ||
275 | do_tree_popup(GtkWidget *widget, GdkEventButton *event, gpointer data) | ||
276 | { | ||
277 | struct trace_tree_info *info = data; | ||
278 | static GtkWidget *menu; | ||
279 | static GtkWidget *menu_filter_enable; | ||
280 | static GtkWidget *menu_filter_add_task; | ||
281 | static GtkWidget *menu_filter_hide_task; | ||
282 | static GtkWidget *menu_filter_clear_tasks; | ||
283 | struct pevent *pevent; | ||
284 | struct record *record; | ||
285 | TraceViewRecord *vrec; | ||
286 | GtkTreeModel *model; | ||
287 | const char *comm; | ||
288 | gchar *text; | ||
289 | gint pid; | ||
290 | gint len; | ||
291 | guint64 offset; | ||
292 | gint row; | ||
293 | gint cpu; | ||
294 | |||
295 | if (!menu) { | ||
296 | menu = gtk_menu_new(); | ||
297 | |||
298 | menu_filter_enable = gtk_menu_item_new_with_label("Enable Filter"); | ||
299 | gtk_widget_show(menu_filter_enable); | ||
300 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_enable); | ||
301 | |||
302 | g_signal_connect_swapped (G_OBJECT (menu_filter_enable), "activate", | ||
303 | G_CALLBACK (filter_list_clicked), | ||
304 | data); | ||
305 | |||
306 | menu_filter_add_task = gtk_menu_item_new_with_label("Add Task"); | ||
307 | gtk_widget_show(menu_filter_add_task); | ||
308 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_add_task); | ||
309 | |||
310 | g_signal_connect_swapped (G_OBJECT (menu_filter_add_task), "activate", | ||
311 | G_CALLBACK (filter_add_task_clicked), | ||
312 | data); | ||
313 | |||
314 | menu_filter_hide_task = gtk_menu_item_new_with_label("Hide Task"); | ||
315 | gtk_widget_show(menu_filter_hide_task); | ||
316 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_hide_task); | ||
317 | |||
318 | g_signal_connect_swapped (G_OBJECT (menu_filter_hide_task), "activate", | ||
319 | G_CALLBACK (filter_hide_task_clicked), | ||
320 | data); | ||
321 | |||
322 | menu_filter_clear_tasks = gtk_menu_item_new_with_label("Clear Task Filter"); | ||
323 | gtk_widget_show(menu_filter_clear_tasks); | ||
324 | gtk_menu_shell_append(GTK_MENU_SHELL (menu), menu_filter_clear_tasks); | ||
325 | |||
326 | g_signal_connect_swapped (G_OBJECT (menu_filter_clear_tasks), "activate", | ||
327 | G_CALLBACK (filter_clear_tasks_clicked), | ||
328 | data); | ||
329 | |||
330 | } | ||
331 | |||
332 | row = trace_view_get_selected_row(GTK_WIDGET(info->trace_tree)); | ||
333 | if (row >= 0) { | ||
334 | |||
335 | model = gtk_tree_view_get_model(GTK_TREE_VIEW(info->trace_tree)); | ||
336 | vrec = trace_view_store_get_row(TRACE_VIEW_STORE(model), row); | ||
337 | offset = vrec->offset; | ||
338 | |||
339 | record = tracecmd_read_at(info->handle, offset, &cpu); | ||
340 | |||
341 | if (record) { | ||
342 | pevent = tracecmd_get_pevent(info->handle); | ||
343 | pid = pevent_data_pid(pevent, record); | ||
344 | comm = pevent_data_comm_from_pid(pevent, pid); | ||
345 | |||
346 | len = strlen(comm) + 50; | ||
347 | |||
348 | text = g_malloc(len); | ||
349 | g_assert(text); | ||
350 | |||
351 | if (filter_task_find_pid(info->task_filter, pid)) | ||
352 | snprintf(text, len, "Remove %s-%d to filter", comm, pid); | ||
353 | else | ||
354 | snprintf(text, len, "Add %s-%d to filter", comm, pid); | ||
355 | |||
356 | info->filter_task_selected = pid; | ||
357 | |||
358 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_add_task), | ||
359 | text); | ||
360 | |||
361 | if (filter_task_find_pid(info->hide_tasks, pid)) | ||
362 | snprintf(text, len, "Show %s-%d", comm, pid); | ||
363 | else | ||
364 | snprintf(text, len, "Hide %s-%d", comm, pid); | ||
365 | |||
366 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_hide_task), | ||
367 | text); | ||
368 | |||
369 | g_free(text); | ||
370 | |||
371 | info->filter_task_selected = pid; | ||
372 | |||
373 | gtk_widget_show(menu_filter_add_task); | ||
374 | gtk_widget_show(menu_filter_hide_task); | ||
375 | free_record(record); | ||
376 | } | ||
377 | } else { | ||
378 | gtk_widget_hide(menu_filter_add_task); | ||
379 | gtk_widget_hide(menu_filter_hide_task); | ||
380 | } | ||
381 | |||
382 | if (info->filter_enabled) | ||
383 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_enable), | ||
384 | "Disable List Filter"); | ||
385 | else | ||
386 | gtk_menu_item_set_label(GTK_MENU_ITEM(menu_filter_enable), | ||
387 | "Enable List Filter"); | ||
388 | |||
389 | if (filter_task_count(info->task_filter) || | ||
390 | filter_task_count(info->hide_tasks)) { | ||
391 | gtk_widget_set_sensitive(menu_filter_clear_tasks, TRUE); | ||
392 | gtk_widget_set_sensitive(menu_filter_enable, TRUE); | ||
393 | } else { | ||
394 | gtk_widget_set_sensitive(menu_filter_clear_tasks, FALSE); | ||
395 | gtk_widget_set_sensitive(menu_filter_enable, FALSE); | ||
396 | } | ||
397 | |||
398 | gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, | ||
399 | gtk_get_current_event_time()); | ||
400 | |||
401 | return TRUE; | ||
402 | } | ||
403 | |||
404 | static gboolean | ||
405 | button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data) | ||
406 | { | ||
407 | if (event->button == 3) | ||
408 | return do_tree_popup(widget, event, data); | ||
409 | |||
410 | return FALSE; | ||
218 | } | 411 | } |
219 | #endif | ||
220 | 412 | ||
221 | void trace_view(int argc, char **argv) | 413 | void trace_view(int argc, char **argv) |
222 | { | 414 | { |
223 | static struct tracecmd_input *handle; | 415 | static struct tracecmd_input *handle = NULL; |
224 | struct trace_tree_info tree_info; | 416 | struct trace_tree_info tree_info; |
225 | struct stat st; | 417 | struct stat st; |
226 | GtkWidget *trace_tree; | 418 | GtkWidget *trace_tree; |
@@ -268,6 +460,11 @@ void trace_view(int argc, char **argv) | |||
268 | if (input_file) | 460 | if (input_file) |
269 | handle = tracecmd_open(input_file); | 461 | handle = tracecmd_open(input_file); |
270 | 462 | ||
463 | memset(&tree_info, 0, sizeof(tree_info)); | ||
464 | tree_info.handle = handle; | ||
465 | tree_info.task_filter = filter_task_hash_alloc(); | ||
466 | tree_info.hide_tasks = filter_task_hash_alloc(); | ||
467 | |||
271 | /* --- Main window --- */ | 468 | /* --- Main window --- */ |
272 | 469 | ||
273 | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | 470 | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
@@ -455,6 +652,10 @@ void trace_view(int argc, char **argv) | |||
455 | gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | 652 | gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); |
456 | gtk_widget_show(label); | 653 | gtk_widget_show(label); |
457 | 654 | ||
655 | gtk_signal_connect(GTK_OBJECT(trace_tree), "button_press_event", | ||
656 | (GtkSignalFunc) button_press_event, | ||
657 | (gpointer) &tree_info); | ||
658 | |||
458 | trace_view_search_setup(GTK_BOX(hbox), GTK_TREE_VIEW(trace_tree)); | 659 | trace_view_search_setup(GTK_BOX(hbox), GTK_TREE_VIEW(trace_tree)); |
459 | 660 | ||
460 | /* --- Top Level Hbox --- */ | 661 | /* --- Top Level Hbox --- */ |