From fa2c4dbef9d6f7f509a1d13ca8b7d16f95236100 Mon Sep 17 00:00:00 2001 From: compudj Date: Sun, 28 Sep 2003 20:02:59 +0000 Subject: [PATCH] guiControlFlow Process List completed git-svn-id: http://ltt.polymtl.ca/svn@272 04897980-b3bd-0310-b5e0-8ef037075253 --- .../poly/lttv/modules/guiControlFlow/CFV.c | 19 +- .../lttv/modules/guiControlFlow/Drawing.c | 50 +- .../lttv/modules/guiControlFlow/Drawing.h | 39 +- .../lttv/modules/guiControlFlow/Makefile.am | 4 +- .../modules/guiControlFlow/Process_List.c | 449 +++++++++++++++++- .../modules/guiControlFlow/Process_List.h | 30 +- .../poly/lttv/modules/guiControlFlow/test.c | 6 +- 7 files changed, 530 insertions(+), 67 deletions(-) diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/CFV.c b/ltt/branches/poly/lttv/modules/guiControlFlow/CFV.c index 9a29ae1a..18f3b52e 100644 --- a/ltt/branches/poly/lttv/modules/guiControlFlow/CFV.c +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/CFV.c @@ -34,7 +34,7 @@ struct _ControlFlowData { /* Shown events information */ guint First_Event, Last_Event; - ltt_time Begin_Time, End_Time; + LttTime Begin_Time, End_Time; /* TEST DATA, TO BE READ FROM THE TRACE */ @@ -75,16 +75,16 @@ GuiControlFlow(void) /* Create the Process list */ - //Control_Flow_Data->Process_List = ProcessList_contruct(); + Control_Flow_Data->Process_List = ProcessList_construct(); - //Process_List_Widget = - // ProcessList_getWidget(Control_Flow_Data->Process_List); + Process_List_Widget = + ProcessList_getWidget(Control_Flow_Data->Process_List); Control_Flow_Data->Inside_HBox_V = gtk_hbox_new(0, 0); - //gtk_box_pack_start( - // GTK_BOX(Control_Flow_Data->Inside_HBox_V), - // Process_List_Widget, FALSE, TRUE, 0); + gtk_box_pack_start( + GTK_BOX(Control_Flow_Data->Inside_HBox_V), + Process_List_Widget, TRUE, TRUE, 0); // FALSE TRUE //gtk_box_pack_start( // GTK_BOX(Control_Flow_Data->Inside_HBox_V), // Control_Flow_Data->Drawing_Area_V, TRUE, TRUE, 0); @@ -133,7 +133,7 @@ GuiControlFlow(void) //gtk_widget_show(Control_Flow_Data->Drawing_Area_V); - //gtk_widget_show(Process_List_Widget); + gtk_widget_show(Process_List_Widget); gtk_widget_show(Control_Flow_Data->Inside_HBox_V); gtk_widget_show(Control_Flow_Data->Scrolled_Window_VC); @@ -164,7 +164,8 @@ void GuiControlFlow_Destructor(ControlFlowData *Control_Flow_Data) { guint index; - + + /* Process List is removed with it's widget */ //ProcessList_destroy(Control_Flow_Data->Process_List); g_slist_remove(gControl_Flow_Data_List,Control_Flow_Data); diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c b/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c index 53873b70..009109f8 100644 --- a/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.c @@ -1,3 +1,4 @@ + #include "Drawing.h" /***************************************************************************** @@ -44,7 +45,7 @@ Drawing_t *Drawing(void) G_OBJECT(Drawing->Drawing_Area_V), "Drawing_Data", Drawing, - Drawing_destroy); + (GDestroyNotify)Drawing_destroy); gtk_widget_modify_bg( Control_Flow_Data->Drawing_Area_V, GTK_STATE_NORMAL, @@ -68,28 +69,47 @@ void Drawing_destroy(Drawing_t *Drawing) * function uses TimeMul, which should only be used if the float value is lower * that 4, and here it's always lower than 1, so it's ok. */ -void get_time_from_pixels( - guint area_x, - guint area_width, - guint window_width, - ltt_time *window_time_begin, - ltt_time *window_time_end, - ltt_time *time_begin, - ltt_time *time_end) +void convert_pixels_to_time( + Drawing_t *Drawing, + guint x, + LttTime *window_time_begin, + LttTime *window_time_end, + LttTime *time, + ); { - ltt_time window_time_interval; + LttTime window_time_interval; - TimeSub(window_time_interval, window_time_end, window_time_begin); + TimeSub(window_time_interval, *window_time_end, window_time_begin); - TimeMul(time_begin, window_time_interval, (area_x/(float)window_width)); - TimeAdd(time_begin, window_time_begin, time_begin); + TimeMul(*time, window_time_interval, + (x/(float)Drawing->width)); + TimeAdd(*time, window_time_begin, *time); - TimeMul(time_end, window_time_interval, (area_width/(float)window_width)); - TimeAdd(time_end, time_begin, time_end); +} + + + +void convert_time_to_pixels( + LttTime window_time_begin, + LttTime window_time_end, + LttTime time, + Drawing_t *Drawing, + guint *x, + ) +{ + LttTime window_time_interval; + + TimeSub(window_time_interval, window_time_end, window_time_begin); + + TimeSub(time, time, wimdow_time_begin); + + *x = (guint)((time/(float)window_time_interval) * Drawing->width); } + + void Drawing_Resize(Drawing_t *Drawing, guint h, guint, w) { guint w; diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.h b/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.h index a3c28e44..801ef2d1 100644 --- a/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.h +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/Drawing.h @@ -1,17 +1,17 @@ #ifndef _DRAWING_H #define _DRAWING_H -#include #include +#include -typedef time_t ltt_time; - -typedef struct _ltt_time_interval -{ - ltt_time time_begin, time_end; -} ltt_time_interval; - - +/* This part of the viewer does : + * Draw horizontal lines, getting line color and width as arguments. + * Copy region of the screen into another. + * Modify the boundaries to reflect a scale change. + * + * A helper function is provided here to convert from time and process + * identifier to pixels and the contrary (will be useful for mouse selection). + */ typedef struct _Drawing_t Drawing_t; @@ -21,14 +21,19 @@ void Drawing_Resize(Drawing_t *Drawing, guint h, guint w); -void get_time_from_pixels( - guint area_x, - guint area_width, - guint window_width, - ltt_time *window_time_begin, - ltt_time *window_time_end, - ltt_time *time_begin, - ltt_time *time_end); +void convert_pixels_to_time( + Drawing_t *Drawing, + guint x, + LttTime *window_time_begin, + LttTime *window_time_end, + LttTime *begin); + +void convert_time_to_pixels( + LttTime window_time_begin, + LttTime window_time_end, + LttTime time, + Drawing_t *Drawing, + guint *x); #endif // _DRAWING_H diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/Makefile.am b/ltt/branches/poly/lttv/modules/guiControlFlow/Makefile.am index 9de1c42b..d24fb492 100644 --- a/ltt/branches/poly/lttv/modules/guiControlFlow/Makefile.am +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/Makefile.am @@ -13,6 +13,4 @@ libdir = ${lttvplugindir} lib_LTLIBRARIES = libguiControlFlow.la libguiControlFlow_la_LDFLAGS = -module -libguiControlFlow_la_SOURCES = module.c Event_Hooks.c CFV.c -#libguiControlFlow_la_DEPENDENCIES = CFV.h \ -# Event_Hooks.h +libguiControlFlow_la_SOURCES = module.c Event_Hooks.c CFV.c Process_List.c diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/Process_List.c b/ltt/branches/poly/lttv/modules/guiControlFlow/Process_List.c index 6085a672..84c66eca 100644 --- a/ltt/branches/poly/lttv/modules/guiControlFlow/Process_List.c +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/Process_List.c @@ -1,28 +1,273 @@ +#include +#include #include "Process_List.h" + /***************************************************************************** * Methods to synchronize process list * *****************************************************************************/ -typedef struct _ProcessList { +typedef struct _ProcessInfo { + + guint pid; + LttTime birth; + +} ProcessInfo; + + +struct _ProcessList { GtkWidget *Process_List_VC; GtkListStore *Store_M; + + /* A hash table by PID to speed up process position find in the list */ + GHashTable *Process_Hash; guint Number_Of_Process; -} ProcessList ; +}; /* Enumeration of the columns */ enum { PROCESS_COLUMN, + PID_COLUMN, + BIRTH_S_COLUMN, + BIRTH_NS_COLUMN, N_COLUMNS }; +gint process_sort_func ( GtkTreeModel *model, + GtkTreeIter *it_a, + GtkTreeIter *it_b, + gpointer user_data) +{ + GValue a, b; + + memset(&a, 0, sizeof(GValue)); + memset(&b, 0, sizeof(GValue)); + + /* Order by PID */ + gtk_tree_model_get_value( model, + it_a, + PID_COLUMN, + &a); + + gtk_tree_model_get_value( model, + it_b, + PID_COLUMN, + &b); + + if(G_VALUE_TYPE(&a) == G_TYPE_UINT + && G_VALUE_TYPE(&b) == G_TYPE_UINT ) + { + if(g_value_get_uint(&a) > g_value_get_uint(&b)) + { + g_value_unset(&a); + g_value_unset(&b); + return 1; + } + if(g_value_get_uint(&a) < g_value_get_uint(&b)) + { + g_value_unset(&a); + g_value_unset(&b); + return 0; + } + } + + g_value_unset(&a); + g_value_unset(&b); + + + /* Order by birth second */ + gtk_tree_model_get_value( model, + it_a, + BIRTH_S_COLUMN, + &a); + + gtk_tree_model_get_value( model, + it_b, + BIRTH_S_COLUMN, + &b); + + + if(G_VALUE_TYPE(&a) == G_TYPE_ULONG + && G_VALUE_TYPE(&b) == G_TYPE_ULONG ) + { + if(g_value_get_ulong(&a) > g_value_get_ulong(&b)) + { + g_value_unset(&a); + g_value_unset(&b); + return 1; + } + if(g_value_get_ulong(&a) < g_value_get_ulong(&b)) + { + g_value_unset(&a); + g_value_unset(&b); + return 0; + } + + } + + g_value_unset(&a); + g_value_unset(&b); + + /* Order by birth nanosecond */ + gtk_tree_model_get_value( model, + it_a, + BIRTH_NS_COLUMN, + &a); + + gtk_tree_model_get_value( model, + it_b, + BIRTH_NS_COLUMN, + &b); + + + if(G_VALUE_TYPE(&a) == G_TYPE_ULONG + && G_VALUE_TYPE(&b) == G_TYPE_ULONG ) + { + if(g_value_get_ulong(&a) > g_value_get_ulong(&b)) + { + g_value_unset(&a); + g_value_unset(&b); + return 1; + } + // Final condition + //if(g_value_get_ulong(&a) < g_value_get_ulong(&b)) + //{ + // g_value_unset(&a); + // g_value_unset(&b); + // return 0; + //} + + } + + g_value_unset(&a); + g_value_unset(&b); + + return 0; + +} + +void send_test_data(ProcessList *Process_List) +{ + guint height; + int i; + ProcessInfo Process_Info = {10000, 12000, 55600}; + //ProcessInfo Process_Info = {156, 14000, 55500}; + GtkTreeRowReference *got_RowRef; + + LttTime birth; + birth.tv_sec = 12000; + birth.tv_nsec = 55500; + + ProcessList_add(Process_List, + 1, + &birth, + &height); + + g_critical("height : %u", height); + + birth.tv_sec = 14000; + birth.tv_nsec = 55500; + + ProcessList_add(Process_List, + 156, + &birth, + &height); + + g_critical("height : %u", height); + + birth.tv_sec = 12000; + birth.tv_nsec = 55700; + + ProcessList_add(Process_List, + 10, + &birth, + &height); + + for(i=0; i<150; i++) + { + birth.tv_sec = i*12000; + birth.tv_nsec = i*55700; + + ProcessList_add(Process_List, + i, + &birth, + &height); + + } + g_critical("height : %u", height); + + birth.tv_sec = 12000; + birth.tv_nsec = 55600; + + ProcessList_add(Process_List, + 10, + &birth, + &height); + g_critical("height : %u", height); + + ProcessList_add(Process_List, + 10000, + &birth, + &height); + g_critical("height : %u", height); + + + ProcessList_remove( Process_List, + 10000, + &birth); + + if(got_RowRef = + (GtkTreeRowReference*)g_hash_table_lookup( + Process_List->Process_Hash, + &Process_Info)) + { + g_critical("key found"); + g_critical("position in the list : %s", + gtk_tree_path_to_string ( + gtk_tree_row_reference_get_path( + (GtkTreeRowReference*)got_RowRef) + )); + + } + +} + + +guint hash_fct(gconstpointer key) +{ + return ((ProcessInfo*)key)->pid; +} + +gboolean equ_fct(gconstpointer a, gconstpointer b) +{ + if(((ProcessInfo*)a)->pid != ((ProcessInfo*)b)->pid) + return 0; + g_critical("compare %u and %u",((ProcessInfo*)a)->pid,((ProcessInfo*)b)->pid); + if(((ProcessInfo*)a)->birth.tv_sec != ((ProcessInfo*)b)->birth.tv_sec) + return 0; + g_critical("compare %u and %u",((ProcessInfo*)a)->birth.tv_sec,((ProcessInfo*)b)->birth.tv_sec); + + if(((ProcessInfo*)a)->birth.tv_nsec != ((ProcessInfo*)b)->birth.tv_nsec) + return 0; + g_critical("compare %u and %u",((ProcessInfo*)a)->birth.tv_nsec,((ProcessInfo*)b)->birth.tv_nsec); + + return 1; +} + +void Destroy_hash_key(gpointer key); + +void Destroy_hash_data(gpointer data); + + + + ProcessList *ProcessList_construct(void) { GtkTreeViewColumn *column; @@ -30,9 +275,14 @@ ProcessList *ProcessList_construct(void) ProcessList* Process_List = g_new(ProcessList,1); + Process_List->Number_Of_Process = 0; + /* Create the Process list */ Process_List->Store_M = gtk_list_store_new ( N_COLUMNS, - G_TYPE_STRING); + G_TYPE_STRING, + G_TYPE_UINT, + G_TYPE_ULONG, + G_TYPE_ULONG); Process_List->Process_List_VC = @@ -41,6 +291,24 @@ ProcessList *ProcessList_construct(void) g_object_unref (G_OBJECT (Process_List->Store_M)); + gtk_tree_sortable_set_sort_func( + GTK_TREE_SORTABLE(Process_List->Store_M), + PID_COLUMN, + process_sort_func, + NULL, + NULL); + + gtk_tree_sortable_set_sort_column_id( + GTK_TREE_SORTABLE(Process_List->Store_M), + PID_COLUMN, + GTK_SORT_ASCENDING); + + Process_List->Process_Hash = g_hash_table_new_full( + hash_fct, equ_fct, + Destroy_hash_key, Destroy_hash_data + ); + + gtk_tree_view_set_headers_visible( GTK_TREE_VIEW(Process_List->Process_List_VC), FALSE); @@ -57,20 +325,50 @@ ProcessList *ProcessList_construct(void) gtk_tree_view_column_set_fixed_width (column, 45); gtk_tree_view_append_column ( GTK_TREE_VIEW (Process_List->Process_List_VC), column); + + column = gtk_tree_view_column_new_with_attributes ( "PID", + renderer, + "text", + PID_COLUMN, + NULL); + gtk_tree_view_append_column ( + GTK_TREE_VIEW (Process_List->Process_List_VC), column); + + + column = gtk_tree_view_column_new_with_attributes ( "Birth sec", + renderer, + "text", + BIRTH_S_COLUMN, + NULL); + gtk_tree_view_append_column ( + GTK_TREE_VIEW (Process_List->Process_List_VC), column); + + //gtk_tree_view_column_set_visible(column, 0); + // + column = gtk_tree_view_column_new_with_attributes ( "Birth nsec", + renderer, + "text", + BIRTH_NS_COLUMN, + NULL); + gtk_tree_view_append_column ( + GTK_TREE_VIEW (Process_List->Process_List_VC), column); + + //gtk_tree_view_column_set_visible(column, 0); g_object_set_data_full( G_OBJECT(Process_List->Process_List_VC), "Process_List_Data", Process_List, - ProcessList_destroy); + (GDestroyNotify)ProcessList_destroy); - + send_test_data(Process_List); + return Process_List; } - void ProcessList_destroy(ProcessList *Process_List) { - g_object_unref (G_OBJECT (Process_List->Process_List_VC)); + g_hash_table_destroy(Process_List->Process_Hash); + Process_List->Process_Hash = NULL; g_free(Process_List); } @@ -84,7 +382,7 @@ GtkWidget *ProcessList_getWidget(ProcessList *Process_List) gint get_cell_height(GtkTreeView *TreeView) { - gint height, width; + gint height; GtkTreeViewColumn *Column = gtk_tree_view_get_column(TreeView, 0); GList *Render_List = gtk_tree_view_column_get_cell_renderers(Column); GtkCellRenderer *Renderer = g_list_first(Render_List)->data; @@ -95,25 +393,140 @@ gint get_cell_height(GtkTreeView *TreeView) return height; } -#ifdef 0 -int ProcessList_add(Process *myproc, ProcessList *Process_List, guint *height) +void Destroy_hash_key(gpointer key) { - // add proc to container + g_free(key); +} + +void Destroy_hash_data(gpointer data) +{ + g_free(data); +} + +int ProcessList_add( ProcessList *Process_List, + guint pid, + LttTime *birth, + guint *height) +{ + GtkTreeIter iter ; + ProcessInfo *Process_Info = g_new(ProcessInfo, 1); + GtkTreeRowReference *RowRef; + + Process_Info->pid = pid; + Process_Info->birth = *birth; + + /* Add a new row to the model */ + gtk_list_store_append ( Process_List->Store_M, &iter); + g_critical ( "iter before : %s", gtk_tree_path_to_string ( + gtk_tree_model_get_path ( + GTK_TREE_MODEL(Process_List->Store_M), + &iter))); + gtk_list_store_set ( Process_List->Store_M, &iter, + PROCESS_COLUMN, "name", + PID_COLUMN, pid, + BIRTH_S_COLUMN, birth->tv_sec, + BIRTH_NS_COLUMN, birth->tv_nsec, + -1); + RowRef = gtk_tree_row_reference_new ( + GTK_TREE_MODEL(Process_List->Store_M), + gtk_tree_model_get_path( + GTK_TREE_MODEL(Process_List->Store_M), + &iter)); + + g_hash_table_insert( Process_List->Process_Hash, + (gpointer)Process_Info, + (gpointer)RowRef); + + g_critical ( "iter after : %s", gtk_tree_path_to_string ( + gtk_tree_model_get_path ( + GTK_TREE_MODEL(Process_List->Store_M), + &iter))); + Process_List->Number_Of_Process++; - height = get_cell_height(GTK_TREE_VIEW(Process_List->Process_List_VC)) + *height = get_cell_height(GTK_TREE_VIEW(Process_List->Process_List_VC)) * Process_List->Number_Of_Process ; + return 0; } -int ProcessList_remove(Process *myproc, ProcessList *Process_List) +int ProcessList_remove( ProcessList *Process_List, + guint pid, + LttTime *birth) { - // remove proc from container + ProcessInfo Process_Info; + gint *path_indices; + GtkTreeRowReference *got_RowRef; + GtkTreeIter iter; - get_cell_height(GTK_TREE_VIEW(Process_List->Process_List_VC)) + Process_Info.pid = pid; + Process_Info.birth = *birth; + + if(got_RowRef = + (GtkTreeRowReference*)g_hash_table_lookup( + Process_List->Process_Hash, + &Process_Info)) + { + gtk_tree_model_get_iter ( + GTK_TREE_MODEL(Process_List->Store_M), + &iter, + gtk_tree_row_reference_get_path( + (GtkTreeRowReference*)got_RowRef) + ); + + gtk_list_store_remove (Process_List->Store_M, &iter); + + g_hash_table_remove(Process_List->Process_Hash, + &Process_Info); + + Process_List->Number_Of_Process--; + + return 0; + } else { + return 1; + } +} + + +guint ProcessList_get_height(ProcessList *Process_List) +{ + return get_cell_height(GTK_TREE_VIEW(Process_List->Process_List_VC)) * Process_List->Number_Of_Process ; - - return 0; } -#endif + + +gint ProcessList_get_process_pixels( ProcessList *Process_List, + guint pid, LttTime *birth, + guint *x, + guint *height) +{ + ProcessInfo Process_Info; + gint *path_indices; + GtkTreeRowReference *got_RowRef; + + Process_Info.pid = pid; + Process_Info.birth = *birth; + + if(got_RowRef = + (GtkTreeRowReference*)g_hash_table_lookup( + Process_List->Process_Hash, + &Process_Info)) + { + path_indices = gtk_tree_path_get_indices ( + gtk_tree_row_reference_get_path( + (GtkTreeRowReference*)got_RowRef) + ); + + *height = get_cell_height( + GTK_TREE_VIEW(Process_List->Process_List_VC)); + *x = *height * path_indices[0]; + + return 0; + } else { + return 1; + } + + + +} diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/Process_List.h b/ltt/branches/poly/lttv/modules/guiControlFlow/Process_List.h index 75bb05ab..ef38a9a2 100644 --- a/ltt/branches/poly/lttv/modules/guiControlFlow/Process_List.h +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/Process_List.h @@ -1,12 +1,38 @@ #ifndef _PROCESS_LIST_H #define _PROCESS_LIST_H +#include +#include +#include + +/* The process list + * + * Tasks : + * Create a process list + * contains the data for the process list + * tells the height of the process list widget + * provides methods to add/remove process from the list + * note : the sync with drawing is left to the caller. + * provides helper function to convert a process unique identifier to + * pixels (in height). + */ + typedef struct _ProcessList ProcessList; ProcessList *ProcessList_construct(void); void ProcessList_destroy(ProcessList *Process_List); GtkWidget *ProcessList_getWidget(ProcessList *Process_List); -//int ProcessList_add(Process *myproc, ProcessList *Process_List, guint *height); -//int ProcessList_remove(Process *myproc, ProcessList *Process_List); +// out : success (0) and height +int ProcessList_add(ProcessList *Process_List, guint pid, LttTime *birth, + guint *height); +// out : success (0) and height +int ProcessList_remove(ProcessList *Process_List, guint pid, LttTime *birth); + +guint ProcessList_get_pixels(ProcessList *Process_List); + +// Returns 0 on success +gint ProcessList_get_process_pixels(ProcessList *Process_List, + guint pid, LttTime *birth, + guint *x, guint *height); #endif // _PROCESS_LIST_H diff --git a/ltt/branches/poly/lttv/modules/guiControlFlow/test.c b/ltt/branches/poly/lttv/modules/guiControlFlow/test.c index ada84ea2..664696d6 100644 --- a/ltt/branches/poly/lttv/modules/guiControlFlow/test.c +++ b/ltt/branches/poly/lttv/modules/guiControlFlow/test.c @@ -83,9 +83,9 @@ void add_test_process(ControlFlowData *Control_Flow_Data) { /* Add a new row to the model */ gtk_list_store_append (Control_Flow_Data->Store_M, &iter); - gtk_list_store_set (Control_Flow_Data->Store_M, &iter, - PROCESS_COLUMN, process[i], - -1); + gtk_list_store_set ( Control_Flow_Data->Store_M, &iter, + PROCESS_COLUMN, process[i], + -1); } } -- 2.34.1