viewer -> lttvwindow name change
[lttv.git] / ltt / branches / poly / lttv / modules / gui / lttvwindow / lttvwindow / callbacks.c
index c4568cf49498bc3af206c4b6afc7a702fa35b883..4ffac2dba52da5c6ebf039f95689d7031eed70a1 100644 (file)
 #include "callbacks.h"
 #include "interface.h"
 #include "support.h"
+#include <ltt/trace.h>
+#include <ltt/facility.h>
+#include <ltt/time.h>
+#include <ltt/event.h>
 #include <lttv/lttv.h>
+#include <lttv/module.h>
+#include <lttv/iattribute.h>
+#include <lttv/stats.h>
 #include <lttvwindow/mainwindow.h>
 #include <lttvwindow/menu.h>
 #include <lttvwindow/toolbar.h>
-#include <lttvwindow/viewer.h>
-#include <lttv/module.h>
+#include <lttvwindow/lttvwindow.h>
 #include <lttvwindow/gtkdirsel.h>
-#include <lttv/iattribute.h>
 #include <lttvwindow/lttvfilter.h>
-#include <ltt/trace.h>
-#include <ltt/facility.h>
 
 #define PATH_LENGTH          256
 #define DEFAULT_TIME_WIDTH_S   1
@@ -48,7 +51,7 @@ extern GSList * g_main_window_list;
 
 static int g_win_count = 0;
 
-// MD : keep old directory
+/** MD : keep old directory. */
 static char remember_plugins_dir[PATH_LENGTH] = "";
 static char remember_trace_dir[PATH_LENGTH] = "";
 
@@ -73,7 +76,7 @@ void add_trace_into_traceset_selector(GtkMultiVPaned * paned, LttTrace * trace);
 
 LttvTracesetSelector * construct_traceset_selector(LttvTraceset * traceset);
 
-void redraw_viewer(MainWindow * mw_data, TimeWindow * time_window);
+static gboolean lttvwindow_process_pending_requests(Tab *tab);
 unsigned get_max_event_number(MainWindow * mw_data);
 
 enum {
@@ -159,40 +162,34 @@ insert_viewer_wrap(GtkWidget *menuitem, gpointer user_data)
 
 
 /* internal functions */
-void insert_viewer(GtkWidget* widget, lttvwindow_viewer_constructor constructor)
+static void insert_viewer(GtkWidget* widget, lttvwindow_viewer_constructor constructor)
 {
   GtkMultiVPaned * multi_vpaned;
-  MainWindow * mw_data;  
+  MainWindow * mw_data = get_window_data_struct(widget);
   GtkWidget * viewer;
   LttvTracesetSelector  * s;
   TimeInterval * time_interval;
-  TimeWindow  time_window, t;
+  Tab *tab = mw_data->current_tab;
 
-  mw_data = get_window_data_struct(widget);
-  if(!mw_data->current_tab) return;
-  multi_vpaned = mw_data->current_tab->multi_vpaned;
+  if(!tab) return;
+  multi_vpaned = tab->multi_vpaned;
 
-  s = construct_traceset_selector(mw_data->current_tab->traceset_info->traceset);
-  viewer = (GtkWidget*)constructor(mw_data, s, "Traceset_Selector");
+  s = construct_traceset_selector(tab->traceset_info->traceset);
+  viewer = (GtkWidget*)constructor(tab, s, "Traceset_Selector");
   if(viewer)
   {
     gtk_multi_vpaned_widget_add(multi_vpaned, viewer); 
-    // Added by MD
-    //    g_object_unref(G_OBJECT(viewer));
-
-    time_window = mw_data->current_tab->time_window;
-    time_interval = (TimeInterval*)g_object_get_data(G_OBJECT(viewer), TRACESET_TIME_SPAN);
-    if(time_interval){
-      t = time_window;
-      time_window.start_time = time_interval->startTime;
-      time_window.time_width = ltt_time_sub(time_interval->endTime,time_interval->startTime);
-    }
-
-    redraw_viewer(mw_data,&time_window);
-    lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
-    if(time_interval){
-      lttvwindow_report_time_window(mw_data,&t);
-    }
+    // We unref here, because it is now referenced by the multi_vpaned!
+    g_object_unref(G_OBJECT(viewer));
+
+    // The viewer will show itself when it receives a show notify
+    // So we call the show notify hooks here. It will
+    // typically add hooks for reading, we call process trace, and the
+    // end of reading hook will call gtk_widget_show and unregister the
+    // hooks.
+    // Note that show notify gets the time_requested through the call_data.
+    //show_viewer(mw_data);
+    // in expose now call_pending_read_hooks(mw_data);
   }
 }
 
@@ -319,6 +316,7 @@ void delete_viewer(GtkWidget * widget, gpointer user_data)
 
 /* open_traceset will open a traceset saved in a file
  * Right now, it is not finished yet, (not working)
+ * FIXME
  */
 
 void open_traceset(GtkWidget * widget, gpointer user_data)
@@ -377,47 +375,474 @@ unsigned get_max_event_number(MainWindow * mw_data)
 }
 
 
-/* redraw_viewer parses the traceset first by calling 
- * process_traceset, then display all viewers of 
- * the current tab
+/* lttvwindow_process_pending_requests
+ * 
+ * This internal function gets called by g_idle, taking care of the pending
+ * requests. It is responsible for concatenation of time intervals and position
+ * requests. It does it with the following algorithm organizing process traceset
+ * calls. Here is the detailed description of the way it works :
+ *
+ * - Events Requests Servicing Algorithm
+ *
+ *   Data structures necessary :
+ *
+ *   List of requests added to context : list_in
+ *   List of requests not added to context : list_out
+ *
+ *   Initial state :
+ *
+ *   list_in : empty
+ *   list_out : many events requests
+ *
+ *  FIXME : insert rest of algorithm here
+ *
  */
 
-void redraw_viewer(MainWindow * mw_data, TimeWindow * time_window)
+
+gboolean lttvwindow_process_pending_requests(Tab *tab)
 {
   unsigned max_nb_events;
   GdkWindow * win;
   GdkCursor * new;
   GtkWidget* widget;
-  LttvTracesetContext *tsc = 
-   LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->
-                            traceset_context);
+  LttvTracesetContext *tsc;
+  LttvTracefileContext *tfc;
+  GSList *events_requests = tab->events_requests;
+  GSList *list_out = events_requests;
+  GSList *list_in = NULL;
+  LttTime end_time;
+  guint end_nb_events;
+  LttvTracesetContextPosition *end_position;
+    
+  
+  /* Current tab check : if no current tab is present, no hooks to call. */
+  /* (Xang Xiu) It makes the expose works..  MD:? */
+  if(tab == NULL)
+    return FALSE;
+
+  /* There is no events requests pending : we should never have been called! */
+  g_assert(g_slist_length(events_requests) != 0);
+
+  tsc = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
 
   //set the cursor to be X shape, indicating that the computer is busy in doing its job
   new = gdk_cursor_new(GDK_X_CURSOR);
-  widget = lookup_widget(mw_data->mwindow, "MToolbar1");
+  widget = lookup_widget(tab->mw_data->mwindow, "MToolbar1");
   win = gtk_widget_get_parent_window(widget);  
   gdk_window_set_cursor(win, new);
   gdk_cursor_unref(new);  
   gdk_window_stick(win);
   gdk_window_unstick(win);
-  //update time window of each viewer, let viewer insert hooks needed by process_traceset
-  lttvwindow_report_time_window(mw_data, time_window);
+
+  g_debug("SIZE events req len  : %d", g_slist_length(events_request));
   
-  max_nb_events = get_max_event_number(mw_data);
+  /* Events processing algorithm implementation */
+  /* A. Servicing loop */
+  while( (g_slist_length(list_in) != 0 || g_slist_length(list_out) != 0)
+         && !gtk_events_pending() ) {
+
+    /* 1. If list_in is empty (need a seek) */
+    if( g_slist_length(list_in) ==  0 ) {
+
+      /* list in is empty, need a seek */
+      {
+        /* 1.1 Add requests to list_in */
+        GArray *ltime = g_array_new(FALSE, FALSE, sizeof(guint));
+        GArray *lpos = g_array_new(FALSE, FALSE, sizeof(guint));
+        guint i;
+        
+        /* 1.1.1 Find all time requests with the lowest start time in list_out
+         * (ltime)
+         */
+        if(list_out->len > 0)
+          g_array_append_val(ltime, 0);
+        for(i=1;i<list_out->len;i++) {
+          /* Find all time requests with the lowest start time in list_out */
+          guint index_ltime = g_array_index(ltime, guint, 0);
+          EventsRequest *event_request_ltime = &g_array_index(list_out,
+                                                            EventsRequest,
+                                                            index_ltime);
+          EventsRequest *event_request_list_out = &g_array_index(list_out,
+                                                            EventsRequest,
+                                                            i);
+          int comp;
+          comp = ltt_time_compare(event_request_ltime->start_time,
+                                  event_request_list_out->start_time);
+          if(comp == 0)
+            g_array_append_val(ltime, i);
+          else if(comp > 0) {
+            /* Remove all elements from ltime, and add current */
+            g_array_remove_range(ltime, 0, ltime->len);
+            g_array_append_val(ltime, i);
+
+          }
+        }
+        
+        /* 1.1.2 Find all position requests with the lowest position in list_out
+         * (lpos)
+         */
+        if(list_out->len > 0)
+          g_array_append(lpos, 0);
+        for(i=1;i<list_out->len;i++) {
+          /* Find all position requests with the lowest position in list_out */
+          guint index_lpos = g_array_index(lpos, guint, 0);
+          EventsRequest *event_request_lpos = &g_array_index(lpos,
+                                                            EventsRequest,
+                                                            index_lpos);
+          EventsRequest *event_request_list_out = &g_array_index(list_out,
+                                                            EventsRequest,
+                                                            i);
+          int comp;
+          comp = lttv_traceset_context_pos_pos_compare
+                                 (event_request_pos->start_position,
+                                  event_request_list_out->start_position);
+          if(comp == 0)
+            g_array_append_val(lpos, i);
+          else if(comp > 0) {
+            /* Remove all elements from lpos, and add current */
+            g_array_remove_range(lpos, 0, lpos->len);
+            g_array_append_val(lpos, i);
+          }
+        }
+        
+        /* 1.1.3 If lpos.start time < ltime */
+        {
+          guint i;
+          EventsRequest *event_request_lpos = &g_array_index(lpos, 0);
+          EventsRequest *event_request_ltime = &g_array_index(ltime,0);
+          LttTime lpos_start_time =
+            lttv_traceset_context_position_get_time(event_request_lpos);
+          
+          if(ltt_time_compare(lpos_start_time,
+                              event_request_ltime->start_time)<0) {
+            /* Add lpos to list_in, remove them from list_out */
+            
+            for(i=0;i<lpos->len;i++) {
+              /* Add to list_in */
+              guint index_lpos = g_array_index(lpos, guint, i);
+              EventsRequest *event_request_lpos = 
+                                    &g_array_index(lpos,index_lpos);
+
+              g_array_append_val(list_in, *event_request_lpos);
+
+            }
+
+            for(i=0;i<lpos->len;i++) {
+              /* Remove from list_out */
+              guint index_lpos = g_array_index(lpos, guint, i);
+
+              g_array_remove_index_fast(list_out, index_lpos);
+            }
+
+          } else {
+            /* 1.1.4 (lpos.start time >= ltime) */
+            /* Add ltime to list_in, remove them from list_out */
+
+            for(i=0;i<ltime->len;i++) {
+              /* Add to list_in */
+              guint index_ltime = g_array_index(ltime, guint, i);
+              EventsRequest *event_request_ltime = 
+                                    &g_array_index(ltime,index_ltime);
+
+              g_array_append_val(list_in, *event_request_ltime);
+            }
+
+            for(i=0;i<ltime->len;i++) {
+              /* Remove from list_out */
+              guint index_ltime = g_array_index(ltime, guint, i);
+
+              g_array_remove_index_fast(list_out, index_ltime);
+            }
+          }
+        }
+        g_array_free(lpos, TRUE);
+        g_array_free(ltime, TRUE);
+      }
+
+      /* 1.2 Seek */
+      {
+        EventsRequest *events_request = &g_array_index(list_in,
+                                                      EventsRequest,
+                                                      0);
+
+        /* 1.2.1 If first request in list_in is a time request */
+        if(events_request->start_position == NULL) {
+          /* 1.2.1.1 Seek to that time */
+          lttv_process_traceset_seek_time(tsc, events_request->start_time);
+        } else {
+          /* Else, the first request in list_in is a position request */
+          /* 1.2.2.1 Seek to that position */
+          lttv_process_traceset_seek_position(tsc, events_request->start_position);
+        }
+      }
+
+      /* 1.3 Call begin for all list_in members */
+      {
+        guint i;
+        
+        for(i=0;i<list_in->len;i++) {
+          EventsRequest *events_request = &g_array_index(list_in,
+                                                      EventsRequest,
+                                                      i);
+          /* (1.3.1 begin hooks called) */
+          /* (1.3.2 middle hooks added) */
+          lttv_process_traceset_begin(tsc, events_request->before_traceset,
+                                           events_request->before_trace,
+                                           events_request->before_tracefile,
+                                           events_request->event,
+                                           events_request->event_by_id);
+        }
+      }
+    } else {
+      /* 2. Else, list_in is not empty, we continue a read */
+      guint i;
+      tfc = lttv_traceset_context_get_current_tfc(tsc);
+    
+      /* 2.1 For each req of list_out */
+      for(i=0;i<list_out->len;i++) {
+        EventsRequest *events_request = &g_array_index(list_out,
+                                                      EventsRequest,
+                                                      i);
+        if(ltt_time_compare(events_request->start_time,
+                            tfc->timestamp) == 0) {
+          /* if req.start time == current context time */
+          /* Call Begin */
+          lttv_process_traceset_begin(tsc, events_request->before_traceset,
+                                           events_request->before_trace,
+                                           events_request->before_tracefile,
+                                           events_request->event,
+                                           events_request->event_by_id);
+   
+
+          /* Add to list_in */
+          g_array_append_val(list_in, *events_request);
+        } else if(events_request->start_position != NULL && 
+                          lttv_traceset_context_ctx_pos_compare(tsc,
+                                        events_request->start_position) == 0) {
+          /* if req.start position == current position */       
+          /* Call Begin */
+          lttv_process_traceset_begin(tsc, events_request->before_traceset,
+                                         events_request->before_trace,
+                                         events_request->before_tracefile,
+                                         events_request->event,
+                                         events_request->event_by_id);
+
+          /* Add to list_in */
+          g_array_append_val(list_in, *events_request);
+
+        }
+
+      }
+    
+
+      for(i=0;i<list_out->len;i++) {
+        EventsRequest *events_request = &g_array_index(list_out,
+                                                      EventsRequest,
+                                                      i);
+        if(ltt_time_compare(events_request->start_time,
+                            tfc->timestamp) == 0) {
+          /* if req.start time == current context time */
+          /* Remove from list_out */
+          g_array_remove_index_fast(list_out, i);
+        } else if(events_request->start_position != NULL && 
+                          lttv_traceset_context_ctx_pos_compare(tsc,
+                                        events_request->start_position) == 0) {
+          /* if req.start position == current position */       
+          /* Remove from list_out */
+          g_array_remove_index_fast(list_out, i);
+   
+        }
+      }
+    }
+
+
+
+    /* 3. Find end criterions */
+    {
+      /* 3.1 End time */
+      guint i;
+      
+      /* 3.1.1 Find lowest end time in list_in */
+      end_time = g_array_index(list_in, EventsRequest,0).end_time;
+      
+      for(i=1;i<list_in->len;i++) {
+        EventsRequest *events_request = &g_array_index(list_in,
+                                              EventsRequest,
+                                              i);
+        if(ltt_time_compare(events_request->end_time,
+                            end_time) < 0)
+          end_time = events_request->end_time;
+      }
+       
+      /* 3.1.2 Find lowest start time in list_out */
+      for(i=0;i<list_out->len;i++) {
+        EventsRequest *events_request = &g_array_index(list_out,
+                                              EventsRequest,
+                                              i);
+        if(ltt_time_compare(events_request->start_time,
+                            end_time) < 0)
+          end_time = events_request->start_time;
+      }
+    }
+
+    {
+      /* 3.2 Number of events */
+
+      /* 3.2.1 Find lowest number of events in list_in */
+      guint i;
+
+      end_nb_events = g_array_index(list_in, EventsRequest, 0).num_events;
+
+      for(i=1;i<list_in->len;i++) {
+        EventsRequest *events_request = &g_array_index(list_in,
+                                              EventsRequest,
+                                              i);
+        if(events_request->num_events < end_nb_events)
+          end_nb_events = events_request->num_events;
+      }
+    }
+
+    {
+      /* 3.3 End position */
 
-  lttv_process_traceset_seek_time(tsc, time_window->start_time);
-  lttv_process_traceset(tsc,
-                      ltt_time_add(time_window->start_time,time_window->time_width),
-                      max_nb_events);
+      /* 3.3.1 Find lowest end position in list_in */
+      guint i;
 
-  //call hooks to show each viewer and let them remove hooks
-  show_viewer(mw_data);  
+      end_position = g_array_index(list_in, EventsRequest, 0).end_position;
 
+      for(i=1;i<list_in->len;i++) {
+        EventsRequest *events_request = &g_array_index(list_in,
+                                              EventsRequest,
+                                              i);
+
+        if(lttv_traceset_context_pos_pos_compare(events_request->end_position,
+                                                 end_position) <0)
+          end_position = events_request->end_position;
+      }
+    }
+    
+    {  
+      /* 3.3.2 Find lowest start position in list_out */
+      guint i;
+
+      for(i=0;i<list_out->len;i++) {
+        EventsRequest *events_request = &g_array_index(list_out,
+                                              EventsRequest,
+                                              i);
+
+        if(lttv_traceset_context_pos_pos_compare(events_request->end_position,
+                                                 end_position) <0)
+          end_position = events_request->end_position;
+      }
+    }
+
+
+  }
+
+  /* B. When interrupted */
+
+  /* 1. for each request in list_in */
+  {
+    GSList *iter = list_in;
+    
+    while(iter != NULL) {
+
+      gboolean remove = FALSE;
+      gboolean free_data = FALSE;
+      EventsRequest events_request = (EventsRequest *)iter->data;
+      
+      /* 1.1. Use current postition as start position */
+      g_free(events_request->start_position);
+      lttv_traceset_context_position_save(tsc, events_request->start_position);
+
+      /* 1.2. Remove start time */
+      events_request->start_time = { G_MAXUINT, G_MAXUINT };
+      
+      /* 1.3. Call after_traceset */
+      /* 1.4. Remove event hooks */
+      lttv_process_traceset_end(tsc, events_request->after_traceset,
+                                     events_request->after_trace,
+                                     events_request->after_tracefile,
+                                     events_request->event,
+                                     events_request->event_by_id);
+
+      /* 1.5. Put it back in list_out */
+      remove = TRUE;
+      free_data = FALSE;
+      list_out = g_slist_append(list_out, events_request);
+
+
+      /* Go to next */
+      if(remove)
+      {
+        GSList *remove_iter = iter;
+
+        iter = g_slist_next(iter);
+        if(free_data) g_free(remove_iter->data);
+        list_in = g_slist_remove_link(list_in, remove_iter);
+      } else { // not remove
+        iter = g_slist_next(iter);
+      }
+    }
+
+
+  }
+
+  /* 2. Save current state into saved_state. */
+  {
+    /* 2.1 Free old saved state. */
+    //FIXME : free will need to be able to remove state for a traceset
+    //with changed traces!
+    //FIXME lttv_state_state_saved_free( , tab->interrupted_state);
+
+    /* 2.2 save current state. */
+    //FIXME
+    //lttv_state_save( ,tab->interrupted_state);
+
+  }
+  
   //set the cursor back to normal
   gdk_window_set_cursor(win, NULL);  
+
+
+  
+  if( g_slist_length(list_in) == 0 && g_slist_length(list_out) == 0 ) {
+    /* Put tab's request pending flag back to normal */
+    tab->time_request_pending = FALSE;
+    return FALSE; /* Remove the idle function */
+  }
+
+  return TRUE; /* Leave the idle function */
+
 }
 
+#ifdef TESTCODE
+   GSList *iter = list_in;
+    
+    /* 1. for each request in list_in */
+    while(iter != NULL) {
+
+      gboolean remove = FALSE;
+      gboolean free_data = FALSE;
+     
+
+
+      /* Go to next */
+      if(remove)
+      {
+        GSList *remove_iter = iter;
+
+        iter = g_slist_next(iter);
+        if(free_data) g_free(remove_iter->data);
+        list_in = g_slist_remove_link(list_in, remove_iter);
+      } else { // not remove
+        iter = g_slist_next(iter);
+      }
+    }
+#endif //TESTCODE
+
+
 
 /* add_trace_into_traceset_selector, each instance of a viewer has an associated
  * selector (filter), when a trace is added into traceset, the selector should 
@@ -485,9 +910,9 @@ void add_trace(GtkWidget * widget, gpointer user_data)
   LttTrace *trace;
   LttvTrace * trace_v;
   LttvTraceset * traceset;
-  LttvTracesetStats* tmp_context;
   const char * dir;
   gint id;
+  gint i;
   MainWindow * mw_data = get_window_data_struct(widget);
   GtkDirSelection * file_selector = (GtkDirSelection *)gtk_dir_selection_new("Select a trace");
   gtk_dir_selection_hide_fileop_buttons(file_selector);
@@ -500,20 +925,34 @@ void add_trace(GtkWidget * widget, gpointer user_data)
     case GTK_RESPONSE_OK:
       dir = gtk_dir_selection_get_dir (file_selector);
       strncpy(remember_trace_dir, dir, PATH_LENGTH);
-      if(!dir || strlen(dir) ==0){
-       gtk_widget_destroy((GtkWidget*)file_selector);
-       break;
+      if(!dir || strlen(dir) == 0){
+       gtk_widget_destroy((GtkWidget*)file_selector);
+       break;
       }
       trace = ltt_trace_open(dir);
       if(trace == NULL) g_critical("cannot open trace %s", dir);
       trace_v = lttv_trace_new(trace);
       traceset = mw_data->current_tab->traceset_info->traceset;
 
-      // Keep the context until the new one is created.
-      tmp_context = mw_data->current_tab->traceset_info->traceset_context;
-      mw_data->current_tab->traceset_info->traceset_context = NULL;
+      //Keep a reference to the traces so they are not freed.
+      for(i=0; i<lttv_traceset_number(traceset); i++)
+      {
+        LttvTrace * trace = lttv_traceset_get(traceset, i);
+        lttv_trace_ref(trace);
+      }
+
+      //remove state update hooks
+      lttv_state_remove_event_hooks(
+         (LttvTracesetState*)mw_data->current_tab->traceset_info->traceset_context);
+
+      lttv_context_fini(LTTV_TRACESET_CONTEXT(
+              mw_data->current_tab->traceset_info->traceset_context));
+      g_object_unref(mw_data->current_tab->traceset_info->traceset_context);
+  
 
       lttv_traceset_add(traceset, trace_v);
+
+      /* Create new context */
       mw_data->current_tab->traceset_info->traceset_context =
                                g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
       lttv_context_init(
@@ -523,37 +962,45 @@ void add_trace(GtkWidget * widget, gpointer user_data)
       //add state update hooks
       lttv_state_add_event_hooks(
       (LttvTracesetState*)mw_data->current_tab->traceset_info->traceset_context);
-      if(tmp_context != NULL)
+      //Remove local reference to the traces.
+      for(i=0; i<lttv_traceset_number(traceset); i++)
       {
-        //remove state update hooks
-        lttv_state_remove_event_hooks(
-           (LttvTracesetState*)tmp_context);
-       lttv_context_fini(LTTV_TRACESET_CONTEXT(tmp_context));
-       g_object_unref(tmp_context);
+        LttvTrace * trace = lttv_traceset_get(traceset, i);
+        lttv_trace_unref(trace);
       }
 
 
       add_trace_into_traceset_selector(mw_data->current_tab->multi_vpaned, trace);
 
       gtk_widget_destroy((GtkWidget*)file_selector);
       
       //update current tab
-      update_traceset(mw_data);
+      //update_traceset(mw_data);
 
       //get_traceset_time_span(mw_data,LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->traceset_context)->Time_Span);
-      if(lttv_traceset_number(mw_data->current_tab->traceset_info->traceset) == 1 ||
-        ltt_time_compare(mw_data->current_tab->current_time,
-             LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->traceset_context)->Time_Span->startTime)<0){
-       mw_data->current_tab->current_time = 
-           LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->traceset_context)->Time_Span->startTime;
-       mw_data->current_tab->time_window.start_time = mw_data->current_tab->current_time;
-       mw_data->current_tab->time_window.time_width.tv_sec = DEFAULT_TIME_WIDTH_S;
-       mw_data->current_tab->time_window.time_width.tv_nsec = 0;
+      if(
+       lttv_traceset_number(mw_data->current_tab->traceset_info->traceset) == 1
+       || ltt_time_compare(mw_data->current_tab->current_time,
+            LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->
+                    traceset_context)->time_span.start_time)<0)
+      {
+        /* Set initial time if this is the first trace in the traceset */
+       mw_data->current_tab->current_time = 
+           LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->
+                        traceset_context)->time_span.start_time;
+             mw_data->current_tab->time_window.start_time = 
+           mw_data->current_tab->current_time;
+             mw_data->current_tab->time_window.time_width.tv_sec = 
+           DEFAULT_TIME_WIDTH_S;
+             mw_data->current_tab->time_window.time_width.tv_nsec = 0;
       } 
 
-      redraw_viewer(mw_data, &(mw_data->current_tab->time_window));
-      lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
+      /* Call the updatetraceset hooks */
+      
+      SetTraceset(mw_data, (gpointer)traceset);
+      // in expose now call_pending_read_hooks(mw_data);
+      
+      //lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
       break;
     case GTK_RESPONSE_REJECT:
     case GTK_RESPONSE_CANCEL:
@@ -602,8 +1049,7 @@ void remove_trace(GtkWidget * widget, gpointer user_data)
   LttTrace *trace;
   LttvTrace * trace_v;
   LttvTraceset * traceset;
-  LttvTracesetStats* tmp_context;
-  gint i, nb_trace;
+  gint i, j, nb_trace;
   char ** name, *remove_trace_name;
   MainWindow * mw_data = get_window_data_struct(widget);
   LttvTracesetSelector * s;
@@ -655,37 +1101,51 @@ void remove_trace(GtkWidget * widget, gpointer user_data)
          trace_v = lttv_traceset_get(traceset, i);
          if(lttv_trace_get_ref_number(trace_v) <= 1)
            ltt_trace_close(lttv_trace(trace_v));
-    
-    // Keep the context until the new one is created.
-    tmp_context = mw_data->current_tab->traceset_info->traceset_context;
-    mw_data->current_tab->traceset_info->traceset_context = NULL;
+
+    //Keep a reference to the traces so they are not freed.
+    for(j=0; j<lttv_traceset_number(traceset); j++)
+    {
+      LttvTrace * trace = lttv_traceset_get(traceset, j);
+      lttv_trace_ref(trace);
+    }
+
+    //remove state update hooks
+    lttv_state_remove_event_hooks(
+         (LttvTracesetState*)mw_data->current_tab->traceset_info->traceset_context);
+    lttv_context_fini(LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->traceset_context));
+    g_object_unref(mw_data->current_tab->traceset_info->traceset_context);
+
     
          lttv_traceset_remove(traceset, i);
+    lttv_trace_unref(trace_v);  // Remove local reference
          if(!lttv_trace_get_ref_number(trace_v))
             lttv_trace_destroy(trace_v);
+    
          mw_data->current_tab->traceset_info->traceset_context =
            g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
-           lttv_context_init(
+    lttv_context_init(
                            LTTV_TRACESET_CONTEXT(mw_data->current_tab->
                                      traceset_info->traceset_context),traceset);      
       //add state update hooks
-      lttv_state_add_event_hooks(
+    lttv_state_add_event_hooks(
       (LttvTracesetState*)mw_data->current_tab->traceset_info->traceset_context);
 
-         if(tmp_context != NULL){
-      //remove state update hooks
-      lttv_state_remove_event_hooks(
-           (LttvTracesetState*)tmp_context);
-           lttv_context_fini(LTTV_TRACESET_CONTEXT(tmp_context));
-           g_object_unref(tmp_context);
-         }
+    //Remove local reference to the traces.
+    for(j=0; j<lttv_traceset_number(traceset); j++)
+    {
+      LttvTrace * trace = lttv_traceset_get(traceset, j);
+      lttv_trace_unref(trace);
+    }
+
 
-      
          //update current tab
-         update_traceset(mw_data);
+         //update_traceset(mw_data);
          if(nb_trace > 1){
-           redraw_viewer(mw_data, &(mw_data->current_tab->time_window));
-           lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
+
+      SetTraceset(mw_data, (gpointer)traceset);
+         // in expose now call_pending_read_hooks(mw_data);
+
+           //lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
          }else{
            if(mw_data->current_tab){
              while(mw_data->current_tab->multi_vpaned->num_children){
@@ -704,7 +1164,7 @@ void remove_trace(GtkWidget * widget, gpointer user_data)
 
 
 /* save will save the traceset to a file
- * Not implemented yet
+ * Not implemented yet FIXME
  */
 
 void save(GtkWidget * widget, gpointer user_data)
@@ -726,44 +1186,79 @@ void save_as(GtkWidget * widget, gpointer user_data)
 void zoom(GtkWidget * widget, double size)
 {
   TimeInterval *time_span;
-  TimeWindow time_window;
-  LttTime    current_time, time_delta, time_s, time_e, time_t;
+  TimeWindow new_time_window;
+  LttTime    current_time, time_delta, time_s, time_e, time_tmp;
   MainWindow * mw_data = get_window_data_struct(widget);
+  Tab *tab = mw_data->current_tab;
+  LttvTracesetContext *tsc =
+    LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
 
   if(size == 1) return;
 
-  time_span = LTTV_TRACESET_CONTEXT(mw_data->current_tab->
-                                   traceset_info->traceset_context)->Time_Span;
-  time_window =  mw_data->current_tab->time_window;
-  current_time = mw_data->current_tab->current_time;
+  time_span = &tsc->time_span;
+  new_time_window =  tab->time_window;
+  current_time = tab->current_time;
   
-  time_delta = ltt_time_sub(time_span->endTime,time_span->startTime);
+  time_delta = ltt_time_sub(time_span->end_time,time_span->start_time);
   if(size == 0){
-    time_window.start_time = time_span->startTime;
-    time_window.time_width = time_delta;
+    new_time_window.start_time = time_span->start_time;
+    new_time_window.time_width = time_delta;
   }else{
-    time_window.time_width = ltt_time_div(time_window.time_width, size);
-    if(ltt_time_compare(time_window.time_width,time_delta) > 0)
-      time_window.time_width = time_delta;
-
-    time_t = ltt_time_div(time_window.time_width, 2);
-    if(ltt_time_compare(current_time, time_t) < 0){
-      time_s = time_span->startTime;
-    } else {
-      time_s = ltt_time_sub(current_time,time_t);
+    new_time_window.time_width = ltt_time_div(new_time_window.time_width, size);
+    if(ltt_time_compare(new_time_window.time_width,time_delta) > 0)
+    { /* Case where zoom out is bigger than trace length */
+      new_time_window.start_time = time_span->start_time;
+      new_time_window.time_width = time_delta;
     }
-    time_e = ltt_time_add(current_time,time_t);
-    if(ltt_time_compare(time_span->startTime, time_s) > 0){
-      time_s = time_span->startTime;
-    }else if(ltt_time_compare(time_span->endTime, time_e) < 0){
-      time_e = time_span->endTime;
-      time_s = ltt_time_sub(time_e,time_window.time_width);
+    else
+    {
+      /* Center the image on the current time */
+      g_critical("update is HERE");
+      new_time_window.start_time = 
+        ltt_time_sub(current_time, ltt_time_div(new_time_window.time_width, 2.0));
+      /* If on borders, don't fall off */
+      if(ltt_time_compare(new_time_window.start_time, time_span->start_time) <0)
+      {
+        new_time_window.start_time = time_span->start_time;
+      }
+      else 
+      {
+        if(ltt_time_compare(
+           ltt_time_add(new_time_window.start_time, new_time_window.time_width),
+           time_span->end_time) > 0)
+        {
+          new_time_window.start_time = 
+                  ltt_time_sub(time_span->end_time, new_time_window.time_width);
+        }
+      }
+      
     }
-    time_window.start_time = time_s;    
+
+    
+
+    //time_tmp = ltt_time_div(new_time_window.time_width, 2);
+    //if(ltt_time_compare(current_time, time_tmp) < 0){
+    //  time_s = time_span->startTime;
+    //} else {
+    //  time_s = ltt_time_sub(current_time,time_tmp);
+    //}
+    //time_e = ltt_time_add(current_time,time_tmp);
+    //if(ltt_time_compare(time_span->startTime, time_s) > 0){
+    //  time_s = time_span->startTime;
+    //}else if(ltt_time_compare(time_span->endTime, time_e) < 0){
+    //  time_e = time_span->endTime;
+    //  time_s = ltt_time_sub(time_e,new_time_window.time_width);
+    //}
+    //new_time_window.start_time = time_s;    
   }
-  redraw_viewer(mw_data, &time_window);
-  lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
-  gtk_multi_vpaned_set_adjust(mw_data->current_tab->multi_vpaned, FALSE);
+
+  //lttvwindow_report_time_window(mw_data, &new_time_window);
+  //call_pending_read_hooks(mw_data);
+
+  //lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
+  set_time_window(tab, &new_time_window);
+  // in expose now call_pending_read_hooks(mw_data);
+  gtk_multi_vpaned_set_adjust(tab->multi_vpaned, &new_time_window, FALSE);
 }
 
 void zoom_in(GtkWidget * widget, gpointer user_data)
@@ -824,7 +1319,7 @@ void create_new_tab(GtkWidget* widget, gpointer user_data){
 
   strcpy(label,"Page");
   if(get_label(mw_data, label,"Get the name of the tab","Please input tab's name"))    
-    create_tab (mw_data, mw_data, notebook, label);
+    create_tab (NULL, mw_data, notebook, label);
 }
 
 void
@@ -1039,9 +1534,10 @@ on_trace_filter_activate              (GtkMenuItem     *menuitem,
     return;
   }
   if(get_filter_selection(s, "Configure trace and tracefile filter", "Select traces and tracefiles")){
-    update_traceset(mw_data);
-    redraw_viewer(mw_data, &(mw_data->current_tab->time_window));
-    lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
+    //FIXME report filter change
+    //update_traceset(mw_data);
+    //call_pending_read_hooks(mw_data);
+    //lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
   }
 }
 
@@ -1086,8 +1582,6 @@ on_load_module_activate                (GtkMenuItem     *menuitem,
        str1++;
       }
       lttv_module_require(str1, NULL);
-      g_slist_foreach(g_main_window_list, (gpointer)insert_menu_toolbar_item,
-          NULL);
       g_strfreev(dir);
     case GTK_RESPONSE_REJECT:
     case GTK_RESPONSE_CANCEL:
@@ -1131,7 +1625,7 @@ on_unload_module_activate              (GtkMenuItem     *menuitem,
       library = lttv_library_get(i);
       lttv_library_info(library, &library_info);
       if(strcmp(unload_module_name, library_info.name) == 0){
-       lttv_library_unload(library);
+             lttv_library_unload(library);
        break;
       }
     }    
@@ -1334,13 +1828,34 @@ void
 on_MWindow_destroy                     (GtkObject       *object,
                                         gpointer         user_data)
 {
-  MainWindow *Main_Window = get_window_data_struct((GtkWidget*)object);
+  MainWindow *main_window = get_window_data_struct((GtkWidget*)object);
   GtkWidget  *widget;
-  Tab *tab = Main_Window->tab;
+  Tab *tab = main_window->tab;
+  LttvIAttribute *attributes = main_window->attributes;
+  LttvAttributeValue value;
  
-  g_printf("There are : %d windows\n",g_slist_length(g_main_window_list));
+  //This is unnecessary, since widgets will be destroyed
+  //by the main window widget anyway.
+  //remove_all_menu_toolbar_constructors(main_window, NULL);
+
+  g_assert(lttv_iattribute_find_by_path(attributes,
+           "viewers/menu", LTTV_POINTER, &value));
+  lttv_menus_destroy((LttvMenus*)*(value.v_pointer));
+
+  g_assert(lttv_iattribute_find_by_path(attributes,
+           "viewers/toolbar", LTTV_POINTER, &value));
+  lttv_toolbars_destroy((LttvToolbars*)*(value.v_pointer));
+  
+  while(main_window->tab){
+    lttv_state_remove_event_hooks(
+         (LttvTracesetState*)main_window->tab->traceset_info->traceset_context);
+    main_window->tab = main_window->tab->next;
+  }
+  g_object_unref(main_window->attributes);
+  g_main_window_list = g_slist_remove(g_main_window_list, main_window);
 
   g_win_count--;
+  g_printf("There are now : %d windows\n",g_slist_length(g_main_window_list));
   if(g_win_count == 0)
     gtk_main_quit ();
 }
@@ -1380,7 +1895,6 @@ on_MWindow_configure                   (GtkWidget         *widget,
   return FALSE;
 }
 
-
 /* Set current tab
  */
 
@@ -1727,87 +2241,108 @@ char * get_selection(char ** loaded_module_name, int nb_module,
 }
 
 
-/* hash funtions 
- */
-
-void main_window_destroy_hash_key(gpointer key)
-{
-  g_free(key);
-}
-
-void main_window_destroy_hash_data(gpointer data)
-{
-}
-
-
-/* Insert menu entry and tool button into all main windows for modules
- * It checks whether the menu entry or tool button exists or not,
- * if they do not exist, then construct the widget and insert them 
- * into all main windows
+/* Insert all menu entry and tool buttons into this main window
+ * for modules.
+ *
  */
 
-void insert_menu_toolbar_item(MainWindow * mw, gpointer user_data)
+void add_all_menu_toolbar_constructors(MainWindow * mw, gpointer user_data)
 {
   int i;
   GdkPixbuf *pixbuf;
   lttvwindow_viewer_constructor constructor;
-  LttvMenus * menu;
-  LttvToolbars * toolbar;
-  lttv_menu_closure *menu_item;
-  lttv_toolbar_closure *toolbar_item;
+  LttvMenus * global_menu, * instance_menu;
+  LttvToolbars * global_toolbar, * instance_toolbar;
+  LttvMenuClosure *menu_item;
+  LttvToolbarClosure *toolbar_item;
   LttvAttributeValue value;
-  LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
-  GtkWidget * tool_menu_title_menu, *insert_view, *pixmap, *tmp;
+  LttvIAttribute *global_attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
+  LttvIAttribute *attributes = mw->attributes;
+  GtkWidget * tool_menu_title_menu, *new_widget, *pixmap;
+
+  g_assert(lttv_iattribute_find_by_path(global_attributes,
+          "viewers/menu", LTTV_POINTER, &value));
+  if(*(value.v_pointer) == NULL)
+    *(value.v_pointer) = lttv_menus_new();
+  global_menu = (LttvMenus*)*(value.v_pointer);
 
   g_assert(lttv_iattribute_find_by_path(attributes,
           "viewers/menu", LTTV_POINTER, &value));
-  menu = (LttvMenus*)*(value.v_pointer);
-
-  if(menu){
-    for(i=0;i<menu->len;i++){
-      menu_item = &g_array_index(menu, lttv_menu_closure, i);
-      tmp = g_hash_table_lookup(mw->hash_menu_item, g_strdup(menu_item->menuText));
-      if(tmp)continue;
-      constructor = menu_item->con;
-      tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
-      insert_view = gtk_menu_item_new_with_mnemonic (menu_item->menuText);
-      gtk_widget_show (insert_view);
-      gtk_container_add (GTK_CONTAINER (tool_menu_title_menu), insert_view);
-      g_signal_connect ((gpointer) insert_view, "activate",
-                       G_CALLBACK (insert_viewer_wrap),
-                       constructor);  
-      g_hash_table_insert(mw->hash_menu_item, g_strdup(menu_item->menuText),
-                         insert_view);
-    }
-  }
+  if(*(value.v_pointer) == NULL)
+    *(value.v_pointer) = lttv_menus_new();
+  instance_menu = (LttvMenus*)*(value.v_pointer);
+
+
+
+  g_assert(lttv_iattribute_find_by_path(global_attributes,
+          "viewers/toolbar", LTTV_POINTER, &value));
+  if(*(value.v_pointer) == NULL)
+    *(value.v_pointer) = lttv_toolbars_new();
+  global_toolbar = (LttvToolbars*)*(value.v_pointer);
 
   g_assert(lttv_iattribute_find_by_path(attributes,
           "viewers/toolbar", LTTV_POINTER, &value));
-  toolbar = (LttvToolbars*)*(value.v_pointer);
-
-  if(toolbar){
-    for(i=0;i<toolbar->len;i++){
-      toolbar_item = &g_array_index(toolbar, lttv_toolbar_closure, i);
-      tmp = g_hash_table_lookup(mw->hash_toolbar_item, g_strdup(toolbar_item->tooltip));
-      if(tmp)continue;
-      constructor = toolbar_item->con;
-      tool_menu_title_menu = lookup_widget(mw->mwindow,"MToolbar1");
-      pixbuf = gdk_pixbuf_new_from_xpm_data ((const char**)toolbar_item->pixmap);
-      pixmap = gtk_image_new_from_pixbuf(pixbuf);
-      insert_view = gtk_toolbar_append_element (GTK_TOOLBAR (tool_menu_title_menu),
-                                               GTK_TOOLBAR_CHILD_BUTTON,
-                                               NULL,
-                                               "",
-                                               toolbar_item->tooltip, NULL,
-                                               pixmap, NULL, NULL);
-      gtk_label_set_use_underline (GTK_LABEL (((GtkToolbarChild*) (g_list_last (GTK_TOOLBAR (tool_menu_title_menu)->children)->data))->label), TRUE);
-      gtk_widget_show (insert_view);
-      gtk_container_set_border_width (GTK_CONTAINER (insert_view), 1);
-      g_signal_connect ((gpointer) insert_view, "clicked",G_CALLBACK (insert_viewer_wrap),constructor);       
-      g_hash_table_insert(mw->hash_toolbar_item, g_strdup(toolbar_item->tooltip),
-                         insert_view);
-    }
+  if(*(value.v_pointer) == NULL)
+    *(value.v_pointer) = lttv_toolbars_new();
+  instance_toolbar = (LttvToolbars*)*(value.v_pointer);
+
+  /* Add missing menu entries to window instance */
+  for(i=0;i<global_menu->len;i++) {
+    menu_item = &g_array_index(global_menu, LttvMenuClosure, i);
+
+    //add menu_item to window instance;
+    constructor = menu_item->con;
+    tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
+    new_widget =
+      gtk_menu_item_new_with_mnemonic (menu_item->menu_text);
+    gtk_container_add (GTK_CONTAINER (tool_menu_title_menu),
+        new_widget);
+    g_signal_connect ((gpointer) new_widget, "activate",
+        G_CALLBACK (insert_viewer_wrap),
+        constructor);  
+    gtk_widget_show (new_widget);
+    lttv_menus_add(instance_menu, menu_item->con, 
+        menu_item->menu_path,
+        menu_item->menu_text,
+        new_widget);
+
   }
+
+  /* Add missing toolbar entries to window instance */
+  for(i=0;i<global_toolbar->len;i++) {
+    toolbar_item = &g_array_index(global_toolbar, LttvToolbarClosure, i);
+
+    //add toolbar_item to window instance;
+    constructor = toolbar_item->con;
+    tool_menu_title_menu = lookup_widget(mw->mwindow,"MToolbar1");
+    pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)toolbar_item->pixmap);
+    pixmap = gtk_image_new_from_pixbuf(pixbuf);
+    new_widget =
+       gtk_toolbar_append_element (GTK_TOOLBAR (tool_menu_title_menu),
+          GTK_TOOLBAR_CHILD_BUTTON,
+          NULL,
+          "",
+          toolbar_item->tooltip, NULL,
+          pixmap, NULL, NULL);
+    gtk_label_set_use_underline(
+        GTK_LABEL (((GtkToolbarChild*) (
+                         g_list_last (GTK_TOOLBAR 
+                            (tool_menu_title_menu)->children)->data))->label),
+        TRUE);
+    gtk_container_set_border_width (GTK_CONTAINER (new_widget), 1);
+    g_signal_connect ((gpointer) new_widget,
+        "clicked",
+        G_CALLBACK (insert_viewer_wrap),
+        constructor);       
+    gtk_widget_show (new_widget);
+    lttv_toolbars_add(instance_toolbar, toolbar_item->con, 
+                      toolbar_item->tooltip,
+                      toolbar_item->pixmap,
+                      new_widget);
+
+  }
+
 }
 
 
@@ -1833,24 +2368,22 @@ void construct_main_window(MainWindow * parent)
   new_window  = create_MWindow();
   gtk_widget_show (new_window);
     
-  new_m_window->attributes = attributes;
-  
   new_m_window->mwindow = new_window;
   new_m_window->tab = NULL;
   new_m_window->current_tab = NULL;
-  new_m_window->attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
+  new_m_window->attributes = attributes;
+
+  g_assert(lttv_iattribute_find_by_path(attributes,
+           "viewers/menu", LTTV_POINTER, &value));
+  *(value.v_pointer) = lttv_menus_new();
 
-  new_m_window->hash_menu_item = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                             main_window_destroy_hash_key, 
-                                             main_window_destroy_hash_data);
-  new_m_window->hash_toolbar_item = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                             main_window_destroy_hash_key, 
-                                             main_window_destroy_hash_data);
+  g_assert(lttv_iattribute_find_by_path(attributes,
+           "viewers/toolbar", LTTV_POINTER, &value));
+  *(value.v_pointer) = lttv_toolbars_new();
 
-  insert_menu_toolbar_item(new_m_window, NULL);
+  add_all_menu_toolbar_constructors(new_m_window, NULL);
   
   g_object_set_data(G_OBJECT(new_window), "mainWindow", (gpointer)new_m_window);    
-
   //create a default tab
   notebook = (GtkNotebook *)lookup_widget(new_m_window->mwindow, "MNotebook");
   if(notebook == NULL){
@@ -1859,15 +2392,16 @@ void construct_main_window(MainWindow * parent)
   }
   //for now there is no name field in LttvTraceset structure
   //Use "Traceset" as the label for the default tab
-  create_tab(parent, new_m_window, notebook,"Traceset");
+  create_tab(parent, new_m_window, notebook, "Traceset");
 
   g_object_set_data_full(
                        G_OBJECT(new_m_window->mwindow),
                        "Main_Window_Data",
                        new_m_window,
-                       (GDestroyNotify)main_window_free);
+                       NULL);
 
   g_win_count++;
+  g_printf("There are now : %d windows\n",g_slist_length(g_main_window_list));
 }
 
 
@@ -1881,7 +2415,11 @@ void tab_destructor(Tab * tab_instance)
   LttvTrace * trace;
 
   if(tab_instance->attributes)
-    g_object_unref(tab_instance->attributes);  
+    g_object_unref(tab_instance->attributes);
+
+  if(tab_instance->interrupted_state)
+    g_object_unref(tab_instance->interrupted_state);
+
 
   if(tab_instance->mw->tab == tab_instance){
     tab_instance->mw->tab = tab_instance->next;
@@ -1915,7 +2453,11 @@ void tab_destructor(Tab * tab_instance)
       //      lttv_trace_destroy(trace);
     }
   }  
-  lttv_traceset_destroy(tab_instance->traceset_info->traceset); 
+  lttv_traceset_destroy(tab_instance->traceset_info->traceset);
+  /* Remove the idle events requests processing function of the tab */
+  g_idle_remove_by_data(tab_instance);
+
+  g_slist_free(tab_instance->events_requests);
   g_free(tab_instance->traceset_info);
   g_free(tab_instance);
 }
@@ -1931,7 +2473,7 @@ void * create_tab(MainWindow * parent, MainWindow* current_window,
   Tab * tmp_tab;
   MainWindow * mw_data = current_window;
   LttTime tmp_time;
-
+  
   //create a new tab data structure
   tmp_tab = mw_data->tab;
   while(tmp_tab && tmp_tab->next) tmp_tab = tmp_tab->next;
@@ -1947,22 +2489,32 @@ void * create_tab(MainWindow * parent, MainWindow* current_window,
   //construct and initialize the traceset_info
   tmp_tab->traceset_info = g_new(TracesetInfo,1);
   if(parent){
-    tmp_tab->traceset_info->traceset = 
-      lttv_traceset_copy(parent->current_tab->traceset_info->traceset);
-  }else{
+    if(parent->current_tab){
+      tmp_tab->traceset_info->traceset = 
+                      lttv_traceset_new();
+        //FIXME lttv_traceset_copy(parent->current_tab->traceset_info->traceset);
+    }else{
+      tmp_tab->traceset_info->traceset = lttv_traceset_new();
+    }
+
+  }else{  /* Initial window */
     if(mw_data->current_tab){
       tmp_tab->traceset_info->traceset = 
-        lttv_traceset_copy(mw_data->current_tab->traceset_info->traceset);
+                      lttv_traceset_new();
+        //FIXME lttv_traceset_copy(mw_data->current_tab->traceset_info->traceset);
     }else{
       tmp_tab->traceset_info->traceset = lttv_traceset_new();    
       /* Add the command line trace */
-      if(g_init_trace != NULL)
+      if(g_init_trace != NULL){
        lttv_traceset_add(tmp_tab->traceset_info->traceset, g_init_trace);
+      }
     }
   }
+  
   //FIXME copy not implemented in lower level
   tmp_tab->traceset_info->traceset_context =
     g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
+  g_assert(tmp_tab->traceset_info->traceset_context != NULL);
   lttv_context_init(
            LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context),
                                  tmp_tab->traceset_info->traceset);
@@ -1970,7 +2522,6 @@ void * create_tab(MainWindow * parent, MainWindow* current_window,
   lttv_state_add_event_hooks(
        (LttvTracesetState*)tmp_tab->traceset_info->traceset_context);
   
   //determine the current_time and time_window of the tab
   if(mw_data->current_tab){
     // Will have to read directly at the main window level, as we want
@@ -1982,24 +2533,27 @@ void * create_tab(MainWindow * parent, MainWindow* current_window,
     // to be able to modify a traceset on the fly.
     // get_traceset_time_span(mw_data,&tmp_tab->traceStartTime, &tmp_tab->traceEndTime);
     tmp_tab->time_window.start_time   = 
-           LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->startTime;
+           LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.start_time;
     if(DEFAULT_TIME_WIDTH_S <
-              LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->endTime.tv_sec)
+              LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.end_time.tv_sec)
       tmp_time.tv_sec = DEFAULT_TIME_WIDTH_S;
     else
       tmp_time.tv_sec =
-              LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->endTime.tv_sec;
+              LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.end_time.tv_sec;
     tmp_time.tv_nsec = 0;
     tmp_tab->time_window.time_width = tmp_time ;
     tmp_tab->current_time.tv_sec = 
-       LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->startTime.tv_sec;
+       LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.start_time.tv_sec;
     tmp_tab->current_time.tv_nsec = 
-       LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->startTime.tv_nsec;
+       LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.start_time.tv_nsec;
   }
+  /* Become the current tab */
+  mw_data->current_tab = tmp_tab;
+
   tmp_tab->attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
-  //  mw_data->current_tab = tmp_tab;
+  tmp_tab->interrupted_state = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
   tmp_tab->multi_vpaned = (GtkMultiVPaned*)gtk_multi_vpaned_new();
-  tmp_tab->multi_vpaned->mw = mw_data;
+  tmp_tab->multi_vpaned->tab = mw_data->current_tab;
   gtk_widget_show((GtkWidget*)tmp_tab->multi_vpaned);
   tmp_tab->next = NULL;    
   tmp_tab->mw   = mw_data;
@@ -2007,6 +2561,10 @@ void * create_tab(MainWindow * parent, MainWindow* current_window,
   tmp_tab->label = gtk_label_new (label);
   gtk_widget_show (tmp_tab->label);
 
+  /* Start with empty events requests list */
+  tmp_tab->events_requests = NULL;
+  tmp_tab->events_request_pending = FALSE;
+
   g_object_set_data_full(
            G_OBJECT(tmp_tab->multi_vpaned),
            "Tab_Info",
@@ -2017,96 +2575,53 @@ void * create_tab(MainWindow * parent, MainWindow* current_window,
   gtk_notebook_append_page(notebook, (GtkWidget*)tmp_tab->multi_vpaned, tmp_tab->label);  
   list = gtk_container_get_children(GTK_CONTAINER(notebook));
   gtk_notebook_set_current_page(notebook,g_list_length(list)-1);
-  if(g_list_length(list)>1)
-    gtk_notebook_set_show_tabs(notebook, TRUE);
+  // always show : not if(g_list_length(list)>1)
+  gtk_notebook_set_show_tabs(notebook, TRUE);
 }
 
-
-/* Remove menu entry and tool button from main window for the 
- * unloaded  module
+/**
+ * Function to show each viewer in the current tab.
+ * It will be called by main window, call show on each registered viewer,
+ * will call process traceset and then it will
+ * @param main_win the main window the viewer belongs to.
  */
-
-void remove_menu_item(gpointer main_win, gpointer user_data)
+//FIXME Only one time request maximum for now!
+void show_viewer(MainWindow *main_win)
 {
-  MainWindow * mw = (MainWindow *) main_win;
-  lttv_menu_closure *menu_item = (lttv_menu_closure *)user_data;
-  GtkWidget * tool_menu_title_menu, *insert_view;
-
-  tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
-  insert_view = (GtkWidget*)g_hash_table_lookup(mw->hash_menu_item,
-                                               menu_item->menuText);
-  if(insert_view){
-    g_hash_table_remove(mw->hash_menu_item, menu_item->menuText);
-    gtk_container_remove (GTK_CONTAINER (tool_menu_title_menu), insert_view);
+  LttvAttributeValue value;
+  LttvHooks * tmp;
+  int i;
+  LttvTracesetContext * tsc = 
+              (LttvTracesetContext*)main_win->current_tab->
+                                      traceset_info->traceset_context;
+  
+  g_assert(lttv_iattribute_find_by_path(main_win->current_tab->attributes,
+           "hooks/showviewer", LTTV_POINTER, &value));
+  tmp = (LttvHooks*)*(value.v_pointer);
+  if(tmp == NULL)
+  {
+    g_warning("The viewer(s) did not add any show hook");
+    return;
   }
-}
-
-void remove_toolbar_item(gpointer main_win, gpointer user_data)
-{
-  MainWindow * mw = (MainWindow *) main_win;
-  lttv_toolbar_closure *toolbar_item = (lttv_toolbar_closure *)user_data;
-  GtkWidget * tool_menu_title_menu, *insert_view;
 
+  
+  // Call the show, where viewers add hooks to context and fill the
+  // time and number of events requested it the time_requests GArray.
+  lttv_hooks_call(tmp, NULL);
 
-  tool_menu_title_menu = lookup_widget(mw->mwindow,"MToolbar1");
-  insert_view = (GtkWidget*)g_hash_table_lookup(mw->hash_toolbar_item,
-                                               toolbar_item->tooltip);
-  if(insert_view){
-    g_hash_table_remove(mw->hash_toolbar_item, toolbar_item->tooltip);
-    gtk_container_remove (GTK_CONTAINER (tool_menu_title_menu), insert_view);
-  }
 }
 
-/**
- * Remove menu and toolbar item when a module unloaded from all 
- * main windows
+/*
+ * execute_events_requests
+ *
+ * Idle function that executes the pending requests for a tab.
+ *
+ * @return return value : TRUE : keep the idle function, FALSE : remove it.
  */
-
-void main_window_remove_menu_item(lttvwindow_viewer_constructor constructor)
+gboolean execute_events_requests(Tab *tab)
 {
-  int i;
-  LttvMenus * menu;
-  lttv_menu_closure *menu_item;
-  LttvAttributeValue value;
-  LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
-
-  g_assert(lttv_iattribute_find_by_path(attributes,
-          "viewers/menu", LTTV_POINTER, &value));
-  menu = (LttvMenus*)*(value.v_pointer);
-
-  if(menu){
-    for(i=0;i<menu->len;i++){
-      menu_item = &g_array_index(menu, lttv_menu_closure, i);
-      if(menu_item->con != constructor) continue;
-      if(g_main_window_list){
-       g_slist_foreach(g_main_window_list, remove_menu_item, menu_item);
-      }
-      break;
-    }
-  }
-  
+  return ( lttvwindow_process_pending_requests(tab) );
 }
 
-void main_window_remove_toolbar_item(lttvwindow_viewer_constructor constructor)
-{
-  int i;
-  LttvToolbars * toolbar;
-  lttv_toolbar_closure *toolbar_item;
-  LttvAttributeValue value;
-  LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
-
-  g_assert(lttv_iattribute_find_by_path(attributes,
-          "viewers/toolbar", LTTV_POINTER, &value));
-  toolbar = (LttvToolbars*)*(value.v_pointer);
-
-  if(toolbar){
-    for(i=0;i<toolbar->len;i++){
-      toolbar_item = &g_array_index(toolbar, lttv_toolbar_closure, i);
-      if(toolbar_item->con != constructor) continue;
-      if(g_main_window_list){
-       g_slist_foreach(g_main_window_list, remove_toolbar_item, toolbar_item);
-      }
-      break;
-    }
-  }
-}
This page took 0.039809 seconds and 4 git commands to generate.