resourceview: collapse pixmaps when collapsing branches in the resource tree, and...
[lttv.git] / ltt / branches / poly / lttv / modules / gui / resourceview / processlist.c
index 71c7fe6381427fa4ed870a5715f5b062e0ee3e20..03c838254a4845dc770f2e1aa6a98fe0068a60bf 100644 (file)
@@ -106,6 +106,77 @@ gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data)
        return TRUE;
 }
 
+void expand_event(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *arg2, gpointer user_data)
+{
+  ControlFlowData *resourceview_data = 
+      (ControlFlowData*)g_object_get_data(
+                G_OBJECT(treeview),
+                "resourceview_data");
+  ProcessList *process_list = (ProcessList *) user_data;
+  ResourceUnique *rup;
+  HashedResourceData *hrd;
+  gboolean result;
+
+  GtkTreeModel *model;
+  GtkTreeIter child;
+
+  /* Determine which trace has been expanded */
+  model = gtk_tree_view_get_model(treeview);
+
+  /* mark each of the trace's resources invisible */
+  result = gtk_tree_model_iter_children(model, &child, iter);
+
+  /* for each child of the collapsed row */
+  while(result) {
+    /* hide the item */
+    gtk_tree_model_get(model, &child, DATA_COLUMN, &hrd, -1);
+    hrd->hidden=0;
+
+    /* find next */
+    result = gtk_tree_model_iter_next(model, &child);
+  }
+
+  update_index_to_pixmap(process_list);
+
+  gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
+}
+
+void collapse_event(GtkTreeView *treeview, GtkTreeIter *iter, GtkTreePath *arg2, gpointer user_data)
+{
+  ControlFlowData *resourceview_data = 
+      (ControlFlowData*)g_object_get_data(
+                G_OBJECT(treeview),
+                "resourceview_data");
+  ProcessList *process_list = (ProcessList *) user_data;
+  ResourceUnique *rup;
+  HashedResourceData *hrd;
+  gboolean result;
+
+  GtkTreeModel *model;
+  GtkTreeIter child;
+
+  /* Determine which trace has been expanded */
+  model = gtk_tree_view_get_model(treeview);
+
+  /* mark each of the trace's resources invisible */
+  result = gtk_tree_model_iter_children(model, &child, iter);
+
+  /* for each child of the collapsed row */
+  while(result) {
+    char *name;
+    /* hide the item */
+    gtk_tree_model_get(model, &child, NAME_COLUMN, &name, DATA_COLUMN, &hrd, -1);
+    hrd->hidden=1;
+
+    /* find next */
+    result = gtk_tree_model_iter_next(model, &child);
+  }
+
+  update_index_to_pixmap(process_list);
+
+  gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
+}
+
 static gboolean update_index_to_pixmap_each (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, UpdateIndexPixmapArg *arg) 
 {
   guint array_index = arg->count;
@@ -116,11 +187,13 @@ static gboolean update_index_to_pixmap_each (GtkTreeModel *model, GtkTreePath *p
   
   g_assert(array_index < arg->process_list->index_to_pixmap->len);
   
-  GdkPixmap **pixmap =
-    (GdkPixmap**)&g_ptr_array_index(arg->process_list->index_to_pixmap, array_index);
-  *pixmap = hdata->pixmap;
+  if(hdata->hidden == 0) {
+    GdkPixmap **pixmap =
+      (GdkPixmap**)&g_ptr_array_index(arg->process_list->index_to_pixmap, array_index);
+    *pixmap = hdata->pixmap;
 
-  arg->count++;
+    arg->count++;
+  }
 
   return FALSE;
 }
@@ -134,6 +207,8 @@ void update_index_to_pixmap(ProcessList *process_list)
     items += g_hash_table_size(process_list->restypes[i].hash_table);
   }
 
+  /* we don't know the exact number of items there will be,
+   * so set an upper bound */
   g_ptr_array_set_size(process_list->index_to_pixmap, items);
 
   arg.count = 0;
@@ -141,6 +216,9 @@ void update_index_to_pixmap(ProcessList *process_list)
 
   gtk_tree_model_foreach(GTK_TREE_MODEL(process_list->list_store),
       (GtkTreeModelForeachFunc)update_index_to_pixmap_each, &arg);
+
+  /* now that we know the exact number of items, set it */
+  g_ptr_array_set_size(process_list->index_to_pixmap, arg.count);
 }
 
 
@@ -298,13 +376,7 @@ ProcessList *processlist_construct(void)
   process_list->process_list_widget = 
     gtk_tree_view_new_with_model
     (GTK_TREE_MODEL (process_list->list_store));
-
-  gtk_tree_view_set_show_expanders(
-    GTK_TREE_VIEW(process_list->process_list_widget), FALSE);
-  gtk_tree_view_set_level_indentation(
-    process_list->process_list_widget, 20);
-  
-  gtk_tree_view_set_enable_tree_lines(process_list->process_list_widget, TRUE);
+  g_object_set(process_list->process_list_widget, "enable-tree-lines", TRUE, NULL);
 
   g_object_unref (G_OBJECT (process_list->list_store));
 
@@ -314,6 +386,7 @@ ProcessList *processlist_construct(void)
       NULL,
       NULL);
  
+
   gtk_tree_sortable_set_sort_column_id(
       GTK_TREE_SORTABLE(process_list->list_store),
       GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
@@ -339,6 +412,9 @@ ProcessList *processlist_construct(void)
       NULL,
       NULL,
       &process_list->cell_height);
+
+  g_signal_connect(process_list->process_list_widget, "row-expanded", G_CALLBACK(expand_event), process_list);
+  g_signal_connect(process_list->process_list_widget, "row-collapsed", G_CALLBACK(collapse_event), process_list);
        
 #if GTK_CHECK_VERSION(2,4,15)
   guint ypad;
@@ -372,8 +448,10 @@ ProcessList *processlist_construct(void)
   process_list->restypes[RV_RESOURCE_MACHINE].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
   process_list->restypes[RV_RESOURCE_CPU].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
   process_list->restypes[RV_RESOURCE_IRQ].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
+  process_list->restypes[RV_RESOURCE_SOFT_IRQ].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
+  process_list->restypes[RV_RESOURCE_TRAP].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
   process_list->restypes[RV_RESOURCE_BDEV].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
-
+  
   return process_list;
 }
 
@@ -445,86 +523,67 @@ void destroy_hash_data(gpointer data)
   g_free(data);
 }
 
-HashedResourceData *resourcelist_obtain_machine(ControlFlowData *resourceview_data, guint trace_num, guint id)
+GQuark make_cpu_name(ControlFlowData *resourceview_data, guint trace_num, guint id)
 {
-  ResourceUniqueNumeric *ru = g_new(ResourceUniqueNumeric, 1);
-  HashedResourceData *data = g_new(HashedResourceData, 1);
-  
-  /* Prepare hash key */
-  ru->trace_num = trace_num;
-  ru->id = id;
-  
-  /* Search within hash table */
-  GHashTable *ht = resourceview_data->process_list->restypes[RV_RESOURCE_MACHINE].hash_table;
-  data = g_hash_table_lookup(ht, ru);
-  
-  /* If not found in hash table, add it */
-  if(data == NULL) {
-    GQuark name;
+  GQuark name;
+  gchar *str;
 
-    data = g_malloc(sizeof(HashedResourceData));
-    /* Prepare hashed data */
-    data->type = RV_RESOURCE_MACHINE;
-    data->x.over = 0;
-    data->x.over_used = FALSE;
-    data->x.over_marked = FALSE;
-    data->x.middle = 0; // last 
-    data->x.middle_used = FALSE;
-    data->x.middle_marked = FALSE;
-    data->x.under = 0;
-    data->x.under_used = FALSE;
-    data->x.under_marked = FALSE;
-    data->next_good_time = ltt_time_zero;
+  str = g_strdup_printf("CPU%u", id);
+  name = g_quark_from_string(str);
+  g_free(str);
 
-    data->height = resourceview_data->process_list->cell_height;
-    data->pixmap = 
-        gdk_pixmap_new(resourceview_data->drawing->drawing_area->window,
-                       resourceview_data->drawing->alloc_width,
-                       data->height,
-                       -1);
-    g_assert(data->pixmap);
+  return name;
+}
 
-    gdk_draw_rectangle (data->pixmap,
-        resourceview_data->drawing->drawing_area->style->black_gc,
-        TRUE,
-        0, 0,
-        resourceview_data->drawing->alloc_width,
-        data->height);
+GQuark make_irq_name(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+  GQuark name;
+  gchar *str;
 
-    /* add to hash table */
-    g_hash_table_insert(ht, ru, data);
-    resourceview_data->process_list->number_of_process++; // TODO: check
+  str = g_strdup_printf("IRQ %u", id);
+  name = g_quark_from_string(str);
+  g_free(str);
 
-    /* add to process list */
-    {
-      gchar *str;
-      str = g_strdup_printf("Trace %u", id);
-      name = g_quark_from_string(str);
-      g_free(str);
-    }
+  return name;
+}
 
-    gtk_tree_store_append(resourceview_data->process_list->list_store, &data->y_iter, NULL);
-    gtk_tree_store_set(resourceview_data->process_list->list_store, &data->y_iter,
-         NAME_COLUMN, g_quark_to_string(name), DATA_COLUMN, data,
-         -1);
+GQuark make_soft_irq_name(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+  GQuark name;
+  gchar *str;
 
-    update_index_to_pixmap(resourceview_data->process_list);
+  str = g_strdup_printf("SOFTIRQ %u", id);
+  name = g_quark_from_string(str);
+  g_free(str);
 
-    int heightall = data->height * resourceview_data->process_list->number_of_process;
+  return name;
+}
 
-    gtk_widget_set_size_request(resourceview_data->drawing->drawing_area,
-                              -1,
-                              heightall);
+GQuark make_trap_name(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+  GQuark name;
+  gchar *str;
 
-    gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
-  }
+  str = g_strdup_printf("Trap %u", id);
+  name = g_quark_from_string(str);
+  g_free(str);
 
-  gtk_tree_view_expand_all(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget));
+  return name;
+}
 
-  return data;
+GQuark make_bdev_name(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+  GQuark name;
+  gchar *str;
+
+  str = g_strdup_printf("Block (%u,%u)", MAJOR(id), MINOR(id));
+  name = g_quark_from_string(str);
+  g_free(str);
+
+  return name;
 }
 
-HashedResourceData *resourcelist_obtain_cpu(ControlFlowData *resourceview_data, guint trace_num, guint id)
+HashedResourceData *resourcelist_obtain_machine(ControlFlowData *resourceview_data, guint trace_num, guint id)
 {
   ResourceUniqueNumeric *ru = g_new(ResourceUniqueNumeric, 1);
   HashedResourceData *data = g_new(HashedResourceData, 1);
@@ -534,21 +593,16 @@ HashedResourceData *resourcelist_obtain_cpu(ControlFlowData *resourceview_data,
   ru->id = id;
   
   /* Search within hash table */
-  GHashTable *ht = resourceview_data->process_list->restypes[RV_RESOURCE_CPU].hash_table;
+  GHashTable *ht = resourceview_data->process_list->restypes[RV_RESOURCE_MACHINE].hash_table;
   data = g_hash_table_lookup(ht, ru);
   
   /* If not found in hash table, add it */
   if(data == NULL) {
     GQuark name;
-    HashedResourceData *parent;
 
-    /* Find the parent machine */
-    parent = resourcelist_obtain_machine(resourceview_data, trace_num, trace_num);
-
-    /* Prepare hashed data */
     data = g_malloc(sizeof(HashedResourceData));
-
-    data->type = RV_RESOURCE_CPU;
+    /* Prepare hashed data */
+    data->type = RV_RESOURCE_MACHINE;
     data->x.over = 0;
     data->x.over_used = FALSE;
     data->x.over_marked = FALSE;
@@ -559,6 +613,7 @@ HashedResourceData *resourcelist_obtain_cpu(ControlFlowData *resourceview_data,
     data->x.under_used = FALSE;
     data->x.under_marked = FALSE;
     data->next_good_time = ltt_time_zero;
+    data->hidden = 0;
 
     data->height = resourceview_data->process_list->cell_height;
     data->pixmap = 
@@ -566,6 +621,7 @@ HashedResourceData *resourcelist_obtain_cpu(ControlFlowData *resourceview_data,
                        resourceview_data->drawing->alloc_width,
                        data->height,
                        -1);
+    g_assert(data->pixmap);
 
     gdk_draw_rectangle (data->pixmap,
         resourceview_data->drawing->drawing_area->style->black_gc,
@@ -581,12 +637,12 @@ HashedResourceData *resourcelist_obtain_cpu(ControlFlowData *resourceview_data,
     /* add to process list */
     {
       gchar *str;
-      str = g_strdup_printf("CPU%u", id);
+      str = g_strdup_printf("Trace %u", id);
       name = g_quark_from_string(str);
       g_free(str);
     }
 
-    gtk_tree_store_append(resourceview_data->process_list->list_store, &data->y_iter, &parent->y_iter);
+    gtk_tree_store_append(resourceview_data->process_list->list_store, &data->y_iter, NULL);
     gtk_tree_store_set(resourceview_data->process_list->list_store, &data->y_iter,
          NAME_COLUMN, g_quark_to_string(name), DATA_COLUMN, data,
          -1);
@@ -602,20 +658,32 @@ HashedResourceData *resourcelist_obtain_cpu(ControlFlowData *resourceview_data,
     gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
   }
 
+  /* expand the newly added machine */
+  {
+    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget));
+    GtkTreePath *path;
+    path = gtk_tree_model_get_path(model, &data->y_iter);
+
+    gtk_tree_view_expand_row(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget), path, FALSE);
+
+    gtk_tree_path_free(path);
+  }
+
   return data;
 }
 
-HashedResourceData *resourcelist_obtain_irq(ControlFlowData *resourceview_data, guint trace_num, guint id)
+HashedResourceData *resourcelist_obtain_generic(ControlFlowData *resourceview_data, gint res_type, guint trace_num, guint id, GQuark (*make_name_func)(ControlFlowData *resourceview_data, guint trace_num, guint id))
 {
   ResourceUniqueNumeric *ru = g_new(ResourceUniqueNumeric, 1);
   HashedResourceData *data = g_new(HashedResourceData, 1);
   
   /* Prepare hash key */
+  ru->ru.type = &(resourceview_data->process_list->restypes[res_type]);
   ru->trace_num = trace_num;
   ru->id = id;
   
   /* Search within hash table */
-  GHashTable *ht = resourceview_data->process_list->restypes[RV_RESOURCE_IRQ].hash_table;
+  GHashTable *ht = resourceview_data->process_list->restypes[res_type].hash_table;
   data = g_hash_table_lookup(ht, ru);
   
   /* If not found in hash table, add it */
@@ -629,7 +697,7 @@ HashedResourceData *resourcelist_obtain_irq(ControlFlowData *resourceview_data,
     /* Prepare hashed data */
     data = g_malloc(sizeof(HashedResourceData));
 
-    data->type = RV_RESOURCE_IRQ;
+    data->type = res_type;
     data->x.over = 0;
     data->x.over_used = FALSE;
     data->x.over_marked = FALSE;
@@ -660,18 +728,26 @@ HashedResourceData *resourcelist_obtain_irq(ControlFlowData *resourceview_data,
     resourceview_data->process_list->number_of_process++; // TODO: check
 
     /* add to process list */
-    {
-      gchar *str;
-      str = g_strdup_printf("IRQ %u", id);
-      name = g_quark_from_string(str);
-      g_free(str);
-    }
+    name = make_name_func(resourceview_data, trace_num, id);
 
     gtk_tree_store_append(resourceview_data->process_list->list_store, &data->y_iter, &parent->y_iter);
     gtk_tree_store_set(resourceview_data->process_list->list_store, &data->y_iter,
          NAME_COLUMN, g_quark_to_string(name), DATA_COLUMN, data,
          -1);
 
+    /* Determine if we should add it hidden or not */
+    {
+      gboolean result;
+      GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget));
+      GtkTreeIter parent_iter;
+
+      result = gtk_tree_model_iter_parent(model, &parent_iter, &data->y_iter);
+      GtkTreePath *path = gtk_tree_model_get_path(model, &parent_iter);
+      data->hidden = gtk_tree_view_row_expanded(GTK_TREE_VIEW(resourceview_data->process_list->process_list_widget), path)?0:1;
+      gtk_tree_path_free(path);
+    }
+
+
     update_index_to_pixmap(resourceview_data->process_list);
 
     int heightall = data->height * resourceview_data->process_list->number_of_process;
@@ -686,83 +762,28 @@ HashedResourceData *resourcelist_obtain_irq(ControlFlowData *resourceview_data,
   return data;
 }
 
-HashedResourceData *resourcelist_obtain_bdev(ControlFlowData *resourceview_data, guint trace_num, guint id)
+HashedResourceData *resourcelist_obtain_cpu(ControlFlowData *resourceview_data, guint trace_num, guint id)
 {
-  ResourceUniqueNumeric *ru = g_new(ResourceUniqueNumeric, 1);
-  HashedResourceData *data = g_new(HashedResourceData, 1);
-  
-  /* Prepare hash key */
-  ru->trace_num = trace_num;
-  ru->id = id;
-  
-  /* Search within hash table */
-  GHashTable *ht = resourceview_data->process_list->restypes[RV_RESOURCE_BDEV].hash_table;
-  data = g_hash_table_lookup(ht, ru);
-  
-  /* If not found in hash table, add it */
-  if(data == NULL) {
-    GQuark name;
-    HashedResourceData *parent;
-
-    /* Find the parent machine */
-    parent = resourcelist_obtain_machine(resourceview_data, trace_num, trace_num);
-
-    /* Prepare hashed data */
-    data = g_malloc(sizeof(HashedResourceData));
-
-    data->type = RV_RESOURCE_BDEV;
-    data->x.over = 0;
-    data->x.over_used = FALSE;
-    data->x.over_marked = FALSE;
-    data->x.middle = 0; // last 
-    data->x.middle_used = FALSE;
-    data->x.middle_marked = FALSE;
-    data->x.under = 0;
-    data->x.under_used = FALSE;
-    data->x.under_marked = FALSE;
-    data->next_good_time = ltt_time_zero;
-
-    data->height = resourceview_data->process_list->cell_height;
-    data->pixmap = 
-        gdk_pixmap_new(resourceview_data->drawing->drawing_area->window,
-                       resourceview_data->drawing->alloc_width,
-                       data->height,
-                       -1);
-
-    gdk_draw_rectangle (data->pixmap,
-        resourceview_data->drawing->drawing_area->style->black_gc,
-        TRUE,
-        0, 0,
-        resourceview_data->drawing->alloc_width,
-        data->height);
-
-    /* add to hash table */
-    g_hash_table_insert(ht, ru, data);
-    resourceview_data->process_list->number_of_process++; // TODO: check
-
-    /* add to process list */
-    {
-      gchar *str;
-      str = g_strdup_printf("Block (%u,%u)", MAJOR(id), MINOR(id));
-      name = g_quark_from_string(str);
-      g_free(str);
-    }
-
-    gtk_tree_store_append(resourceview_data->process_list->list_store, &data->y_iter, &parent->y_iter);
-    gtk_tree_store_set(resourceview_data->process_list->list_store, &data->y_iter,
-         NAME_COLUMN, g_quark_to_string(name), DATA_COLUMN, data,
-         -1);
-
-    update_index_to_pixmap(resourceview_data->process_list);
+  return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_CPU, trace_num, id, make_cpu_name);
+}
 
-    int heightall = data->height * resourceview_data->process_list->number_of_process;
+HashedResourceData *resourcelist_obtain_irq(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+  return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_IRQ, trace_num, id, make_irq_name);
+}
 
-    gtk_widget_set_size_request(resourceview_data->drawing->drawing_area,
-                              -1,
-                              heightall);
+HashedResourceData *resourcelist_obtain_soft_irq(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+  return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_SOFT_IRQ, trace_num, id, make_soft_irq_name);
+}
 
-    gtk_widget_queue_draw(resourceview_data->drawing->drawing_area);
-  }
+HashedResourceData *resourcelist_obtain_trap(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+  return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_TRAP, trace_num, id, make_trap_name);
+}
 
-  return data;
+HashedResourceData *resourcelist_obtain_bdev(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+  return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_BDEV, trace_num, id, make_bdev_name);
 }
+
This page took 0.030491 seconds and 4 git commands to generate.