[anjuta/newproject] Change IAnjutaProject interface, reload should work now



commit 6b0a806236550f97c6c3501e065bc57d0bdd3576
Author: Sébastien Granjoux <seb sfo free fr>
Date:   Mon May 3 22:39:16 2010 +0200

    Change IAnjutaProject interface, reload should work now

 libanjuta/interfaces/libanjuta.idl |   28 ++-
 plugins/am-project/am-project.c    |   19 ++
 plugins/dir-project/dir-project.c  |  231 +++++++++---------
 plugins/dir-project/dir-project.h  |    1 +
 plugins/project-manager/plugin.c   |   18 --
 plugins/project-manager/project.c  |  483 ++++++++++++++++++++----------------
 6 files changed, 433 insertions(+), 347 deletions(-)
---
diff --git a/libanjuta/interfaces/libanjuta.idl b/libanjuta/interfaces/libanjuta.idl
index e54e750..e125342 100644
--- a/libanjuta/interfaces/libanjuta.idl
+++ b/libanjuta/interfaces/libanjuta.idl
@@ -3079,10 +3079,11 @@ interface IAnjutaProject
 	/**
 	* IAnjutaProject::project_updated:
 	* @obj: Self
+	* @node: Updated node.
 	* 
 	* This signal is emitted when the project is changed.
 	*/
-	void ::project_updated ();
+	void ::node_updated (gpointer node);
 
 	/**
 	 * ianjuta_project_load_node:
@@ -3109,6 +3110,31 @@ interface IAnjutaProject
 	AnjutaProjectNode *save_node (AnjutaProjectNode *node);
 
 	/**
+	 * ianjuta_project_new_node:
+	 * @obj: Self
+	 * @parent: Parent
+	 * @type: Node type
+	 * @file: Optional file object for the node
+	 * @name: Optional name for the node
+	 * @err: Error propagation and reporting
+	 *
+	 * Create a new node
+	 *
+	 * Return value: The new node, NULL if error
+	 */
+	AnjutaProjectNode *new_node (AnjutaProjectNode *parent, AnjutaProjectNodeType type, GFile *file, const gchar *name);
+
+	/**
+	 * ianjuta_project_free_node:
+	 * @obj: Self
+	 * @node: Node
+	 * @err: Error propagation and reporting
+	 *
+	 * Free an already existing node
+	 */
+	void free_node (AnjutaProjectNode *node);
+
+	/**
 	 * ianjuta_project_new_root_node:
 	 * @obj: Self
 	 * @file: Project file or directory
diff --git a/plugins/am-project/am-project.c b/plugins/am-project/am-project.c
index 3ad80eb..7010c82 100644
--- a/plugins/am-project/am-project.c
+++ b/plugins/am-project/am-project.c
@@ -3284,6 +3284,23 @@ iproject_save_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **error
 }
 
 static AnjutaProjectNode *
+iproject_new_node (IAnjutaProject *obj, AnjutaProjectNode *parent, AnjutaProjectNodeType type, GFile *file, const gchar *name, GError **err)
+{
+	AnjutaProjectNode *node;
+	
+	node = project_node_new (AMP_PROJECT (obj), ANJUTA_PROJECT_ROOT, file, name);
+	node->parent = parent;
+	
+	return node;
+}
+
+static AnjutaProjectNode *
+iproject_free_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err)
+{
+	project_node_destroy (AMP_PROJECT (obj), node);
+}
+
+static AnjutaProjectNode *
 iproject_new_root_node (IAnjutaProject *obj, GFile *file, GError **err)
 {
 	return project_node_new (AMP_PROJECT (obj), ANJUTA_PROJECT_ROOT, file, NULL);
@@ -3358,6 +3375,8 @@ iproject_iface_init(IAnjutaProjectIface* iface)
 	iface->configure_node = iproject_configure_node;
 	iface->load_node = iproject_load_node;
 	iface->save_node = iproject_save_node;
+	iface->new_node = iproject_new_node;
+	iface->free_node = iproject_free_node;
 	iface->new_root_node = iproject_new_root_node;
 	iface->add_file_node = iproject_add_file_node;
 	iface->add_name_node = iproject_add_name_node;
diff --git a/plugins/dir-project/dir-project.c b/plugins/dir-project/dir-project.c
index 847117b..29c46d9 100644
--- a/plugins/dir-project/dir-project.c
+++ b/plugins/dir-project/dir-project.c
@@ -76,6 +76,8 @@ typedef struct _DirGroupData DirGroupData;
 
 struct _DirGroupData {
 	AnjutaProjectNodeData base;
+	GFileMonitor *monitor;
+	GObject *emitter;
 };
 
 typedef struct _DirTargetData DirTargetData;
@@ -135,109 +137,27 @@ static GObject *parent_class;
 /* Helper functions
  *---------------------------------------------------------------------------*/
 
-/*
- * File monitoring support --------------------------------
- * FIXME: review these
- */
 static void
-monitor_cb (GFileMonitor *monitor,
+on_file_changed (GFileMonitor *monitor,
 			GFile *file,
 			GFile *other_file,
 			GFileMonitorEvent event_type,
 			gpointer data)
 {
-	DirProject *project = data;
-
-	g_return_if_fail (project != NULL && DIR_IS_PROJECT (project));
+	AnjutaProjectNode *node = data;
 
+	g_message ("on_file_changed %s type %d emitter %p node %p proxy %d", g_file_get_path (file), event_type, DIR_GROUP_DATA (node)->emitter, node, NODE_DATA (node)->type & ANJUTA_PROJECT_PROXY);
 	switch (event_type) {
 		case G_FILE_MONITOR_EVENT_CHANGED:
 		case G_FILE_MONITOR_EVENT_DELETED:
-			/* monitor will be removed here... is this safe? */
-			//dir_project_reload (project, NULL);
-			g_signal_emit_by_name (G_OBJECT (project), "project-updated");
+		case G_FILE_MONITOR_EVENT_CREATED:
+			g_signal_emit_by_name (DIR_GROUP_DATA (node)->emitter, "node-updated", node);
 			break;
 		default:
 			break;
 	}
 }
 
-
-static void
-monitor_add (DirProject *project, GFile *file)
-{
-	GFileMonitor *monitor = NULL;
-	
-	g_return_if_fail (project != NULL);
-	g_return_if_fail (project->monitors != NULL);
-	
-	if (file == NULL)
-		return;
-	
-	monitor = g_hash_table_lookup (project->monitors, file);
-	if (!monitor) {
-		gboolean exists;
-		
-		/* FIXME clarify if uri is uri, path or both */
-		exists = g_file_query_exists (file, NULL);
-		
-		if (exists) {
-			monitor = g_file_monitor_file (file, 
-						       G_FILE_MONITOR_NONE,
-						       NULL,
-						       NULL);
-			if (monitor != NULL)
-			{
-				g_signal_connect (G_OBJECT (monitor),
-						  "changed",
-						  G_CALLBACK (monitor_cb),
-						  project);
-				g_hash_table_insert (project->monitors,
-						     g_object_ref (file),
-						     monitor);
-			}
-		}
-	}
-}
-
-static void
-monitors_remove (DirProject *project)
-{
-	g_return_if_fail (project != NULL);
-
-	if (project->monitors)
-		g_hash_table_destroy (project->monitors);
-	project->monitors = NULL;
-}
-
-static void
-group_hash_foreach_monitor (gpointer key,
-			    gpointer value,
-			    gpointer user_data)
-{
-	DirGroup *group_node = value;
-	DirProject *project = user_data;
-
-	monitor_add (project, DIR_GROUP_DATA(group_node)->base.file);
-}
-
-static void
-monitors_setup (DirProject *project)
-{
-	g_return_if_fail (project != NULL);
-
-	monitors_remove (project);
-	
-	/* setup monitors hash */
-	project->monitors = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
-						   (GDestroyNotify) g_file_monitor_cancel);
-
-	monitor_add (project, project->root_file);
-	
-	if (project->groups)
-		g_hash_table_foreach (project->groups, group_hash_foreach_monitor, project);
-}
-
 /* Root objects
  *---------------------------------------------------------------------------*/
 
@@ -272,9 +192,10 @@ dir_root_free (AnjutaProjectNode *node)
  *---------------------------------------------------------------------------*/
 
 static DirGroup*
-dir_group_new (GFile *file)
+dir_group_new (GFile *file, GObject *emitter)
 {
     DirGroupData *group = NULL;
+	DirGroup *node;
 
 	g_return_val_if_fail (file != NULL, NULL);
 	
@@ -283,8 +204,24 @@ dir_group_new (GFile *file)
 	group->base.file = g_object_ref (file);
 	group->base.state = ANJUTA_PROJECT_CAN_ADD_GROUP |
 						ANJUTA_PROJECT_CAN_REMOVE;
+	
+	group->emitter = emitter;
+	
+	node = g_node_new (group);
+
+	/* Connect monitor if file exist */
+	if (g_file_query_exists (file, NULL))
+	{
+		group->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
+
+		g_signal_connect (G_OBJECT (group->monitor),
+							"changed",
+							G_CALLBACK (on_file_changed),
+							node);
+	}
+	g_message ("new group %p monitor %p", node, group->monitor);
 
-    return g_node_new (group);
+	return node;
 }
 
 static void
@@ -292,8 +229,10 @@ dir_group_free (DirGroup *node)
 {
     DirGroupData *group = (DirGroupData *)node->data;
 	
+	if (group->monitor != NULL) g_file_monitor_cancel (group->monitor);
 	if (group->base.file) g_object_unref (group->base.file);
     g_slice_free (DirGroupData, group);
+	g_message ("free group %p monitor %p", node, group->monitor);
 
 	g_node_destroy (node);
 }
@@ -380,13 +319,33 @@ project_node_destroy (DirProject *project, AnjutaProjectNode *g_node)
 }
 
 static AnjutaProjectNode *
-project_node_new (DirProject *project, AnjutaProjectNodeType type, GFile *file, const gchar *name)
+project_node_new (DirProject *project, AnjutaProjectNode *parent, AnjutaProjectNodeType type, GFile *file, const gchar *name, GError **error)
 {
 	AnjutaProjectNode *node = NULL;
 	
 	switch (type & ANJUTA_PROJECT_TYPE_MASK) {
 		case ANJUTA_PROJECT_GROUP:
-			node = dir_group_new (file);
+			if (file == NULL)
+			{
+				if (name == NULL)
+				{
+					g_set_error (error, IANJUTA_PROJECT_ERROR, 
+							IANJUTA_PROJECT_ERROR_VALIDATION_FAILED,
+							_("Missing name"));
+				}
+				else
+				{
+					GFile *group_file;
+					
+					group_file = g_file_get_child (anjuta_project_node_get_file (parent), name);
+					node = dir_group_new (group_file, G_OBJECT (project));
+					g_object_unref (group_file);
+				}
+			}
+			else
+			{
+				node = dir_group_new (file, G_OBJECT (project));
+			}
 			break;
 		case ANJUTA_PROJECT_SOURCE:
 			node = dir_source_new (file);
@@ -682,8 +641,11 @@ dir_pattern_stack_is_match (GList *stack, GFile *file)
 	return match;
 }
 
-static gboolean
-dir_project_list_directory (DirProject *project, DirGroup* parent, GError **error) 
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+static AnjutaProjectNode *
+dir_project_load_directory (DirProject *project, AnjutaProjectNode *parent, GError **error)
 {
 	gboolean ok;
 	GFileEnumerator *enumerator;
@@ -716,18 +678,18 @@ dir_project_list_directory (DirProject *project, DirGroup* parent, GError **erro
 				/* Create a group for directory */
 				DirGroup *group;
 				
-				group = project_node_new (project, ANJUTA_PROJECT_GROUP, file, NULL);
+				group = project_node_new (project, NULL, ANJUTA_PROJECT_GROUP, file, NULL, NULL);
 				g_hash_table_insert (project->groups, g_file_get_uri (file), group);
 				anjuta_project_node_append (parent, group);
-				ok = dir_project_list_directory (project, group, error);
-				if (!ok) break;
+				group = dir_project_load_directory (project, group, error);
+				if (group == NULL) break;
 			}
 			else
 			{
 				/* Create a source for files */
 				DirSource *source;
 
-				source = project_node_new (project, ANJUTA_PROJECT_SOURCE, file, NULL);
+				source = project_node_new (project, NULL, ANJUTA_PROJECT_SOURCE, file, NULL, NULL);
 				anjuta_project_node_append (parent, source);
 			}
 		}
@@ -735,12 +697,9 @@ dir_project_list_directory (DirProject *project, DirGroup* parent, GError **erro
         g_object_unref (enumerator);
 	}
 
-	return ok;
+	return parent;
 }
-
-/* Public functions
- *---------------------------------------------------------------------------*/
-
+ 
 static AnjutaProjectNode *
 dir_project_load_root (DirProject *project, AnjutaProjectNode *node, GError **error) 
 {
@@ -765,7 +724,7 @@ dir_project_load_root (DirProject *project, AnjutaProjectNode *node, GError **er
 		return NULL;
 	}
 
-	group = project_node_new (project, ANJUTA_PROJECT_GROUP, root_file, NULL);
+	group = project_node_new (project, NULL, ANJUTA_PROJECT_GROUP, root_file, NULL, NULL);
 	anjuta_project_node_append (node, group);
 	g_hash_table_insert (project->groups, g_file_get_uri (root_file), group);
 
@@ -774,9 +733,7 @@ dir_project_load_root (DirProject *project, AnjutaProjectNode *node, GError **er
 	project->sources = dir_push_pattern_list (NULL, g_object_ref (root_file), source_file, FALSE, NULL);
 	g_object_unref (source_file);
 	
-	dir_project_list_directory (project, group, NULL);
-	
-	monitors_setup (project);
+	dir_project_load_directory (project, group, NULL);
 
 	return node;
 }
@@ -788,11 +745,40 @@ dir_project_load_node (DirProject *project, AnjutaProjectNode *node, GError **er
 	{
 	case ANJUTA_PROJECT_ROOT:
 		return dir_project_load_root (project, node, error);
+	case ANJUTA_PROJECT_GROUP:
+		return dir_project_load_directory (project, node, error);
 	default:
 		return NULL;
 	}
 }
 
+static void
+foreach_node_save (AnjutaProjectNode *node,
+					gpointer  data)
+{
+	gint type = anjuta_project_node_get_full_type (node);
+	
+	if (type & ANJUTA_PROJECT_MODIFIED)
+	{
+		switch (anjuta_project_node_get_type (node))
+		{
+		case ANJUTA_PROJECT_GROUP:
+			g_file_make_directory_with_parents (anjuta_project_node_get_file (node), NULL, NULL);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+AnjutaProjectNode *
+dir_project_save_node (DirProject *project, AnjutaProjectNode *node, GError **error)
+{
+	anjuta_project_node_all_foreach (node, foreach_node_save, project);
+	
+	return node;
+}
+
 gboolean
 dir_project_load (DirProject  *project,
     GFile *directory,
@@ -813,8 +799,6 @@ dir_project_load (DirProject  *project,
 void
 dir_project_unload (DirProject *project)
 {
-	monitors_remove (project);
-	
 	/* project data */
 	/*project_node_destroy (project, project->root_node);
 	project->root_node = NULL;*/
@@ -997,13 +981,29 @@ iproject_load_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err)
 static AnjutaProjectNode *
 iproject_save_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err)
 {
-	return NULL;
+	return dir_project_save_node (DIR_PROJECT (obj), node, err);
 }
 
 static AnjutaProjectNode *
-iproject_new_root_node (IAnjutaProject *obj, GFile *file, GError **err)
+iproject_new_node (IAnjutaProject *obj, AnjutaProjectNode *parent, AnjutaProjectNodeType type, GFile *file, const gchar *name, GError **error)
 {
-	return project_node_new (DIR_PROJECT (obj), ANJUTA_PROJECT_ROOT, file, NULL);
+	AnjutaProjectNode *node;
+	
+	node = project_node_new (DIR_PROJECT (obj), parent, type | ANJUTA_PROJECT_MODIFIED, file, name, error);
+
+	return node;
+}
+
+static void
+iproject_free_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err)
+{
+	project_node_destroy (DIR_PROJECT (obj), node);
+}
+
+static AnjutaProjectNode *
+iproject_new_root_node (IAnjutaProject *obj, GFile *file, GError **error)
+{
+	return project_node_new (DIR_PROJECT (obj), NULL, ANJUTA_PROJECT_ROOT, file, NULL, error);
 }
 
 static AnjutaProjectNode *
@@ -1025,7 +1025,7 @@ iproject_add_name_node (IAnjutaProject *obj, AnjutaProjectNode *parent, AnjutaPr
 		file = g_file_get_child (anjuta_project_node_get_file (parent), name);
 		if (g_file_make_directory (file, NULL, error))
 		{
-			node = project_node_new (DIR_PROJECT (obj), type, file, NULL);
+			node = project_node_new (DIR_PROJECT (obj), NULL, type, file, NULL, NULL);
 			anjuta_project_node_append (parent, node);
 		}
 		g_object_unref (file);
@@ -1081,6 +1081,11 @@ iproject_get_node_info (IAnjutaProject *obj, GError **err)
 static void
 iproject_iface_init(IAnjutaProjectIface* iface)
 {
+	iface->load_node = iproject_load_node;
+	iface->save_node = iproject_save_node;
+	iface->new_node = iproject_new_node;
+	iface->free_node = iproject_free_node;
+
 	iface->add_group = iproject_add_group;
 	iface->add_source = iproject_add_source;
 	iface->add_target = iproject_add_target;
@@ -1091,8 +1096,6 @@ iproject_iface_init(IAnjutaProjectIface* iface)
 	iface->get_target_types = iproject_get_target_types;
 	iface->load = iproject_load;
 	iface->refresh = iproject_refresh;
-	iface->load_node = iproject_load_node;
-	iface->save_node = iproject_save_node;
 	iface->new_root_node = iproject_new_root_node;
 	iface->add_file_node = iproject_add_file_node;
 	iface->add_name_node = iproject_add_name_node;
diff --git a/plugins/dir-project/dir-project.h b/plugins/dir-project/dir-project.h
index 12b0214..e82cf13 100644
--- a/plugins/dir-project/dir-project.h
+++ b/plugins/dir-project/dir-project.h
@@ -58,6 +58,7 @@ gint dir_project_probe (GFile *directory, GError     **error);
 
 gboolean dir_project_load (DirProject *project, GFile *directory, GError **error);
 AnjutaProjectNode *dir_project_load_node (DirProject *project, AnjutaProjectNode *node, GError **error);
+AnjutaProjectNode *dir_project_save_node (DirProject *project, AnjutaProjectNode *node, GError **error);
 gboolean dir_project_reload (DirProject *project, GError **error);
 void dir_project_unload (DirProject *project);
 
diff --git a/plugins/project-manager/plugin.c b/plugins/project-manager/plugin.c
index e76c3b2..580f2d7 100644
--- a/plugins/project-manager/plugin.c
+++ b/plugins/project-manager/plugin.c
@@ -1224,7 +1224,6 @@ on_project_updated (AnjutaPmProject *project, GError *error, ProjectManagerPlugi
 	gchar *dirname;
 
 	dirname = anjuta_util_get_local_path_from_uri (plugin->project_root_uri);
-	status = anjuta_shell_get_status (ANJUTA_PLUGIN (plugin)->shell, NULL);
 	if (error)
 	{
 		GtkWidget *toplevel;
@@ -1265,25 +1264,8 @@ on_project_updated (AnjutaPmProject *project, GError *error, ProjectManagerPlugi
 				}
 			}
 		}
-		gchar *basename = g_path_get_basename (dirname);
-		
-		anjuta_status_progress_tick (status, NULL, _("Update project viewâ?¦"));
-		update_ui (plugin);
-		anjuta_shell_present_widget (ANJUTA_PLUGIN (plugin)->shell,
-									plugin->scrolledwindow,
-									NULL);
-		anjuta_status_set_default (status, _("Project"), basename);
-		g_free (basename);
 	}
 	g_free (dirname);
-
-	if (plugin->busy)
-	{
-		anjuta_status_pop (status);
-		anjuta_status_busy_pop (status);
-		plugin->busy = FALSE;
-	}
-	
 }
 
 static void
diff --git a/plugins/project-manager/project.c b/plugins/project-manager/project.c
index 9f1fece..28fadd6 100644
--- a/plugins/project-manager/project.c
+++ b/plugins/project-manager/project.c
@@ -100,16 +100,23 @@ automatic reload.
 
 typedef enum
 {
-	LOAD,
-	UNLOAD,
+	LOAD = 0,
 	RELOAD,
-	RELOAD_NODE,
-	EXIT
+	ADD,
+	EXIT,
+	LAST_COMMAND
 } PmCommand;
 
 typedef struct _PmJob PmJob;
 
-typedef void (*PmJobCallback) (AnjutaPmProject *project, PmJob *job);
+typedef gboolean (*PmCommandFunc) (AnjutaPmProject *project, PmJob *job);
+
+typedef struct _PmCommandWork
+{
+	PmCommandFunc setup;
+	PmCommandFunc worker;
+	PmCommandFunc complete;
+} PmCommandWork;
 
 struct _PmJob
 {
@@ -117,7 +124,6 @@ struct _PmJob
 	GFile *file;
 	gchar *name;
 	AnjutaProjectNode *node;
-	PmJobCallback callback;
 	GError *error;
 	AnjutaProjectNode *proxy;
 	GHashTable *map;
@@ -135,78 +141,41 @@ enum
 
 static unsigned int signals[LAST_SIGNAL] = { 0 };
 
+/* Command functions
+ *---------------------------------------------------------------------------*/
+
+static PmCommandWork PmCommands[LAST_COMMAND];
+
+
+/* Forward declarations
+ *---------------------------------------------------------------------------*/
+
+static gboolean pm_project_idle_func (AnjutaPmProject *project);
+static gboolean pm_project_run_command (AnjutaPmProject *project);
+
 /* Job functions
  *---------------------------------------------------------------------------*/
 
 static PmJob *
-pm_job_new (PmCommand command, GFile *file, const gchar *name, AnjutaProjectNode *node, PmJobCallback callback)
+pm_job_new (PmCommand command, AnjutaProjectNode *node)
 {
 	PmJob *job;
 
 	job = g_new0 (PmJob, 1);
 	job->command = command;
-	job->file = file != NULL ? g_object_ref (file) : NULL;
-	job->name = name != NULL ? g_strdup (name) : NULL;
-	if (node != NULL)
-	{
-		job->node = node;
-		job->proxy = anjuta_project_proxy_new (node);
-		g_message ("node %p proxy %p", job->node, job->proxy);
-	}
-	job->callback = callback;
+	job->node = node;
 
 	return job;
 }
 
 static void
-pm_free_node (AnjutaProjectNode *node, IAnjutaProject *project)
+pm_job_free (PmJob *job)
 {
-	gint type = anjuta_project_node_get_full_type (node);
-	
-	if (type & ANJUTA_PROJECT_PROXY)
-	{
-		g_message ("free proxy %p", node);
-		anjuta_project_proxy_unref (node);
-	}
-	else
-	{
-		ianjuta_project_remove_node (project, node, NULL);
-	}
-}
-
-static void
-pm_job_free (PmJob *job, IAnjutaProject *project)
-{
-	if (job->file != NULL) g_object_unref (job->file);
-	if (job->name != NULL) g_free (job->name);
 	if (job->error != NULL) g_error_free (job->error);
-	if ((job->proxy != NULL) && (job->node != NULL))
-	{
-		g_message ("free proxy %p", job->node);
-		anjuta_project_node_all_foreach (job->node, (AnjutaProjectNodeFunc)pm_free_node, project);
-	}
 	if (job->map != NULL) g_hash_table_destroy (job->map);
 }
 
-static void
-pm_project_push_command (AnjutaPmProject *project, PmCommand command, GFile *file, const gchar *name, AnjutaProjectNode *node, PmJobCallback callback)
-{
-	PmJob *job;
-
-	job = pm_job_new (command, file, name, node, callback);
-
-	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
+/* Worker thread functions
  *---------------------------------------------------------------------------*/
 
 static gint
@@ -244,7 +213,6 @@ pm_project_map_children (PmJob *job, AnjutaProjectNode *old_node, AnjutaProjectN
 		GList *same;
 
 		same = g_list_find_custom (children, old_node, (GCompareFunc)pm_project_compare_node);
-		g_message ("find %p get %p", old_node, same->data);
 		
 		if (same != NULL)
 		{
@@ -280,98 +248,74 @@ pm_project_map_node (PmJob *job)
 		}
 	}
 }
- 
-static gpointer
-pm_project_thread_main_loop (AnjutaPmProject *project)
+
+static gboolean
+pm_command_load_work (AnjutaPmProject *project, PmJob *job)
 {
-	PmJob *job;
+	AnjutaProjectNode *node;
 	
-	for (;;)
+	g_message ("thread load node %p", job->proxy);
+	node = ianjuta_project_load_node (project->project, job->proxy, &(job->error));
+	g_message ("thread load node complete");
+	if (job->error == NULL)
 	{
-		AnjutaProjectNode *root;
-		AnjutaProjectNode *node;
-		
-		job = (PmJob *)g_async_queue_pop (project->work_queue);
-
-		switch (job->command)
-		{
-		case LOAD:
-			root = ianjuta_project_new_root_node (project->project, job->file, NULL);
-			node = ianjuta_project_load_node (project->project, root, &(job->error));
-			g_message ("load get root %p node %p, error %p", root, node, job->error);
-			if (job->error == NULL)
-			{
-				job->node = node;
-			}
-			else
-			{
-				ianjuta_project_remove_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 RELOAD_NODE:
-			g_message ("thread load node %p", job->proxy);
-			node = ianjuta_project_load_node (project->project, job->proxy, &(job->error));
-			g_message ("thread load node complete");
-			if (job->error == NULL)
-			{
-				pm_project_map_node (job);
-			}
-			/*if (job->error == NULL)
-			{
-				job->node = node;
-			}*/
-			break;
-		case EXIT:
-			do
-			{
-				pm_job_free (job, project->project);
-				job = (PmJob *)g_async_queue_try_pop (project->done_queue);
-			}
-			while (job != NULL);
-			return NULL;
-		default:
-			break;
-		}
-		g_async_queue_push (project->done_queue, job);
+		pm_project_map_node (job);
 	}
+	
+	return TRUE;
 }
 
 static gboolean
-pm_project_idle_func (AnjutaPmProject *project)
+pm_command_add_work (AnjutaPmProject *project, PmJob *job)
 {
-	PmJob *job;
+	AnjutaProjectNode *node;
+	
+	node = ianjuta_project_save_node (project->project, job->node, &(job->error));
+	
+	return TRUE;
+}
 
+static gboolean
+pm_command_exit_work (AnjutaPmProject *project, PmJob *job)
+{
+	g_return_val_if_fail (job != NULL, FALSE);
+	g_return_val_if_fail (job->node != NULL, FALSE);
+
+	/* Push job in complete queue as g_thread_exit will stop the thread
+	 * immediatly */
+	g_async_queue_push (project->done_queue, job);
+	g_thread_exit (0);
+	
+	return TRUE;
+}
+
+/* Run work function in worker thread */
+static gpointer
+pm_project_thread_main_loop (AnjutaPmProject *project)
+{
 	for (;;)
 	{
-		job = (PmJob *)g_async_queue_try_pop (project->done_queue);
-
-		if (job == NULL) return TRUE;
+		PmJob *job;
+		PmCommandFunc func;
+		
+		/* Get new job */
+		job = (PmJob *)g_async_queue_pop (project->work_queue);
 
-		if (job->callback != NULL)
-		{
-			job->callback (project, job);
-		}
-		pm_job_free (job, project->project);
-		project->busy--;
-		if (project->busy == 0)
+		/* Get work function and call it if possible */
+		func = PmCommands[job->command].worker;
+		if (func != NULL)
 		{
-			job = g_queue_pop_head (project->job_queue);
-			if (job != NULL)
-		    {
-				project->busy = 1;
-				g_async_queue_push (project->work_queue, job);
-			}
+			func (project, job);
 		}
+		
+		/* Push completed job in queue */
+		g_async_queue_push (project->done_queue, job);
 	}
 }
 
+/* Main thread functions
+ *---------------------------------------------------------------------------*/
+
 static gboolean
 pm_project_start_thread (AnjutaPmProject *project, GError **error)
 {
@@ -414,7 +358,7 @@ pm_project_stop_thread (AnjutaPmProject *project)
 		project->idle_func = 0;
 
 		// Request to terminate thread
-		job = pm_job_new (EXIT, NULL, NULL, NULL, NULL);
+		job = pm_job_new (EXIT, NULL);
 		g_async_queue_push (project->work_queue, job);
 		g_thread_join (project->worker);
 		project->worker = NULL;
@@ -429,7 +373,7 @@ pm_project_stop_thread (AnjutaPmProject *project)
 		{
 			job = g_async_queue_try_pop (project->done_queue);
 			if (job == NULL) break;
-			pm_job_free (job, project->project);
+			pm_job_free (job);
 		}
 		project->done_queue = NULL;
 	}
@@ -437,13 +381,59 @@ pm_project_stop_thread (AnjutaPmProject *project)
 	return TRUE;
 }
 
-/* Public functions
- *---------------------------------------------------------------------------*/
+static void
+pm_free_node (AnjutaProjectNode *node, IAnjutaProject *project)
+{
+	gint type = anjuta_project_node_get_full_type (node);
+	
+	if (type & ANJUTA_PROJECT_PROXY)
+	{
+		g_message ("free proxy %p", node);
+		anjuta_project_proxy_unref (node);
+	}
+	else
+	{
+		ianjuta_project_free_node (project, node, NULL);
+	}
+}
 
-static void on_pm_project_load_incomplete (AnjutaProjectNode *node, AnjutaPmProject *project);
+static void
+pm_project_push_command (AnjutaPmProject *project, PmCommand command, AnjutaProjectNode *node)
+{
+	PmJob *job;
+
+	job = pm_job_new (command, node);
+	g_queue_push_tail (project->job_queue, job);
+	
+	pm_project_run_command (project);
+}
 
 static void
-on_pm_project_reloaded_node (AnjutaPmProject *project, PmJob *job)
+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))
+	{
+		project->incomplete_node++;
+		anjuta_project_node_set_state (node, ANJUTA_PROJECT_LOADING);
+		pm_project_push_command (project, RELOAD, node);
+	}
+}
+
+static gboolean
+pm_command_load_setup (AnjutaPmProject *project, PmJob *job)
+{
+	g_return_val_if_fail (job != NULL, FALSE);
+	g_return_val_if_fail (job->node != NULL, FALSE);
+	
+	job->proxy = anjuta_project_proxy_new (job->node);
+	
+	return TRUE;
+}
+
+static gboolean
+pm_command_load_complete (AnjutaPmProject *project, PmJob *job)
 {
 	if (job->error != NULL)
 	{
@@ -456,15 +446,11 @@ on_pm_project_reloaded_node (AnjutaPmProject *project, PmJob *job)
 	else
 	{
 		g_message ("reloaded node");
-		//g_object_set (G_OBJECT (project->model), "project", project, NULL);
-		// Check for incompletely loaded object and load them
-		if (anjuta_project_node_get_state (job->proxy) & ANJUTA_PROJECT_INCOMPLETE)
+		if (job->command == LOAD)
 		{
-			project->incomplete_node--;
-			g_message ("remaining node %d", project->incomplete_node);
+			g_object_set (G_OBJECT (project->model), "project", project, NULL);
+			project->incomplete_node = 0;
 		}
-		anjuta_project_node_clear_state (job->proxy, ANJUTA_PROJECT_LOADING | ANJUTA_PROJECT_INCOMPLETE);
-		anjuta_project_node_all_foreach (job->proxy, (AnjutaProjectNodeFunc)on_pm_project_load_incomplete, project);
 		
 		if (project->root == job->node)
 		{
@@ -483,88 +469,145 @@ on_pm_project_reloaded_node (AnjutaPmProject *project, PmJob *job)
 		}
 		
 		
-		if (project->incomplete_node == 0)
+		// Check for incompletely loaded object and load them
+		if (anjuta_project_node_get_state (job->proxy) & ANJUTA_PROJECT_INCOMPLETE)
 		{
-			g_signal_emit (G_OBJECT (project), signals[LOADED], 0, NULL);
+			project->incomplete_node--;
+			g_message ("remaining node %d", project->incomplete_node);
 		}
-	}
-}
-
-static void
-on_pm_project_reloaded (AnjutaPmProject *project, PmJob *job)
-{
-	if (job->error != NULL)
-	{
-		g_warning ("unable to load node");
-		pm_project_stop_thread (project);
-		g_object_unref (project->project);
-		project->project = NULL;
-		g_signal_emit (G_OBJECT (project), signals[LOADED], 0, job->error);
-	}
-	else
-	{
-#if 0
-		//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);
-		g_message ("remaining node %d", project->incomplete_node);
-		project->incomplete_node--;
-		anjuta_project_node_all_foreach (job->node, (AnjutaProjectNodeFunc)on_pm_project_load_incomplete, project);
-		//g_signal_emit (G_OBJECT (project), signals[UPDATED], 0, job->error);
-		gbf_project_model_update_tree (project->model, NULL, NULL, NULL);
+		anjuta_project_node_clear_state (job->proxy, ANJUTA_PROJECT_LOADING | ANJUTA_PROJECT_INCOMPLETE);
+		anjuta_project_node_all_foreach (job->proxy, (AnjutaProjectNodeFunc)on_pm_project_load_incomplete, project);
 		
 		if (project->incomplete_node == 0)
 		{
-			g_signal_emit (G_OBJECT (project), signals[LOADED], 0, NULL);
+			g_signal_emit (G_OBJECT (project), signals[job->command == LOAD ? LOADED : UPDATED], 0, NULL);
 		}
-#endif
 	}
+	anjuta_project_node_all_foreach (job->node, (AnjutaProjectNodeFunc)pm_free_node, project->project);
+	
+	return TRUE;
 }
 
-static void
-on_pm_project_load_incomplete (AnjutaProjectNode *node, AnjutaPmProject *project)
+static gboolean
+pm_command_add_setup (AnjutaPmProject *project, PmJob *job)
 {
-	gint state = anjuta_project_node_get_state (node);
+	AnjutaProjectNode *parent;
 	
-	if ((state & ANJUTA_PROJECT_INCOMPLETE) && !(state & ANJUTA_PROJECT_LOADING))
+	g_return_val_if_fail (job != NULL, FALSE);
+	g_return_val_if_fail (job->node != NULL, FALSE);
+
+	/* Add new node in project tree.
+	 * It is safe to do it here because the worker thread is waiting */
+	parent = anjuta_project_node_parent (job->node);
+	g_message ("parent %p node name %s", parent, anjuta_project_node_get_name (job->node));
+	anjuta_project_node_insert_before (parent, NULL, job->node);
+	
+	return TRUE;
+}
+ 
+static PmCommandWork PmCommands[LAST_COMMAND] = {
+			{pm_command_load_setup,
+			pm_command_load_work,
+			pm_command_load_complete},
+			{pm_command_load_setup,
+			pm_command_load_work,
+			pm_command_load_complete},
+			{pm_command_add_setup,
+			pm_command_add_work,
+			NULL},
+			{NULL,
+			pm_command_exit_work,
+			NULL}};
+
+/* Run a command in job queue */
+static gboolean
+pm_project_run_command (AnjutaPmProject *project)
+{
+	gboolean running = TRUE;
+	
+	if (project->busy == 0)
 	{
-		project->incomplete_node++;
-		anjuta_project_node_set_state (node, ANJUTA_PROJECT_LOADING);
-		pm_project_push_command (project, RELOAD_NODE, NULL, NULL, node, on_pm_project_reloaded_node);
+		/* Worker thread is waiting for new command, check job queue */
+		PmJob *job;
+		
+		do
+		{
+			PmCommandFunc func;
+			
+			/* Get next command */
+			job = g_queue_pop_head (project->job_queue);
+			running = job != NULL;
+			if (!running) break;
+			
+			/* Get setup function and call it if possible */
+			func = PmCommands[job->command].setup;
+			if (func != NULL)
+			{
+				running = func (project, job);
+			}
+				
+			if (running)
+			{
+				/* Execute work function in the worker thread */
+				project->busy = 1;
+				
+				if (project->idle_func == 0)
+				{
+					project->idle_func = g_idle_add ((GSourceFunc) pm_project_idle_func, project);
+				}
+				g_async_queue_push (project->work_queue, job);
+			}
+			else
+			{
+				/* Discard command */
+				pm_job_free (job);
+			}
+		} while (!running);
 	}
+	
+	return running;
 }
 
-static void
-on_pm_project_loaded (AnjutaPmProject *project, PmJob *job)
+static gboolean
+pm_project_idle_func (AnjutaPmProject *project)
 {
-	if (job->error != NULL)
-	{
-		g_warning ("unable to load project");
-		/* Unable to load project, destroy project object */
-		pm_project_stop_thread (project);
-		g_object_unref (project->project);
-		project->project = NULL;
-		g_signal_emit (G_OBJECT (project), signals[LOADED], 0, job->error);
-	}
-	else
+	gboolean running;
+
+	for (;;)
 	{
-		g_message ("project loaded project root %p node %p", anjuta_pm_project_get_root (project), job->node);
-		g_message ("root child %d", g_node_n_children (job->node));
-		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, project->root, NULL, NULL);
+		PmCommandFunc func;
+		PmJob *job;
 		
-		// Check for incompletely loaded object and load them
-		project->incomplete_node = 0;
-		anjuta_project_node_all_foreach (job->node, (AnjutaProjectNodeFunc)on_pm_project_load_incomplete, project);
-		if (project->incomplete_node == 0)
+		/* Get completed command */
+		job = (PmJob *)g_async_queue_try_pop (project->done_queue);
+		if (job == NULL) break;
+
+		/* Get complete function and call it if possible */
+		func = PmCommands[job->command].complete;
+		if (func != NULL)
 		{
-			g_signal_emit (G_OBJECT (project), signals[LOADED], 0, NULL);
+			running = func (project, job);
 		}
+		pm_job_free (job);
+		project->busy--;
 	}
+	
+	running = pm_project_run_command (project);
+	if (!running) project->idle_func = 0;
+	
+	return running;
 }
 
+/* Public functions
+ *---------------------------------------------------------------------------*/
+
+static void
+on_node_updated (IAnjutaProject *sender, AnjutaProjectNode *node, AnjutaPmProject *project)
+{
+	g_message ("on node updated");
+	pm_project_push_command (project, RELOAD, node);
+}
+ 
 gboolean 
 anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
 {
@@ -647,16 +690,22 @@ anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
 	{
 		return FALSE;
 	}
-
-	pm_project_push_command (project, LOAD, file, NULL, NULL, on_pm_project_loaded);
-
+	g_message ("connect node-update %p", project->project);
+	g_signal_connect (G_OBJECT (project->project),
+						"node-updated",
+						G_CALLBACK (on_node_updated),
+						project);
+	
+	project->root = ianjuta_project_new_node (project->project, NULL, ANJUTA_PROJECT_ROOT, file, NULL, NULL);
+	pm_project_push_command (project, LOAD, project->root);
+	
 	return TRUE;
 }
 
-gboolean
+static gboolean
 anjuta_pm_project_reload_node (AnjutaPmProject *project, AnjutaProjectNode *node, GError **error)
 {
-	pm_project_push_command (project, RELOAD, NULL, NULL, node, on_pm_project_reloaded);
+	pm_project_push_command (project, RELOAD, node);
 
 	return TRUE;
 }
@@ -681,7 +730,8 @@ gboolean
 anjuta_pm_project_refresh (AnjutaPmProject *project, GError **error)
 {
 	g_message ("reload project");
-	pm_project_push_command (project, RELOAD_NODE, NULL, NULL, project->root, on_pm_project_reloaded_node);
+	
+	pm_project_push_command (project, RELOAD, project->root);
 
 	return TRUE;
 }
@@ -722,9 +772,14 @@ anjuta_pm_project_get_packages (AnjutaPmProject *project)
 AnjutaProjectNode *
 anjuta_pm_project_add_group (AnjutaPmProject *project, AnjutaProjectNode *group, const gchar *name, GError **error)
 {
+	AnjutaProjectNode *node;
+	
 	g_return_val_if_fail (project->project != NULL, NULL);
 	
-	return ianjuta_project_add_name_node (project->project, group, NULL, ANJUTA_PROJECT_GROUP, name, error);
+	node = ianjuta_project_new_node (project->project, group, ANJUTA_PROJECT_GROUP, NULL, name, error);
+	pm_project_push_command (project, ADD, node);
+
+	return node;
 }
 
 AnjutaProjectNode *



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