aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-02-17 11:18:44 -0500
committerSteven Rostedt <rostedt@goodmis.org>2010-02-17 11:18:44 -0500
commitca3d47c45d871007f734510748b660bd7d432a12 (patch)
tree5fd6abaac85a82ab215ce335fbdae7895572f618
parent9c029f42a9a21654e27d612d614abd8d9866a317 (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.c223
-rw-r--r--trace-filter.h8
-rw-r--r--trace-view.c28
-rw-r--r--trace-view.h1
-rw-r--r--util.h14
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
38int str_cmp(const void *a, const void *b) 40int str_cmp(const void *a, const void *b)
39{ 41{
@@ -62,10 +64,58 @@ struct dialog_helper {
62 64
63struct adv_event_filter_helper { 65struct 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
72enum {
73 ADV_COL_DELETE,
74 ADV_COL_EVENT,
75 ADV_COL_FILTER,
76 ADV_COL_ID,
77 NUM_ADV_FILTER_COLS,
78};
79
80static 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 */
70static void 120static void
71adv_filter_dialog_response (gpointer data, gint response_id) 121adv_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
148static GtkTreeModel *
149create_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
195static 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
237static GtkWidget *
238create_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 */
39typedef void (*trace_adv_filter_cb_func)(gboolean accept, 44typedef 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
34enum { 35enum {
35 COL_INDEX, 36 COL_INDEX,
@@ -434,6 +435,7 @@ void trace_view_event_filter_callback(gboolean accept,
434 435
435void trace_view_adv_filter_callback(gboolean accept, 436void 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
50void trace_view_adv_filter_callback(gboolean accept, 50void 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
54void trace_view_cpu_filter_callback(gboolean accept, 55void trace_view_cpu_filter_callback(gboolean accept,
diff --git a/util.h b/util.h
index 342cfa1..2bb9fe6 100644
--- a/util.h
+++ b/util.h
@@ -47,4 +47,18 @@ static inline char *strim(char *string)
47 return ret; 47 return ret;
48} 48}
49 49
50static 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