gui filter module is now nearly finished
[lttv.git] / ltt / branches / poly / lttv / modules / gui / filter / filter.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Simon Bouvier-Zappa
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19 #include <glib.h>
20 #include <string.h>
21 #include <gtk/gtk.h>
22 #include <gdk/gdk.h>
23
24 #include <lttv/lttv.h>
25 #include <lttv/module.h>
26 #include <lttv/hook.h>
27 #include <lttv/filter.h>
28
29 #include <lttvwindow/lttvwindow.h>
30 #include <lttvwindow/lttvwindowtraces.h>
31
32 #include "hGuiFilterInsert.xpm"
33
34 /*
35 * TODO
36 * - connect the gui filter to the core filter
37 */
38
39 typedef struct _FilterViewerData FilterViewerData;
40 typedef struct _FilterViewerDataLine FilterViewerDataLine;
41
42 /*
43 * Prototypes
44 */
45 GtkWidget *guifilter_get_widget(FilterViewerData *fvd);
46 FilterViewerData *gui_filter(Tab *tab);
47 void gui_filter_destructor(FilterViewerData *fvd);
48 FilterViewerDataLine* gui_filter_add_line(FilterViewerData *fvd);
49 void gui_filter_line_set_visible(FilterViewerDataLine *fvdl, gboolean v);
50 void gui_filter_line_reset(FilterViewerDataLine *fvdl);
51 gboolean filter_traceset_changed(void * hook_data, void * call_data);
52 gboolean filter_viewer_data(void * hook_data, void * call_data);
53 GtkWidget* h_guifilter(Tab *tab);
54 void filter_destroy_walk(gpointer data, gpointer user_data);
55
56 /*
57 * Callback functions
58 */
59 void callback_process_button(GtkWidget *widget, gpointer data);
60 void callback_add_button(GtkWidget *widget, gpointer data);
61 void callback_logical_op_box(GtkWidget *widget, gpointer data);
62 void callback_expression_field(GtkWidget *widget, gpointer data);
63
64 struct _FilterViewerDataLine {
65 int row;
66 gboolean visible;
67 GtkWidget *f_logical_op_box;
68 GtkWidget *f_struct_box;
69 GtkWidget *f_subfield_box;
70 GtkWidget *f_math_op_box;
71 GtkWidget *f_value_field;
72 };
73
74 /**
75 * @struct _FilterViewerData
76 * Main struct for the filter gui module
77 */
78 struct _FilterViewerData {
79 Tab *tab;
80
81 GtkWidget *f_main_box;
82
83 GtkWidget *f_hbox1;
84 GtkWidget *f_hbox2;
85
86 GtkWidget *f_expression_field;
87 GtkWidget *f_process_button;
88
89 GtkWidget *f_logical_op_junction_box;
90
91 int rows;
92 GPtrArray *f_lines;
93
94 GtkWidget *f_add_button;
95
96 GtkWidget *f_textwnd;
97 GtkWidget *f_selectwnd;
98 GtkWidget *f_treewnd;
99
100 };
101
102 /**
103 * This function returns the current main widget
104 * used by this module
105 * @param fvd the module struct
106 * @return The main widget
107 */
108 GtkWidget
109 *guifilter_get_widget(FilterViewerData *fvd)
110 {
111 return fvd->f_main_box;
112 }
113
114 /**
115 * Constructor is used to create FilterViewerData data structure.
116 * @param the tab structure used by the widget
117 * @return The Filter viewer data created.
118 */
119 FilterViewerData*
120 gui_filter(Tab *tab)
121 {
122 g_print("filter::gui_filter()");
123
124 GtkCellRenderer *renderer;
125 GtkTreeViewColumn *column;
126
127 FilterViewerData* fvd = g_new(FilterViewerData,1);
128
129 fvd->tab = tab;
130
131 lttvwindow_register_traceset_notify(fvd->tab,
132 filter_traceset_changed,
133 filter_viewer_data);
134 // request_background_data(filter_viewer_data);
135
136 /*
137 * Initiating GtkTable layout
138 * starts with 2 rows and 5 columns and
139 * expands when expressions added
140 */
141 fvd->f_main_box = gtk_table_new(3,6,FALSE);
142 gtk_table_set_row_spacings(GTK_TABLE(fvd->f_main_box),5);
143 gtk_table_set_col_spacings(GTK_TABLE(fvd->f_main_box),5);
144
145 /*
146 * First half of the filter window
147 * - textual entry of filter expression
148 * - processing button
149 */
150 fvd->f_expression_field = gtk_entry_new(); //gtk_scrolled_window_new (NULL, NULL);
151 // gtk_entry_set_text(GTK_ENTRY(fvd->f_expression_field),"state.cpu>0");
152 gtk_widget_show (fvd->f_expression_field);
153
154 g_signal_connect (G_OBJECT (fvd->f_expression_field), "changed",
155 G_CALLBACK (callback_expression_field), (gpointer) fvd);
156
157 fvd->f_process_button = gtk_button_new_with_label("Process");
158 gtk_widget_show (fvd->f_process_button);
159
160 g_signal_connect (G_OBJECT (fvd->f_process_button), "clicked",
161 G_CALLBACK (callback_process_button), (gpointer) fvd);
162
163 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvd->f_expression_field,0,5,0,1,GTK_FILL,GTK_FILL,0,0);
164 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvd->f_process_button,5,6,0,1,GTK_FILL,GTK_FILL,0,0);
165
166
167
168 /*
169 * Second half of the filter window
170 * - combo boxes featuring filtering options added to the expression
171 */
172 fvd->f_add_button = gtk_button_new_with_label("Add Expression");
173 gtk_widget_show (fvd->f_add_button);
174
175 g_signal_connect (G_OBJECT (fvd->f_add_button), "clicked",
176 G_CALLBACK (callback_add_button), (gpointer) fvd);
177
178 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvd->f_add_button,5,6,1,2,GTK_FILL,GTK_FILL,0,0);
179
180 fvd->f_logical_op_junction_box = gtk_combo_box_new_text();
181 gtk_combo_box_append_text (GTK_COMBO_BOX (fvd->f_logical_op_junction_box), "");
182 gtk_combo_box_append_text (GTK_COMBO_BOX (fvd->f_logical_op_junction_box), "&");
183 gtk_combo_box_append_text (GTK_COMBO_BOX (fvd->f_logical_op_junction_box), "|");
184 gtk_combo_box_append_text (GTK_COMBO_BOX (fvd->f_logical_op_junction_box), "^");
185 gtk_combo_box_append_text (GTK_COMBO_BOX (fvd->f_logical_op_junction_box), "!");
186 //gtk_widget_show(fvd->f_logical_op_box);
187
188 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvd->f_logical_op_junction_box,0,1,1,2,GTK_SHRINK,GTK_FILL,0,0);
189
190 /* initialize a new line */
191 fvd->f_lines = g_ptr_array_new();
192 fvd->rows = 1;
193 FilterViewerDataLine* fvdl = gui_filter_add_line(fvd);
194 g_ptr_array_add(fvd->f_lines,(gpointer) fvdl);
195
196 /*
197 * show main container
198 */
199 gtk_widget_show(fvd->f_main_box);
200
201
202 g_object_set_data_full(
203 G_OBJECT(guifilter_get_widget(fvd)),
204 "filter_viewer_data",
205 fvd,
206 (GDestroyNotify)gui_filter_destructor);
207
208
209 return fvd;
210 }
211
212 /**
213 * Adds a filter option line on the module tab
214 * @param fvd The filter module structure
215 * @return The line structure
216 */
217 FilterViewerDataLine*
218 gui_filter_add_line(FilterViewerData* fvd) {
219
220 FilterViewerDataLine* fvdl = g_new(FilterViewerDataLine,1);
221
222 fvdl->row = fvd->rows;
223 fvdl->visible = TRUE;
224
225 fvdl->f_struct_box = gtk_combo_box_new_text();
226 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_struct_box), "");
227 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_struct_box), "event");
228 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_struct_box), "tracefile");
229 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_struct_box), "trace");
230 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_struct_box), "state");
231 gtk_widget_show(fvdl->f_struct_box);
232
233 fvdl->f_subfield_box = gtk_combo_box_new_text();
234 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "");
235 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "name");
236 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "category");
237 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "time");
238 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "tsc");
239 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "pid");
240 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "ppid");
241 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "creation time");
242 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "insertion time");
243 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "process name");
244 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "execution mode");
245 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "execution submode");
246 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "process status");
247 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_subfield_box), "cpu");
248 gtk_widget_show(fvdl->f_subfield_box);
249
250 fvdl->f_math_op_box = gtk_combo_box_new_text();
251 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_math_op_box), "");
252 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_math_op_box), "=");
253 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_math_op_box), "!=");
254 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_math_op_box), "<");
255 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_math_op_box), "<=");
256 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_math_op_box), ">");
257 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_math_op_box), ">=");
258 gtk_widget_show(fvdl->f_math_op_box);
259
260 fvdl->f_value_field = gtk_entry_new();
261 gtk_widget_show(fvdl->f_value_field);
262
263 fvdl->f_logical_op_box = gtk_combo_box_new_text();
264 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_logical_op_box), "");
265 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_logical_op_box), "&");
266 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_logical_op_box), "|");
267 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_logical_op_box), "^");
268 gtk_combo_box_append_text (GTK_COMBO_BOX (fvdl->f_logical_op_box), "!");
269 gtk_widget_show(fvdl->f_logical_op_box);
270
271 gtk_widget_set_events(fvdl->f_logical_op_box,
272 GDK_ENTER_NOTIFY_MASK |
273 GDK_LEAVE_NOTIFY_MASK |
274 GDK_FOCUS_CHANGE_MASK);
275
276 g_signal_connect (G_OBJECT (fvdl->f_logical_op_box), "changed",
277 G_CALLBACK (callback_logical_op_box), (gpointer) fvd);
278
279 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvdl->f_struct_box,0,1,fvd->rows+1,fvd->rows+2,GTK_SHRINK,GTK_FILL,0,0);
280 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvdl->f_subfield_box,1,2,fvd->rows+1,fvd->rows+2,GTK_SHRINK,GTK_FILL,0,0);
281 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvdl->f_math_op_box,2,3,fvd->rows+1,fvd->rows+2,GTK_SHRINK,GTK_FILL,0,0);
282 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvdl->f_value_field,3,4,fvd->rows+1,fvd->rows+2,GTK_SHRINK,GTK_FILL,0,0);
283 gtk_table_attach( GTK_TABLE(fvd->f_main_box),fvdl->f_logical_op_box,4,5,fvd->rows+1,fvd->rows+2,GTK_SHRINK,GTK_FILL,0,0);
284
285 return fvdl;
286 }
287
288 void gui_filter_line_set_visible(FilterViewerDataLine *fvdl, gboolean v) {
289
290 fvdl->visible = v;
291 if(v) {
292 gtk_widget_show(fvdl->f_struct_box);
293 gtk_widget_show(fvdl->f_subfield_box);
294 gtk_widget_show(fvdl->f_math_op_box);
295 gtk_widget_show(fvdl->f_value_field);
296 gtk_widget_show(fvdl->f_logical_op_box);
297 } else {
298 gtk_widget_hide(fvdl->f_struct_box);
299 gtk_widget_hide(fvdl->f_subfield_box);
300 gtk_widget_hide(fvdl->f_math_op_box);
301 gtk_widget_hide(fvdl->f_value_field);
302 gtk_widget_hide(fvdl->f_logical_op_box);
303 }
304
305 }
306
307 void gui_filter_line_reset(FilterViewerDataLine *fvdl) {
308
309 gtk_combo_box_set_active(GTK_COMBO_BOX(fvdl->f_struct_box),0);
310 gtk_combo_box_set_active(GTK_COMBO_BOX(fvdl->f_subfield_box),0);
311 gtk_combo_box_set_active(GTK_COMBO_BOX(fvdl->f_math_op_box),0);
312 gtk_entry_set_text(GTK_COMBO_BOX(fvdl->f_value_field),"");
313 gtk_combo_box_set_active(GTK_COMBO_BOX(fvdl->f_logical_op_box),0);
314 }
315
316 /**
317 * Destructor for the filter gui module
318 * @param fvd The module structure
319 */
320 void
321 gui_filter_destructor(FilterViewerData *fvd)
322 {
323 Tab *tab = fvd->tab;
324
325 /* May already been done by GTK window closing */
326 if(GTK_IS_WIDGET(guifilter_get_widget(fvd))){
327 g_info("widget still exists");
328 }
329 if(tab != NULL) {
330 lttvwindow_unregister_traceset_notify(fvd->tab,
331 filter_traceset_changed,
332 filter_viewer_data);
333 }
334 lttvwindowtraces_background_notify_remove(fvd);
335
336 g_free(fvd);
337 }
338
339 /**
340 * Hook function
341 * @param hook_data The hook data
342 * @param call_data The call data
343 * @return Success/Failure of operation
344 */
345 gboolean
346 filter_traceset_changed(void * hook_data, void * call_data) {
347
348 return FALSE;
349 }
350
351 /**
352 * Hook function
353 * @param hook_data The hook data
354 * @param call_data The call data
355 * @return Success/Failure of operation
356 */
357 gboolean
358 filter_viewer_data(void * hook_data, void * call_data) {
359
360 return FALSE;
361 }
362
363 /**
364 * Filter Module's constructor hook
365 *
366 * This constructor is given as a parameter to the menuitem and toolbar button
367 * registration. It creates the list.
368 * @param tab A pointer to the parent window.
369 * @return The widget created.
370 */
371 GtkWidget *
372 h_guifilter(Tab *tab)
373 {
374 FilterViewerData* f = gui_filter(tab) ;
375
376 g_print("FilterViewerData:%p\n",f);
377 if(f)
378 return guifilter_get_widget(f);
379 else return NULL;
380
381 }
382
383 /**
384 * This function initializes the Filter Viewer functionnality through the
385 * gtkTraceSet API.
386 */
387 static void init() {
388
389 lttvwindow_register_constructor("guifilter",
390 "/",
391 "Insert Filter Module",
392 hGuiFilterInsert_xpm,
393 "Insert Filter Module",
394 h_guifilter);
395 }
396
397 /**
398 * Initiate the destruction of the current gui module
399 * on the GTK Interface
400 */
401 void filter_destroy_walk(gpointer data, gpointer user_data)
402 {
403 FilterViewerData *fvd = (FilterViewerData*)data;
404
405 g_debug("CFV.c : filter_destroy_walk, %p", fvd);
406 /* May already have been done by GTK window closing */
407 if(GTK_IS_WIDGET(guifilter_get_widget(fvd)))
408 gtk_widget_destroy(guifilter_get_widget(fvd));
409 }
410
411 /**
412 * plugin's destroy function
413 *
414 * This function releases the memory reserved by the module and unregisters
415 * everything that has been registered in the gtkTraceSet API.
416 */
417 static void destroy() {
418
419 lttvwindow_unregister_constructor(h_guifilter);
420
421 }
422
423 /**
424 * The Process Button callback function
425 * @param widget The Button widget passed to the callback function
426 * @param data Data sent along with the callback function
427 */
428 void callback_process_button(GtkWidget *widget, gpointer data) {
429
430 FilterViewerData *fvd = (FilterViewerData*)data;
431
432 if(strlen(gtk_entry_get_text(GTK_ENTRY(fvd->f_expression_field))) !=0)
433 lttv_filter_new(gtk_entry_get_text(GTK_ENTRY(fvd->f_expression_field)),NULL);
434 }
435
436 /**
437 * The Add Button callback function
438 * @param widget The Button widget passed to the callback function
439 * @param data Data sent along with the callback function
440 */
441 void callback_expression_field(GtkWidget *widget, gpointer data) {
442
443 FilterViewerData *fvd = (FilterViewerData*)data;
444
445 if(strlen(gtk_entry_get_text(GTK_ENTRY(fvd->f_expression_field))) !=0) {
446 gtk_widget_show(fvd->f_logical_op_junction_box);
447 } else {
448 gtk_widget_hide(fvd->f_logical_op_junction_box);
449 }
450 }
451
452
453 /**
454 * The Add Button callback function
455 * @param widget The Button widget passed to the callback function
456 * @param data Data sent along with the callback function
457 */
458 void callback_add_button(GtkWidget *widget, gpointer data) {
459
460 g_print("filter::callback_add_button()\n");
461
462 FilterViewerData *fvd = (FilterViewerData*)data;
463 FilterViewerDataLine *fvdl = NULL;
464 GString* a_filter_string = g_string_new("");
465
466 // g_string_append(a_filter_string,gtk_combo_box_get_active_text(GTK_COMBO_BOX(fvd->f_logical_op_junction_box)));
467 gtk_combo_box_set_active(fvd->f_logical_op_junction_box,0);
468
469 g_string_append_c(a_filter_string,"(");
470
471 int i;
472 for(i=0;i<fvd->f_lines->len;i++) {
473 fvdl = (FilterViewerDataLine*)g_ptr_array_index(fvd->f_lines,i);
474 // g_string_append(a_filter_string,gtk_combo_box_get_active_text(GTK_COMBO_BOX(fvdl->f_struct_box)));
475 g_string_append_c(a_filter_string,".");
476 // g_string_append(a_filter_string,gtk_combo_box_get_active_text(GTK_COMBO_BOX(fvdl->f_subfield_box)));
477 // g_string_append(a_filter_string,gtk_combo_box_get_active_text(GTK_COMBO_BOX(fvdl->f_math_op_box)));
478 // g_string_append(a_filter_string,gtk_entry_get_text(GTK_ENTRY(fvdl->f_value_field)));
479 // g_string_append(a_filter_string,gtk_combo_box_get_active_text(GTK_COMBO_BOX(fvdl->f_logical_op_box)));
480 gui_filter_line_reset(fvdl);
481 if(i) gui_filter_line_set_visible(fvdl,FALSE);
482 }
483
484 g_string_append(a_filter_string,")");
485
486 gtk_entry_set_text(GTK_ENTRY(fvdl->f_value_field),a_filter_string->str);
487
488 }
489
490 /**
491 * The logical op box callback function
492 * @param widget The Button widget passed to the callback function
493 * @param data Data sent along with the callback function
494 */
495 void callback_logical_op_box(GtkWidget *widget, gpointer data) {
496
497 g_print("filter::callback_logical_op_box()\n");
498
499 FilterViewerData *fvd = (FilterViewerData*)data;
500 FilterViewerDataLine *fvdl = NULL;
501
502 int i;
503 for(i=0;i<fvd->f_lines->len;i++) {
504 fvdl = (FilterViewerDataLine*)g_ptr_array_index(fvd->f_lines,i);
505 if(fvdl->f_logical_op_box == widget) {
506 if(gtk_combo_box_get_active(fvdl->f_logical_op_box) == 0) return;
507 if(i==fvd->f_lines->len-1) { /* create a new line */
508 fvd->rows++;
509 FilterViewerDataLine* fvdl2 = gui_filter_add_line(fvd);
510 g_ptr_array_add(fvd->f_lines,(gpointer) fvdl2);
511 } else {
512 FilterViewerDataLine *fvdl2 = (FilterViewerDataLine*)g_ptr_array_index(fvd->f_lines,i+1);
513 if(!fvdl2->visible) gui_filter_line_set_visible(fvdl2,TRUE);
514 }
515 }
516 }
517
518 }
519
520 LTTV_MODULE("guifilter", "Filter window", \
521 "Graphical module that let user specify their filtering options", \
522 init, destroy, "lttvwindow")
523
This page took 0.04057 seconds and 4 git commands to generate.