[anjuta/newproject] Load package header in the project manager



commit 226e1d27dd0177b49518e9156911778b568554ca
Author: Sébastien Granjoux <seb sfo free fr>
Date:   Mon Apr 12 17:28:05 2010 +0200

    Load package header in the project manager

 libanjuta/anjuta-project.c                  |   21 +++
 libanjuta/anjuta-project.h                  |   11 +-
 plugins/am-project/am-project.c             |  249 ++++++++++++++++++---------
 plugins/project-manager/gbf-project-model.c |  180 ++++++++++----------
 plugins/project-manager/gbf-project-model.h |    5 +
 plugins/project-manager/gbf-project-util.c  |    1 -
 plugins/project-manager/project.c           |   97 +++++++++--
 plugins/project-manager/project.h           |    4 +-
 8 files changed, 380 insertions(+), 188 deletions(-)
---
diff --git a/libanjuta/anjuta-project.c b/libanjuta/anjuta-project.c
index 5c3f457..e0b6d3d 100644
--- a/libanjuta/anjuta-project.c
+++ b/libanjuta/anjuta-project.c
@@ -309,6 +309,27 @@ anjuta_project_node_prepend (AnjutaProjectNode *parent, AnjutaProjectNode *node)
 	return g_node_prepend (parent, node);
 }
 
+gboolean
+anjuta_project_node_set_state (AnjutaProjectNode *node, AnjutaProjectNodeState state)
+{
+	if (node == NULL) return FALSE;
+	NODE_DATA (node)->state |= state;
+	return TRUE;
+}
+
+gboolean
+anjuta_project_node_clear_state (AnjutaProjectNode *node, AnjutaProjectNodeState state)
+{
+	if (node == NULL) return FALSE;
+	NODE_DATA (node)->state &= ~state;
+	return TRUE;
+}
+
+AnjutaProjectNodeState
+anjuta_project_node_get_state (const AnjutaProjectNode *node)
+{
+	return node == NULL ? ANJUTA_PROJECT_OK : (NODE_DATA (node)->state);
+}
 
 AnjutaProjectNodeType
 anjuta_project_node_get_type (const AnjutaProjectNode *node)
diff --git a/libanjuta/anjuta-project.h b/libanjuta/anjuta-project.h
index a0de46a..fd2df89 100644
--- a/libanjuta/anjuta-project.h
+++ b/libanjuta/anjuta-project.h
@@ -46,8 +46,10 @@ typedef enum
 
 typedef enum
 {
-	ANJUTA_PROJECT_LOADING = 1 << 0,
-	ANJUTA_PROJECT_SAVED = 1 << 1
+	ANJUTA_PROJECT_OK = 0,
+	ANJUTA_PROJECT_MODIFIED = 1 << 0,		/* Node has been modified */
+	ANJUTA_PROJECT_INCOMPLETE = 1 << 1,	/* Node is not fully loaded */
+	ANJUTA_PROJECT_LOADING = 1 << 2	    	/* Node is send to the worker thread */
 } AnjutaProjectNodeState;
 
 typedef enum
@@ -109,6 +111,7 @@ typedef struct
 	GFile *file;
 	gchar *name;
 	AnjutaProjectTargetType target_type;
+	AnjutaProjectNodeState state;
 } AnjutaProjectNodeData;
 
 #if 0
@@ -166,8 +169,12 @@ AnjutaProjectNode *anjuta_project_node_insert_after (AnjutaProjectNode *parent,
 void anjuta_project_node_all_foreach (AnjutaProjectNode *node, AnjutaProjectNodeFunc func, gpointer data);
 void anjuta_project_node_children_foreach (AnjutaProjectNode *node, AnjutaProjectNodeFunc func, gpointer data);
 
+gboolean anjuta_project_node_set_state (AnjutaProjectNode *node, AnjutaProjectNodeState state);
+gboolean anjuta_project_node_clear_state (AnjutaProjectNode *node, AnjutaProjectNodeState state);
+
 AnjutaProjectNodeType anjuta_project_node_get_type (const AnjutaProjectNode *node);
 AnjutaProjectNodeType anjuta_project_node_get_full_type (const AnjutaProjectNode *node);
+AnjutaProjectNodeState anjuta_project_node_get_state (const AnjutaProjectNode *node);
 gchar *anjuta_project_node_get_name (const AnjutaProjectNode *node);
 gchar *anjuta_project_node_get_uri (AnjutaProjectNode *node);
 GFile *anjuta_project_node_get_file (AnjutaProjectNode *node);
diff --git a/plugins/am-project/am-project.c b/plugins/am-project/am-project.c
index 4e21bfe..a5147a0 100644
--- a/plugins/am-project/am-project.c
+++ b/plugins/am-project/am-project.c
@@ -1092,7 +1092,6 @@ project_node_new (AmpProject *project, AnjutaProjectNodeType type, GFile *file,
 			break;
 		case ANJUTA_PROJECT_ROOT:
 			node = amp_root_new (file);
-			g_message ("root node file %s file %s", g_file_get_path (anjuta_project_node_get_file (node)), g_file_get_path (file));
 			break;
 		default:
 			g_assert_not_reached ();
@@ -1198,6 +1197,7 @@ amp_project_load_module (AmpProject *project, AnjutaToken *module_token)
 			{
 				package = amp_package_new (value);
 				anjuta_project_node_append (module, package);
+				anjuta_project_node_set_state ((AnjutaProjectNode *)package, ANJUTA_PROJECT_INCOMPLETE);
 				g_free (value);
 				compare = NULL;
 			}
@@ -1835,7 +1835,7 @@ amp_project_set_am_variable (AmpProject* project, AmpGroup* group, AnjutaTokenTy
  *---------------------------------------------------------------------------*/
 
 AnjutaProjectNode *
-amp_project_load_node (AmpProject *project, AnjutaProjectNode *node, GError **error) 
+amp_project_load_root (AmpProject *project, AnjutaProjectNode *node, GError **error) 
 {
 	AmpAcScanner *scanner;
 	AnjutaToken *arg;
@@ -1845,98 +1845,192 @@ amp_project_load_node (AmpProject *project, AnjutaProjectNode *node, GError **er
 	gboolean ok = TRUE;
 	GError *err = NULL;
 
-	switch (anjuta_project_node_get_type (node))
-	{
-	case ANJUTA_PROJECT_ROOT:
-
-		/* Unload current project */
-		amp_project_unload (project);
-		DEBUG_PRINT ("reload project %p root file %p", project, root_file);
+	/* Unload current project */
+	amp_project_unload (project);
+	DEBUG_PRINT ("reload project %p root file %p", project, root_file);
 
-		root_file = g_object_ref (anjuta_project_node_get_file (node));
-		g_message ("reload project %s", g_file_get_path (root_file));
-		project->root_file = root_file;
-		project->root_node = node;
+	root_file = g_object_ref (anjuta_project_node_get_file (node));
+	project->root_file = root_file;
+	project->root_node = node;
 
-		/* shortcut hash tables */
-		project->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-		project->files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, g_object_unref);
-		project->configs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, NULL, (GDestroyNotify)amp_config_file_free);
-		amp_project_new_module_hash (project);
+	/* shortcut hash tables */
+	project->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	project->files = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, g_object_unref, g_object_unref);
+	project->configs = g_hash_table_new_full (g_file_hash, (GEqualFunc)g_file_equal, NULL, (GDestroyNotify)amp_config_file_free);
+	amp_project_new_module_hash (project);
 
-		/* Initialize list styles */
-		project->ac_space_list = anjuta_token_style_new (NULL, " ", "\n", NULL, 0);
-		project->am_space_list = anjuta_token_style_new (NULL, " ", " \\\n", NULL, 0);
-		project->arg_list = anjuta_token_style_new (NULL, ", ", ", ", ")", 0);
+	/* Initialize list styles */
+	project->ac_space_list = anjuta_token_style_new (NULL, " ", "\n", NULL, 0);
+	project->am_space_list = anjuta_token_style_new (NULL, " ", " \\\n", NULL, 0);
+	project->arg_list = anjuta_token_style_new (NULL, ", ", ", ", ")", 0);
 	
-		/* Find configure file */
-		if (file_type (root_file, "configure.ac") == G_FILE_TYPE_REGULAR)
-		{
-			configure_file = g_file_get_child (root_file, "configure.ac");
-		}
-		else if (file_type (root_file, "configure.in") == G_FILE_TYPE_REGULAR)
-		{
-			configure_file = g_file_get_child (root_file, "configure.in");
-		}
-		else
-		{
-			g_set_error (error, IANJUTA_PROJECT_ERROR, 
-						IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
-				_("Project doesn't exist or invalid path"));
+	/* Find configure file */
+	if (file_type (root_file, "configure.ac") == G_FILE_TYPE_REGULAR)
+	{
+		configure_file = g_file_get_child (root_file, "configure.ac");
+	}
+	else if (file_type (root_file, "configure.in") == G_FILE_TYPE_REGULAR)
+	{
+		configure_file = g_file_get_child (root_file, "configure.in");
+	}
+	else
+	{
+		g_set_error (error, IANJUTA_PROJECT_ERROR, 
+					IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+			_("Project doesn't exist or invalid path"));
+
+		return NULL;
+	}
 
+	/* Parse configure */
+	project->configure_file = anjuta_token_file_new (configure_file);
+	g_hash_table_insert (project->files, configure_file, project->configure_file);
+	g_object_add_toggle_ref (G_OBJECT (project->configure_file), remove_config_file, project);
+	arg = anjuta_token_file_load (project->configure_file, NULL);
+	//fprintf (stdout, "AC file before parsing\n");
+	//anjuta_token_dump (arg);
+	//fprintf (stdout, "\n");
+	scanner = amp_ac_scanner_new (project);
+	project->configure_token = amp_ac_scanner_parse_token (scanner, arg, 0, &err);
+	//fprintf (stdout, "AC file after parsing\n");
+	//anjuta_token_check (arg);
+	//anjuta_token_dump (project->configure_token);
+	//fprintf (stdout, "\n");
+	amp_ac_scanner_free (scanner);
+	if (project->configure_token == NULL)
+	{
+		g_set_error (error, IANJUTA_PROJECT_ERROR, 
+						IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED,
+						err == NULL ? _("Unable to parse project file") : err->message);
+		if (err != NULL) g_error_free (err);
 			return NULL;
-		}
+	}
+
+	monitors_setup (project);
+
+	/* Load all makefiles recursively */
+	if (project_load_makefile (project, project->root_file, node, FALSE) == NULL)
+	{
+		g_set_error (error, IANJUTA_PROJECT_ERROR, 
+					IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
+			_("Project doesn't exist or invalid path"));
+
+		return NULL;
+	}
+
+	return node;
+}
+
+static void
+list_all_children (GList **children, GFile *dir)
+{
+	GFileEnumerator *list;
+					
+	list = g_file_enumerate_children (dir,
+	    G_FILE_ATTRIBUTE_STANDARD_NAME,
+	    G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+	    NULL,
+	    NULL);
+
+	if (list != NULL)
+	{
+		GFileInfo *info;
 		
-	
-		/* Create first group */
-		/*group = amp_group_new (root_file, FALSE);
-		anjuta_project_node_append (node, group);
-		g_hash_table_insert (project->groups, g_file_get_uri (root_file), group);*/
-	
-		/* Parse configure */
-		project->configure_file = anjuta_token_file_new (configure_file);
-		g_hash_table_insert (project->files, configure_file, project->configure_file);
-		g_object_add_toggle_ref (G_OBJECT (project->configure_file), remove_config_file, project);
-		arg = anjuta_token_file_load (project->configure_file, NULL);
-		//fprintf (stdout, "AC file before parsing\n");
-		//anjuta_token_dump (arg);
-		//fprintf (stdout, "\n");
-		scanner = amp_ac_scanner_new (project);
-		project->configure_token = amp_ac_scanner_parse_token (scanner, arg, 0, &err);
-		//fprintf (stdout, "AC file after parsing\n");
-		//anjuta_token_check (arg);
-		//anjuta_token_dump (project->configure_token);
-		//fprintf (stdout, "\n");
-		amp_ac_scanner_free (scanner);
-		if (project->configure_token == NULL)
+		while ((info = g_file_enumerator_next_file (list, NULL, NULL)) != NULL)
 		{
-			g_set_error (error, IANJUTA_PROJECT_ERROR, 
-							IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED,
-							err == NULL ? _("Unable to parse project file") : err->message);
-			if (err != NULL) g_error_free (err);
+			const gchar *name;
+			GFile *file;
 
-			return NULL;
+			name = g_file_info_get_name (info);
+			file = g_file_get_child (dir, name);
+			g_object_unref (info);
+
+			if (g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL) == G_FILE_TYPE_DIRECTORY)
+			{
+				list_all_children (children, file);
+				g_object_unref (file);
+			}
+			else
+			{
+				*children = g_list_prepend (*children, file);
+			}
 		}
-		     
-		monitors_setup (project);
+		g_file_enumerator_close (list, NULL, NULL);
+		g_object_unref (list);
+	}
+}
 
-		/* Load all makefiles recursively */
-		if (project_load_makefile (project, project->root_file, node, FALSE) == NULL)
+AnjutaProjectNode *
+amp_project_load_package (AmpProject *project, AnjutaProjectNode *node, GError **error)
+{
+	gchar *cmd;
+	gchar *err;
+	gchar *out;
+	gint status;
+	
+	cmd = g_strdup_printf ("pkg-config --cflags %s", anjuta_project_node_get_name (node));
+
+	if (g_spawn_command_line_sync (cmd, &out, &err, &status, error))
+	{
+		gchar **flags;
+		
+		anjuta_project_node_clear_state (node, ANJUTA_PROJECT_INCOMPLETE);
+
+		flags = g_strsplit (out, " ", -1);
+
+		if (flags != NULL)
 		{
-			g_set_error (error, IANJUTA_PROJECT_ERROR, 
-						IANJUTA_PROJECT_ERROR_DOESNT_EXIST,
-				_("Project doesn't exist or invalid path"));
+			gchar **flag;
+			
+			for (flag = flags; *flag != NULL; flag++)
+			{
+				if (g_regex_match_simple ("\\.*/include/\\w+", *flag, 0, 0) == TRUE)
+                {
+                    /* FIXME the +2. It's to skip the -I */
+					GFile *dir;
+					GList *children = NULL;
+					GList *file;
+					
+					dir = g_file_new_for_path (*flag + 2);
+					list_all_children (&children, dir);
+					for (file = g_list_first (children); file != NULL; file = g_list_next (file))
+					{
+						/* Create a source for files */
+						AmpSource *source;
 
-			return NULL;
+						source = amp_source_new ((GFile *)file->data);
+						anjuta_project_node_append (node, source);
+						g_object_unref ((GObject *)file->data);
+					}
+					g_list_free (children);
+					g_object_unref (dir);
+				}
+			}
 		}
-		break;
-	default:
-		break;
 	}
-	
+	else
+	{
+		node = NULL;
+	}
+	g_free (cmd);
+
 	return node;
 }
 
+AnjutaProjectNode *
+amp_project_load_node (AmpProject *project, AnjutaProjectNode *node, GError **error) 
+{
+	switch (anjuta_project_node_get_type (node))
+	{
+	case ANJUTA_PROJECT_ROOT:
+		return amp_project_load_root (project, node, error);
+	case ANJUTA_PROJECT_PACKAGE:
+		return amp_project_load_package (project, node, error);
+	default:
+		return NULL;
+	}
+}
+
 gboolean
 amp_project_load (AmpProject  *project,
     GFile *directory,
@@ -2619,7 +2713,6 @@ amp_project_get_config_modules   (AmpProject *project, GError **error)
 	GList *modules = NULL;
 
 	g_return_val_if_fail (project != NULL, NULL);
-	g_return_val_if_fail (module != NULL, NULL);
 	
 	for (module = anjuta_project_node_first_child (project->root_node); module != NULL; module = anjuta_project_node_next_sibling (module))
 	{
@@ -2642,7 +2735,7 @@ amp_project_get_config_packages  (AmpProject *project,
 	GList *packages = NULL;
 
 	g_return_val_if_fail (project != NULL, NULL);
-	g_return_val_if_fail (module != NULL, NULL);
+
 	
 	for (module = anjuta_project_node_first_child (project->root_node); module != NULL; module = anjuta_project_node_next_sibling (module))
 	{
diff --git a/plugins/project-manager/gbf-project-model.c b/plugins/project-manager/gbf-project-model.c
index babda0b..ab72788 100644
--- a/plugins/project-manager/gbf-project-model.c
+++ b/plugins/project-manager/gbf-project-model.c
@@ -496,6 +496,7 @@ add_package (GbfProjectModel    	      *model,
 {
 	GtkTreeIter iter;
 	GbfTreeData *data;
+	AnjutaProjectNode *node;
 
 	if ((!package) || (anjuta_project_node_get_type (package) != ANJUTA_PROJECT_PACKAGE))
 		return;
@@ -505,6 +506,12 @@ add_package (GbfProjectModel    	      *model,
 	gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 
 			    GBF_PROJECT_MODEL_COLUMN_DATA, data,
 			    -1);
+	
+	/* ... and sources */
+	for (node = anjuta_project_node_first_child (package); node; node = anjuta_project_node_next_sibling (node))
+	{
+		add_source (model, node, &iter);
+	}
 }
 
 static void 
@@ -519,7 +526,6 @@ add_module (GbfProjectModel 		*model,
 	if ((!module) || (anjuta_project_node_get_type (module) != ANJUTA_PROJECT_MODULE))
 		return;
 	
-	g_message ("new module");
 	data = gbf_tree_data_new_module (module);
 	gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
 	gtk_tree_store_set (GTK_TREE_STORE (model), &iter, 
@@ -634,103 +640,19 @@ add_root (GbfProjectModel 	*model,
 	model->priv->root_row = gtk_tree_row_reference_new (GTK_TREE_MODEL (model), root_path);
 	gtk_tree_path_free (root_path);*/
 
-	g_message ("add group");
 	/* add groups ... */
 	for (node = anjuta_project_node_first_child (root); node; node = anjuta_project_node_next_sibling (node))
 		add_target_group (model, node, NULL);
 	
-	g_message ("add module");
 	/* ... and module */
 	for (node = anjuta_project_node_first_child (root); node; node = anjuta_project_node_next_sibling (node))
 		add_module (model, node, NULL);
 }
 
 static void
-update_tree (GbfProjectModel *model, AnjutaProjectNode *parent, GtkTreeIter *iter)
-{
-	GtkTreeIter child;
-	GList *node;
-	GList *nodes;
-
-	/* group can be NULL, but we iterate anyway to remove any
-	 * shortcuts the old group could have had */
-	
-	/* Get all new nodes */
-	nodes = gbf_project_util_all_child (parent, ANJUTA_PROJECT_UNKNOWN);
-	g_message ("get all nodes %d", g_list_length (nodes));
-
-	/* walk the tree nodes */
-	if (gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &child, iter)) {
-		gboolean valid = TRUE;
-		
-		while (valid) {
-			AnjutaProjectNode* data;
-			GbfTreeData *tree_data = NULL;
-
-			/* Get tree data */
-			gtk_tree_model_get (GTK_TREE_MODEL (model), &child,
-			    GBF_PROJECT_MODEL_COLUMN_DATA, &tree_data,
-			    -1);
-
-			data = gbf_project_model_get_node (model, &child);
-
-			if (data != NULL)
-			{
-				/* Remove from the new node list */
-				node = g_list_find (nodes, data);
-				if (node != NULL)
-				{
-					nodes = g_list_delete_link (nodes, node);
-				}
-
-				/* update recursively */
-				update_tree (model, data, &child);
-				
-				valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
-			}
-			else
-			{
-				/* update recursively */
-				update_tree (model, data, &child);
-				
-				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_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;
-		}
-	}
-}
-
-static void
 project_updated_cb (IAnjutaProject *project, GbfProjectModel *model)
 {
-	update_tree (model, NULL, NULL);
+	gbf_project_model_update_tree (model, NULL, NULL);
 }
 
 static void
@@ -745,6 +667,9 @@ load_project (GbfProjectModel *model, AnjutaPmProject *proj)
 	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);
@@ -775,7 +700,7 @@ unload_project (GbfProjectModel *model)
 
 		g_list_free (model->priv->shortcuts);
 		model->priv->shortcuts = NULL;
-		
+
 		g_signal_handler_disconnect (anjuta_pm_project_get_project (model->priv->proj),
 					     model->priv->project_updated_handler);
 		model->priv->project_updated_handler = 0;
@@ -819,6 +744,87 @@ recursive_find_tree_data (GtkTreeModel  *model,
 	return retval;
 }
 
+void
+gbf_project_model_update_tree (GbfProjectModel *model, AnjutaProjectNode *parent, GtkTreeIter *iter)
+{
+	GtkTreeIter child;
+	GList *node;
+	GList *nodes;
+
+	/* group can be NULL, but we iterate anyway to remove any
+	 * shortcuts the old group could have had */
+	
+	/* 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) {
+			AnjutaProjectNode* data;
+			GbfTreeData *tree_data = NULL;
+
+			/* Get tree data */
+			gtk_tree_model_get (GTK_TREE_MODEL (model), &child,
+			    GBF_PROJECT_MODEL_COLUMN_DATA, &tree_data,
+			    -1);
+
+			data = gbf_project_model_get_node (model, &child);
+
+			if (data != NULL)
+			{
+				/* Remove from the new node list */
+				node = g_list_find (nodes, data);
+				if (node != NULL)
+				{
+					nodes = g_list_delete_link (nodes, node);
+				}
+
+				/* update recursively */
+				gbf_project_model_update_tree (model, data, &child);
+				
+				valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
+			}
+			else
+			{
+				/* update recursively */
+				gbf_project_model_update_tree (model, data, &child);
+				
+				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_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,
diff --git a/plugins/project-manager/gbf-project-model.h b/plugins/project-manager/gbf-project-model.h
index dbeeae4..de61868 100644
--- a/plugins/project-manager/gbf-project-model.h
+++ b/plugins/project-manager/gbf-project-model.h
@@ -80,4 +80,9 @@ void             gbf_project_model_add_shortcut      (GbfProjectModel *model,
                                                       GtkTreeIter     *before, 
                                                       GbfTreeData     *target);
 
+void            gbf_project_model_update_tree (GbfProjectModel *model,
+                                                    AnjutaProjectNode *parent,
+                                                    GtkTreeIter *iter);
+
+
 #endif
diff --git a/plugins/project-manager/gbf-project-util.c b/plugins/project-manager/gbf-project-util.c
index 3963990..753f119 100644
--- a/plugins/project-manager/gbf-project-util.c
+++ b/plugins/project-manager/gbf-project-util.c
@@ -507,7 +507,6 @@ setup_modules_treeview (AnjutaPmProject *project,
     GtkTreePath *path = NULL;
     GbfProjectModel *model;
     
-    g_return_if_fail (model != NULL);
     g_return_if_fail (view != NULL && GBF_IS_PROJECT_VIEW (view));
 
     model = anjuta_pm_project_get_model (project);
diff --git a/plugins/project-manager/project.c b/plugins/project-manager/project.c
index 8bd003b..22916e2 100644
--- a/plugins/project-manager/project.c
+++ b/plugins/project-manager/project.c
@@ -164,7 +164,15 @@ pm_project_push_command (AnjutaPmProject *project, PmCommand command, GFile *fil
 
 	job = pm_job_new (command, file, name, node, callback);
 
-	g_async_queue_push (project->job_queue, job);
+	if (project->busy == 0)
+	{
+		project->busy++;
+		g_async_queue_push (project->work_queue, job);
+	}
+	else
+	{
+		g_queue_push_tail (project->job_queue, job);
+	}
 }
 
 /* Thread functions
@@ -180,7 +188,7 @@ pm_project_thread_main_loop (AnjutaPmProject *project)
 		AnjutaProjectNode *root;
 		AnjutaProjectNode *node;
 		
-		job = (PmJob *)g_async_queue_pop (project->job_queue);
+		job = (PmJob *)g_async_queue_pop (project->work_queue);
 
 		switch (job->command)
 		{
@@ -197,6 +205,13 @@ pm_project_thread_main_loop (AnjutaPmProject *project)
 				ianjuta_project_free_node (project->project, root, NULL);
 			}
 			break;
+		case RELOAD:
+			node = ianjuta_project_load_node (project->project, job->node, &(job->error));
+			if (job->error == NULL)
+			{
+				job->node = node;
+			}
+			break;						
 		case EXIT:
 			do
 			{
@@ -228,6 +243,16 @@ pm_project_idle_func (AnjutaPmProject *project)
 			job->callback (project, job);
 		}
 		pm_job_free (job);
+		project->busy--;
+		if (project->busy == 0)
+		{
+			job = g_queue_pop_head (project->job_queue);
+			if (job != NULL)
+		    {
+				project->busy = 1;
+				g_async_queue_push (project->work_queue, job);
+			}
+		}
 	}
 }
 
@@ -235,15 +260,18 @@ static gboolean
 pm_project_start_thread (AnjutaPmProject *project, GError **error)
 {
 	project->done_queue = g_async_queue_new ();
-	project->job_queue = g_async_queue_new ();
+	project->work_queue = g_async_queue_new ();
+	project->job_queue = g_queue_new ();
 
 	project->worker = g_thread_create ((GThreadFunc) pm_project_thread_main_loop, project, TRUE, error);
 
 	if (project->worker == NULL) {
-		g_async_queue_unref (project->job_queue);
-		project->job_queue = NULL;
+		g_async_queue_unref (project->work_queue);
+		project->work_queue = NULL;
 		g_async_queue_unref (project->done_queue);
 		project->done_queue = NULL;
+		g_queue_free (project->job_queue);
+		project->job_queue = NULL;
 
 		return FALSE;
 	}
@@ -271,12 +299,15 @@ pm_project_stop_thread (AnjutaPmProject *project)
 
 		// Request to terminate thread
 		job = pm_job_new (EXIT, NULL, NULL, NULL, NULL);
-		g_async_queue_push (project->job_queue, job);
+		g_async_queue_push (project->work_queue, job);
 		g_thread_join (project->worker);
 		project->worker = NULL;
 
 		// Free queue
-		g_async_queue_unref (project->job_queue);
+		g_async_queue_unref (project->work_queue);
+		project->work_queue = NULL;
+		g_queue_foreach (project->job_queue, (GFunc)pm_job_free, NULL);
+		g_queue_free (project->job_queue);
 		project->job_queue = NULL;
 		for (;;)
 		{
@@ -293,6 +324,39 @@ pm_project_stop_thread (AnjutaPmProject *project)
 /* Public functions
  *---------------------------------------------------------------------------*/
 
+static void on_pm_project_load_incomplete (AnjutaProjectNode *node, AnjutaPmProject *project);
+
+static void
+on_pm_project_reloaded (AnjutaPmProject *project, PmJob *job)
+{
+	if (job->error != NULL)
+	{
+		g_warning ("unable to load node");
+	}
+	else
+	{
+		//g_object_set (G_OBJECT (project->model), "project", project, NULL);
+		// Check for incompletely loaded object and load them
+		anjuta_project_node_clear_state (job->node, ANJUTA_PROJECT_LOADING | ANJUTA_PROJECT_INCOMPLETE);
+		anjuta_project_node_all_foreach (job->node, (AnjutaProjectNodeFunc)on_pm_project_load_incomplete, project);
+		g_message ("Emit project updated on %p", project);
+		//g_signal_emit (G_OBJECT (project), signals[UPDATED], 0, job->error);
+		gbf_project_model_update_tree (project->model, NULL, NULL);
+	}
+}
+
+static void
+on_pm_project_load_incomplete (AnjutaProjectNode *node, AnjutaPmProject *project)
+{
+	gint state = anjuta_project_node_get_state (node);
+	
+	if ((state & ANJUTA_PROJECT_INCOMPLETE) && !(state & ANJUTA_PROJECT_LOADING))
+	{
+		anjuta_project_node_set_state (node, ANJUTA_PROJECT_LOADING);
+		pm_project_push_command (project, RELOAD, NULL, NULL, node, on_pm_project_reloaded);
+	}
+}
+
 static void
 on_pm_project_loaded (AnjutaPmProject *project, PmJob *job)
 {
@@ -311,8 +375,12 @@ on_pm_project_loaded (AnjutaPmProject *project, PmJob *job)
 		g_message ("root all nodes %d", g_node_n_nodes (job->node, G_TRAVERSE_ALL));
 		project->root = job->node;
 		g_object_set (G_OBJECT (project->model), "project", project, NULL);
+		gbf_project_model_update_tree (project->model, NULL, NULL);		
 	}
 	g_signal_emit (G_OBJECT (project), signals[UPDATED], 0, job->error);
+
+	// Check for incompletely loaded object and load them
+	anjuta_project_node_all_foreach (job->node, (AnjutaProjectNodeFunc)on_pm_project_load_incomplete, project);
 }
 
 gboolean 
@@ -403,17 +471,6 @@ anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
 	return TRUE;
 }
 
-static void
-on_pm_project_reloaded (AnjutaPmProject *project, PmJob *job)
-{
-	if (job->error == NULL)
-	{
-		project->root = job->node;
-		g_object_set (G_OBJECT (project->model), "project", project, NULL);
-	}
-	g_signal_emit (G_OBJECT (project), signals[UPDATED], 0, job->error);
-}
-
 gboolean
 anjuta_pm_project_reload_node (AnjutaPmProject *project, AnjutaProjectNode *node, GError **error)
 {
@@ -623,12 +680,14 @@ anjuta_pm_project_init (AnjutaPmProject *project)
 {
 	project->model = gbf_project_model_new (NULL);
 	project->plugin = NULL;
-	
+
 	project->job_queue = NULL;
+	project->work_queue = NULL;
 	project->done_queue = NULL;
 	project->worker = NULL;
 	project->idle_func = 0;
 	project->stopping = FALSE;
+	project->busy = 0;
 }
 
 static void
diff --git a/plugins/project-manager/project.h b/plugins/project-manager/project.h
index 8877916..c83f67a 100644
--- a/plugins/project-manager/project.h
+++ b/plugins/project-manager/project.h
@@ -62,11 +62,13 @@ struct _AnjutaPmProject
 	AnjutaProjectNode *root;
 	
 	/* Thread queue */
-	GAsyncQueue *job_queue;
+	GQueue *job_queue;
+	GAsyncQueue *work_queue;
 	GAsyncQueue *done_queue;
 	GThread *worker;
 	guint idle_func;
 	gboolean stopping;
+	guint busy;
 };
 
 GType anjuta_pm_project_get_type (void) G_GNUC_CONST;



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