[anjuta] project-manager: Save and restore expanded node in project view



commit e2e09b0499d898441049786ffcd0b557add93471
Author: Sébastien Granjoux <seb sfo free fr>
Date:   Sun Dec 12 19:52:18 2010 +0100

    project-manager: Save and restore expanded node in project view

 plugins/project-manager/plugin.c        |   16 ++
 plugins/project-manager/project-model.c |  269 +++++++++---------------
 plugins/project-manager/project-model.h |   29 +++-
 plugins/project-manager/project-view.c  |  357 ++++++++++++++++++++++++++++---
 plugins/project-manager/project-view.h  |   25 ++-
 plugins/project-manager/tree-data.c     |   51 +++++
 plugins/project-manager/tree-data.h     |    5 +
 7 files changed, 540 insertions(+), 212 deletions(-)
---
diff --git a/plugins/project-manager/plugin.c b/plugins/project-manager/plugin.c
index c0181f8..0500f2a 100644
--- a/plugins/project-manager/plugin.c
+++ b/plugins/project-manager/plugin.c
@@ -189,17 +189,33 @@ on_session_save (AnjutaShell *shell, AnjutaSessionPhase phase,
 		g_list_free (list);
 	}
 
+	/* Save expanded node */
+	list = gbf_project_view_get_expanded_list (GBF_PROJECT_VIEW (plugin->view));
+	if (list != NULL)
+	{
+    	anjuta_session_set_string_list (session, "Project Manager", "Expand", list);
+		g_list_foreach (list, (GFunc)g_free, NULL);
+		g_list_free (list);
+	}
+	
 }
 
 static void
 on_session_load (AnjutaShell *shell, AnjutaSessionPhase phase, AnjutaSession *session, ProjectManagerPlugin *plugin)
 {
+	GList *list;
+	
 	if (phase != ANJUTA_SESSION_PHASE_NORMAL)
 		return;
 
 	g_list_foreach (plugin->shortcuts, (GFunc)g_free, NULL);
 	g_list_free (plugin->shortcuts);
 	plugin->shortcuts = anjuta_session_get_string_list (session, "Project Manager", "Shortcut");
+
+	list = anjuta_session_get_string_list (session, "Project Manager", "Expand");
+	gbf_project_view_set_expanded_list (GBF_PROJECT_VIEW (plugin->view), list);
+	g_list_foreach (list, (GFunc)g_free, NULL);
+	g_list_free (list);
 }
 
 static void
diff --git a/plugins/project-manager/project-model.c b/plugins/project-manager/project-model.c
index 34b0839..7d34095 100644
--- a/plugins/project-manager/project-model.c
+++ b/plugins/project-manager/project-model.c
@@ -41,7 +41,7 @@ struct _GbfProjectModelPrivate {
 	AnjutaPmProject      *proj;
 	gulong               project_updated_handler;
 	
-	GtkTreeRowReference *root_row;
+	GtkTreeRowReference *root_group;
 	GList               *shortcuts;
 
 };
@@ -259,6 +259,37 @@ gbf_project_model_instance_init (GbfProjectModel *model)
 	insert_empty_node (model);
 }
 
+static GtkTreeRowReference *
+gbf_project_model_get_root (GbfProjectModel *model)
+{
+	if (model->priv->root_group == NULL)
+	{
+		GtkTreeIter iter;
+		gboolean valid;
+
+		/* Search root group */
+		for (valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &iter, NULL); valid; valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter))
+		{
+			GbfTreeData *data;
+			
+			gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
+	   			 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
+		    		-1);
+			
+			if (data->type == GBF_TREE_NODE_GROUP)
+			{
+				GtkTreePath *path;
+				
+				path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
+				model->priv->root_group = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), path);
+				gtk_tree_path_free (path);
+			}
+		}
+	}
+
+	return model->priv->root_group;
+}
+
 /* Model data functions ------------ */
 
 /* Remove node without checking its shortcuts */
@@ -455,8 +486,8 @@ default_sort_func (GtkTreeModel *model,
 }
 
 
-static void 
-add_source (GbfProjectModel    	      *model,
+void 
+gbf_project_model_add_source (GbfProjectModel    	      *model,
 	    AnjutaProjectNode *source,
 	    GtkTreeIter               *parent)
 {
@@ -473,8 +504,8 @@ add_source (GbfProjectModel    	      *model,
 			    -1);
 }
 
-static void 
-add_target_shortcut (GbfProjectModel *model,
+void 
+gbf_project_model_add_target_shortcut (GbfProjectModel *model,
                      GtkTreeIter     *shortcut,
 		     GbfTreeData     *target,
 		     GtkTreePath     *before_path)
@@ -488,7 +519,7 @@ add_target_shortcut (GbfProjectModel *model,
 	if (!target)
 		return;
 
-	root_path = gtk_tree_row_reference_get_path (model->priv->root_row);
+	root_path = gtk_tree_row_reference_get_path (gbf_project_model_get_root (model));
 	/* check before_path */
 	if (!before_path ||
 	    gtk_tree_path_get_depth (before_path) > 1 ||
@@ -518,7 +549,7 @@ add_target_shortcut (GbfProjectModel *model,
 	/* add sources */
 	parent = gbf_tree_data_get_node (target);
 	for (node = anjuta_project_node_first_child (parent); node; node = anjuta_project_node_next_sibling (node))
-		add_source (model, node, &iter);
+		gbf_project_model_add_source (model, node, &iter);
 
 	gtk_tree_path_free (root_path);
 
@@ -540,7 +571,7 @@ move_target_shortcut (GbfProjectModel *model,
 	if (!shortcut)
 		return;
 
-	root_path = gtk_tree_row_reference_get_path (model->priv->root_row);
+	root_path = gtk_tree_row_reference_get_path (gbf_project_model_get_root (model));
 	
 	/* check before_path */
 	if (!before_path ||
@@ -576,7 +607,7 @@ move_target_shortcut (GbfProjectModel *model,
 		/* add sources */
 		parent = gbf_tree_data_get_node (shortcut->shortcut);
 		for (node = anjuta_project_node_first_child (parent); node; node = anjuta_project_node_next_sibling (node))
-			add_source (model, node, iter);
+			gbf_project_model_add_source (model, node, iter);
 	}
 
 	gtk_tree_path_free (src_path);
@@ -584,8 +615,8 @@ move_target_shortcut (GbfProjectModel *model,
 
 }
 
-static void 
-add_package (GbfProjectModel    	      *model,
+void 
+gbf_project_model_add_package (GbfProjectModel    	      *model,
 	    AnjutaProjectNode *package,
 	    GtkTreeIter               *parent)
 {
@@ -605,12 +636,12 @@ add_package (GbfProjectModel    	      *model,
 	/* ... and sources */
 	for (node = anjuta_project_node_first_child (package); node; node = anjuta_project_node_next_sibling (node))
 	{
-		add_source (model, node, &iter);
+		gbf_project_model_add_source (model, node, &iter);
 	}
 }
 
-static void 
-add_module (GbfProjectModel 		*model,
+void 
+gbf_project_model_add_module (GbfProjectModel 		*model,
 	    AnjutaProjectNode   *module,
 	    GtkTreeIter     	        *parent)
 {
@@ -630,12 +661,12 @@ add_module (GbfProjectModel 		*model,
 	/* add package */
 	for (l = anjuta_project_node_first_child (module); l; l = anjuta_project_node_next_sibling (l))
 	{
-		add_package (model, l, &iter);
+		gbf_project_model_add_package (model, l, &iter);
 	}
 }
 
-static void 
-add_target (GbfProjectModel 		*model,
+void 
+gbf_project_model_add_target (GbfProjectModel 		*model,
 	    AnjutaProjectNode   *target,
 	    GtkTreeIter     	        *parent)
 {
@@ -655,7 +686,7 @@ add_target (GbfProjectModel 		*model,
 	/* add sources */
 	for (l = anjuta_project_node_first_child (target); l; l = anjuta_project_node_next_sibling (l))
 	{
-		add_source (model, l, &iter);
+		gbf_project_model_add_source (model, l, &iter);
 	}
 
 	/* add a shortcut to the target if the target's type is a primary */
@@ -669,8 +700,8 @@ add_target (GbfProjectModel 		*model,
 	}*/
 }
 
-static void 
-add_target_group (GbfProjectModel 	*model,
+void 
+gbf_project_model_add_target_group (GbfProjectModel 	*model,
 		  AnjutaProjectNode	*group,
 		  GtkTreeIter     	*parent)
 {
@@ -687,31 +718,21 @@ add_target_group (GbfProjectModel 	*model,
 			    GBF_PROJECT_MODEL_COLUMN_DATA, data,
 			    -1);
 
-	/* create root reference */
-	if (parent == NULL) {
-		GtkTreePath *root_path;
-
-		root_path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
-		model->priv->root_row = gtk_tree_row_reference_new (
-			GTK_TREE_MODEL (model), root_path);
-		gtk_tree_path_free (root_path);
-	}
-
 	/* add groups ... */
 	for (node = anjuta_project_node_first_child (group); node; node = anjuta_project_node_next_sibling (node))
-		add_target_group (model, node, &iter);
+		gbf_project_model_add_target_group (model, node, &iter);
 	
 	/* ... and targets */
 	for (node = anjuta_project_node_first_child (group); node; node = anjuta_project_node_next_sibling (node))
-		add_target (model, node, &iter);
+		gbf_project_model_add_target (model, node, &iter);
 	
 	/* ... and sources */
 	for (node = anjuta_project_node_first_child (group); node; node = anjuta_project_node_next_sibling (node))
-		add_source (model, node, &iter);
+		gbf_project_model_add_source (model, node, &iter);
 }
 
-static void
-add_root (GbfProjectModel 	*model,
+void
+gbf_project_model_add_root (GbfProjectModel 	*model,
     AnjutaProjectNode	*root,
     GtkTreeIter     	*parent)
 {
@@ -722,16 +743,16 @@ add_root (GbfProjectModel 	*model,
 
 	/* create root reference */
 	/*root_path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
-	model->priv->root_row = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), root_path);
+	model->priv->root_group = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), root_path);
 	gtk_tree_path_free (root_path);*/
 
 	/* add groups ... */
 	for (node = anjuta_project_node_first_child (root); node; node = anjuta_project_node_next_sibling (node))
-		add_target_group (model, node, NULL);
+		gbf_project_model_add_target_group (model, node, NULL);
 	
 	/* ... and module */
 	for (node = anjuta_project_node_first_child (root); node; node = anjuta_project_node_next_sibling (node))
-		add_module (model, node, NULL);
+		gbf_project_model_add_module (model, node, NULL);
 }
 
 static void
@@ -740,18 +761,7 @@ load_project (GbfProjectModel *model, AnjutaPmProject *proj)
 	model->priv->proj = proj;
 	g_object_ref (proj);
 
-	/* to get rid of the empty node */
-	gbf_project_model_clear (model);
-
-	add_root (model, anjuta_pm_project_get_root (proj), NULL);
-	//add_target_group (model, anjuta_pm_project_get_root (proj), NULL);
-
-	//model->priv->project_updated_handler =
-	//	g_signal_connect (anjuta_pm_project_get_project (model->priv->proj), "project-updated",
-	//			  (GCallback) project_updated_cb, model);
-	//model->priv->project_updated_handler =
-	//	g_signal_connect (anjuta_pm_project_get_project (model->priv->proj), "project-updated",
-	//			  (GCallback) project_updated_cb, model);
+	gbf_project_model_add_root (model, anjuta_pm_project_get_root (proj), NULL);
 }
 
 static void 
@@ -772,8 +782,8 @@ static void
 unload_project (GbfProjectModel *model)
 {
 	if (model->priv->proj) {
-		gtk_tree_row_reference_free (model->priv->root_row);
-		model->priv->root_row = NULL;
+		gtk_tree_row_reference_free (model->priv->root_group);
+		model->priv->root_group = NULL;
 
 		gbf_project_model_clear (model);
 
@@ -823,121 +833,6 @@ recursive_find_tree_data (GtkTreeModel  *model,
 	return retval;
 }
 
-static void
-gbf_project_model_update_shortcut (GbfProjectModel *model, AnjutaProjectNode *parent)
-{
-	GtkTreeIter child;
-	gboolean valid;
-
-	/* Get all root node */
-	valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &child, NULL);
-
-	while (valid)
-	{
-		GbfTreeData *data;
-		AnjutaProjectNode* old_node = NULL;
-
-		gtk_tree_model_get (GTK_TREE_MODEL (model), &child,
-	  			 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
-	    			-1);
-
-		/* Shortcuts are always at the beginning */
-		if (data->type != GBF_TREE_NODE_SHORTCUT) break;
-
-		old_node = gbf_tree_data_get_node (data);
-		if (old_node == parent)
-		{
-			/* check children */
-			gbf_project_model_update_tree (model, parent, &child);
-		}
-		valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
-	}	
-}
-
-void
-gbf_project_model_update_tree (GbfProjectModel *model, AnjutaProjectNode *parent, GtkTreeIter *iter)
-{
-	GtkTreeIter child;
-	GList *node;
-	GList *nodes;
-
-	/* Get all new nodes */
-	nodes = gbf_project_util_all_child (parent, ANJUTA_PROJECT_UNKNOWN);
-
-	/* walk the tree nodes */
-	if (gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &child, iter))
-	{
-		gboolean valid = TRUE;
-		
-		while (valid) {
-			GbfTreeData *data = NULL;
-			AnjutaProjectNode* data_node = NULL;
-
-			/* Look for current node */
-			gtk_tree_model_get (GTK_TREE_MODEL (model), &child,
-				GBF_PROJECT_MODEL_COLUMN_DATA, &data,
-				-1);
-
-			data_node = gbf_tree_data_get_node (data);
-			
-			/* Skip shortcuts */
-			if (data->type == GBF_TREE_NODE_SHORTCUT)
-			{	
-				valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
-				continue;
-			}
-
-			node = g_list_find (nodes, data_node);
-			if (node != NULL)
-			{
-				/* Node already exist, remove it from the list */
-				nodes = g_list_delete_link (nodes, node);
-
-				/* Update shortcut */
-				gbf_project_model_update_shortcut (model, data_node);
-				                                   
-				/* update recursively */
-				gbf_project_model_update_tree (model, data_node, &child);
-
-				valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
-			}
-			else
-			{
-				/* Node has been deleted */
-				valid = gbf_project_model_remove (model, &child);
-			}
-		}
-	}
-
-	/* add the remaining sources, targets and groups */
-	for (node = nodes; node; node = node->next)
-	{
-		switch (anjuta_project_node_get_node_type (node->data))
-		{
-		case ANJUTA_PROJECT_GROUP:
-			add_target_group (model, node->data, iter);
-			break;
-		case ANJUTA_PROJECT_TARGET:
-			add_target (model, node->data, iter);
-			break;
-		case ANJUTA_PROJECT_SOURCE:
-			add_source (model, node->data, iter);
-			break;
-		case ANJUTA_PROJECT_MODULE:
-			add_module (model, node->data, iter);
-			break;
-		case ANJUTA_PROJECT_PACKAGE:
-			add_package (model, node->data, iter);
-			break;
-		case ANJUTA_PROJECT_ROOT:
-			add_root (model, node->data, iter);
-			break;
-		default:
-			break;
-		}
-	}
-}
-
 gboolean 
 gbf_project_model_find_tree_data (GbfProjectModel 	*model,
 			          GtkTreeIter     	*iter,
@@ -1030,6 +925,34 @@ gbf_project_model_find_node (GbfProjectModel 	*model,
 	return valid;
 }
 
+/* Can return shortcut node if exist */
+gboolean 
+gbf_project_model_find_child_name (GbfProjectModel 	*model,
+	GtkTreeIter		*found,
+	GtkTreeIter		*parent,
+        const gchar		*name)                        
+{
+	GtkTreeIter iter;
+	gboolean valid;
+
+	/* Search for direct children only */
+	for (valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &iter, parent); valid == TRUE; valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &iter))
+	{
+		GbfTreeData *data;
+		
+		gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
+		    GBF_PROJECT_MODEL_COLUMN_DATA, &data, -1);
+
+		if (gbf_tree_data_equal_name (data, name))
+		{
+			*found = iter;
+			break;
+		}
+	}
+
+	return valid;
+}
+
 GbfProjectModel *
 gbf_project_model_new (AnjutaPmProject *project)
 {
@@ -1045,7 +968,7 @@ gbf_project_model_set_project (GbfProjectModel *model, AnjutaPmProject *project)
 	
 	if (model->priv->proj != project)
 	{
-		unload_project (model);
+		//unload_project (model);
 
 		/* project can be NULL */
 		if (project)
@@ -1068,8 +991,8 @@ gbf_project_model_get_project_root (GbfProjectModel *model)
 	
 	g_return_val_if_fail (GBF_IS_PROJECT_MODEL (model), NULL);
 
-	if (model->priv->root_row)
-		path = gtk_tree_row_reference_get_path (model->priv->root_row);
+	if (gbf_project_model_get_root (model))
+		path = gtk_tree_row_reference_get_path (model->priv->root_group);
 	
 	return path;
 }
@@ -1096,7 +1019,7 @@ gbf_project_model_add_shortcut (GbfProjectModel *model,
 	GtkTreePath *path;
 
 	path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), before);
-	add_target_shortcut (model, iter, target, path);
+	gbf_project_model_add_target_shortcut (model, iter, target, path);
 	gtk_tree_path_free (path);
 }
 
@@ -1167,7 +1090,7 @@ drag_data_received (GtkTreeDragDest  *drag_dest,
 				}
 				else
 				{
-					add_target_shortcut (GBF_PROJECT_MODEL (drag_dest),
+					gbf_project_model_add_target_shortcut (GBF_PROJECT_MODEL (drag_dest),
 						     	NULL, data, dest);
 				}
 				retval = TRUE;
@@ -1224,7 +1147,7 @@ row_drop_possible (GtkTreeDragDest  *drag_dest,
 				{
 					GtkTreePath *root_path;
 					
-					root_path = gtk_tree_row_reference_get_path (model->priv->root_row);
+					root_path = gtk_tree_row_reference_get_path (gbf_project_model_get_root (model));
 					retval = gtk_tree_path_compare (dest_path, root_path) <= 0;
 					gtk_tree_path_free (root_path);
 				}
diff --git a/plugins/project-manager/project-model.h b/plugins/project-manager/project-model.h
index 35217bf..f0a0938 100644
--- a/plugins/project-manager/project-model.h
+++ b/plugins/project-manager/project-model.h
@@ -76,6 +76,10 @@ gboolean         gbf_project_model_find_node         (GbfProjectModel   *model,
                                                       GtkTreeIter       *iter,
                                                       GtkTreeIter       *parent,
                                                       AnjutaProjectNode *node);
+gboolean         gbf_project_model_find_child_name   (GbfProjectModel   *model,
+                                                      GtkTreeIter       *iter,
+                                                      GtkTreeIter       *parent,
+                                                      const gchar       *name);
 AnjutaProjectNode *gbf_project_model_get_node        (GbfProjectModel *model,
                                                       GtkTreeIter     *iter);
 
@@ -84,9 +88,28 @@ void             gbf_project_model_add_shortcut      (GbfProjectModel *model,
                                                       GtkTreeIter     *before, 
                                                       GbfTreeData     *target);
 
-void            gbf_project_model_update_tree (GbfProjectModel *model,
-                                                    AnjutaProjectNode *parent,
-                                                    GtkTreeIter *iter);
+void            gbf_project_model_add_source                (GbfProjectModel    	      *model,
+                                                	    AnjutaProjectNode *source,
+                                                	    GtkTreeIter               *parent);
+void            gbf_project_model_add_target_shortcut       (GbfProjectModel *model,
+                                                     GtkTreeIter     *shortcut,
+                                                		     GbfTreeData     *target,
+                                            		     GtkTreePath     *before_path);
+void            gbf_project_model_add_package               (GbfProjectModel    	      *model,
+	                                                    AnjutaProjectNode *package,
+                                                	    GtkTreeIter               *parent);
+void            gbf_project_model_add_module                (GbfProjectModel 		*model,
+                                                	    AnjutaProjectNode   *module,
+                                                	    GtkTreeIter     	        *parent);
+void            gbf_project_model_add_target                (GbfProjectModel 		*model,
+                                                	    AnjutaProjectNode   *target,
+                                                	    GtkTreeIter     	        *parent);
+void            gbf_project_model_add_target_group          (GbfProjectModel 	*model,
+                                                		  AnjutaProjectNode	*group,
+                                                		  GtkTreeIter     	*parent);
+void            gbf_project_model_add_root                  (GbfProjectModel 	*model,
+                                                        AnjutaProjectNode	*root,
+                                                        GtkTreeIter     	*parent);
 
 
 #endif
diff --git a/plugins/project-manager/project-view.c b/plugins/project-manager/project-view.c
index e95bec0..fdc7fe7 100644
--- a/plugins/project-manager/project-view.c
+++ b/plugins/project-manager/project-view.c
@@ -38,6 +38,7 @@
 #include "project-model.h"
 #include "project-view.h"
 #include "project-marshal.h"
+#include "project-util.h"
 
 #define ICON_SIZE 16
 
@@ -109,11 +110,29 @@ row_activated (GtkTreeView       *tree_view,
 }
 
 static void
+free_expanded_node (GNode *node, gpointer data)
+{
+	g_free (node->data);
+}
+
+static void
 dispose (GObject *object)
 {
 	GbfProjectView *view;
 	
 	view = GBF_PROJECT_VIEW (object);
+	if (view->expanded != NULL)
+	{
+		g_node_children_foreach (view->expanded, G_TRAVERSE_ALL, free_expanded_node, NULL);
+		g_node_destroy (view->expanded);
+		view->expanded = NULL;
+	}
+
+	if (view->filter)
+	{
+		g_object_unref (G_OBJECT (view->filter));
+		view->filter = NULL;
+	}
 	if (view->model)
 	{
 		g_object_unref (G_OBJECT (view->model));
@@ -373,6 +392,18 @@ gbf_project_view_class_init (GbfProjectViewClass *klass)
 	
 }
 
+static gboolean
+is_project_node_visible (GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data)
+{
+	GbfTreeData *data;
+	
+	gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
+		    GBF_PROJECT_MODEL_COLUMN_DATA, &data,
+		    -1);
+
+	return (data != NULL) && (gbf_tree_data_get_node (data) != NULL);
+}
+
 static void 
 gbf_project_view_init (GbfProjectView *tree)
 {
@@ -411,9 +442,14 @@ gbf_project_view_init (GbfProjectView *tree)
 
 	gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
 
+	tree->expanded = NULL;
+
 	/* Create model */
 	tree->model = gbf_project_model_new (NULL);
-	gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (tree->model));
+	tree->filter = GTK_TREE_MODEL_FILTER (gtk_tree_model_filter_new (GTK_TREE_MODEL (tree->model), NULL));
+	gtk_tree_model_filter_set_visible_func (tree->filter, is_project_node_visible, tree, NULL);
+	
+	gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (tree->filter));
 }
 
 GtkWidget *
@@ -425,24 +461,17 @@ gbf_project_view_new (void)
 AnjutaProjectNode *
 gbf_project_view_find_selected (GbfProjectView *view, AnjutaProjectNodeType type)
 {
-	GtkTreeIter iter;
 	AnjutaProjectNode *node = NULL;
+	GbfTreeData *data;
 
 	g_return_val_if_fail (view != NULL, NULL);
 	g_return_val_if_fail (GBF_IS_PROJECT_VIEW (view), NULL);
 
-	if (gbf_project_view_get_first_selected (view, &iter) != NULL)
+	data = gbf_project_view_get_first_selected (view, NULL);
+	if (data != NULL)
 	{
-		GtkTreeModel *model;
-		
-		model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
-		if (GTK_IS_TREE_MODEL_FILTER (model))
-		{
-			GtkTreeIter filter_iter = iter;
-			gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &iter, &filter_iter);
-			model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
-		}			
-		node = gbf_project_model_get_node (GBF_PROJECT_MODEL (model), &iter);
+			
+		node = gbf_tree_data_get_node (data);
 		
 		/* walk up the hierarchy searching for a node of the given type */
 		while ((node != NULL) && (type != ANJUTA_PROJECT_UNKNOWN) && (anjuta_project_node_get_node_type (node) != type))
@@ -473,7 +502,20 @@ gbf_project_view_get_first_selected (GbfProjectView *view, GtkTreeIter* selected
 		
 		if (gtk_tree_model_get_iter (model, &iter, list->data))
 		{
-			if (selected) *selected = iter;
+			if (selected)
+			{
+				if (GTK_IS_TREE_MODEL_FILTER (model))
+				{
+					GtkTreeIter child_iter;
+
+					gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, &iter);
+					*selected = child_iter;
+				}
+				else
+				{
+					*selected = iter;
+				}
+			}
 
 			gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
 				    GBF_PROJECT_MODEL_COLUMN_DATA, &data,
@@ -495,14 +537,6 @@ on_each_get_data (GtkTreeModel *model,
 	GList **selected = (GList **)user_data;
 	GbfTreeData *data;
 
-	/*if (GTK_IS_TREE_MODEL_FILTER (model))
-	{
-		GtkTreeIter child_iter;
-			
-		gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model), &child_iter, iter);
-		*iter = child_iter;
-	}*/
-	
 	gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
 		    GBF_PROJECT_MODEL_COLUMN_DATA, &data,
 		    -1);
@@ -551,6 +585,169 @@ gbf_project_view_get_all_selected_iter (GbfProjectView *view)
 	return g_list_reverse (selected);
 }
 
+static void
+gbf_project_view_update_shortcut (GbfProjectView *view, AnjutaProjectNode *parent)
+{
+	GtkTreeIter child;
+	gboolean valid;
+
+	/* Get all root node */
+	valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (view->model), &child, NULL);
+
+	while (valid)
+	{
+		GbfTreeData *data;
+		AnjutaProjectNode* old_node = NULL;
+
+		gtk_tree_model_get (GTK_TREE_MODEL (view->model), &child,
+	  			 GBF_PROJECT_MODEL_COLUMN_DATA, &data,
+	    			-1);
+
+		/* Shortcuts are always at the beginning */
+		if (data->type != GBF_TREE_NODE_SHORTCUT) break;
+
+		old_node = gbf_tree_data_get_node (data);
+		if (old_node == parent)
+		{
+			/* check children */
+			gbf_project_view_update_tree (view, parent, &child);
+		}
+		valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (view->model), &child);
+	}	
+}
+
+static gint
+compare_node_name (gconstpointer a, gconstpointer b)
+{
+	const AnjutaProjectNode *node = (const AnjutaProjectNode *)a;
+	const gchar *name = (const gchar *)b;
+
+	return g_strcmp0 (anjuta_project_node_get_name (node), name);
+}
+
+void
+gbf_project_view_update_tree (GbfProjectView *view, AnjutaProjectNode *parent, GtkTreeIter *iter)
+{
+	GtkTreeIter child;
+	GList *node;
+	GList *nodes;
+
+	/* Get all new nodes */
+	nodes = gbf_project_util_all_child (parent, ANJUTA_PROJECT_UNKNOWN);
+
+	/* walk the tree nodes */
+	if (gtk_tree_model_iter_children (GTK_TREE_MODEL (view->model), &child, iter))
+	{
+		gboolean valid = TRUE;
+		
+		while (valid) {
+			GbfTreeData *data = NULL;
+			AnjutaProjectNode* data_node = NULL;
+
+			/* Look for current node */
+			gtk_tree_model_get (GTK_TREE_MODEL (view->model), &child,
+				GBF_PROJECT_MODEL_COLUMN_DATA, &data,
+				-1);
+
+			data_node = gbf_tree_data_get_node (data);
+
+			/* Skip shortcuts */
+			if (data->type == GBF_TREE_NODE_SHORTCUT)
+			{	
+				valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (view->model), &child);
+				continue;
+			}
+			
+			if ((data->type == GBF_TREE_NODE_UNKNOWN) && (data->expanded))
+			{
+				node = g_list_find_custom (nodes, data->name, compare_node_name);
+				if (node != NULL)
+				{
+					GtkTreePath *path;
+					GtkTreePath *child_path;
+					GtkTreeModelFilter *filter;
+					gboolean expanded;
+
+					data_node = (AnjutaProjectNode *)node->data;
+					gbf_tree_data_free (data);
+					data = gbf_tree_data_new_node (data_node);
+					gtk_tree_store_set (GTK_TREE_STORE (view->model), &child,
+								GBF_PROJECT_MODEL_COLUMN_DATA, data,
+								-1);
+
+					/* Node already exist, remove it from the list */
+					nodes = g_list_delete_link (nodes, node);
+
+					/* Update shortcut */
+					gbf_project_view_update_shortcut (view, data_node);
+				                                   
+					/* update recursively */
+					gbf_project_view_update_tree (view, data_node, &child);
+
+					filter = GTK_TREE_MODEL_FILTER (gtk_tree_view_get_model (GTK_TREE_VIEW (view)));
+					path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->model), &child);
+					child_path = gtk_tree_model_filter_convert_child_path_to_path (filter, path);
+					gtk_tree_view_expand_to_path (GTK_TREE_VIEW (view), child_path);
+					expanded = gtk_tree_view_row_expanded (GTK_TREE_VIEW (view), child_path);
+					gtk_tree_path_free (child_path);
+					gtk_tree_path_free (path);
+				}
+				valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (view->model), &child);
+			}
+			else
+			{
+				node = g_list_find (nodes, data_node);
+				if (node != NULL)
+				{
+					/* Node already exist, remove it from the list */
+					nodes = g_list_delete_link (nodes, node);
+
+					/* Update shortcut */
+					gbf_project_view_update_shortcut (view, data_node);
+				                                   
+					/* update recursively */
+					gbf_project_view_update_tree (view, data_node, &child);
+
+					valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (view->model), &child);
+				}
+				else
+				{
+					/* Node has been deleted */
+					valid = gbf_project_model_remove (view->model, &child);
+				}
+			}
+		}
+	}
+
+	/* add the remaining sources, targets and groups */
+	for (node = nodes; node; node = node->next)
+	{
+		switch (anjuta_project_node_get_node_type (node->data))
+		{
+		case ANJUTA_PROJECT_GROUP:
+			gbf_project_model_add_target_group (view->model, node->data, iter);
+			break;
+		case ANJUTA_PROJECT_TARGET:
+			gbf_project_model_add_target (view->model, node->data, iter);
+			break;
+		case ANJUTA_PROJECT_SOURCE:
+			gbf_project_model_add_source (view->model, node->data, iter);
+			break;
+		case ANJUTA_PROJECT_MODULE:
+			gbf_project_model_add_module (view->model, node->data, iter);
+			break;
+		case ANJUTA_PROJECT_PACKAGE:
+			gbf_project_model_add_package (view->model, node->data, iter);
+			break;
+		case ANJUTA_PROJECT_ROOT:
+			gbf_project_model_add_root (view->model, node->data, iter);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 /* Shorcuts functions
  *---------------------------------------------------------------------------*/
 
@@ -597,6 +794,54 @@ gbf_project_view_get_shortcut_list (GbfProjectView *view)
 	return list;
 }
 
+static void
+save_expanded_node (GtkTreeView *view, GtkTreePath *path, gpointer user_data)
+{
+	GList **list = (GList **)user_data;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	
+	model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
+
+	if (gtk_tree_model_get_iter (model, &iter, path))
+	{
+		GString *str;
+		GtkTreeIter child;
+		
+		str = g_string_new (NULL);
+		do
+		{
+			GbfTreeData *data;
+
+			child = iter;
+			gtk_tree_model_get (GTK_TREE_MODEL (model), &iter, 
+				GBF_PROJECT_MODEL_COLUMN_DATA, &data,
+				-1);
+
+			if (data->node != NULL)
+			{
+				if (str->len != 0) g_string_prepend (str, "//");
+				g_string_prepend (str, anjuta_project_node_get_name (data->node));
+			}
+		}
+		while (gtk_tree_model_iter_parent (model, &iter, &child));
+
+		*list = g_list_prepend (*list, str->str);
+		g_string_free (str, FALSE);
+	}
+}
+
+GList *
+gbf_project_view_get_expanded_list (GbfProjectView *view)
+{
+	GList *list = NULL;
+
+	gtk_tree_view_map_expanded_rows (GTK_TREE_VIEW (view), save_expanded_node, &list);
+	list = g_list_reverse (list);
+
+	return list;
+}
+
 void
 gbf_project_view_remove_all_shortcut (GbfProjectView* view)
 {
@@ -631,16 +876,12 @@ gbf_project_view_remove_all_shortcut (GbfProjectView* view)
 void
 gbf_project_view_set_shortcut_list (GbfProjectView *view, GList *shortcuts)
 {
-	GtkTreeModel* model;
-
-	model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
-
 	if (shortcuts != NULL)
 	{
 		gboolean valid;
 		GtkTreeIter iter;
 		
-		valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &iter, NULL);
+		valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (view->model), &iter, NULL);
 
 		if (valid)
 		{
@@ -665,18 +906,18 @@ gbf_project_view_set_shortcut_list (GbfProjectView *view, GList *shortcuts)
 				}
 				file = g_file_new_for_uri (uri);
 
-				if (gbf_project_model_find_file  (GBF_PROJECT_MODEL (model), &shortcut, NULL, ANJUTA_PROJECT_UNKNOWN, file))
+				if (gbf_project_model_find_file  (GBF_PROJECT_MODEL (view->model), &shortcut, NULL, ANJUTA_PROJECT_UNKNOWN, file))
 				{
 					GbfTreeData *data;
 
-					gtk_tree_model_get (GTK_TREE_MODEL (model), &shortcut, 
+					gtk_tree_model_get (GTK_TREE_MODEL (view->model), &shortcut, 
 			    			GBF_PROJECT_MODEL_COLUMN_DATA, &data,
 		    				-1);
 
 					/* Avoid duplicated shortcuts */
 					if (data->type != GBF_TREE_NODE_SHORTCUT)
 					{
-						gbf_project_model_add_shortcut (GBF_PROJECT_MODEL (model),
+						gbf_project_model_add_shortcut (GBF_PROJECT_MODEL (view->model),
 					    		&shortcut,
 					    		&iter,
 					    		data);
@@ -685,7 +926,7 @@ gbf_project_view_set_shortcut_list (GbfProjectView *view, GList *shortcuts)
 						{
 							GtkTreePath *path;
 
-							path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &shortcut);
+							path = gtk_tree_model_get_path (GTK_TREE_MODEL (view->model), &shortcut);
 							gtk_tree_view_expand_row (GTK_TREE_VIEW (view), path, FALSE);
 							gtk_tree_path_free (path);
 						}
@@ -701,6 +942,49 @@ gbf_project_view_set_shortcut_list (GbfProjectView *view, GList *shortcuts)
 	return;
 }
 
+void
+gbf_project_view_set_expanded_list (GbfProjectView *view, GList *expand)
+{
+	GList *item;
+
+	for (item = g_list_first (expand); item != NULL; item = g_list_next (item))
+	{
+		gchar *name = (gchar *)item->data;
+		gchar *end;
+		GtkTreeIter iter;
+		GtkTreeIter *parent = NULL;
+
+		do
+		{
+			end = strstr (name, "/" "/");   /* Avoid troubles with auto indent */
+			if (end != NULL) *end = '\0';
+			if (*name != '\0')
+			{
+				if (!gbf_project_model_find_child_name (view->model, &iter, parent, name))
+				{
+					GbfTreeData *data;
+					
+					/* Create proxy node */
+					data = gbf_tree_data_new_proxy (name, TRUE);
+					gtk_tree_store_append (GTK_TREE_STORE (view->model), &iter, parent);
+					gtk_tree_store_set (GTK_TREE_STORE (view->model), &iter, 
+							    GBF_PROJECT_MODEL_COLUMN_DATA, data,
+							    -1);
+				}
+				parent = &iter;
+			}
+			if (end != NULL)
+			{
+				*end = '/';
+				name = end + 2;
+			}
+		}
+		while (end != NULL);
+	}
+	
+	return;
+}
+
 AnjutaProjectNode *
 gbf_project_view_get_node_from_iter (GbfProjectView *view, GtkTreeIter *iter)
 {
@@ -751,13 +1035,20 @@ on_node_loaded (AnjutaPmProject *sender, AnjutaProjectNode *node, gboolean compl
 	{
 		GtkTreeIter iter;
 		gboolean found;
-			
+
+		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (view->model),
+		                                      GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID,
+		                                      GTK_SORT_ASCENDING);
+		                                      
 		found = gbf_project_model_find_node (view->model, &iter, NULL, node);
-		gbf_project_model_update_tree (view->model, node, found ? &iter : NULL);
+		gbf_project_view_update_tree (view, node, found ? &iter : NULL);
 		if (!found)
 		{
 			gtk_tree_model_get_iter_first (GTK_TREE_MODEL (view->model), &iter);
 		}
+		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (view->model),
+		                                      GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
+		                                      GTK_SORT_ASCENDING);
 
 		g_signal_emit (G_OBJECT (view), signals[NODE_LOADED], 0, &iter, complete, NULL);
 	}
diff --git a/plugins/project-manager/project-view.h b/plugins/project-manager/project-view.h
index ea6bb96..29c0a07 100644
--- a/plugins/project-manager/project-view.h
+++ b/plugins/project-manager/project-view.h
@@ -43,6 +43,9 @@ struct _GbfProjectView {
 	GtkTreeView parent;
 
 	GbfProjectModel *model;
+	GtkTreeModelFilter *filter;
+
+	GNode *expanded;
 };
 
 struct _GbfProjectViewClass {
@@ -65,6 +68,11 @@ struct _GbfProjectViewClass {
 GType                       gbf_project_view_get_type          (void);
 GtkWidget                  *gbf_project_view_new               (void);
 
+AnjutaProjectNode          *gbf_project_filter_view_find_selected     (GtkTreeView *view,
+									AnjutaProjectNodeType type);
+GList                      *gbf_project_filter_view_get_all_selected  (GtkTreeView *view);
+
+
 AnjutaProjectNode          *gbf_project_view_find_selected     (GbfProjectView *view,
 							        AnjutaProjectNodeType type);
 GbfTreeData                *gbf_project_view_get_first_selected(GbfProjectView *view,
@@ -72,11 +80,20 @@ GbfTreeData                *gbf_project_view_get_first_selected(GbfProjectView *
 GList                      *gbf_project_view_get_all_selected  (GbfProjectView *view);
 GList                      *gbf_project_view_get_all_selected_iter  (GbfProjectView *view);
 
-GList                      *gbf_project_view_get_shortcut_list (GbfProjectView *view);
+GList			*gbf_project_view_get_shortcut_list (GbfProjectView *view);
+GList			*gbf_project_view_get_expanded_list (GbfProjectView *view);
+
 void			gbf_project_view_remove_all_shortcut (GbfProjectView* view);
-void                        gbf_project_view_set_shortcut_list (GbfProjectView *view,
-                                                                 GList          *shortcuts);
+void			gbf_project_view_set_shortcut_list (GbfProjectView *view,
+								GList          *shortcuts);
+void			gbf_project_view_set_expanded_list (GbfProjectView *view,
+								GList   *expanded);
 
+void            gbf_project_view_update_tree (GbfProjectView *view,
+                                                    AnjutaProjectNode *parent,
+                                                    GtkTreeIter *iter);
+
+			                                       
 AnjutaProjectNode *gbf_project_view_get_node_from_iter (GbfProjectView *view, GtkTreeIter *iter);
 
 AnjutaProjectNode *gbf_project_view_get_node_from_file (GbfProjectView *view, AnjutaProjectNodeType type, GFile *file);
@@ -89,6 +106,8 @@ gboolean gbf_project_view_find_file (GbfProjectView *view, GtkTreeIter* iter, GF
 
 GbfProjectModel *gbf_project_view_get_model (GbfProjectView *view);
 
+
+
 G_END_DECLS
 
 #endif /* _PROJECT_VIEW_H_ */
diff --git a/plugins/project-manager/tree-data.c b/plugins/project-manager/tree-data.c
index cbccacf..12f3f00 100644
--- a/plugins/project-manager/tree-data.c
+++ b/plugins/project-manager/tree-data.c
@@ -192,6 +192,12 @@ gbf_tree_data_equal_file (GbfTreeData *data, AnjutaProjectNodeType type, GFile *
 	return equal;
 }
 
+gboolean
+gbf_tree_data_equal_name (GbfTreeData *data, const gchar *name)
+{
+	return g_strcmp0 (data->name, name) == 0;
+}
+
 void
 gbf_tree_data_invalidate (GbfTreeData *data)
 {
@@ -228,6 +234,19 @@ gbf_tree_data_new_shortcut (GbfTreeData *src)
 }
 
 GbfTreeData *
+gbf_tree_data_new_proxy (const char *name, gboolean expanded)
+{
+	GbfTreeData *data = g_slice_new0 (GbfTreeData);
+
+	data->type = GBF_TREE_NODE_UNKNOWN;
+	data->node = NULL;
+	data->name = g_strdup (name);
+	data->expanded = expanded;
+	
+	return data;
+}
+
+GbfTreeData *
 gbf_tree_data_new_group (AnjutaProjectNode *group)
 {
 	GbfTreeData *data = g_slice_new0 (GbfTreeData);
@@ -339,6 +358,38 @@ gbf_tree_data_new_package (AnjutaProjectNode *package)
 	return data;
 }
 
+GbfTreeData *
+gbf_tree_data_new_node (AnjutaProjectNode *node)
+{
+	GbfTreeData *data;
+	
+	switch (anjuta_project_node_get_node_type (node))
+	{
+		case ANJUTA_PROJECT_GROUP:
+			data = gbf_tree_data_new_group (node);
+			break;
+		case ANJUTA_PROJECT_TARGET:
+			data = gbf_tree_data_new_target(node);
+			break;
+		case ANJUTA_PROJECT_SOURCE:
+			data = gbf_tree_data_new_source (node);
+			break;
+		case ANJUTA_PROJECT_MODULE:
+			data = gbf_tree_data_new_module (node);
+			break;
+		case ANJUTA_PROJECT_PACKAGE:
+			data = gbf_tree_data_new_package (node);
+			break;
+		case ANJUTA_PROJECT_ROOT:
+			data = NULL;
+			break;
+		default:
+			break;
+	}
+
+	return data;
+}
+
 
 void
 gbf_tree_data_free (GbfTreeData *data)
diff --git a/plugins/project-manager/tree-data.h b/plugins/project-manager/tree-data.h
index 974e182..79cb548 100644
--- a/plugins/project-manager/tree-data.h
+++ b/plugins/project-manager/tree-data.h
@@ -52,6 +52,7 @@ struct _GbfTreeData
 	gchar			*target;
 	GFile			*source;
 	gboolean		is_shortcut;
+	gboolean		expanded;
 	GbfTreeData		*shortcut;
 	GtkWidget		*properties_dialog;
 };
@@ -68,14 +69,18 @@ gboolean       gbf_tree_data_equal              (GbfTreeData           *data_a,
 gboolean       gbf_tree_data_equal_file         (GbfTreeData           *data,
                                                  AnjutaProjectNodeType type,
                                                  GFile                 *file);
+gboolean       gbf_tree_data_equal_name         (GbfTreeData           *data,
+                                                 const gchar           *name);
 
 GbfTreeData   *gbf_tree_data_new_string         (const gchar           *string);
 GbfTreeData   *gbf_tree_data_new_shortcut       (GbfTreeData		   *src);
+GbfTreeData   *gbf_tree_data_new_proxy   					(const gchar           *name, gboolean expanded);
 GbfTreeData   *gbf_tree_data_new_group          (AnjutaProjectNode     *group);
 GbfTreeData   *gbf_tree_data_new_target         (AnjutaProjectNode     *target);
 GbfTreeData   *gbf_tree_data_new_source         (AnjutaProjectNode     *source);
 GbfTreeData   *gbf_tree_data_new_module         (AnjutaProjectNode     *module);
 GbfTreeData   *gbf_tree_data_new_package        (AnjutaProjectNode     *package);
+GbfTreeData			*gbf_tree_data_new_node							(AnjutaProjectNode     *node);
 void				gbf_tree_data_invalidate (GbfTreeData *data);
 void           gbf_tree_data_free               (GbfTreeData           *data);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]