1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers and XangXiu Yang
3 * 2005 Mathieu Desnoyers
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License Version 2 as
7 * published by the Free Software Foundation;
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21 //*! \defgroup GuiEvents libGuiEvents: The GUI Events display plugin */
25 * \brief Graphical plugin for showing events.
27 * This plugin lists all the events contained in the current time interval
30 * This plugin adds a Events Viewer functionnality to Linux TraceToolkit
31 * GUI when this plugin is loaded. The init and destroy functions add the
32 * viewer's insertion menu item and toolbar icon by calling viewer.h's
33 * API functions. Then, when a viewer's object is created, the constructor
34 * creates ans register through API functions what is needed to interact
35 * with the lttvwindow.
37 * Authors : Mathieu Desnoyers and XangXiu Yang, June to December 2003
38 * Inspired from original LTT, made by Karim Yaghmour
40 * Mostly rewritten by Mathieu Desnoyers, August 2005.
50 #include <glib/gprintf.h>
57 #include <ltt/event.h>
58 #include <ltt/trace.h>
59 #include <lttv/lttv.h>
60 #include <lttv/module.h>
61 #include <lttv/hook.h>
62 #include <lttv/traceset.h>
63 #include <lttv/state.h>
65 #include <lttv/filter.h>
66 #endif //babel_cleanup
67 #include <lttv/print.h>
68 #include <lttvwindow/lttvwindow.h>
69 #include <lttvwindow/lttvwindowtraces.h>
70 #include <lttvwindow/lttv_plugin_tab.h>
71 #include <lttvwindow/support.h>
72 #include "lttv_plugin_evd.h"
75 #include "hGuiEventsInsert.xpm"
77 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
80 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
83 #define abs(a) (((a)<0)?(-a):(a))
84 #define max(a,b) ((a)>(b)?(a):(b))
85 #define min(a,b) ((a)<(b)?(a):(b))
87 /** Array containing instanced objects. Used when module is unloaded */
88 static GSList
*g_event_viewer_data_list
= NULL
;
90 typedef enum _ScrollDirection
{
99 /** hook functions for update time interval, current time ... */
100 gboolean
update_current_time(void * hook_data
, void * call_data
);
101 gboolean
update_current_position(void * hook_data
, void * call_data
);
102 //gboolean show_event_detail(void * hook_data, void * call_data);
103 gboolean
traceset_changed(void * hook_data
, void * call_data
);
104 gboolean
timespan_changed(void * hook_data
, void * call_data
);
106 gboolean
filter_changed(void * hook_data
, void * call_data
);
107 #endif // babel_cleanup
108 static void request_background_data(EventViewerData
*event_viewer_data
);
110 //! Event Viewer's constructor hook
111 GtkWidget
*h_gui_events(LttvPlugin
*plugin
);
112 //! Event Viewer's constructor
113 EventViewerData
*gui_events(LttvPluginTab
*ptab
);
114 //! Event Viewer's destructor
115 void gui_events_destructor(gpointer data
);
116 void gui_events_free(gpointer data
);
119 header_size_allocate(GtkWidget
*widget
,
120 GtkAllocation
*allocation
,
123 void tree_v_set_cursor(EventViewerData
*event_viewer_data
);
124 void tree_v_get_cursor(EventViewerData
*event_viewer_data
);
126 /* Prototype for selection handler callback */
127 static void tree_selection_changed_cb (GtkTreeSelection
*selection
,
129 static void v_scroll_cb (GtkAdjustment
*adjustment
, gpointer data
);
130 static void tree_v_size_allocate_cb (GtkWidget
*widget
, GtkAllocation
*alloc
,
132 static void tree_v_size_request_cb (GtkWidget
*widget
,
133 GtkRequisition
*requisition
, gpointer data
);
134 static void tree_v_cursor_changed_cb (GtkWidget
*widget
, gpointer data
);
135 static void tree_v_move_cursor_cb (GtkWidget
*widget
, GtkMovementStep arg1
,
136 gint arg2
, gpointer data
);
137 static void filter_button (GtkToolButton
*toolbutton
,
139 static gboolean
tree_v_scroll_handler (GtkWidget
*widget
, GdkEventScroll
*event
, gpointer data
);
140 static gboolean
key_handler(GtkWidget
*widget
, GdkEventKey
*event
,
143 static void get_events(double time
, EventViewerData
*event_viewer_data
);
145 int event_hook(void *hook_data
, void *call_data
);
147 /* Enumeration of the columns */
151 TRACEFILE_NAME_COLUMN
,
163 * Event Viewer's constructor hook
165 * This constructor is given as a parameter to the menuitem and toolbar button
166 * registration. It creates the list.
167 * @param parent_window A pointer to the parent window.
168 * @return The widget created.
171 h_gui_events(LttvPlugin
*plugin
)
173 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
174 EventViewerData
* event_viewer_data
= gui_events(ptab
) ;
175 if(event_viewer_data
)
176 return event_viewer_data
->top_widget
;
182 * Event Viewer's constructor
184 * This constructor is used to create EventViewerData data structure.
185 * @return The Event viewer data created.
188 gui_events(LttvPluginTab
*ptab
)
190 /*To disable the error bell when we reach the end(or the top) of the list of
191 event. Since we overload the management of the list*/
192 GtkSettings
* gtk_settings
= gtk_settings_get_default();
193 g_object_set(gtk_settings
, "gtk-error-bell", FALSE
, NULL
);
197 GtkTreeViewColumn
*column
;
198 GtkCellRenderer
*renderer
;
199 EventViewerData
* event_viewer_data
= g_new(EventViewerData
,1);
200 LttvPluginEVD
*plugin_evd
= g_object_new(LTTV_TYPE_PLUGIN_EVD
, NULL
);
201 GtkTooltips
*tooltips
= gtk_tooltips_new();
202 plugin_evd
->evd
= event_viewer_data
;
203 Tab
*tab
= ptab
->tab
;
204 event_viewer_data
->tab
= tab
;
205 event_viewer_data
->ptab
= ptab
;
206 GtkWidget
*tmp_toolbar_icon
;
208 LttvTraceset
*ts
=lttvwindow_get_traceset(event_viewer_data
->tab
);
210 event_viewer_data
->event_hooks
= lttv_hooks_new();
211 lttv_hooks_add(event_viewer_data
->event_hooks
,
216 lttvwindow_register_current_time_notify(tab
,
217 update_current_time
,event_viewer_data
);
218 lttvwindow_register_current_position_notify(tab
,
219 update_current_position
,event_viewer_data
);
220 lttvwindow_register_traceset_notify(tab
,
221 traceset_changed
,event_viewer_data
);
222 lttvwindow_register_timespan_notify(tab
,
223 timespan_changed
,event_viewer_data
);
225 lttvwindow_register_filter_notify(tab
,
226 filter_changed
, event_viewer_data
);
228 lttvwindow_register_redraw_notify(tab
,
229 evd_redraw_notify
, event_viewer_data
);
230 event_viewer_data
->scroll_win
= gtk_scrolled_window_new (NULL
, NULL
);
231 gtk_widget_show (event_viewer_data
->scroll_win
);
232 gtk_scrolled_window_set_policy(
233 GTK_SCROLLED_WINDOW(event_viewer_data
->scroll_win
),
234 GTK_POLICY_AUTOMATIC
, GTK_POLICY_NEVER
);
236 event_viewer_data
->currently_selected_position
=
237 lttv_traceset_create_position(ts
);
238 event_viewer_data
->first_event
=
239 lttv_traceset_create_position(ts
);
240 event_viewer_data
->last_event
=
241 lttv_traceset_create_position(ts
);
242 event_viewer_data
->main_win_filter
= lttvwindow_get_filter(tab
);
244 event_viewer_data
->update_cursor
= TRUE
;
245 event_viewer_data
->report_position
= TRUE
;
247 event_viewer_data
->last_tree_update_time
= 0;
249 event_viewer_data
->init_done
= 0;
251 /* Create a model for storing the data list */
252 event_viewer_data
->store_m
= gtk_list_store_new (
253 N_COLUMNS
, /* Total number of columns */
254 G_TYPE_STRING
, /* Trace name */
255 G_TYPE_STRING
, /* Tracefile name */
256 G_TYPE_UINT
, /* CPUID */
257 G_TYPE_STRING
, /* Event */
258 G_TYPE_UINT
, /* Time s */
259 G_TYPE_UINT
, /* Time ns */
260 G_TYPE_INT
, /* PID */
261 G_TYPE_STRING
, /* Event's description */
262 G_TYPE_POINTER
);/* Position (not shown) */
264 event_viewer_data
->pos
= g_ptr_array_sized_new(10);
266 /* Create the viewer widget for the columned list */
267 event_viewer_data
->tree_v
=
268 gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data
->store_m
));
270 g_signal_connect (G_OBJECT (event_viewer_data
->tree_v
), "size-allocate",
271 G_CALLBACK (tree_v_size_allocate_cb
),
273 g_signal_connect (G_OBJECT (event_viewer_data
->tree_v
), "size-request",
274 G_CALLBACK (tree_v_size_request_cb
),
277 g_signal_connect (G_OBJECT (event_viewer_data
->tree_v
), "cursor-changed",
278 G_CALLBACK (tree_v_cursor_changed_cb
),
281 g_signal_connect (G_OBJECT (event_viewer_data
->tree_v
), "move-cursor",
282 G_CALLBACK (tree_v_move_cursor_cb
),
285 g_signal_connect (G_OBJECT(event_viewer_data
->tree_v
), "key-press-event",
286 G_CALLBACK(key_handler
),
289 g_signal_connect (G_OBJECT(event_viewer_data
->tree_v
), "scroll-event",
290 G_CALLBACK(tree_v_scroll_handler
),
295 // Use on each column!
296 //gtk_tree_view_column_set_sizing(event_viewer_data->tree_v,
297 //GTK_TREE_VIEW_COLUMN_FIXED);
299 /* The view now holds a reference. We can get rid of our own
301 g_object_unref (G_OBJECT (event_viewer_data
->store_m
));
304 /* Create a column, associating the "text" attribute of the
305 * cell_renderer to the first column of the model */
306 /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */
307 renderer
= gtk_cell_renderer_text_new ();
308 column
= gtk_tree_view_column_new_with_attributes ("Trace",
310 "text", TRACE_NAME_COLUMN
,
312 gtk_tree_view_column_set_alignment (column
, 0.0);
313 gtk_tree_view_column_set_fixed_width (column
, 120);
314 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
317 event_viewer_data
->button
= column
->button
;
319 g_signal_connect (G_OBJECT(event_viewer_data
->button
),
321 G_CALLBACK(header_size_allocate
),
322 (gpointer
)event_viewer_data
);
326 renderer
= gtk_cell_renderer_text_new ();
327 column
= gtk_tree_view_column_new_with_attributes ("Tracefile",
329 "text", TRACEFILE_NAME_COLUMN
,
331 gtk_tree_view_column_set_alignment (column
, 0.0);
332 gtk_tree_view_column_set_fixed_width (column
, 120);
333 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
337 renderer
= gtk_cell_renderer_text_new ();
338 column
= gtk_tree_view_column_new_with_attributes ("CPUID",
340 "text", CPUID_COLUMN
,
342 gtk_tree_view_column_set_alignment (column
, 0.0);
343 gtk_tree_view_column_set_fixed_width (column
, 45);
344 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
347 renderer
= gtk_cell_renderer_text_new ();
348 column
= gtk_tree_view_column_new_with_attributes ("Event",
350 "text", EVENT_COLUMN
,
352 gtk_tree_view_column_set_alignment (column
, 0.0);
353 gtk_tree_view_column_set_fixed_width (column
, 120);
354 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
357 renderer
= gtk_cell_renderer_text_new ();
358 column
= gtk_tree_view_column_new_with_attributes ("Time (s)",
360 "text", TIME_S_COLUMN
,
362 gtk_tree_view_column_set_alignment (column
, 1.0);
363 gtk_tree_view_column_set_fixed_width (column
, 120);
364 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
367 renderer
= gtk_cell_renderer_text_new ();
368 column
= gtk_tree_view_column_new_with_attributes ("Time (ns)",
370 "text", TIME_NS_COLUMN
,
372 gtk_tree_view_column_set_alignment (column
, 1.0);
373 gtk_tree_view_column_set_fixed_width (column
, 120);
374 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
378 renderer
= gtk_cell_renderer_text_new ();
379 column
= gtk_tree_view_column_new_with_attributes ("PID",
383 gtk_tree_view_column_set_alignment (column
, 1.0);
384 gtk_tree_view_column_set_fixed_width (column
, 45);
385 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
388 renderer
= gtk_cell_renderer_text_new ();
389 column
= gtk_tree_view_column_new_with_attributes ("Event Description",
391 "text", EVENT_DESCR_COLUMN
,
393 gtk_tree_view_column_set_alignment (column
, 0.0);
394 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
398 /* Setup the selection handler */
399 event_viewer_data
->select_c
=
400 gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data
->tree_v
));
401 gtk_tree_selection_set_mode (event_viewer_data
->select_c
,
402 GTK_SELECTION_SINGLE
);
403 g_signal_connect (G_OBJECT (event_viewer_data
->select_c
), "changed",
404 G_CALLBACK (tree_selection_changed_cb
),
407 gtk_container_add (GTK_CONTAINER (event_viewer_data
->scroll_win
),
408 event_viewer_data
->tree_v
);
410 event_viewer_data
->hbox_v
= gtk_hbox_new(0, 0);
411 event_viewer_data
->top_widget
= event_viewer_data
->hbox_v
;
412 plugin_evd
->parent
.top_widget
= event_viewer_data
->hbox_v
;
414 event_viewer_data
->toolbar
= gtk_toolbar_new();
415 gtk_toolbar_set_orientation(GTK_TOOLBAR(event_viewer_data
->toolbar
),
416 GTK_ORIENTATION_VERTICAL
);
418 tmp_toolbar_icon
= create_pixmap (main_window_get_widget(tab
),
419 "guifilter16x16.png");
420 gtk_widget_show(tmp_toolbar_icon
);
421 event_viewer_data
->button_filter
= gtk_tool_button_new(tmp_toolbar_icon
,
423 g_signal_connect (G_OBJECT(event_viewer_data
->button_filter
),
425 G_CALLBACK (filter_button
),
426 (gpointer
)plugin_evd
);
427 gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(event_viewer_data
->button_filter
),
428 tooltips
, "Open the filter window", NULL
);
429 gtk_toolbar_insert(GTK_TOOLBAR(event_viewer_data
->toolbar
),
430 event_viewer_data
->button_filter
,
432 gtk_toolbar_set_style(GTK_TOOLBAR(event_viewer_data
->toolbar
),
434 gtk_box_pack_start(GTK_BOX(event_viewer_data
->hbox_v
),
435 event_viewer_data
->toolbar
, FALSE
, FALSE
, 0);
436 event_viewer_data
->filter
= NULL
;
438 gtk_box_pack_start(GTK_BOX(event_viewer_data
->hbox_v
),
439 event_viewer_data
->scroll_win
, TRUE
, TRUE
, 0);
441 gtk_container_set_border_width(GTK_CONTAINER(event_viewer_data
->hbox_v
), 1);
443 /* Create vertical scrollbar and pack it */
444 event_viewer_data
->vscroll_vc
= gtk_vscrollbar_new(NULL
);
445 gtk_range_set_update_policy (GTK_RANGE(event_viewer_data
->vscroll_vc
),
446 GTK_UPDATE_CONTINUOUS
);
447 // Changed by MD : more user friendly :)
448 //GTK_UPDATE_DISCONTINUOUS);
449 gtk_box_pack_start(GTK_BOX(event_viewer_data
->hbox_v
),
450 event_viewer_data
->vscroll_vc
, FALSE
, TRUE
, 0);
452 /* Get the vertical scrollbar's adjustment */
453 event_viewer_data
->vadjust_c
=
454 gtk_range_get_adjustment(GTK_RANGE(event_viewer_data
->vscroll_vc
));
455 event_viewer_data
->vtree_adjust_c
= gtk_tree_view_get_vadjustment(
456 GTK_TREE_VIEW (event_viewer_data
->tree_v
));
458 g_signal_connect (G_OBJECT (event_viewer_data
->vadjust_c
), "value-changed",
459 G_CALLBACK (v_scroll_cb
),
461 //TODO ybrosseau 2011-01-06: Fix comment
462 /* Set the upper bound to the last event number */
463 event_viewer_data
->previous_value
= 0;
464 event_viewer_data
->vadjust_c
->lower
= 0.0;
465 //event_viewer_data->vadjust_c->upper = event_viewer_data->number_of_events;
467 LttTime time
= lttvwindow_get_current_time(tab
);
468 TimeInterval time_span
= lttv_traceset_get_time_span_real(ts
);
469 time
= ltt_time_sub(time
, time_span
.start_time
);
470 //TODO ybrosseau 2011-01-06: Which one do we keep?
472 event_viewer_data
->vadjust_c
->value
= ltt_time_to_double(time
);
473 #endif //babel_cleanup
474 event_viewer_data
->vadjust_c
->value
= 0.0;
475 event_viewer_data
->vadjust_c
->step_increment
= 1.0;
476 event_viewer_data
->vadjust_c
->page_increment
= 2.0;
477 // event_viewer_data->vtree_adjust_c->upper;
478 event_viewer_data
->vadjust_c
->page_size
= 2.0;
479 // event_viewer_data->vtree_adjust_c->upper;
480 /* Raw event trace */
481 gtk_widget_show(GTK_WIDGET(event_viewer_data
->button_filter
));
482 gtk_widget_show(event_viewer_data
->toolbar
);
483 gtk_widget_show(event_viewer_data
->hbox_v
);
484 gtk_widget_show(event_viewer_data
->tree_v
);
485 gtk_widget_show(event_viewer_data
->vscroll_vc
);
487 /* Add the object's information to the module's array */
488 g_event_viewer_data_list
= g_slist_append(g_event_viewer_data_list
,
491 event_viewer_data
->num_visible_events
= 1;
493 //get the life span of the traceset and set the upper of the scroll bar
495 end
= ltt_time_sub(time_span
.end_time
, time_span
.start_time
);
497 event_viewer_data
->vadjust_c
->upper
= ltt_time_to_double(end
);
499 /* Set the Selected Event */
500 // tree_v_set_cursor(event_viewer_data);
502 // event_viewer_data->current_time_updated = FALSE;
504 g_object_set_data_full(
505 G_OBJECT(event_viewer_data
->hbox_v
),
508 (GDestroyNotify
)gui_events_free
);
511 G_OBJECT(event_viewer_data
->hbox_v
),
515 event_viewer_data
->background_info_waiting
= 0;
518 request_background_data(event_viewer_data
);
519 return event_viewer_data
;
524 static gint
background_ready(void *hook_data
, void *call_data
)
526 EventViewerData
*event_viewer_data
= (EventViewerData
*)hook_data
;
528 event_viewer_data
->background_info_waiting
--;
530 if(event_viewer_data
->background_info_waiting
== 0) {
531 g_message("event viewer : background computation data ready.");
533 evd_redraw_notify(event_viewer_data
, NULL
);
540 static void request_background_data(EventViewerData
*event_viewer_data
)
543 lttvwindow_get_traceset(event_viewer_data
->tab
);
544 gint num_traces
= ts
->traces
->len
;
547 LttvTraceState
*tstate
;
549 LttvHooks
*background_ready_hook
=
551 lttv_hooks_add(background_ready_hook
, background_ready
, event_viewer_data
,
553 event_viewer_data
->background_info_waiting
= 0;
555 for(i
=0;i
<num_traces
;i
++) {
556 trace
= g_ptr_array_index(ts
->traces
,i
);
558 tstate
= LTTV_TRACE_STATE(tsc
->traces
[i
]);
559 #endif /*babel_cleanup*/
561 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
562 /*&& !tstate->has_precomputed_states*/) {
564 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
566 /* We first remove requests that could have been done for the same
567 * information. Happens when two viewers ask for it before servicing
570 if(!lttvwindowtraces_background_request_find(trace
, "state"))
571 lttvwindowtraces_background_request_queue(
572 main_window_get_widget(event_viewer_data
->tab
), trace
, "state");
573 lttvwindowtraces_background_notify_queue(event_viewer_data
,
577 background_ready_hook
);
578 event_viewer_data
->background_info_waiting
++;
579 } else { /* in progress */
581 lttvwindowtraces_background_notify_current(event_viewer_data
,
585 background_ready_hook
);
586 event_viewer_data
->background_info_waiting
++;
589 /* Data ready. By its nature, this viewer doesn't need to have
590 * its data ready hook called there, because a background
591 * request is always linked with a redraw.
597 lttv_hooks_destroy(background_ready_hook
);
601 header_size_allocate(GtkWidget
*widget
,
602 GtkAllocation
*allocation
,
605 EventViewerData
*event_viewer_data
= (EventViewerData
*)user_data
;
607 event_viewer_data
->header_height
= allocation
->height
;
613 void tree_v_set_cursor(EventViewerData
*event_viewer_data
)
615 g_debug("set cursor cb");
618 if(event_viewer_data
->currently_selected_event
!= -1)
620 path
= gtk_tree_path_new_from_indices(
621 event_viewer_data
->currently_selected_event
,
624 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
626 gtk_tree_path_free(path
);
631 void tree_v_get_cursor(EventViewerData
*event_viewer_data
)
633 g_debug("get cursor cb");
637 gtk_tree_view_get_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
639 indices
= gtk_tree_path_get_indices(path
);
642 event_viewer_data
->currently_selected_event
= indices
[0];
644 event_viewer_data
->currently_selected_event
= -1;
646 gtk_tree_path_free(path
);
650 /* Filter out the key repeats that come too fast */
651 static gboolean
key_handler(GtkWidget
*widget
, GdkEventKey
*event
,
654 EventViewerData
*evd
= (EventViewerData
*)user_data
;
656 g_debug("event time : %u , last time : %u", event
->time
,
657 evd
->last_tree_update_time
);
659 if(guint32_before(event
->time
, evd
->last_tree_update_time
))
665 void tree_v_move_cursor_cb (GtkWidget
*widget
,
666 GtkMovementStep arg1
,
671 GtkTreePath
*path
; // = gtk_tree_path_new();
672 EventViewerData
*event_viewer_data
= (EventViewerData
*)data
;
674 g_debug("move cursor cb");
675 //gtk_tree_view_get_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
679 /* No prior cursor, put it at beginning of page
680 * and let the execution do */
681 // path = gtk_tree_path_new_from_indices(0, -1);
682 // gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
683 // path, NULL, FALSE);
686 //indices = gtk_tree_path_get_indices(path);
688 //value = gtk_adjustment_get_value(event_viewer_data->vadjust_c);
690 /* If events request pending, do nothing*/
691 if(lttvwindow_events_request_pending(event_viewer_data
->tab
)) return;
693 /* If no prior position... */
696 lttv_traceset_context_position_get_time(
697 event_viewer_data
->currently_selected_position
),
698 ltt_time_infinite
) == 0) {
700 path
= gtk_tree_path_new_from_indices(0, -1);
701 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
704 gtk_tree_path_free(path
);
710 g_debug("tree view move cursor : arg1 is %u and arg2 is %d",
714 case GTK_MOVEMENT_DISPLAY_LINES
:
716 /* Move one line down */
717 if(event_viewer_data
->pos
->len
> 0) {
718 LttvTracesetPosition
*end_pos
=
719 (LttvTracesetPosition
*)g_ptr_array_index(
720 event_viewer_data
->pos
,
721 event_viewer_data
->pos
->len
-1);
722 if(lttv_traceset_position_compare(end_pos
,
723 event_viewer_data
->currently_selected_position
) == 0) {
724 /* Must get down one event and select the last one */
725 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
726 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
727 event_viewer_data
->update_cursor
= FALSE
;
728 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
729 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 1);
730 event_viewer_data
->update_cursor
= TRUE
;
731 if(event_viewer_data
->pos
->len
> 0) {
732 path
= gtk_tree_path_new_from_indices(
733 max(0, event_viewer_data
->pos
->len
- 1), -1);
735 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
737 gtk_tree_path_free(path
);
742 /* Must get down one event and select the last one */
743 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
744 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
745 event_viewer_data
->update_cursor
= FALSE
;
746 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
747 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 1);
748 event_viewer_data
->update_cursor
= TRUE
;
749 if(event_viewer_data
->pos
->len
> 0) {
750 path
= gtk_tree_path_new_from_indices(
751 max(0, event_viewer_data
->pos
->len
- 1), -1);
753 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
755 gtk_tree_path_free(path
);
761 if(event_viewer_data
->pos
->len
> 0) {
762 /* Move one line up */
763 LttvTracesetPosition
*begin_pos
=
764 (LttvTracesetPosition
*)g_ptr_array_index(
765 event_viewer_data
->pos
,
767 if(lttv_traceset_position_compare(begin_pos
,
768 event_viewer_data
->currently_selected_position
) == 0) {
769 /* Must get up one event and select the first one */
770 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
771 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
772 event_viewer_data
->update_cursor
= FALSE
;
773 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
774 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 1);
775 event_viewer_data
->update_cursor
= TRUE
;
776 if(event_viewer_data
->pos
->len
> 0) {
777 path
= gtk_tree_path_new_from_indices(
780 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
782 gtk_tree_path_free(path
);
787 /* Must get up one event and select the first one */
788 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
789 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
790 event_viewer_data
->update_cursor
= FALSE
;
791 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
792 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 1);
793 event_viewer_data
->update_cursor
= TRUE
;
794 if(event_viewer_data
->pos
->len
> 0) {
795 path
= gtk_tree_path_new_from_indices(
798 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
800 gtk_tree_path_free(path
);
806 case GTK_MOVEMENT_PAGES
:
808 /* Move one page down */
809 if(event_viewer_data
->pos
->len
> 0) {
810 LttvTracesetPosition
*end_pos
=
811 (LttvTracesetPosition
*)g_ptr_array_index(
812 event_viewer_data
->pos
,
813 event_viewer_data
->pos
->len
-1);
814 if(lttv_traceset_position_compare(end_pos
,
815 event_viewer_data
->currently_selected_position
) == 0) {
816 /* Must get down one page and select the last one */
817 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
818 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
819 event_viewer_data
->update_cursor
= FALSE
;
820 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
821 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 2);
822 event_viewer_data
->update_cursor
= TRUE
;
823 if(event_viewer_data
->pos
->len
> 0) {
824 path
= gtk_tree_path_new_from_indices(
825 event_viewer_data
->pos
->len
- 1, -1);
827 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
829 gtk_tree_path_free(path
);
834 /* Must get down one page and select the last one */
835 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
836 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
837 event_viewer_data
->update_cursor
= FALSE
;
838 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
839 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 2);
840 event_viewer_data
->update_cursor
= TRUE
;
841 if(event_viewer_data
->pos
->len
> 0) {
842 path
= gtk_tree_path_new_from_indices(
843 event_viewer_data
->pos
->len
- 1, -1);
845 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
847 gtk_tree_path_free(path
);
852 /* Move one page up */
853 if(event_viewer_data
->pos
->len
> 0) {
854 LttvTracesetPosition
*begin_pos
=
855 (LttvTracesetPosition
*)g_ptr_array_index(
856 event_viewer_data
->pos
,
858 if(lttv_traceset_position_compare(begin_pos
,
859 event_viewer_data
->currently_selected_position
) == 0) {
860 /* Must get up one page and select the first one */
861 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
862 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
863 event_viewer_data
->update_cursor
= FALSE
;
864 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
865 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 2);
866 event_viewer_data
->update_cursor
= TRUE
;
867 if(event_viewer_data
->pos
->len
> 0) {
868 path
= gtk_tree_path_new_from_indices(
871 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
873 gtk_tree_path_free(path
);
878 /* Must get up one page and select the first one */
879 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
880 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
881 event_viewer_data
->update_cursor
= FALSE
;
882 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
883 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 2);
884 event_viewer_data
->update_cursor
= TRUE
;
885 if(event_viewer_data
->pos
->len
> 0) {
886 path
= gtk_tree_path_new_from_indices(
889 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
891 gtk_tree_path_free(path
);
900 //gtk_tree_path_free(path);
902 if(arg1
== GTK_MOVEMENT_DISPLAY_LINES
)
907 /* move one line down */
908 if(indices
[0]) // Do we need an empty field here (before first)?
910 if(value
+ event_viewer_data
->num_visible_events
<=
911 event_viewer_data
->number_of_events
-1)
913 event_viewer_data
->currently_selected_event
+= 1;
914 // gtk_adjustment_set_value(event_viewer_data->vadjust_c, value+1);
915 //gtk_tree_path_free(path);
916 //path = gtk_tree_path_new_from_indices(event_viewer_data->num_visible_events-1, -1);
917 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
918 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
922 /* Move one line up */
927 event_viewer_data
->currently_selected_event
-= 1;
928 // gtk_adjustment_set_value(event_viewer_data->vadjust_c, value-1);
929 //gtk_tree_path_free(path);
930 //path = gtk_tree_path_new_from_indices(0, -1);
931 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
932 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
938 if(arg1
== GTK_MOVEMENT_PAGES
)
943 if(event_viewer_data
->num_visible_events
== 1)
945 /* move one page down */
946 if(value
+ event_viewer_data
->num_visible_events
-1 <=
947 event_viewer_data
->number_of_events
)
949 event_viewer_data
->currently_selected_event
+=
950 event_viewer_data
->num_visible_events
-1;
951 // gtk_adjustment_set_value(event_viewer_data->vadjust_c,
952 // value+(event_viewer_data->num_visible_events-1));
953 //gtk_tree_path_free(path);
954 //path = gtk_tree_path_new_from_indices(0, -1);
955 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
956 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
959 /* Move one page up */
960 if(event_viewer_data
->num_visible_events
== 1)
963 if(indices
[0] < event_viewer_data
->num_visible_events
- 2 )
965 if(value
- (event_viewer_data
->num_visible_events
-1) >= 0)
967 event_viewer_data
->currently_selected_event
-=
968 event_viewer_data
->num_visible_events
-1;
970 // gtk_adjustment_set_value(event_viewer_data->vadjust_c,
971 // value-(event_viewer_data->num_visible_events-1));
972 //gtk_tree_path_free(path);
973 //path = gtk_tree_path_new_from_indices(0, -1);
974 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
975 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
978 /* Go to first Event */
979 event_viewer_data
->currently_selected_event
== 0 ;
980 // gtk_adjustment_set_value(event_viewer_data->vadjust_c,
982 //gtk_tree_path_free(path);
983 //path = gtk_tree_path_new_from_indices(0, -1);
984 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
985 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
992 if(arg1
== GTK_MOVEMENT_BUFFER_ENDS
)
994 /* Move to the ends of the buffer */
997 /* move end of buffer */
998 event_viewer_data
->currently_selected_event
=
999 event_viewer_data
->number_of_events
-1 ;
1000 // gtk_adjustment_set_value(event_viewer_data->vadjust_c,
1001 // event_viewer_data->number_of_events -
1002 // event_viewer_data->num_visible_events);
1003 //gtk_tree_path_free(path);
1004 //path = gtk_tree_path_new_from_indices(event_viewer_data->num_visible_events-1, -1);
1005 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
1006 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
1008 /* Move beginning of buffer */
1009 event_viewer_data
->currently_selected_event
= 0 ;
1010 // gtk_adjustment_set_value(event_viewer_data->vadjust_c, 0);
1011 //gtk_tree_path_free(path);
1012 //path = gtk_tree_path_new_from_indices(0, -1);
1013 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
1014 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
1020 static void filter_button (GtkToolButton
*toolbutton
,
1023 LttvPluginEVD
*plugin_evd
= (LttvPluginEVD
*)user_data
;
1024 LttvAttribute
*attribute
;
1025 LttvAttributeValue value
;
1027 g_printf("Filter button clicked\n");
1029 attribute
= LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
1030 LTTV_IATTRIBUTE(lttv_global_attributes()),
1031 LTTV_VIEWER_CONSTRUCTORS
));
1032 g_assert(attribute
);
1034 ret
= lttv_iattribute_find_by_path(LTTV_IATTRIBUTE(attribute
),
1035 "guifilter", LTTV_POINTER
, &value
);
1037 lttvwindow_viewer_constructor constructor
=
1038 (lttvwindow_viewer_constructor
)*(value
.v_pointer
);
1039 if(constructor
) constructor(&plugin_evd
->parent
);
1040 else g_warning("Filter module not loaded.");
1042 //FIXME : viewer returned.
1045 gboolean
tree_v_scroll_handler (GtkWidget
*widget
, GdkEventScroll
*event
, gpointer data
)
1047 EventViewerData
*event_viewer_data
= (EventViewerData
*) data
;
1049 switch(event
->direction
) {
1051 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
1052 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 1);
1054 case GDK_SCROLL_DOWN
:
1055 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
1056 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 1);
1059 g_error("Only scroll up and down expected");
1064 void tree_v_cursor_changed_cb (GtkWidget
*widget
, gpointer data
)
1067 EventViewerData
*event_viewer_data
= (EventViewerData
*) data
;
1069 Tab
*tab
= event_viewer_data
->tab
;
1071 GtkTreeModel
* model
= GTK_TREE_MODEL(event_viewer_data
->store_m
);
1073 LttvTracesetPosition
*pos
;
1075 g_debug("cursor changed cb");
1077 /* On cursor change, modify the currently selected event by calling
1078 * the right API function */
1079 if(event_viewer_data
->report_position
) {
1080 if(event_viewer_data
->pos
->len
> 0) {
1081 gtk_tree_view_get_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
1084 if(gtk_tree_model_get_iter(model
,&iter
,path
)){
1085 gtk_tree_model_get(model
, &iter
, POSITION_COLUMN
, &pos
, -1);
1087 if(lttv_traceset_position_compare(pos
,
1088 event_viewer_data
->currently_selected_position
) != 0)
1089 lttvwindow_report_current_position(tab
, pos
);
1091 g_warning("Can not get iter\n");
1093 gtk_tree_path_free(path
);
1100 static void tree_selection_changed_cb (GtkTreeSelection
*selection
,
1103 g_debug("tree sel changed cb");
1106 /* Set the cursor to currently selected event */
1107 GtkTreeModel
* model
= GTK_TREE_MODEL(event_viewer_data
->store_m
);
1109 LttvTracesetContextPosition
*pos
;
1111 GtkTreePath
*tree_path
;
1113 for(i
=0;i
<event_viewer_data
->num_visible_events
;i
++) {
1114 tree_path
= gtk_tree_path_new_from_indices(
1117 if(gtk_tree_model_get_iter(model
,&iter
,tree_path
)){
1118 gtk_tree_model_get(model
, &iter
, POSITION_COLUMN
, &pos
, -1);
1120 if(lttv_traceset_context_pos_pos_compare(pos
,
1121 event_viewer_data
->currently_selected_position
) == 0) {
1123 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
1124 tree_path
, NULL
, FALSE
);
1129 g_warning("Can not get iter\n");
1131 gtk_tree_path_free(tree_path
);
1137 static gint
key_snooper(GtkWidget
*grab_widget
, GdkEventKey
*event
,
1144 /* This callback may be recalled after a step up/down, but we don't want to lose
1145 * the exact position : what we do is that we only set the value if it has
1146 * changed : a step up/down that doesn't change the time value of the first
1147 * event won't trigger a scrollbar change. */
1149 void v_scroll_cb (GtkAdjustment
*adjustment
, gpointer data
)
1151 EventViewerData
*event_viewer_data
= (EventViewerData
*)data
;
1152 g_debug("SCROLL begin");
1153 g_debug("SCROLL values : %g , %g, %g",
1154 adjustment
->value
, event_viewer_data
->previous_value
,
1155 (adjustment
->value
- event_viewer_data
->previous_value
));
1157 LttTime new_time_off
= ltt_time_from_double(adjustment
->value
);
1158 LttTime old_time_off
= ltt_time_from_double(event_viewer_data
->previous_value
);
1159 g_debug("SCROLL time values %lu.%lu, %lu.%lu", new_time_off
.tv_sec
,
1160 new_time_off
.tv_nsec
, old_time_off
.tv_sec
, old_time_off
.tv_nsec
);
1161 /* If same value : nothing to update */
1162 if(ltt_time_compare(new_time_off
, old_time_off
) == 0)
1165 //LttTime old_time = event_viewer_data->first_event;
1168 //gint snoop = gtk_key_snooper_install(key_snooper, NULL);
1170 get_events(adjustment
->value
, event_viewer_data
);
1172 //gtk_key_snooper_remove(snoop);
1174 LttTime time
= ltt_time_sub(event_viewer_data
->first_event
,
1175 tsc
->time_span
.start_time
);
1176 double value
= ltt_time_to_double(time
);
1177 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
, value
);
1179 if(event_viewer_data
->currently_selected_event
!= -1) {
1181 tree_path
= gtk_tree_path_new_from_indices(
1182 event_viewer_data
->currently_selected_event
,
1185 // gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), tree_path,
1187 gtk_tree_path_free(tree_path
);
1190 g_debug("SCROLL end");
1193 static __inline gint
get_cell_height(GtkTreeView
*TreeView
)
1196 GtkTreeViewColumn
*column
= gtk_tree_view_get_column(TreeView
, 0);
1198 gtk_tree_view_column_cell_get_size(column
, NULL
, NULL
, NULL
, NULL
, &height
);
1200 gint vertical_separator
;
1201 gtk_widget_style_get (GTK_WIDGET (TreeView
),
1202 "vertical-separator", &vertical_separator
,
1205 height
+= vertical_separator
;
1210 void tree_v_size_allocate_cb (GtkWidget
*widget
, GtkAllocation
*alloc
, gpointer data
)
1212 EventViewerData
*event_viewer_data
= (EventViewerData
*)data
;
1213 gint cell_height
= get_cell_height(GTK_TREE_VIEW(event_viewer_data
->tree_v
));
1214 gint last_num_visible_events
= event_viewer_data
->num_visible_events
;
1215 gdouble exact_num_visible
;
1217 exact_num_visible
= ( alloc
->height
-
1218 event_viewer_data
->header_height
)
1219 / (double)cell_height
;
1221 event_viewer_data
->num_visible_events
= ceil(exact_num_visible
) ;
1223 event_viewer_data
->vadjust_c
->page_increment
=
1224 floor(exact_num_visible
);
1225 event_viewer_data
->vadjust_c
->page_size
=
1226 floor(exact_num_visible
);
1229 g_debug("size allocate %p : last_num_visible_events : %d",
1230 event_viewer_data
, last_num_visible_events
);
1231 g_debug("num_visible_events : %d, value %f",
1232 event_viewer_data
->num_visible_events
,
1233 event_viewer_data
->vadjust_c
->value
);
1235 if(event_viewer_data
->num_visible_events
!= last_num_visible_events
) {
1236 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1242 void tree_v_size_request_cb (GtkWidget
*widget
, GtkRequisition
*requisition
, gpointer data
)
1245 EventViewerData
*event_viewer_data
= (EventViewerData
*)data
;
1246 gint cell_height
= get_cell_height(GTK_TREE_VIEW(event_viewer_data
->tree_v
));
1248 h
= cell_height
+ event_viewer_data
->header_height
;
1249 requisition
->height
= h
;
1254 gboolean
show_event_detail(void * hook_data
, void * call_data
)
1256 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1257 LttvTracesetContext
* tsc
= lttvwindow_get_traceset_context(event_viewer_data
->tab
);
1259 if(event_viewer_data
->event_fields_queue_tmp
->length
== 0 &&
1260 event_viewer_data
->event_fields_queue
->length
== 0){
1261 event_viewer_data
->shown
= FALSE
;
1265 if(event_viewer_data
->shown
== FALSE
){
1266 event_viewer_data
->shown
= TRUE
;
1267 update_raw_data_array(event_viewer_data
,
1268 event_viewer_data
->event_fields_queue_tmp
->length
);
1270 get_data(event_viewer_data
->vadjust_c
->value
,
1271 event_viewer_data
->num_visible_events
,
1274 remove_context_hooks(event_viewer_data
,tsc
);
1281 static gboolean
events_check_handler(guint count
, gboolean
*stop_flag
,
1284 EventViewerData
*evd
= (EventViewerData
*)data
;
1285 if(count
% CHECK_GDK_INTERVAL
== 0) {
1288 while((event
= gdk_event_get()) != NULL
) {
1289 widget
= gtk_get_event_widget(event
);
1291 lookup_widget(main_window_get_widget(evd
->tab
),
1292 "StopProcessingButton")
1293 || widget
== evd
->vscroll_vc
) {
1294 gtk_main_do_event(event
);
1295 gdk_window_process_all_updates();
1297 gdk_event_free(event
);
1303 } else return FALSE
;
1306 static void get_events(double new_value
, EventViewerData
*event_viewer_data
)
1308 #ifdef BABEL_CLEANUP
1309 LttvTracesetStats
*tss
=
1310 lttvwindow_get_traceset_stats(event_viewer_data
->tab
);
1311 #endif //babel_cleanup
1312 LttvTraceset
*ts
= lttvwindow_get_traceset(event_viewer_data
->tab
);
1314 gboolean seek_by_time
;
1316 if(lttvwindow_preempt_count
> 0) return;
1318 double value
= new_value
- event_viewer_data
->previous_value
;
1320 /* Set stop button status for foreground processing */
1321 event_viewer_data
->tab
->stop_foreground
= FALSE
;
1322 lttvwindow_events_request_disable();
1324 /* See where we have to scroll... */
1325 ScrollDirection direction
;
1326 gint relative_position
;
1329 if(value
>= -1.0) direction
= SCROLL_STEP_UP
;
1331 if(value
>= -2.0) direction
= SCROLL_PAGE_UP
;
1332 else direction
= SCROLL_JUMP
;
1334 } else if(value
> 0.8) {
1335 if(value
<= 1.0) direction
= SCROLL_STEP_DOWN
;
1337 if(value
<= 2.0) direction
= SCROLL_PAGE_DOWN
;
1338 else direction
= SCROLL_JUMP
;
1340 } else direction
= SCROLL_NONE
; /* 0.0 */
1343 case SCROLL_STEP_UP
:
1344 g_debug("get_events : SCROLL_STEP_UP");
1345 relative_position
= -1;
1348 case SCROLL_STEP_DOWN
:
1349 g_debug("get_events : SCROLL_STEP_DOWN");
1350 relative_position
= 1;
1353 case SCROLL_PAGE_UP
:
1354 g_debug("get_events : SCROLL_PAGE_UP");
1355 relative_position
= -(event_viewer_data
->num_visible_events
);
1358 case SCROLL_PAGE_DOWN
:
1359 g_debug("get_events : SCROLL_PAGE_DOWN");
1360 relative_position
= event_viewer_data
->num_visible_events
;
1364 g_debug("get_events : SCROLL_JUMP");
1365 relative_position
= 0;
1369 g_debug("get_events : SCROLL_NONE");
1370 relative_position
= 0;
1375 LttTime time
= ltt_time_from_double(new_value
);
1376 TimeInterval time_span
= lttv_traceset_get_time_span_real(ts
);
1377 time
= ltt_time_add(time_span
.start_time
, time
);
1379 LttvTracesetPosition
*timePos
= lttv_traceset_create_time_position(ts
,time
);
1384 /* Remember the beginning position */
1385 if(event_viewer_data
->pos
->len
> 0) {
1387 if(relative_position
!= 0)
1389 LttvTracesetPosition
*pos
= 0;
1390 pos
= (LttvTracesetPosition
*)g_ptr_array_index(
1391 event_viewer_data
->pos
,
1393 lttv_traceset_seek_to_position(pos
);
1397 /* Note that, as we mess with the tsc position, this function CANNOT be called
1398 * from a hook inside the lttv_process_traceset_middle. */
1399 /* As the lttvwindow API keeps a sync_position inside the tsc to go back at
1400 * the right spot after being interrupted, it's ok to change the tsc position,
1401 * as long as we do not touch the sync_position. */
1403 /* Get the beginning position of the read (with seek backward or seek forward)
1405 if(relative_position
> 0) {
1406 lttv_process_traceset_seek_n_forward(ts
, relative_position
,
1407 events_check_handler
,
1408 &event_viewer_data
->tab
->stop_foreground
,
1409 event_viewer_data
->main_win_filter
,
1410 event_viewer_data
->filter
, NULL
, event_viewer_data
);
1411 } else if(relative_position
< 0) {
1412 /* Get an idea of currently shown event dispersion */
1413 guint64 first_event_time_stamp
=
1414 lttv_traceset_position_get_timestamp(event_viewer_data
->first_event
);
1415 guint64 last_event_time_stamp
=
1416 lttv_traceset_position_get_timestamp(event_viewer_data
->last_event
);
1417 guint64 timeSpan
= (last_event_time_stamp
- first_event_time_stamp
);
1418 gdouble ratio
= (gdouble
)timeSpan
/ (gdouble
)event_viewer_data
->num_visible_events
;
1420 ratio
= SEEK_BACK_DEFAULT_RATIO
;
1423 lttv_process_traceset_seek_n_backward(ts
,
1424 (guint
)abs(relative_position
),
1426 events_check_handler
,
1427 &event_viewer_data
->tab
->stop_foreground
,
1428 event_viewer_data
->main_win_filter
,
1429 event_viewer_data
->filter
, NULL
, event_viewer_data
);
1430 } /* else 0 : do nothing : we are already at the beginning position */
1432 /* Save the first event position */
1434 event_viewer_data
->first_event
= lttv_traceset_create_position(ts
);
1436 time
= ltt_time_from_uint64(lttv_traceset_position_get_timestamp(
1437 event_viewer_data
->first_event
));
1438 //if(ltt_time_compare(time, tsc->time_span.end_time) > 0)
1439 // time = tsc->time_span.end_time;
1441 LttTime time_val
= ltt_time_sub(time
,time_span
.start_time
);
1442 event_viewer_data
->previous_value
= ltt_time_to_double(time_val
);
1444 lttv_traceset_seek_to_position(event_viewer_data
->first_event
);
1448 lttv_traceset_seek_to_position(timePos
);
1451 LttTime time_val
= ltt_time_sub(time
,time_span
.start_time
);
1452 event_viewer_data
->previous_value
= ltt_time_to_double(time_val
);
1453 event_viewer_data
->first_event
= timePos
;
1456 /* Clear the model (don't forget to free the TCS positions!) */
1457 gtk_list_store_clear(event_viewer_data
->store_m
);
1458 for(i
=0;i
<event_viewer_data
->pos
->len
;i
++) {
1459 LttvTracesetPosition
*cur_pos
=
1460 (LttvTracesetPosition
*)g_ptr_array_index(event_viewer_data
->pos
,
1462 lttv_traceset_destroy_position(cur_pos
);
1464 g_ptr_array_set_size(event_viewer_data
->pos
, 0);
1468 * I make the choice not to use the mainwindow lttvwindow API here : the idle
1469 * loop might have a too low priority, and we want good update while
1470 * scrolling. However, we call the gdk loop to get events periodically so the
1471 * processing can be stopped.
1474 lttv_process_traceset_begin(ts
,
1475 NULL
, NULL
, event_viewer_data
->event_hooks
);
1477 event_viewer_data
->num_events
= 0;
1479 lttv_process_traceset_middle(ts
, ltt_time_infinite
, G_MAXUINT
, NULL
);
1481 lttv_process_traceset_end(ts
, NULL
, NULL
, event_viewer_data
->event_hooks
);
1483 /* Get the end position */
1484 if(event_viewer_data
->pos
->len
> 0) {
1485 LttvTracesetPosition
*cur_pos
=
1486 (LttvTracesetPosition
*)g_ptr_array_index(event_viewer_data
->pos
,
1487 event_viewer_data
->pos
->len
- 1);
1488 event_viewer_data
->last_event
= cur_pos
;
1490 event_viewer_data
->last_event
=lttv_traceset_create_position(ts
);
1492 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
1493 event_viewer_data
->previous_value
);
1495 //g_signal_emit_by_name(G_OBJECT (event_viewer_data->select_c),
1498 event_viewer_data
->last_tree_update_time
=
1499 gdk_x11_get_server_time(
1500 gtk_widget_get_parent_window(event_viewer_data
->tree_v
));
1502 lttvwindow_events_request_enable();
1508 int event_hook(void *hook_data
, void *call_data
)
1511 EventViewerData
*event_viewer_data
= (EventViewerData
*)hook_data
;
1513 LttvEvent
* e
= (LttvEvent
*)call_data
;
1515 if(event_viewer_data
->num_events
% CHECK_GDK_INTERVAL
== 0) {
1518 while((event
= gdk_event_get()) != NULL
) {
1519 widget
= gtk_get_event_widget(event
);
1521 lookup_widget(main_window_get_widget(event_viewer_data
->tab
),
1522 "StopProcessingButton")
1523 || widget
== event_viewer_data
->vscroll_vc
) {
1524 gtk_main_do_event(event
);
1525 gdk_window_process_all_updates();
1527 gdk_event_free(event
);
1529 //gtk_main_iteration_do(FALSE);
1530 if(event_viewer_data
->tab
->stop_foreground
)
1534 event_viewer_data
->num_events
++;
1535 #ifdef BABEL_CLEANUP
1536 LttvFilter
*filter
= event_viewer_data
->main_win_filter
;
1537 if(filter
!= NULL
&& filter
->head
!= NULL
)
1538 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
1539 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
1542 filter
= event_viewer_data
->filter
;
1543 if(filter
!= NULL
&& filter
->head
!= NULL
)
1544 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
1545 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
1547 #endif //babel_cleanup
1549 // LttFacility *facility = ltt_event_facility(e);
1550 // LttEventType *event_type = ltt_event_eventtype(e);
1551 LttTime time
= lttv_event_get_timestamp(e
);
1552 gint cpu
= lttv_traceset_get_cpuid_from_event(e
);
1554 LttvTraceState
*traceState
= e
->state
;
1555 LttvProcessState
*process
= traceState
->running_process
[cpu
];
1559 GString
*desc
= g_string_new("");
1561 LttvTracesetPosition
*pos
= lttv_traceset_create_position(traceState
->trace
->traceset
);
1563 lttv_event_to_string(e
, desc
, TRUE
);
1565 g_info("detail : %s", desc
->str
);
1567 gtk_list_store_append (event_viewer_data
->store_m
, &iter
);
1569 gtk_list_store_set (event_viewer_data
->store_m
, &iter
,
1570 TRACE_NAME_COLUMN
, "TraceName",
1571 TRACEFILE_NAME_COLUMN
,"TraceFile" /*traceState->trace->traceset->filename*/,
1573 EVENT_COLUMN
,"EventName" /*bt_ctf_event_name(e->bt_event)*/,
1574 TIME_S_COLUMN
, time
.tv_sec
,
1575 TIME_NS_COLUMN
, time
.tv_nsec
,
1576 PID_COLUMN
, process
->pid
,
1577 EVENT_DESCR_COLUMN
, desc
->str
,
1578 POSITION_COLUMN
, pos
,
1581 g_ptr_array_add(event_viewer_data
->pos
, pos
);
1583 g_string_free(desc
, TRUE
);
1585 if(event_viewer_data
->update_cursor
) {
1586 if(lttv_traceset_position_compare(pos
,
1587 event_viewer_data
->currently_selected_position
) == 0) {
1588 GtkTreePath
*path
= gtk_tree_path_new_from_indices(
1589 event_viewer_data
->pos
->len
- 1, -1);
1591 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
1593 gtk_tree_path_free(path
);
1597 if(event_viewer_data
->pos
->len
>= event_viewer_data
->num_visible_events
)
1606 static void event_update_selection(EventViewerData
*event_viewer_data
)
1610 GPtrArray
*positions
= event_viewer_data
->pos
;
1611 g_info("event_update_selection");
1613 for(i
=0;i
<positions
->len
;i
++) {
1614 LttvTracesetPosition
*cur_pos
=
1615 (LttvTracesetPosition
*)g_ptr_array_index(positions
, i
);
1616 if(lttv_traceset_position_compare(cur_pos
,
1617 event_viewer_data
->currently_selected_position
) == 0) {
1618 GtkTreePath
*path
= gtk_tree_path_new_from_indices(i
, -1);
1620 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
1622 gtk_tree_path_free(path
);
1629 static int current_time_get_first_event_hook(void *hook_data
, void *call_data
)
1631 #ifdef BABEL_CLEANUP
1632 EventViewerData
*event_viewer_data
= (EventViewerData
*)hook_data
;
1634 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1635 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
1637 LttvFilter
*filter
= event_viewer_data
->main_win_filter
;
1638 if(filter
!= NULL
&& filter
->head
!= NULL
)
1639 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
1640 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
1643 filter
= event_viewer_data
->filter
;
1644 if(filter
!= NULL
&& filter
->head
!= NULL
)
1645 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
1646 tfc
->t_context
->t
,tfc
,NULL
,NULL
))
1649 lttv_traceset_context_position_save(tfc
->t_context
->ts_context
,
1650 event_viewer_data
->current_time_get_first
);
1652 #endif // BABEL_CLEANUP
1657 gboolean
update_current_time(void * hook_data
, void * call_data
)
1660 //LttvEvent * e = (LttvEvent *)call_data;
1661 g_info("update_current_time");
1662 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1664 const LttTime
* current_time
= (LttTime
*)call_data
;
1666 lttvwindow_get_traceset(event_viewer_data
->tab
);
1668 /* If the currently selected event time != current time, set the first event
1669 * with this time as currently selected. */
1670 LttTime pos_time
= lttv_traceset_position_get_time(
1671 event_viewer_data
->currently_selected_position
);
1673 if(ltt_time_compare(pos_time
, *current_time
) != 0) {
1676 LttvTracesetPosition
*currentPosition
=
1677 lttv_traceset_create_time_position(ts
,*current_time
);
1678 /*seek to current position*/
1679 lttv_traceset_seek_to_position(currentPosition
);
1681 event_viewer_data
->currently_selected_position
=
1682 lttv_traceset_create_position(ts
);
1687 event_viewer_data
->report_position
= FALSE
;
1689 /* Simply update the current time : it is in the list */
1690 event_update_selection(event_viewer_data
);
1691 event_viewer_data
->report_position
= TRUE
;
1696 gboolean
update_current_position(void * hook_data
, void * call_data
)
1699 g_info("update_current_position");
1700 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1701 const LttvTracesetPosition
*current_pos
= (LttvTracesetPosition
*)call_data
;
1703 if(lttv_traceset_position_compare(
1704 event_viewer_data
->currently_selected_position
, current_pos
) != 0) {
1705 event_viewer_data
->currently_selected_position
= current_pos
;
1706 /* Simply update the current time : it is in the list */
1707 event_update_selection(event_viewer_data
);
1713 gboolean
timespan_changed(void * hook_data
, void * call_data
)
1716 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1717 LttvTraceset
* ts
= lttvwindow_get_traceset(event_viewer_data
->tab
);
1718 TimeInterval time_span
= lttv_traceset_get_time_span(ts
);
1722 end
= ltt_time_sub(time_span
.end_time
, time_span
.start_time
);
1723 event_viewer_data
->vadjust_c
->upper
= ltt_time_to_double(end
);
1725 if(event_viewer_data
->pos
->len
< event_viewer_data
->num_visible_events
) {
1728 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1730 request_background_data(event_viewer_data
);
1735 gboolean
traceset_changed(void * hook_data
, void * call_data
)
1738 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1739 LttvTraceset
* ts
= lttvwindow_get_traceset(event_viewer_data
->tab
);
1740 TimeInterval time_span
= lttv_traceset_get_time_span(ts
);
1743 gtk_list_store_clear(event_viewer_data
->store_m
);
1744 g_ptr_array_set_size(event_viewer_data
->pos
, 0);
1746 end
= ltt_time_sub(time_span
.end_time
, time_span
.start_time
);
1747 event_viewer_data
->vadjust_c
->upper
= ltt_time_to_double(end
);
1748 #ifdef BABEL_CLEANUP
1749 /* Reset the positions */
1750 lttv_traceset_destroy_position(event_viewer_data
->currently_selected_position
);
1751 lttv_traceset_destroy_position(event_viewer_data
->first_event
);
1752 lttv_traceset_destroy_position(event_viewer_data
->last_event
);
1754 event_viewer_data
->currently_selected_position
=
1755 lttv_traceset_create_position(ts
);
1756 event_viewer_data
->first_event
=
1757 lttv_traceset_create_position(ts
);
1758 event_viewer_data
->last_event
=
1759 lttv_traceset_create_position(ts
);
1761 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1762 #endif //babel_cleanup
1763 // event_viewer_data->vadjust_c->value = 0;
1765 request_background_data(event_viewer_data
);
1770 gboolean
filter_changed(void * hook_data
, void * call_data
)
1772 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1774 event_viewer_data
->main_win_filter
=
1775 (LttvFilter
*)call_data
;
1776 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1782 gint
evd_redraw_notify(void *hook_data
, void *call_data
)
1784 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1786 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1790 void gui_events_free(gpointer data
)
1792 #ifdef BABEL_CLEANUP
1793 LttvPluginEVD
*plugin_evd
= (LttvPluginEVD
*)data
;
1794 Tab
*tab
= plugin_evd
->evd
->tab
;
1795 EventViewerData
*event_viewer_data
= plugin_evd
->evd
;
1798 lttv_filter_destroy(plugin_evd
->evd
->filter
);
1801 lttv_hooks_remove(event_viewer_data
->event_hooks
,event_hook
);
1802 lttv_hooks_destroy(event_viewer_data
->event_hooks
);
1804 for(i
=0;i
<event_viewer_data
->pos
->len
;i
++) {
1805 LttvTracesetContextPosition
*cur_pos
=
1806 (LttvTracesetContextPosition
*)g_ptr_array_index(event_viewer_data
->pos
,
1808 lttv_traceset_context_position_destroy(cur_pos
);
1810 lttv_traceset_context_position_destroy(
1811 event_viewer_data
->currently_selected_position
);
1812 lttv_traceset_context_position_destroy(
1813 event_viewer_data
->first_event
);
1814 lttv_traceset_context_position_destroy(
1815 event_viewer_data
->last_event
);
1816 g_ptr_array_free(event_viewer_data
->pos
, TRUE
);
1818 lttvwindow_unregister_current_time_notify(tab
,
1819 update_current_time
, event_viewer_data
);
1820 lttvwindow_unregister_current_position_notify(tab
,
1821 update_current_position
, event_viewer_data
);
1822 //lttvwindow_unregister_show_notify(tab,
1823 // show_event_detail, event_viewer_data);
1824 lttvwindow_unregister_traceset_notify(tab
,
1825 traceset_changed
, event_viewer_data
);
1826 lttvwindow_unregister_timespan_notify(tab
,
1827 timespan_changed
,event_viewer_data
);
1828 lttvwindow_unregister_filter_notify(tab
,
1829 filter_changed
, event_viewer_data
);
1830 lttvwindow_unregister_redraw_notify(tab
,
1831 evd_redraw_notify
, event_viewer_data
);
1834 lttvwindowtraces_background_notify_remove(event_viewer_data
);
1836 g_event_viewer_data_list
= g_slist_remove(g_event_viewer_data_list
,
1838 //g_free(event_viewer_data);
1839 g_object_unref(plugin_evd
);
1840 #endif // BABEL_CLEANUP
1845 void gui_events_destructor(gpointer data
)
1847 LttvPluginEVD
*plugin_evd
= (LttvPluginEVD
*)data
;
1848 /* May already been done by GTK window closing */
1849 if(GTK_IS_WIDGET(plugin_evd
->parent
.top_widget
)){
1850 gtk_widget_destroy(plugin_evd
->parent
.top_widget
);
1857 * plugin's init function
1859 * This function initializes the Event Viewer functionnality through the
1862 static void init() {
1864 lttvwindow_register_constructor("guievents",
1866 "Insert Event Viewer",
1867 hGuiEventsInsert_xpm
,
1868 "Insert Event Viewer",
1872 void event_destroy_walk(gpointer data
, gpointer user_data
)
1874 gui_events_destructor((LttvPluginEVD
*)data
);
1878 * plugin's destroy function
1880 * This function releases the memory reserved by the module and unregisters
1881 * everything that has been registered in the gtkTraceSet API.
1883 static void destroy() {
1885 g_slist_foreach(g_event_viewer_data_list
, event_destroy_walk
, NULL
);
1886 g_slist_free(g_event_viewer_data_list
);
1888 lttvwindow_unregister_constructor(h_gui_events
);
1895 LTTV_MODULE("guievents", "Detailed events view", \
1896 "Graphical module to display a detailed event list", \
1897 init
, destroy
, "lttvwindow", "print")