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.
56 #include <ltt/event.h>
58 #include <ltt/trace.h>
59 #include <ltt/facility.h>
60 #include <lttv/module.h>
61 #include <lttv/hook.h>
62 #include <lttv/tracecontext.h>
63 #include <lttv/state.h>
64 #include <lttv/filter.h>
65 #include <lttv/print.h>
66 #include <lttvwindow/lttvwindow.h>
67 #include <lttvwindow/lttvwindowtraces.h>
68 #include <lttvwindow/lttv_plugin_tab.h>
70 #include "hGuiEventsInsert.xpm"
72 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
75 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
78 #define abs(a) (((a)<0)?(-a):(a))
79 #define max(a,b) ((a)>(b)?(a):(b))
81 /** Array containing instanced objects. Used when module is unloaded */
82 static GSList
*g_event_viewer_data_list
= NULL
;
84 typedef enum _ScrollDirection
{
93 typedef struct _EventViewerData
{
97 LttvHooks
* event_hooks
;
99 /* previous value is used to determine if it is a page up/down or
100 * step up/down, in which case we move of a certain amount of events (one or
101 * the number of events shown on the screen) instead of changing begin time.
103 double previous_value
;
105 //scroll window containing Tree View
106 GtkWidget
* scroll_win
;
108 /* Model containing list data */
109 GtkListStore
*store_m
;
111 GPtrArray
*pos
; /* Array of LttvTracesetContextPosition * */
113 GtkWidget
*top_widget
;
115 /* Widget to display the data in a columned list */
117 GtkAdjustment
*vtree_adjust_c
;
118 GtkWidget
*button
; /* a button of the header, used to get the header_height */
121 /* Vertical scrollbar and its adjustment */
122 GtkWidget
*vscroll_vc
;
123 GtkAdjustment
*vadjust_c
;
125 /* Selection handler */
126 GtkTreeSelection
*select_c
;
128 gint num_visible_events
;
130 LttvTracesetContextPosition
*currently_selected_position
;
131 gboolean update_cursor
; /* Speed optimisation : do not update cursor when
133 gboolean report_position
; /* do not report position when in current_time
136 LttvTracesetContextPosition
*first_event
; /* Time of the first event shown */
137 LttvTracesetContextPosition
*last_event
; /* Time of the first event shown */
139 LttvTracesetContextPosition
*current_time_get_first
;
141 LttvFilter
*main_win_filter
;
143 gint background_info_waiting
;
145 guint32 last_tree_update_time
; /* To filter out repeat keys */
149 /** hook functions for update time interval, current time ... */
150 gboolean
update_current_time(void * hook_data
, void * call_data
);
151 gboolean
update_current_position(void * hook_data
, void * call_data
);
152 //gboolean show_event_detail(void * hook_data, void * call_data);
153 gboolean
traceset_changed(void * hook_data
, void * call_data
);
154 gboolean
filter_changed(void * hook_data
, void * call_data
);
156 static void request_background_data(EventViewerData
*event_viewer_data
);
158 //! Event Viewer's constructor hook
159 GtkWidget
*h_gui_events(LttvPlugin
*plugin
);
160 //! Event Viewer's constructor
161 EventViewerData
*gui_events(LttvPluginTab
*ptab
);
162 //! Event Viewer's destructor
163 void gui_events_destructor(EventViewerData
*event_viewer_data
);
164 void gui_events_free(EventViewerData
*event_viewer_data
);
167 header_size_allocate(GtkWidget
*widget
,
168 GtkAllocation
*allocation
,
171 void tree_v_set_cursor(EventViewerData
*event_viewer_data
);
172 void tree_v_get_cursor(EventViewerData
*event_viewer_data
);
174 /* Prototype for selection handler callback */
175 static void tree_selection_changed_cb (GtkTreeSelection
*selection
,
177 static void v_scroll_cb (GtkAdjustment
*adjustment
, gpointer data
);
178 static void tree_v_size_allocate_cb (GtkWidget
*widget
, GtkAllocation
*alloc
,
180 static void tree_v_size_request_cb (GtkWidget
*widget
,
181 GtkRequisition
*requisition
, gpointer data
);
182 static void tree_v_cursor_changed_cb (GtkWidget
*widget
, gpointer data
);
183 static void tree_v_move_cursor_cb (GtkWidget
*widget
, GtkMovementStep arg1
,
184 gint arg2
, gpointer data
);
185 static gboolean
tree_v_scroll_handler (GtkWidget
*widget
, GdkEventScroll
*event
, gpointer data
);
186 static gboolean
key_handler(GtkWidget
*widget
, GdkEventKey
*event
,
189 static gint
redraw_notify(void *hook_data
, void *call_data
);
191 static void get_events(double time
, EventViewerData
*event_viewer_data
);
193 int event_hook(void *hook_data
, void *call_data
);
195 /* Enumeration of the columns */
199 TRACEFILE_NAME_COLUMN
,
212 * Event Viewer's constructor hook
214 * This constructor is given as a parameter to the menuitem and toolbar button
215 * registration. It creates the list.
216 * @param parent_window A pointer to the parent window.
217 * @return The widget created.
220 h_gui_events(LttvPlugin
*plugin
)
222 LttvPluginTab
*ptab
= LTTV_PLUGIN_TAB(plugin
);
223 EventViewerData
* event_viewer_data
= gui_events(ptab
) ;
224 if(event_viewer_data
)
225 return event_viewer_data
->top_widget
;
231 * Event Viewer's constructor
233 * This constructor is used to create EventViewerData data structure.
234 * @return The Event viewer data created.
237 gui_events(LttvPluginTab
*ptab
)
240 GtkTreeViewColumn
*column
;
241 GtkCellRenderer
*renderer
;
242 EventViewerData
* event_viewer_data
= g_new(EventViewerData
,1) ;
243 Tab
*tab
= ptab
->tab
;
244 event_viewer_data
->tab
= tab
;
245 event_viewer_data
->ptab
= ptab
;
247 LttvTracesetContext
* tsc
=
248 lttvwindow_get_traceset_context(event_viewer_data
->tab
);
251 event_viewer_data
->event_hooks
= lttv_hooks_new();
252 lttv_hooks_add(event_viewer_data
->event_hooks
,
257 lttvwindow_register_current_time_notify(tab
,
258 update_current_time
,event_viewer_data
);
259 lttvwindow_register_current_position_notify(tab
,
260 update_current_position
,event_viewer_data
);
261 lttvwindow_register_traceset_notify(tab
,
262 traceset_changed
,event_viewer_data
);
263 lttvwindow_register_filter_notify(tab
,
264 filter_changed
, event_viewer_data
);
265 lttvwindow_register_redraw_notify(tab
,
266 redraw_notify
, event_viewer_data
);
269 event_viewer_data
->scroll_win
= gtk_scrolled_window_new (NULL
, NULL
);
270 gtk_widget_show (event_viewer_data
->scroll_win
);
271 gtk_scrolled_window_set_policy(
272 GTK_SCROLLED_WINDOW(event_viewer_data
->scroll_win
),
273 GTK_POLICY_AUTOMATIC
, GTK_POLICY_NEVER
);
275 event_viewer_data
->currently_selected_position
=
276 lttv_traceset_context_position_new(tsc
);
277 event_viewer_data
->first_event
=
278 lttv_traceset_context_position_new(tsc
);
279 event_viewer_data
->last_event
=
280 lttv_traceset_context_position_new(tsc
);
282 event_viewer_data
->main_win_filter
= lttvwindow_get_filter(tab
);
284 event_viewer_data
->update_cursor
= TRUE
;
285 event_viewer_data
->report_position
= TRUE
;
287 event_viewer_data
->last_tree_update_time
= 0;
289 /* Create a model for storing the data list */
290 event_viewer_data
->store_m
= gtk_list_store_new (
291 N_COLUMNS
, /* Total number of columns */
292 G_TYPE_STRING
, /* Trace name */
293 G_TYPE_STRING
, /* Tracefile name */
294 G_TYPE_UINT
, /* CPUID */
295 G_TYPE_STRING
, /* Event */
296 G_TYPE_STRING
, /* Facility */
297 G_TYPE_UINT
, /* Time s */
298 G_TYPE_UINT
, /* Time ns */
299 G_TYPE_INT
, /* PID */
300 G_TYPE_STRING
, /* Event's description */
301 G_TYPE_POINTER
);/* Position (not shown) */
303 event_viewer_data
->pos
= g_ptr_array_sized_new(10);
305 /* Create the viewer widget for the columned list */
306 event_viewer_data
->tree_v
=
307 gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data
->store_m
));
309 g_signal_connect (G_OBJECT (event_viewer_data
->tree_v
), "size-allocate",
310 G_CALLBACK (tree_v_size_allocate_cb
),
312 g_signal_connect (G_OBJECT (event_viewer_data
->tree_v
), "size-request",
313 G_CALLBACK (tree_v_size_request_cb
),
316 g_signal_connect (G_OBJECT (event_viewer_data
->tree_v
), "cursor-changed",
317 G_CALLBACK (tree_v_cursor_changed_cb
),
320 g_signal_connect (G_OBJECT (event_viewer_data
->tree_v
), "move-cursor",
321 G_CALLBACK (tree_v_move_cursor_cb
),
324 g_signal_connect (G_OBJECT(event_viewer_data
->tree_v
), "key-press-event",
325 G_CALLBACK(key_handler
),
328 g_signal_connect (G_OBJECT(event_viewer_data
->tree_v
), "scroll-event",
329 G_CALLBACK(tree_v_scroll_handler
),
332 // Use on each column!
333 //gtk_tree_view_column_set_sizing(event_viewer_data->tree_v,
334 //GTK_TREE_VIEW_COLUMN_FIXED);
336 /* The view now holds a reference. We can get rid of our own
338 g_object_unref (G_OBJECT (event_viewer_data
->store_m
));
341 /* Create a column, associating the "text" attribute of the
342 * cell_renderer to the first column of the model */
343 /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */
344 renderer
= gtk_cell_renderer_text_new ();
345 column
= gtk_tree_view_column_new_with_attributes ("Trace",
347 "text", TRACE_NAME_COLUMN
,
349 gtk_tree_view_column_set_alignment (column
, 0.0);
350 gtk_tree_view_column_set_fixed_width (column
, 120);
351 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
354 event_viewer_data
->button
= column
->button
;
356 g_signal_connect (G_OBJECT(event_viewer_data
->button
),
358 G_CALLBACK(header_size_allocate
),
359 (gpointer
)event_viewer_data
);
363 renderer
= gtk_cell_renderer_text_new ();
364 column
= gtk_tree_view_column_new_with_attributes ("Tracefile",
366 "text", TRACEFILE_NAME_COLUMN
,
368 gtk_tree_view_column_set_alignment (column
, 0.0);
369 gtk_tree_view_column_set_fixed_width (column
, 120);
370 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
374 renderer
= gtk_cell_renderer_text_new ();
375 column
= gtk_tree_view_column_new_with_attributes ("CPUID",
377 "text", CPUID_COLUMN
,
379 gtk_tree_view_column_set_alignment (column
, 0.0);
380 gtk_tree_view_column_set_fixed_width (column
, 45);
381 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
384 renderer
= gtk_cell_renderer_text_new ();
385 column
= gtk_tree_view_column_new_with_attributes ("Event",
387 "text", EVENT_COLUMN
,
389 gtk_tree_view_column_set_alignment (column
, 0.0);
390 gtk_tree_view_column_set_fixed_width (column
, 120);
391 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
394 renderer
= gtk_cell_renderer_text_new ();
395 column
= gtk_tree_view_column_new_with_attributes ("Facility",
397 "text", FACILITY_COLUMN
,
399 gtk_tree_view_column_set_alignment (column
, 0.0);
400 gtk_tree_view_column_set_fixed_width (column
, 120);
401 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
404 renderer
= gtk_cell_renderer_text_new ();
405 column
= gtk_tree_view_column_new_with_attributes ("Time (s)",
407 "text", TIME_S_COLUMN
,
409 gtk_tree_view_column_set_alignment (column
, 1.0);
410 gtk_tree_view_column_set_fixed_width (column
, 120);
411 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
414 renderer
= gtk_cell_renderer_text_new ();
415 column
= gtk_tree_view_column_new_with_attributes ("Time (ns)",
417 "text", TIME_NS_COLUMN
,
419 gtk_tree_view_column_set_alignment (column
, 1.0);
420 gtk_tree_view_column_set_fixed_width (column
, 120);
421 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
425 renderer
= gtk_cell_renderer_text_new ();
426 column
= gtk_tree_view_column_new_with_attributes ("PID",
430 gtk_tree_view_column_set_alignment (column
, 1.0);
431 gtk_tree_view_column_set_fixed_width (column
, 45);
432 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
435 renderer
= gtk_cell_renderer_text_new ();
436 column
= gtk_tree_view_column_new_with_attributes ("Event Description",
438 "text", EVENT_DESCR_COLUMN
,
440 gtk_tree_view_column_set_alignment (column
, 0.0);
441 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data
->tree_v
),
445 /* Setup the selection handler */
446 event_viewer_data
->select_c
=
447 gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data
->tree_v
));
448 gtk_tree_selection_set_mode (event_viewer_data
->select_c
,
449 GTK_SELECTION_SINGLE
);
450 g_signal_connect (G_OBJECT (event_viewer_data
->select_c
), "changed",
451 G_CALLBACK (tree_selection_changed_cb
),
454 gtk_container_add (GTK_CONTAINER (event_viewer_data
->scroll_win
),
455 event_viewer_data
->tree_v
);
457 event_viewer_data
->hbox_v
= gtk_hbox_new(0, 0);
458 event_viewer_data
->top_widget
= event_viewer_data
->hbox_v
;
459 gtk_box_pack_start(GTK_BOX(event_viewer_data
->hbox_v
),
460 event_viewer_data
->scroll_win
, TRUE
, TRUE
, 0);
462 gtk_container_set_border_width(GTK_CONTAINER(event_viewer_data
->hbox_v
), 1);
464 /* Create vertical scrollbar and pack it */
465 event_viewer_data
->vscroll_vc
= gtk_vscrollbar_new(NULL
);
466 gtk_range_set_update_policy (GTK_RANGE(event_viewer_data
->vscroll_vc
),
467 GTK_UPDATE_CONTINUOUS
);
468 // Changed by MD : more user friendly :)
469 //GTK_UPDATE_DISCONTINUOUS);
470 gtk_box_pack_start(GTK_BOX(event_viewer_data
->hbox_v
),
471 event_viewer_data
->vscroll_vc
, FALSE
, TRUE
, 0);
473 /* Get the vertical scrollbar's adjustment */
474 event_viewer_data
->vadjust_c
=
475 gtk_range_get_adjustment(GTK_RANGE(event_viewer_data
->vscroll_vc
));
476 event_viewer_data
->vtree_adjust_c
= gtk_tree_view_get_vadjustment(
477 GTK_TREE_VIEW (event_viewer_data
->tree_v
));
479 g_signal_connect (G_OBJECT (event_viewer_data
->vadjust_c
), "value-changed",
480 G_CALLBACK (v_scroll_cb
),
482 /* Set the upper bound to the last event number */
483 event_viewer_data
->previous_value
= 0;
484 event_viewer_data
->vadjust_c
->lower
= 0.0;
485 //event_viewer_data->vadjust_c->upper = event_viewer_data->number_of_events;
486 event_viewer_data
->vadjust_c
->value
= 0.0;
487 event_viewer_data
->vadjust_c
->step_increment
= 1.0;
488 event_viewer_data
->vadjust_c
->page_increment
= 2.0;
489 // event_viewer_data->vtree_adjust_c->upper;
490 event_viewer_data
->vadjust_c
->page_size
= 2.0;
491 // event_viewer_data->vtree_adjust_c->upper;
492 /* Raw event trace */
493 gtk_widget_show(event_viewer_data
->hbox_v
);
494 gtk_widget_show(event_viewer_data
->tree_v
);
495 gtk_widget_show(event_viewer_data
->vscroll_vc
);
497 /* Add the object's information to the module's array */
498 g_event_viewer_data_list
= g_slist_append(g_event_viewer_data_list
,
501 event_viewer_data
->num_visible_events
= 1;
503 //get the life span of the traceset and set the upper of the scroll bar
505 TimeInterval time_span
= tsc
->time_span
;
506 end
= ltt_time_sub(time_span
.end_time
, time_span
.start_time
);
508 event_viewer_data
->vadjust_c
->upper
=
509 ltt_time_to_double(end
);
511 /* Set the Selected Event */
512 // tree_v_set_cursor(event_viewer_data);
514 // event_viewer_data->current_time_updated = FALSE;
516 g_object_set_data_full(
517 G_OBJECT(event_viewer_data
->hbox_v
),
520 (GDestroyNotify
)gui_events_free
);
522 event_viewer_data
->background_info_waiting
= 0;
524 request_background_data(event_viewer_data
);
527 return event_viewer_data
;
532 static gint
background_ready(void *hook_data
, void *call_data
)
534 EventViewerData
*event_viewer_data
= (EventViewerData
*)hook_data
;
535 LttvTrace
*trace
= (LttvTrace
*)call_data
;
537 event_viewer_data
->background_info_waiting
--;
539 if(event_viewer_data
->background_info_waiting
== 0) {
540 g_message("event viewer : background computation data ready.");
542 redraw_notify(event_viewer_data
, NULL
);
549 static void request_background_data(EventViewerData
*event_viewer_data
)
551 LttvTracesetContext
* tsc
=
552 lttvwindow_get_traceset_context(event_viewer_data
->tab
);
553 gint num_traces
= lttv_traceset_number(tsc
->ts
);
557 LttvHooks
*background_ready_hook
=
559 lttv_hooks_add(background_ready_hook
, background_ready
, event_viewer_data
,
561 event_viewer_data
->background_info_waiting
= 0;
563 for(i
=0;i
<num_traces
;i
++) {
564 trace
= lttv_traceset_get(tsc
->ts
, i
);
566 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace
)==FALSE
) {
568 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
570 /* We first remove requests that could have been done for the same
571 * information. Happens when two viewers ask for it before servicing
574 if(!lttvwindowtraces_background_request_find(trace
, "state"))
575 lttvwindowtraces_background_request_queue(
576 main_window_get_widget(event_viewer_data
->tab
), trace
, "state");
577 lttvwindowtraces_background_notify_queue(event_viewer_data
,
581 background_ready_hook
);
582 event_viewer_data
->background_info_waiting
++;
583 } else { /* in progress */
585 lttvwindowtraces_background_notify_current(event_viewer_data
,
589 background_ready_hook
);
590 event_viewer_data
->background_info_waiting
++;
593 /* Data ready. Be its nature, this viewer doesn't need to have
594 * its data ready hook called htere, because a background
595 * request is always linked with a redraw.
601 lttv_hooks_destroy(background_ready_hook
);
606 header_size_allocate(GtkWidget
*widget
,
607 GtkAllocation
*allocation
,
610 EventViewerData
*event_viewer_data
= (EventViewerData
*)user_data
;
612 event_viewer_data
->header_height
= allocation
->height
;
618 void tree_v_set_cursor(EventViewerData
*event_viewer_data
)
622 g_debug("set cursor cb");
625 if(event_viewer_data
->currently_selected_event
!= -1)
627 path
= gtk_tree_path_new_from_indices(
628 event_viewer_data
->currently_selected_event
,
631 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
633 gtk_tree_path_free(path
);
638 void tree_v_get_cursor(EventViewerData
*event_viewer_data
)
643 g_debug("get cursor cb");
647 gtk_tree_view_get_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
649 indices
= gtk_tree_path_get_indices(path
);
652 event_viewer_data
->currently_selected_event
= indices
[0];
654 event_viewer_data
->currently_selected_event
= -1;
656 gtk_tree_path_free(path
);
660 /* Filter out the key repeats that come too fast */
661 static gboolean
key_handler(GtkWidget
*widget
, GdkEventKey
*event
,
664 EventViewerData
*evd
= (EventViewerData
*)user_data
;
666 g_debug("event time : %u , last time : %u", event
->time
,
667 evd
->last_tree_update_time
);
669 if(guint32_before(event
->time
, evd
->last_tree_update_time
))
675 void tree_v_move_cursor_cb (GtkWidget
*widget
,
676 GtkMovementStep arg1
,
680 GtkTreePath
*path
; // = gtk_tree_path_new();
683 EventViewerData
*event_viewer_data
= (EventViewerData
*)data
;
685 g_debug("move cursor cb");
686 //gtk_tree_view_get_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
690 /* No prior cursor, put it at beginning of page
691 * and let the execution do */
692 // path = gtk_tree_path_new_from_indices(0, -1);
693 // gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
694 // path, NULL, FALSE);
697 //indices = gtk_tree_path_get_indices(path);
699 //value = gtk_adjustment_get_value(event_viewer_data->vadjust_c);
701 /* If events request pending, do nothing*/
702 if(lttvwindow_events_request_pending(event_viewer_data
->tab
)) return;
704 /* If no prior position... */
707 lttv_traceset_context_position_get_time(
708 event_viewer_data
->currently_selected_position
),
709 ltt_time_infinite
) == 0) {
711 path
= gtk_tree_path_new_from_indices(0, -1);
712 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
715 gtk_tree_path_free(path
);
721 g_debug("tree view move cursor : arg1 is %u and arg2 is %d",
725 case GTK_MOVEMENT_DISPLAY_LINES
:
727 /* Move one line down */
728 if(event_viewer_data
->pos
->len
> 0) {
729 LttvTracesetContextPosition
*end_pos
=
730 (LttvTracesetContextPosition
*)g_ptr_array_index(
731 event_viewer_data
->pos
,
732 event_viewer_data
->pos
->len
-1);
733 if(lttv_traceset_context_pos_pos_compare(end_pos
,
734 event_viewer_data
->currently_selected_position
) == 0) {
735 /* Must get down one event and select the last one */
736 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
737 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
738 event_viewer_data
->update_cursor
= FALSE
;
739 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
740 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 1);
741 event_viewer_data
->update_cursor
= TRUE
;
742 if(event_viewer_data
->pos
->len
> 0) {
743 path
= gtk_tree_path_new_from_indices(
744 max(0, event_viewer_data
->pos
->len
- 1), -1);
746 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
748 gtk_tree_path_free(path
);
753 /* Must get down one event and select the last one */
754 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
755 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
756 event_viewer_data
->update_cursor
= FALSE
;
757 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
758 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 1);
759 event_viewer_data
->update_cursor
= TRUE
;
760 if(event_viewer_data
->pos
->len
> 0) {
761 path
= gtk_tree_path_new_from_indices(
762 max(0, event_viewer_data
->pos
->len
- 1), -1);
764 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
766 gtk_tree_path_free(path
);
772 if(event_viewer_data
->pos
->len
> 0) {
773 /* Move one line up */
774 LttvTracesetContextPosition
*begin_pos
=
775 (LttvTracesetContextPosition
*)g_ptr_array_index(
776 event_viewer_data
->pos
,
778 if(lttv_traceset_context_pos_pos_compare(begin_pos
,
779 event_viewer_data
->currently_selected_position
) == 0) {
780 /* Must get up one event and select the first one */
781 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
782 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
783 event_viewer_data
->update_cursor
= FALSE
;
784 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
785 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 1);
786 event_viewer_data
->update_cursor
= TRUE
;
787 if(event_viewer_data
->pos
->len
> 0) {
788 path
= gtk_tree_path_new_from_indices(
791 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
793 gtk_tree_path_free(path
);
798 /* Must get up one event and select the first one */
799 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
800 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
801 event_viewer_data
->update_cursor
= FALSE
;
802 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
803 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 1);
804 event_viewer_data
->update_cursor
= TRUE
;
805 if(event_viewer_data
->pos
->len
> 0) {
806 path
= gtk_tree_path_new_from_indices(
809 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
811 gtk_tree_path_free(path
);
817 case GTK_MOVEMENT_PAGES
:
819 /* Move one page down */
820 if(event_viewer_data
->pos
->len
> 0) {
821 LttvTracesetContextPosition
*end_pos
=
822 (LttvTracesetContextPosition
*)g_ptr_array_index(
823 event_viewer_data
->pos
,
824 event_viewer_data
->pos
->len
-1);
825 if(lttv_traceset_context_pos_pos_compare(end_pos
,
826 event_viewer_data
->currently_selected_position
) == 0) {
827 /* Must get down one page and select the last one */
828 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
829 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
830 event_viewer_data
->update_cursor
= FALSE
;
831 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
832 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 2);
833 event_viewer_data
->update_cursor
= TRUE
;
834 if(event_viewer_data
->pos
->len
> 0) {
835 path
= gtk_tree_path_new_from_indices(
836 event_viewer_data
->pos
->len
- 1, -1);
838 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
840 gtk_tree_path_free(path
);
845 /* Must get down one page and select the last one */
846 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
847 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
848 event_viewer_data
->update_cursor
= FALSE
;
849 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
850 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 2);
851 event_viewer_data
->update_cursor
= TRUE
;
852 if(event_viewer_data
->pos
->len
> 0) {
853 path
= gtk_tree_path_new_from_indices(
854 event_viewer_data
->pos
->len
- 1, -1);
856 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
858 gtk_tree_path_free(path
);
863 /* Move one page up */
864 if(event_viewer_data
->pos
->len
> 0) {
865 LttvTracesetContextPosition
*begin_pos
=
866 (LttvTracesetContextPosition
*)g_ptr_array_index(
867 event_viewer_data
->pos
,
869 if(lttv_traceset_context_pos_pos_compare(begin_pos
,
870 event_viewer_data
->currently_selected_position
) == 0) {
871 /* Must get up one page and select the first one */
872 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
873 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
874 event_viewer_data
->update_cursor
= FALSE
;
875 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
876 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 2);
877 event_viewer_data
->update_cursor
= TRUE
;
878 if(event_viewer_data
->pos
->len
> 0) {
879 path
= gtk_tree_path_new_from_indices(
882 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
884 gtk_tree_path_free(path
);
889 /* Must get up one page and select the first one */
890 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
891 GTK_TREE_VIEW(event_viewer_data
->tree_v
)));
892 event_viewer_data
->update_cursor
= FALSE
;
893 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
894 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 2);
895 event_viewer_data
->update_cursor
= TRUE
;
896 if(event_viewer_data
->pos
->len
> 0) {
897 path
= gtk_tree_path_new_from_indices(
900 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
902 gtk_tree_path_free(path
);
912 //gtk_tree_path_free(path);
915 if(arg1
== GTK_MOVEMENT_DISPLAY_LINES
)
920 /* move one line down */
921 if(indices
[0]) // Do we need an empty field here (before first)?
923 if(value
+ event_viewer_data
->num_visible_events
<=
924 event_viewer_data
->number_of_events
-1)
926 event_viewer_data
->currently_selected_event
+= 1;
927 // gtk_adjustment_set_value(event_viewer_data->vadjust_c, value+1);
928 //gtk_tree_path_free(path);
929 //path = gtk_tree_path_new_from_indices(event_viewer_data->num_visible_events-1, -1);
930 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
931 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
935 /* Move one line up */
940 event_viewer_data
->currently_selected_event
-= 1;
941 // gtk_adjustment_set_value(event_viewer_data->vadjust_c, value-1);
942 //gtk_tree_path_free(path);
943 //path = gtk_tree_path_new_from_indices(0, -1);
944 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
945 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
951 if(arg1
== GTK_MOVEMENT_PAGES
)
956 if(event_viewer_data
->num_visible_events
== 1)
958 /* move one page down */
959 if(value
+ event_viewer_data
->num_visible_events
-1 <=
960 event_viewer_data
->number_of_events
)
962 event_viewer_data
->currently_selected_event
+=
963 event_viewer_data
->num_visible_events
-1;
964 // gtk_adjustment_set_value(event_viewer_data->vadjust_c,
965 // value+(event_viewer_data->num_visible_events-1));
966 //gtk_tree_path_free(path);
967 //path = gtk_tree_path_new_from_indices(0, -1);
968 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
969 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
972 /* Move one page up */
973 if(event_viewer_data
->num_visible_events
== 1)
976 if(indices
[0] < event_viewer_data
->num_visible_events
- 2 )
978 if(value
- (event_viewer_data
->num_visible_events
-1) >= 0)
980 event_viewer_data
->currently_selected_event
-=
981 event_viewer_data
->num_visible_events
-1;
983 // gtk_adjustment_set_value(event_viewer_data->vadjust_c,
984 // value-(event_viewer_data->num_visible_events-1));
985 //gtk_tree_path_free(path);
986 //path = gtk_tree_path_new_from_indices(0, -1);
987 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
988 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
991 /* Go to first Event */
992 event_viewer_data
->currently_selected_event
== 0 ;
993 // gtk_adjustment_set_value(event_viewer_data->vadjust_c,
995 //gtk_tree_path_free(path);
996 //path = gtk_tree_path_new_from_indices(0, -1);
997 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
998 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
1005 if(arg1
== GTK_MOVEMENT_BUFFER_ENDS
)
1007 /* Move to the ends of the buffer */
1010 /* move end of buffer */
1011 event_viewer_data
->currently_selected_event
=
1012 event_viewer_data
->number_of_events
-1 ;
1013 // gtk_adjustment_set_value(event_viewer_data->vadjust_c,
1014 // event_viewer_data->number_of_events -
1015 // event_viewer_data->num_visible_events);
1016 //gtk_tree_path_free(path);
1017 //path = gtk_tree_path_new_from_indices(event_viewer_data->num_visible_events-1, -1);
1018 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
1019 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
1021 /* Move beginning of buffer */
1022 event_viewer_data
->currently_selected_event
= 0 ;
1023 // gtk_adjustment_set_value(event_viewer_data->vadjust_c, 0);
1024 //gtk_tree_path_free(path);
1025 //path = gtk_tree_path_new_from_indices(0, -1);
1026 //gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), path, NULL, FALSE);
1027 g_signal_stop_emission_by_name(G_OBJECT(widget
), "move-cursor");
1034 gboolean
tree_v_scroll_handler (GtkWidget
*widget
, GdkEventScroll
*event
, gpointer data
)
1036 EventViewerData
*event_viewer_data
= (EventViewerData
*) data
;
1037 Tab
*tab
= event_viewer_data
->tab
;
1039 switch(event
->direction
) {
1041 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
1042 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) - 1);
1044 case GDK_SCROLL_DOWN
:
1045 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
1046 gtk_adjustment_get_value(event_viewer_data
->vadjust_c
) + 1);
1049 g_error("Only scroll up and down expected");
1054 void tree_v_cursor_changed_cb (GtkWidget
*widget
, gpointer data
)
1056 EventViewerData
*event_viewer_data
= (EventViewerData
*) data
;
1057 Tab
*tab
= event_viewer_data
->tab
;
1059 GtkTreeModel
* model
= GTK_TREE_MODEL(event_viewer_data
->store_m
);
1061 LttvTracesetContextPosition
*pos
;
1063 g_debug("cursor changed cb");
1065 /* On cursor change, modify the currently selected event by calling
1066 * the right API function */
1067 if(event_viewer_data
->report_position
) {
1068 if(event_viewer_data
->pos
->len
> 0) {
1069 gtk_tree_view_get_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
1072 if(gtk_tree_model_get_iter(model
,&iter
,path
)){
1073 gtk_tree_model_get(model
, &iter
, POSITION_COLUMN
, &pos
, -1);
1075 if(lttv_traceset_context_pos_pos_compare(pos
,
1076 event_viewer_data
->currently_selected_position
) != 0)
1077 lttvwindow_report_current_position(tab
, pos
);
1079 g_warning("Can not get iter\n");
1081 gtk_tree_path_free(path
);
1088 static void tree_selection_changed_cb (GtkTreeSelection
*selection
,
1091 g_debug("tree sel changed cb");
1092 EventViewerData
*event_viewer_data
= (EventViewerData
*) data
;
1094 /* Set the cursor to currently selected event */
1095 GtkTreeModel
* model
= GTK_TREE_MODEL(event_viewer_data
->store_m
);
1097 LttvTracesetContextPosition
*pos
;
1099 GtkTreePath
*tree_path
;
1101 for(i
=0;i
<event_viewer_data
->num_visible_events
;i
++) {
1102 tree_path
= gtk_tree_path_new_from_indices(
1105 if(gtk_tree_model_get_iter(model
,&iter
,tree_path
)){
1106 gtk_tree_model_get(model
, &iter
, POSITION_COLUMN
, &pos
, -1);
1108 if(lttv_traceset_context_pos_pos_compare(pos
,
1109 event_viewer_data
->currently_selected_position
) == 0) {
1111 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
1112 tree_path
, NULL
, FALSE
);
1117 g_warning("Can not get iter\n");
1119 gtk_tree_path_free(tree_path
);
1125 static gint
key_snooper(GtkWidget
*grab_widget
, GdkEventKey
*event
,
1132 /* This callback may be recalled after a step up/down, but we don't want to lose
1133 * the exact position : what we do is that we only set the value if it has
1134 * changed : a step up/down that doesn't change the time value of the first
1135 * event won't trigger a scrollbar change. */
1137 void v_scroll_cb (GtkAdjustment
*adjustment
, gpointer data
)
1139 EventViewerData
*event_viewer_data
= (EventViewerData
*)data
;
1140 LttvTracesetStats
*tss
=
1141 lttvwindow_get_traceset_stats(event_viewer_data
->tab
);
1142 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
1143 g_debug("SCROLL begin");
1144 g_debug("SCROLL values : %g , %g, %g",
1145 adjustment
->value
, event_viewer_data
->previous_value
,
1146 (adjustment
->value
- event_viewer_data
->previous_value
));
1148 LttTime new_time_off
= ltt_time_from_double(adjustment
->value
);
1149 LttTime old_time_off
= ltt_time_from_double(event_viewer_data
->previous_value
);
1150 g_debug("SCROLL time values %lu.%lu, %lu.%lu", new_time_off
.tv_sec
,
1151 new_time_off
.tv_nsec
, old_time_off
.tv_sec
, old_time_off
.tv_nsec
);
1152 /* If same value : nothing to update */
1153 if(ltt_time_compare(new_time_off
, old_time_off
) == 0)
1156 //LttTime old_time = event_viewer_data->first_event;
1159 //gint snoop = gtk_key_snooper_install(key_snooper, NULL);
1161 get_events(adjustment
->value
, event_viewer_data
);
1163 //gtk_key_snooper_remove(snoop);
1165 LttTime time
= ltt_time_sub(event_viewer_data
->first_event
,
1166 tsc
->time_span
.start_time
);
1167 double value
= ltt_time_to_double(time
);
1168 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
, value
);
1170 if(event_viewer_data
->currently_selected_event
!= -1) {
1172 tree_path
= gtk_tree_path_new_from_indices(
1173 event_viewer_data
->currently_selected_event
,
1176 // gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v), tree_path,
1178 gtk_tree_path_free(tree_path
);
1181 g_debug("SCROLL end");
1184 static __inline gint
get_cell_height(GtkTreeView
*TreeView
)
1187 GtkTreeViewColumn
*column
= gtk_tree_view_get_column(TreeView
, 0);
1189 gtk_tree_view_column_cell_get_size(column
, NULL
, NULL
, NULL
, NULL
, &height
);
1191 gint vertical_separator
;
1192 gtk_widget_style_get (GTK_WIDGET (TreeView
),
1193 "vertical-separator", &vertical_separator
,
1196 height
+= vertical_separator
;
1201 void tree_v_size_allocate_cb (GtkWidget
*widget
, GtkAllocation
*alloc
, gpointer data
)
1203 EventViewerData
*event_viewer_data
= (EventViewerData
*)data
;
1204 gint cell_height
= get_cell_height(GTK_TREE_VIEW(event_viewer_data
->tree_v
));
1205 gint last_num_visible_events
= event_viewer_data
->num_visible_events
;
1206 gdouble exact_num_visible
;
1208 exact_num_visible
= ( alloc
->height
-
1209 event_viewer_data
->header_height
)
1210 / (double)cell_height
;
1212 event_viewer_data
->num_visible_events
= ceil(exact_num_visible
) ;
1215 event_viewer_data->vadjust_c->page_increment =
1216 floor(exact_num_visible);
1217 event_viewer_data->vadjust_c->page_size =
1218 floor(exact_num_visible);
1221 g_debug("size allocate : last_num_visible_events : %d,\
1222 num_visible_events : %d",
1223 last_num_visible_events
,
1224 event_viewer_data
->num_visible_events
);
1225 if(event_viewer_data
->num_visible_events
!= last_num_visible_events
)
1227 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1233 void tree_v_size_request_cb (GtkWidget
*widget
, GtkRequisition
*requisition
, gpointer data
)
1236 EventViewerData
*event_viewer_data
= (EventViewerData
*)data
;
1237 gint cell_height
= get_cell_height(GTK_TREE_VIEW(event_viewer_data
->tree_v
));
1239 h
= cell_height
+ event_viewer_data
->header_height
;
1240 requisition
->height
= h
;
1245 gboolean
show_event_detail(void * hook_data
, void * call_data
)
1247 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1248 LttvTracesetContext
* tsc
= lttvwindow_get_traceset_context(event_viewer_data
->tab
);
1250 if(event_viewer_data
->event_fields_queue_tmp
->length
== 0 &&
1251 event_viewer_data
->event_fields_queue
->length
== 0){
1252 event_viewer_data
->shown
= FALSE
;
1256 if(event_viewer_data
->shown
== FALSE
){
1257 event_viewer_data
->shown
= TRUE
;
1258 update_raw_data_array(event_viewer_data
,
1259 event_viewer_data
->event_fields_queue_tmp
->length
);
1261 get_data(event_viewer_data
->vadjust_c
->value
,
1262 event_viewer_data
->num_visible_events
,
1265 remove_context_hooks(event_viewer_data
,tsc
);
1278 static void get_events(double new_value
, EventViewerData
*event_viewer_data
)
1280 GtkTreePath
*tree_path
;
1281 LttvTracesetStats
*tss
=
1282 lttvwindow_get_traceset_stats(event_viewer_data
->tab
);
1283 LttvTracesetContext
*tsc
= (LttvTracesetContext
*)tss
;
1285 gboolean seek_by_time
;
1287 double value
= new_value
- event_viewer_data
->previous_value
;
1289 /* See where we have to scroll... */
1290 ScrollDirection direction
;
1291 gint relative_position
;
1294 if(value
>= -1.0) direction
= SCROLL_STEP_UP
;
1296 if(value
>= -2.0) direction
= SCROLL_PAGE_UP
;
1297 else direction
= SCROLL_JUMP
;
1299 } else if(value
> 0.8) {
1300 if(value
<= 1.0) direction
= SCROLL_STEP_DOWN
;
1302 if(value
<= 2.0) direction
= SCROLL_PAGE_DOWN
;
1303 else direction
= SCROLL_JUMP
;
1305 } else direction
= SCROLL_NONE
; /* 0.0 */
1309 case SCROLL_STEP_UP
:
1310 g_debug("get_events : SCROLL_STEP_UP");
1311 relative_position
= -1;
1314 case SCROLL_STEP_DOWN
:
1315 g_debug("get_events : SCROLL_STEP_DOWN");
1316 relative_position
= 1;
1319 case SCROLL_PAGE_UP
:
1320 g_debug("get_events : SCROLL_PAGE_UP");
1321 relative_position
= -(event_viewer_data
->num_visible_events
);
1324 case SCROLL_PAGE_DOWN
:
1325 g_debug("get_events : SCROLL_PAGE_DOWN");
1326 relative_position
= event_viewer_data
->num_visible_events
;
1330 g_debug("get_events : SCROLL_JUMP");
1334 g_debug("get_events : SCROLL_NONE");
1335 relative_position
= 0;
1340 LttTime time
= ltt_time_from_double(new_value
);
1341 time
= ltt_time_add(tsc
->time_span
.start_time
, time
);
1345 LttvTracesetContextPosition
*pos
=
1346 lttv_traceset_context_position_new(tsc
);
1348 /* Remember the beginning position */
1349 if(event_viewer_data
->pos
->len
> 0) {
1350 LttvTracesetContextPosition
*first_pos
=
1351 (LttvTracesetContextPosition
*)g_ptr_array_index(
1352 event_viewer_data
->pos
,
1354 lttv_traceset_context_position_copy(pos
, first_pos
);
1356 if(relative_position
>= 0) {
1357 LttTime first_event_time
=
1358 lttv_traceset_context_position_get_time(
1360 lttv_state_traceset_seek_time_closest((LttvTracesetState
*)tsc
,
1362 lttv_process_traceset_middle(tsc
, ltt_time_infinite
,
1366 } else if(relative_position
< 0) {
1367 g_assert(lttv_process_traceset_seek_position(tsc
, pos
) == 0);
1370 /* There is nothing in the list : simply seek to the time value. */
1371 lttv_state_traceset_seek_time_closest((LttvTracesetState
*)tsc
,
1373 lttv_process_traceset_middle(tsc
, time
, G_MAXUINT
,
1377 /* Note that, as we mess with the tsc position, this function CANNOT be called
1378 * from a hook inside the lttv_process_traceset_middle. */
1379 /* As the lttvwindow API keeps a sync_position inside the tsc to go back at
1380 * the right spot after being interrupted, it's ok to change the tsc position,
1381 * as long as we do not touch the sync_position. */
1383 /* Get the beginning position of the read (with seek backward or seek forward)
1385 if(relative_position
> 0) {
1387 count
= lttv_process_traceset_seek_n_forward(tsc
, relative_position
,
1388 event_viewer_data
->main_win_filter
);
1389 } else if(relative_position
< 0) {
1392 /* Get an idea of currently shown event dispersion */
1393 LttTime first_event_time
=
1394 lttv_traceset_context_position_get_time(event_viewer_data
->first_event
);
1395 LttTime last_event_time
=
1396 lttv_traceset_context_position_get_time(event_viewer_data
->last_event
);
1397 LttTime time_diff
= ltt_time_sub(last_event_time
, first_event_time
);
1398 if(ltt_time_compare(time_diff
, ltt_time_zero
) == 0)
1399 time_diff
= seek_back_default_offset
;
1400 count
= lttv_process_traceset_seek_n_backward(tsc
, abs(relative_position
),
1402 (seek_time_fct
)lttv_state_traceset_seek_time_closest
,
1403 event_viewer_data
->main_win_filter
);
1404 } /* else 0 : do nothing : we are already at the beginning position */
1406 lttv_traceset_context_position_destroy(pos
);
1408 /* Save the first event position */
1409 lttv_traceset_context_position_save(tsc
, event_viewer_data
->first_event
);
1411 time
= lttv_traceset_context_position_get_time(
1412 event_viewer_data
->first_event
);
1413 //if(ltt_time_compare(time, tsc->time_span.end_time) > 0)
1414 // time = tsc->time_span.end_time;
1416 LttTime time_val
= ltt_time_sub(time
,
1417 tsc
->time_span
.start_time
);
1418 event_viewer_data
->previous_value
= ltt_time_to_double(time_val
);
1420 lttv_state_traceset_seek_time_closest((LttvTracesetState
*)tsc
, time
);
1421 lttv_process_traceset_middle(tsc
, ltt_time_infinite
, G_MAXUINT
,
1422 event_viewer_data
->first_event
);
1426 lttv_state_traceset_seek_time_closest((LttvTracesetState
*)tsc
,
1428 lttv_process_traceset_middle(tsc
, time
, G_MAXUINT
,
1430 LttTime time_val
= ltt_time_sub(time
,
1431 tsc
->time_span
.start_time
);
1432 event_viewer_data
->previous_value
= ltt_time_to_double(time_val
);
1433 lttv_traceset_context_position_save(tsc
, event_viewer_data
->first_event
);
1436 /* Clear the model (don't forget to free the TCS positions!) */
1437 gtk_list_store_clear(event_viewer_data
->store_m
);
1438 for(i
=0;i
<event_viewer_data
->pos
->len
;i
++) {
1439 LttvTracesetContextPosition
*cur_pos
=
1440 (LttvTracesetContextPosition
*)g_ptr_array_index(event_viewer_data
->pos
,
1442 lttv_traceset_context_position_destroy(cur_pos
);
1444 g_ptr_array_set_size(event_viewer_data
->pos
, 0);
1448 * I make the choice not to use the mainwindow lttvwindow API here : the idle
1449 * loop might have a too low priority, and we want good update while
1453 lttv_process_traceset_begin(tsc
,
1454 NULL
, NULL
, NULL
, event_viewer_data
->event_hooks
, NULL
);
1456 lttv_process_traceset_middle(tsc
, ltt_time_infinite
, G_MAXUINT
, NULL
);
1458 lttv_process_traceset_end(tsc
,
1459 NULL
, NULL
, NULL
, event_viewer_data
->event_hooks
, NULL
);
1461 /* Get the end position */
1462 if(event_viewer_data
->pos
->len
> 0) {
1463 LttvTracesetContextPosition
*cur_pos
=
1464 (LttvTracesetContextPosition
*)g_ptr_array_index(event_viewer_data
->pos
,
1465 event_viewer_data
->pos
->len
- 1);
1466 lttv_traceset_context_position_copy(event_viewer_data
->last_event
,
1469 lttv_traceset_context_position_save(tsc
, event_viewer_data
->last_event
);
1471 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
,
1472 event_viewer_data
->previous_value
);
1474 //g_signal_emit_by_name(G_OBJECT (event_viewer_data->select_c),
1477 event_viewer_data
->last_tree_update_time
=
1478 gdk_x11_get_server_time(
1479 gtk_widget_get_parent_window(event_viewer_data
->tree_v
));
1486 int event_hook(void *hook_data
, void *call_data
)
1488 EventViewerData
*event_viewer_data
= (EventViewerData
*)hook_data
;
1489 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1490 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
1491 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
1493 LttvFilter
*filter
= event_viewer_data
->main_win_filter
;
1494 if(filter
!= NULL
&& filter
->head
!= NULL
)
1495 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
1496 tfc
->t_context
->t
,tfc
))
1499 LttFacility
*facility
= ltt_event_facility(e
);
1500 LttEventType
*event_type
= ltt_event_eventtype(e
);
1501 LttTime time
= ltt_event_time(e
);
1503 guint cpu
= tfs
->cpu
;
1504 LttvTraceState
*ts
= (LttvTraceState
*)tfc
->t_context
;
1505 LttvProcessState
*process
= ts
->running_process
[cpu
];
1509 GString
*desc
= g_string_new("");
1511 LttvTracesetContextPosition
*pos
=
1512 lttv_traceset_context_position_new(tfc
->t_context
->ts_context
);
1514 lttv_traceset_context_position_save(tfc
->t_context
->ts_context
, pos
);
1516 lttv_event_to_string(e
, desc
, TRUE
, TRUE
, (LttvTracefileState
*)tfc
);
1518 g_info("detail : %s", desc
->str
);
1520 gtk_list_store_append (event_viewer_data
->store_m
, &iter
);
1521 gtk_list_store_set (event_viewer_data
->store_m
, &iter
,
1522 TRACE_NAME_COLUMN
, g_quark_to_string(ltt_trace_name(tfc
->t_context
->t
)),
1523 TRACEFILE_NAME_COLUMN
, g_quark_to_string(ltt_tracefile_name(tfc
->tf
)),
1525 FACILITY_COLUMN
, g_quark_to_string(ltt_facility_name(facility
)),
1526 EVENT_COLUMN
, g_quark_to_string(ltt_eventtype_name(event_type
)),
1527 TIME_S_COLUMN
, time
.tv_sec
,
1528 TIME_NS_COLUMN
, time
.tv_nsec
,
1529 PID_COLUMN
, process
->pid
,
1530 EVENT_DESCR_COLUMN
, desc
->str
,
1531 POSITION_COLUMN
, pos
,
1534 g_ptr_array_add(event_viewer_data
->pos
, pos
);
1536 g_string_free(desc
, TRUE
);
1538 if(event_viewer_data
->update_cursor
) {
1539 if(lttv_traceset_context_pos_pos_compare(pos
,
1540 event_viewer_data
->currently_selected_position
) == 0) {
1541 GtkTreePath
*path
= gtk_tree_path_new_from_indices(
1542 event_viewer_data
->pos
->len
- 1, -1);
1544 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
1546 gtk_tree_path_free(path
);
1551 if(event_viewer_data
->pos
->len
>= event_viewer_data
->num_visible_events
)
1559 static void event_update_selection(EventViewerData
*event_viewer_data
)
1562 GPtrArray
*positions
= event_viewer_data
->pos
;
1563 g_info("event_update_selection");
1565 for(i
=0;i
<positions
->len
;i
++) {
1566 LttvTracesetContextPosition
*cur_pos
=
1567 (LttvTracesetContextPosition
*)g_ptr_array_index(positions
, i
);
1568 if(lttv_traceset_context_pos_pos_compare(cur_pos
,
1569 event_viewer_data
->currently_selected_position
) == 0) {
1570 GtkTreePath
*path
= gtk_tree_path_new_from_indices(i
, -1);
1572 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data
->tree_v
),
1574 gtk_tree_path_free(path
);
1580 static int current_time_get_first_event_hook(void *hook_data
, void *call_data
)
1582 EventViewerData
*event_viewer_data
= (EventViewerData
*)hook_data
;
1583 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
1584 LttEvent
*e
= ltt_tracefile_get_event(tfc
->tf
);
1586 LttvFilter
*filter
= event_viewer_data
->main_win_filter
;
1587 if(filter
!= NULL
&& filter
->head
!= NULL
)
1588 if(!lttv_filter_tree_parse(filter
->head
,e
,tfc
->tf
,
1589 tfc
->t_context
->t
,tfc
))
1592 lttv_traceset_context_position_save(tfc
->t_context
->ts_context
,
1593 event_viewer_data
->current_time_get_first
);
1598 gboolean
update_current_time(void * hook_data
, void * call_data
)
1600 g_info("update_current_time");
1601 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1602 const LttTime
* current_time
= (LttTime
*)call_data
;
1603 LttvTracesetContext
* tsc
=
1604 lttvwindow_get_traceset_context(event_viewer_data
->tab
);
1607 /* If the currently selected event time != current time, set the first event
1608 * with this time as currently selected. */
1609 LttTime pos_time
= lttv_traceset_context_position_get_time(
1610 event_viewer_data
->currently_selected_position
);
1611 if(ltt_time_compare(pos_time
, *current_time
) != 0) {
1613 lttv_state_traceset_seek_time_closest((LttvTracesetState
*)tsc
,
1615 lttv_process_traceset_middle(tsc
, *current_time
, G_MAXUINT
,
1618 /* Get the first event that passes in the filter */
1619 event_viewer_data
->current_time_get_first
=
1620 lttv_traceset_context_position_new(tsc
);
1621 LttvHooks
*hooks
= lttv_hooks_new();
1622 lttv_hooks_add(hooks
,
1623 current_time_get_first_event_hook
,
1627 lttv_process_traceset_begin(tsc
,
1628 NULL
, NULL
, NULL
, hooks
, NULL
);
1630 lttv_process_traceset_middle(tsc
, ltt_time_infinite
, G_MAXUINT
, NULL
);
1632 lttv_process_traceset_end(tsc
,
1633 NULL
, NULL
, NULL
, hooks
, NULL
);
1635 lttv_hooks_destroy(hooks
);
1637 lttv_traceset_context_position_copy(
1638 event_viewer_data
->currently_selected_position
,
1639 event_viewer_data
->current_time_get_first
);
1640 lttv_traceset_context_position_destroy(
1641 event_viewer_data
->current_time_get_first
);
1642 pos_time
= lttv_traceset_context_position_get_time(
1643 event_viewer_data
->currently_selected_position
);
1646 LttTime time
= ltt_time_sub(pos_time
, tsc
->time_span
.start_time
);
1647 double new_value
= ltt_time_to_double(time
);
1649 event_viewer_data
->report_position
= FALSE
;
1650 /* Change the viewed area if does not match */
1651 if(lttv_traceset_context_pos_pos_compare(
1652 event_viewer_data
->currently_selected_position
,
1653 event_viewer_data
->first_event
) < 0
1655 lttv_traceset_context_pos_pos_compare(
1656 event_viewer_data
->currently_selected_position
,
1657 event_viewer_data
->last_event
) > 0) {
1658 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
, new_value
);
1660 /* Simply update the current time : it is in the list */
1661 event_update_selection(event_viewer_data
);
1663 event_viewer_data
->report_position
= TRUE
;
1668 gboolean
update_current_position(void * hook_data
, void * call_data
)
1670 g_info("update_current_position");
1671 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1672 const LttvTracesetContextPosition
*current_pos
=
1673 (LttvTracesetContextPosition
*)call_data
;
1674 LttvTracesetContext
* tsc
=
1675 lttvwindow_get_traceset_context(event_viewer_data
->tab
);
1677 if(lttv_traceset_context_pos_pos_compare(
1678 event_viewer_data
->currently_selected_position
, current_pos
) != 0) {
1679 lttv_traceset_context_position_copy(
1680 event_viewer_data
->currently_selected_position
, current_pos
);
1682 /* Change the viewed area if does not match */
1683 if(lttv_traceset_context_pos_pos_compare(
1684 event_viewer_data
->currently_selected_position
,
1685 event_viewer_data
->first_event
) < 0
1687 lttv_traceset_context_pos_pos_compare(
1688 event_viewer_data
->currently_selected_position
,
1689 event_viewer_data
->last_event
) > 0) {
1690 LttTime time
= lttv_traceset_context_position_get_time(current_pos
);
1691 time
= ltt_time_sub(time
, tsc
->time_span
.start_time
);
1692 double new_value
= ltt_time_to_double(time
);
1693 gtk_adjustment_set_value(event_viewer_data
->vadjust_c
, new_value
);
1695 /* Simply update the current time : it is in the list */
1696 event_update_selection(event_viewer_data
);
1707 gboolean
traceset_changed(void * hook_data
, void * call_data
)
1709 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1710 LttvTracesetContext
* tsc
=
1711 lttvwindow_get_traceset_context(event_viewer_data
->tab
);
1712 TimeInterval time_span
= tsc
->time_span
;
1715 gtk_list_store_clear(event_viewer_data
->store_m
);
1716 g_ptr_array_set_size(event_viewer_data
->pos
, 0);
1718 end
= ltt_time_sub(time_span
.end_time
, time_span
.start_time
);
1719 event_viewer_data
->vadjust_c
->upper
= ltt_time_to_double(end
);
1721 /* Reset the positions */
1722 lttv_traceset_context_position_destroy(
1723 event_viewer_data
->currently_selected_position
);
1724 lttv_traceset_context_position_destroy(
1725 event_viewer_data
->first_event
);
1726 lttv_traceset_context_position_destroy(
1727 event_viewer_data
->last_event
);
1729 event_viewer_data
->currently_selected_position
=
1730 lttv_traceset_context_position_new(tsc
);
1731 event_viewer_data
->first_event
=
1732 lttv_traceset_context_position_new(tsc
);
1733 event_viewer_data
->last_event
=
1734 lttv_traceset_context_position_new(tsc
);
1736 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1737 // event_viewer_data->vadjust_c->value = 0;
1739 request_background_data(event_viewer_data
);
1744 gboolean
filter_changed(void * hook_data
, void * call_data
)
1746 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1747 LttvTracesetContext
* tsc
=
1748 lttvwindow_get_traceset_context(event_viewer_data
->tab
);
1750 event_viewer_data
->main_win_filter
=
1751 (LttvFilter
*)call_data
;
1752 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1758 gint
redraw_notify(void *hook_data
, void *call_data
)
1760 EventViewerData
*event_viewer_data
= (EventViewerData
*) hook_data
;
1762 get_events(event_viewer_data
->vadjust_c
->value
, event_viewer_data
);
1766 void gui_events_free(EventViewerData
*event_viewer_data
)
1768 Tab
*tab
= event_viewer_data
->tab
;
1771 if(event_viewer_data
){
1772 lttv_hooks_remove(event_viewer_data
->event_hooks
,event_hook
);
1773 lttv_hooks_destroy(event_viewer_data
->event_hooks
);
1775 for(i
=0;i
<event_viewer_data
->pos
->len
;i
++) {
1776 LttvTracesetContextPosition
*cur_pos
=
1777 (LttvTracesetContextPosition
*)g_ptr_array_index(event_viewer_data
->pos
,
1779 lttv_traceset_context_position_destroy(cur_pos
);
1781 lttv_traceset_context_position_destroy(
1782 event_viewer_data
->currently_selected_position
);
1783 lttv_traceset_context_position_destroy(
1784 event_viewer_data
->first_event
);
1785 lttv_traceset_context_position_destroy(
1786 event_viewer_data
->last_event
);
1787 g_ptr_array_free(event_viewer_data
->pos
, TRUE
);
1789 lttvwindow_unregister_current_time_notify(tab
,
1790 update_current_time
, event_viewer_data
);
1791 lttvwindow_unregister_current_position_notify(tab
,
1792 update_current_position
, event_viewer_data
);
1793 //lttvwindow_unregister_show_notify(tab,
1794 // show_event_detail, event_viewer_data);
1795 lttvwindow_unregister_traceset_notify(tab
,
1796 traceset_changed
, event_viewer_data
);
1797 lttvwindow_unregister_filter_notify(tab
,
1798 filter_changed
, event_viewer_data
);
1799 lttvwindow_unregister_redraw_notify(tab
,
1800 redraw_notify
, event_viewer_data
);
1802 lttvwindowtraces_background_notify_remove(event_viewer_data
);
1804 g_event_viewer_data_list
= g_slist_remove(g_event_viewer_data_list
,
1806 g_free(event_viewer_data
);
1812 void gui_events_destructor(EventViewerData
*event_viewer_data
)
1814 /* May already been done by GTK window closing */
1815 if(GTK_IS_WIDGET(event_viewer_data
->hbox_v
)){
1816 gtk_widget_destroy(event_viewer_data
->hbox_v
);
1823 * plugin's init function
1825 * This function initializes the Event Viewer functionnality through the
1828 static void init() {
1830 lttvwindow_register_constructor("guievents",
1832 "Insert Event Viewer",
1833 hGuiEventsInsert_xpm
,
1834 "Insert Event Viewer",
1838 void event_destroy_walk(gpointer data
, gpointer user_data
)
1840 gui_events_destructor((EventViewerData
*)data
);
1844 * plugin's destroy function
1846 * This function releases the memory reserved by the module and unregisters
1847 * everything that has been registered in the gtkTraceSet API.
1849 static void destroy() {
1851 g_slist_foreach(g_event_viewer_data_list
, event_destroy_walk
, NULL
);
1852 g_slist_free(g_event_viewer_data_list
);
1854 lttvwindow_unregister_constructor(h_gui_events
);
1861 LTTV_MODULE("guievents", "Detailed events view", \
1862 "Graphical module to display a detailed event list", \
1863 init
, destroy
, "lttvwindow", "print")