See attached patch.

Splits the net name on "/" characters, and makes the netlist window view
this as a tree.

Any objections before I commit this?

Best wishes,

-- 
Peter Clifton

Electrical Engineering Division,
Engineering Department,
University of Cambridge,
9, JJ Thomson Avenue,
Cambridge
CB3 0FA

Tel: +44 (0)7729 980173 - (No signal in the lab!)
commit 217a31ce6dda01fe86fca95b1858914eca7a7aa0
Author: Peter Clifton <[EMAIL PROTECTED]>
Date:   Sun Sep 21 19:51:25 2008 +0100

    Display nets in a tree with hierarchy

diff --git a/src/hid/gtk/gui-netlist-window.c b/src/hid/gtk/gui-netlist-window.c
index dfcd0bc..d3aa04a 100644
--- a/src/hid/gtk/gui-netlist-window.c
+++ b/src/hid/gtk/gui-netlist-window.c
@@ -62,6 +62,8 @@
 #include <dmalloc.h>
 #endif
 
+#define NET_HIERARCHY_SEPARATOR "/"
+
 RCSID ("$Id$");
 
 static GtkWidget	*netlist_window;
@@ -168,6 +170,9 @@ node_model_create (LibraryMenuType * menu)
 
   store = gtk_list_store_new (N_NODE_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER);
 
+  if (menu == NULL)
+    return GTK_TREE_MODEL (store);
+
   ENTRY_LOOP (menu);
   {
     if (!entry->ListEntry)
@@ -300,30 +305,109 @@ static gboolean		loading_new_netlist;
 static GtkTreeModel *
 net_model_create (void)
 {
-  GtkListStore *store;
-  GtkTreeIter iter;
-
-  store = gtk_list_store_new (N_NET_COLUMNS,
+  GtkTreeModel *model;
+  GtkTreeStore *store;
+  GtkTreeIter new_iter;
+  GtkTreeIter parent_iter;
+  GtkTreeIter *parent_ptr;
+  GtkTreePath *path;
+  GtkTreeRowReference *row_ref;
+  GHashTable *prefix_hash;
+  char *display_name;
+  char *hash_string;
+  char **join_array;
+  char **path_segments;
+  int path_depth;
+  int try_depth;
+
+  store = gtk_tree_store_new (N_NET_COLUMNS,
 			      G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
 
+  model = GTK_TREE_MODEL (store);
+
+  /* Hash table stores GtkTreeRowReference for given path prefixes */
+  prefix_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+                                       (GDestroyNotify)
+                                         gtk_tree_row_reference_free);
+
   MENU_LOOP (&PCB->NetlistLib);
   {
     if (!menu->Name)
       continue;
 
-		if (loading_new_netlist)
-			menu->flag = TRUE;
+    if (loading_new_netlist)
+      menu->flag = TRUE;
 
-    gtk_list_store_append (store, &iter);
-    gtk_list_store_set (store, &iter,
-			NET_ENABLED_COLUMN, "",
+    parent_ptr = NULL;
+
+    path_segments = g_strsplit (menu->Name, NET_HIERARCHY_SEPARATOR, 0);
+    path_depth = g_strv_length (path_segments);
+
+    for (try_depth = path_depth - 1; try_depth > 0; try_depth--)
+      {
+        join_array = g_new0 (char *, try_depth + 1);
+        memcpy (join_array, path_segments, sizeof (char *) * try_depth);
+
+        /* See if this net's parent node is in the hash table */
+        hash_string = g_strjoinv (NET_HIERARCHY_SEPARATOR, join_array);
+        g_free (join_array);
+
+        row_ref = g_hash_table_lookup (prefix_hash, hash_string);
+        g_free (hash_string);
+
+        /* If we didn't find the path at this level, keep looping */
+        if (row_ref == NULL)
+          continue;
+
+        path = gtk_tree_row_reference_get_path (row_ref);
+        gtk_tree_model_get_iter (model, &parent_iter, path);
+        parent_ptr = &parent_iter;
+        break;
+      }
+
+    /* NB: parent_ptr may still be NULL if we reached the toplevel */
+
+    /* Now walk up the desired path, adding the nodes */
+
+    for (; try_depth < path_depth - 1; try_depth++)
+      {
+        display_name = g_strconcat (path_segments[try_depth],
+                                    NET_HIERARCHY_SEPARATOR, NULL);
+        gtk_tree_store_append (store, &new_iter, parent_ptr);
+        gtk_tree_store_set (store, &new_iter,
+                            NET_ENABLED_COLUMN, "",
+                            NET_NAME_COLUMN, display_name,
+                            NET_LIBRARY_COLUMN, NULL, -1);
+        g_free (display_name);
+
+        path = gtk_tree_model_get_path (model, &new_iter);
+        row_ref = gtk_tree_row_reference_new (model, path);
+        parent_iter = new_iter;
+        parent_ptr = &parent_iter;
+
+        join_array = g_new0 (char *, try_depth + 1);
+        memcpy (join_array, path_segments, sizeof (char *) * (try_depth + 1));
+
+        hash_string = g_strjoinv (NET_HIERARCHY_SEPARATOR, join_array);
+        g_free (join_array);
+
+        /* Insert those node in the hash table */
+        g_hash_table_insert (prefix_hash, hash_string, row_ref);
+        /* Don't free hash_string, it is now oened by the hash table */
+      }
+
+    gtk_tree_store_append (store, &new_iter, parent_ptr);
+    gtk_tree_store_set (store, &new_iter,
 			NET_ENABLED_COLUMN, menu->flag ? "" : "*",
-			NET_NAME_COLUMN, menu->Name,
+			NET_NAME_COLUMN, path_segments[path_depth - 1],
 			NET_LIBRARY_COLUMN, menu, -1);
+    g_strfreev (path_segments);
   }
   END_LOOP;
 
-  return GTK_TREE_MODEL (store);
+  g_hash_table_unref (prefix_hash);
+
+  return model;
 }
 
 
@@ -341,10 +425,21 @@ net_selection_double_click_cb (GtkTreeView * treeview, GtkTreePath * path,
   model = gtk_tree_view_get_model (treeview);
   if (gtk_tree_model_get_iter (model, &iter, path))
     {
+
+      /* Expand / contract nodes with children */
+      if (gtk_tree_model_iter_has_child (model, &iter))
+        {
+          if (gtk_tree_view_row_expanded (treeview, path))
+            gtk_tree_view_collapse_row (treeview, path);
+          else
+            gtk_tree_view_expand_row (treeview, path, FALSE);
+          return;
+        }
+
       /* Get the current enabled string and toggle it between "" and "*"
        */
       gtk_tree_model_get (model, &iter, NET_ENABLED_COLUMN, &str, -1);
-      gtk_list_store_set (GTK_LIST_STORE (model), &iter,
+      gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
 			  NET_ENABLED_COLUMN, !strcmp (str, "*") ? "" : "*",
 			  -1);
       /* set/clear the flag which says the net is enabled or disabled */
@@ -396,7 +491,7 @@ netlist_disable_all_cb (GtkToggleButton * button, gpointer data)
   if (gtk_tree_model_get_iter_first (net_model, &iter))
     do
       {
-	gtk_list_store_set (GTK_LIST_STORE (net_model), &iter,
+	gtk_tree_store_set (GTK_TREE_STORE (net_model), &iter,
 			    NET_ENABLED_COLUMN, active ? "*" : "", -1);
 	/* set/clear the flag which says the net is enabled or disabled */
 	gtk_tree_model_get (net_model, &iter, NET_LIBRARY_COLUMN, &menu, -1);
@@ -562,6 +657,7 @@ ghid_netlist_window_show (GHidPort * out, gboolean raise)
   GtkTreeModel *model;
   GtkTreeSelection *selection;
   GtkCellRenderer *renderer;
+  GtkTreeViewColumn *column;
 
   /* No point in putting up the window if no netlist is loaded.
    */
@@ -602,6 +698,7 @@ ghid_netlist_window_show (GHidPort * out, gboolean raise)
 					NET_NAME_COLUMN, GTK_SORT_ASCENDING);
 
   gtk_tree_view_set_rules_hint (treeview, FALSE);
+  g_object_set (treeview, "enable-tree-lines", TRUE, NULL);
 
   renderer = gtk_cell_renderer_text_new ();
   gtk_tree_view_insert_column_with_attributes (treeview, -1, _(" "),
@@ -610,9 +707,11 @@ ghid_netlist_window_show (GHidPort * out, gboolean raise)
 					       NULL);
 
   renderer = gtk_cell_renderer_text_new ();
-  gtk_tree_view_insert_column_with_attributes (treeview, -1, _("Net Name"),
-					       renderer,
-					       "text", NET_NAME_COLUMN, NULL);
+  column = gtk_tree_view_column_new_with_attributes (_("Net Name"),
+						     renderer,
+						     "text", NET_NAME_COLUMN, NULL);
+  gtk_tree_view_insert_column (treeview, column, -1);
+  gtk_tree_view_set_expander_column (treeview, column);
 
   /* TODO: dont expand all, but record expanded states when window is
      |  destroyed and restore state here.
@@ -840,7 +939,7 @@ ghid_netlist_window_update (gboolean init_nodes)
 					NET_NAME_COLUMN, GTK_SORT_ASCENDING);
   if (model)
     {
-      gtk_list_store_clear (GTK_LIST_STORE (model));
+      gtk_tree_store_clear (GTK_TREE_STORE (model));
       g_object_unref (model);
     }
 

_______________________________________________
geda-dev mailing list
[email protected]
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev

Reply via email to