[anjuta/newproject] Implement new IAnjutaProject interface (with signals and without thread in pm)
- From: Sebastien Granjoux <sgranjoux src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [anjuta/newproject] Implement new IAnjutaProject interface (with signals and without thread in pm)
- Date: Sat, 23 Oct 2010 20:44:02 +0000 (UTC)
commit 2dd08a39f068e3202b3cdf74e3ca4e7b71c3800d
Author: Sébastien Granjoux <seb sfo free fr>
Date: Sat Oct 23 22:43:16 2010 +0200
Implement new IAnjutaProject interface (with signals and without thread in pm)
libanjuta/interfaces/libanjuta.idl | 36 ++-
plugins/am-project/am-node.c | 19 +
plugins/am-project/am-node.h | 1 +
plugins/am-project/am-project.c | 192 +++++++++-
plugins/project-manager/project-model.c | 93 ++---
plugins/project-manager/project-model.h | 6 +-
plugins/project-manager/project.c | 655 +++----------------------------
plugins/project-manager/project.h | 11 +-
8 files changed, 323 insertions(+), 690 deletions(-)
---
diff --git a/libanjuta/interfaces/libanjuta.idl b/libanjuta/interfaces/libanjuta.idl
index 2206856..e216c49 100644
--- a/libanjuta/interfaces/libanjuta.idl
+++ b/libanjuta/interfaces/libanjuta.idl
@@ -3097,15 +3097,47 @@ interface IAnjutaProject
/* Signals */
/**
- * IAnjutaProject::project_updated:
+ * IAnjutaProject::node_updated:
* @obj: Self
* @node: Updated node.
*
- * This signal is emitted when the project is changed.
+ * This signal is emitted when the project is changed on the disk.
*/
void ::node_updated (gpointer node);
/**
+ * IAnjutaProject::node_modified:
+ * @obj: Self
+ * @node: Modfied node.
+ * @error: Error while modifying node
+ *
+ * This signal is emitted when a node is modified (by a function of this
+ * interface) and return an eventual error.
+ */
+ void ::node_modified (gpointer node, GError *error);
+
+ /**
+ * IAnjutaProject::node_saved:
+ * @obj: Self
+ * @node: Saved node.
+ * @error: Error while saving node
+ *
+ * This signal is emitted when a node is saved and return an eventual error
+ */
+ void ::node_saved (gpointer node, GError *error);
+
+ /**
+ * IAnjutaProject::node_loaded:
+ * @obj: Self
+ * @node: Loaded node.
+ * @error: Error while loading node
+ *
+ * This signal is emitted when a node is loaded and return an eventual error
+ */
+ void ::node_loaded (gpointer node, GError *error);
+
+
+ /**
* ianjuta_project_load_node:
* @obj: Self
* @node: Project node to reload
diff --git a/plugins/am-project/am-node.c b/plugins/am-project/am-node.c
index 3582b3c..cba3b3b 100644
--- a/plugins/am-project/am-node.c
+++ b/plugins/am-project/am-node.c
@@ -574,6 +574,25 @@ amp_group_get_makefile_name (AnjutaAmGroupNode *group)
return basename;
}
+void
+amp_group_update_monitor (AnjutaAmGroupNode *group)
+{
+ if (group->monitor != NULL) g_object_unref (group->monitor);
+
+ group->monitor = g_file_monitor_file (group->makefile,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ NULL);
+ if (group->monitor != NULL)
+ {
+ g_signal_connect (G_OBJECT (group->monitor),
+ "changed",
+ G_CALLBACK (on_group_monitor_changed),
+ group);
+ }
+
+}
+
AnjutaAmGroupNode*
amp_group_new (GFile *file, gboolean dist_only, GError **error)
{
diff --git a/plugins/am-project/am-node.h b/plugins/am-project/am-node.h
index 7964ce9..fad9541 100644
--- a/plugins/am-project/am-node.h
+++ b/plugins/am-project/am-node.h
@@ -65,6 +65,7 @@ AnjutaTokenFile* amp_group_set_makefile (AnjutaAmGroupNode *group, GFile *makefi
AnjutaToken* amp_group_get_makefile_token (AnjutaAmGroupNode *group);
gchar *amp_group_get_makefile_name (AnjutaAmGroupNode *group);
gboolean amp_group_update_makefile (AnjutaAmGroupNode *group, AnjutaToken *token);
+void amp_group_update_monitor (AnjutaAmGroupNode *node);
AnjutaAmGroupNode* amp_group_new (GFile *file, gboolean dist_only, GError **error);
void amp_group_free (AnjutaAmGroupNode *node);
diff --git a/plugins/am-project/am-project.c b/plugins/am-project/am-project.c
index 17780b7..baf2d6b 100644
--- a/plugins/am-project/am-project.c
+++ b/plugins/am-project/am-project.c
@@ -551,7 +551,7 @@ monitor_cb (GFileMonitor *monitor,
/* monitor will be removed here... is this safe? */
//amp_project_reload (project, NULL);
g_message ("project updated");
- g_signal_emit_by_name (G_OBJECT (project), "project-updated");
+ g_signal_emit_by_name (G_OBJECT (project), "node-updated");
break;
default:
break;
@@ -1438,6 +1438,161 @@ amp_project_set_am_variable (AmpProject* project, AnjutaAmGroupNode* group, Anju
}
}
+/* Map function
+ *---------------------------------------------------------------------------*/
+
+static gint
+amp_project_compare_node (AnjutaProjectNode *old_node, AnjutaProjectNode *new_node)
+{
+ gchar *name1;
+ gchar *name2;
+ GFile *file1;
+ GFile *file2;
+
+ name1 = anjuta_project_node_get_name (old_node);
+ name2 = anjuta_project_node_get_name (new_node);
+ file1 = anjuta_project_node_get_file (old_node);
+ file2 = anjuta_project_node_get_file (new_node);
+
+ return (anjuta_project_node_get_node_type (old_node) == anjuta_project_node_get_node_type (new_node))
+ && ((name1 == NULL) || (name2 == NULL) || (strcmp (name1, name2) == 0))
+ && ((file1 == NULL) || (file2 == NULL) || g_file_equal (file1, file2)) ? 0 : 1;
+}
+
+static void
+amp_project_map_children (GHashTable *map, AnjutaProjectNode *old_node, AnjutaProjectNode *new_node)
+{
+ GList *children = NULL;
+
+ if (new_node != NULL)
+ {
+ for (new_node = anjuta_project_node_first_child (new_node); new_node != NULL; new_node = anjuta_project_node_next_sibling (new_node))
+ {
+ children = g_list_prepend (children, new_node);
+ }
+ children = g_list_reverse (children);
+ }
+
+ for (old_node = anjuta_project_node_first_child (old_node); old_node != NULL; old_node = anjuta_project_node_next_sibling (old_node))
+ {
+ GList *same;
+
+ same = g_list_find_custom (children, old_node, (GCompareFunc)amp_project_compare_node);
+
+ if (same != NULL)
+ {
+ g_hash_table_insert (map, (AnjutaProjectNode *)same->data, old_node);
+
+ amp_project_map_children (map, old_node, (AnjutaProjectNode *)same->data);
+ children = g_list_delete_link (children, same);
+ }
+ else
+ {
+ /* Mark deleted node */
+ g_hash_table_insert (map, old_node, NULL);
+ }
+ }
+
+ /* Add remaining node in hash table */
+ for (; children != NULL; children = g_list_delete_link (children, children))
+ {
+ g_hash_table_insert (map, children->data, children->data);
+ }
+}
+
+static GHashTable *
+amp_project_map_node (AnjutaProjectNode *old_node, AnjutaProjectNode *new_node)
+{
+ GHashTable *map;
+
+ map = g_hash_table_new (g_direct_hash, NULL);
+
+ g_hash_table_insert (map, new_node, old_node);
+
+ amp_project_map_children (map, old_node, new_node);
+
+ return map;
+}
+
+
+static void
+amp_project_replace_node (AnjutaProjectNode *new_node, AnjutaProjectNode *old_node, GHashTable *map)
+{
+ if (old_node == NULL)
+ {
+ /* Delete old node */
+ g_object_unref (old_node);
+ }
+ else
+ {
+ if (old_node != new_node)
+ {
+ GTypeQuery type_info;
+ gchar *data;
+
+ g_type_query (G_TYPE_FROM_INSTANCE (old_node), &type_info);
+
+ /* Swap new and old node */
+ data = g_new0 (gchar, type_info.instance_size - sizeof (GInitiallyUnowned));
+ memcpy (data, (gchar *)old_node + sizeof (GInitiallyUnowned), type_info.instance_size - sizeof (GInitiallyUnowned));
+ memcpy ((gchar *)old_node + sizeof (GInitiallyUnowned), (gchar *)new_node + sizeof (GInitiallyUnowned), type_info.instance_size - sizeof (GInitiallyUnowned));
+ memcpy ((gchar *)new_node + sizeof (GInitiallyUnowned), data, type_info.instance_size - sizeof (GInitiallyUnowned));
+ g_free (data);
+
+ /* Update file monitor if it is a group */
+ if (anjuta_project_node_get_node_type (old_node) == ANJUTA_PROJECT_GROUP)
+ {
+ amp_group_update_monitor (old_node);
+ }
+
+ /* Get old file */
+ if (old_node->file != NULL) g_object_unref (old_node->file);
+ old_node->file = new_node->file;
+ new_node->file = NULL;
+
+ /* Unlink old node and free it */
+ new_node->parent = NULL;
+ new_node->children = NULL;
+ new_node->next = NULL;
+ new_node->prev = NULL;
+ g_object_unref (new_node);
+
+ new_node = old_node;
+ }
+
+ /* Update links */
+ old_node = g_hash_table_lookup (map, new_node->parent);
+ if (old_node != NULL) new_node->parent = old_node;
+ old_node = g_hash_table_lookup (map, new_node->children);
+ if (old_node != NULL) new_node->children = old_node;
+ old_node = g_hash_table_lookup (map, new_node->next);
+ if (old_node != NULL) new_node->next = old_node;
+ old_node = g_hash_table_lookup (map, new_node->prev);
+ if (old_node != NULL) new_node->prev = old_node;
+ }
+}
+
+static AnjutaProjectNode *
+amp_project_duplicate_node (AnjutaProjectNode *old_node)
+{
+ AnjutaProjectNode *new_node;
+ GTypeQuery type_info;
+ gchar *data;
+
+ /* Create new node */
+ new_node = g_object_new (G_TYPE_FROM_INSTANCE (old_node), NULL);
+ g_type_query (G_TYPE_FROM_INSTANCE (old_node), &type_info);
+ memcpy ((gchar *)new_node + sizeof (GInitiallyUnowned), (gchar *)old_node + sizeof (GInitiallyUnowned), type_info.instance_size - sizeof (GInitiallyUnowned));
+ new_node->custom_properties = NULL;
+ new_node->file = g_file_dup (new_node->file);
+ new_node->name = g_strdup (new_node->name);
+ new_node->children = NULL;
+
+ /* Remove loaded node specific data */
+ memset ((gchar *)old_node + sizeof (AnjutaProjectNode), 0, type_info.instance_size - sizeof (AnjutaProjectNode));
+
+ return new_node;
+}
/* Public functions
*---------------------------------------------------------------------------*/
@@ -2116,25 +2271,43 @@ amp_project_add_file (AmpProject *project, GFile *file, AnjutaTokenFile* token)
/* Implement IAnjutaProject
*---------------------------------------------------------------------------*/
+
static gboolean
-iproject_load_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err)
+iproject_load_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **error)
{
+ AnjutaProjectNode *new_node;
+ AnjutaProjectNode *proxy;
+ GHashTable *map;
+ GError *err = NULL;
+
if (node == NULL) node = AMP_PROJECT (obj)->root;
+
+ proxy = amp_project_duplicate_node (node);
- node = amp_project_load_node (AMP_PROJECT (obj), node, err);
+ new_node = amp_project_load_node (AMP_PROJECT (obj), proxy, &err);
+ map = amp_project_map_node (node, new_node);
+ g_hash_table_foreach (map, (GHFunc)amp_project_replace_node, map);
+ node->parent = new_node->parent;
+ proxy->parent = NULL;
+ g_hash_table_destroy (map);
+ g_object_unref (proxy);
+ g_signal_emit_by_name (obj, "node-loaded", node, err);
+ g_error_free (err);
- return node != NULL;
+ return new_node != NULL;
}
static gboolean
iproject_save_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **error)
{
+ GError *err = NULL;
+
if (node == NULL) node = AMP_PROJECT (obj)->root;
switch (anjuta_project_node_get_node_type (node))
{
case ANJUTA_PROJECT_ROOT:
- if (!amp_project_save (AMP_PROJECT (obj), error))
+ if (!amp_project_save (AMP_PROJECT (obj), &err))
{
node = NULL;
}
@@ -2143,6 +2316,8 @@ iproject_save_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **error
node = project_node_save (AMP_PROJECT (obj), node, error);
break;
}
+ g_signal_emit_by_name (obj, "node-saved", node, err);
+ g_error_free (err);
return node != NULL;
}
@@ -2181,6 +2356,7 @@ iproject_add_node_before (IAnjutaProject *obj, AnjutaProjectNode *parent, Anjuta
anjuta_project_node_insert_before (parent, sibling, node);
break;
}
+ g_signal_emit_by_name (obj, "node-modified", node, NULL);
return node;
}
@@ -2219,6 +2395,7 @@ iproject_add_node_after (IAnjutaProject *obj, AnjutaProjectNode *parent, AnjutaP
anjuta_project_node_insert_after (parent, sibling, node);
break;
}
+ g_signal_emit_by_name (obj, "node-modified", node, NULL);
return node;
}
@@ -2244,6 +2421,7 @@ iproject_remove_node (IAnjutaProject *obj, AnjutaProjectNode *node, GError **err
default:
break;
}
+ g_signal_emit_by_name (obj, "node-modified", node, NULL);
return TRUE;
}
@@ -2266,6 +2444,7 @@ iproject_set_property (IAnjutaProject *obj, AnjutaProjectNode *node, AnjutaProje
{
amp_project_update_am_property (AMP_PROJECT (obj), node, new_prop);
}
+ g_signal_emit_by_name (obj, "node-modified", node, NULL);
return new_prop;
}
@@ -2277,6 +2456,7 @@ iproject_remove_property (IAnjutaProject *obj, AnjutaProjectNode *node, AnjutaPr
old_prop = anjuta_project_node_remove_property (node, property);
amp_property_free (old_prop);
+ g_signal_emit_by_name (obj, "node-modified", node, NULL);
return TRUE;
}
diff --git a/plugins/project-manager/project-model.c b/plugins/project-manager/project-model.c
index 65aff24..ea9c058 100644
--- a/plugins/project-manager/project-model.c
+++ b/plugins/project-manager/project-model.c
@@ -339,7 +339,7 @@ gbf_project_model_remove_invalid_shortcut (GbfProjectModel *model, GtkTreeIter *
else
{
gbf_project_model_remove_invalid_shortcut (model, &child);
- valid = gtk_tree_model_iter_next (model, &child);
+ valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
}
}
@@ -726,9 +726,7 @@ add_root (GbfProjectModel *model,
AnjutaProjectNode *root,
GtkTreeIter *parent)
{
- GtkTreeIter iter;
AnjutaProjectNode *node;
- GtkTreePath *root_path;
if ((!root) || (anjuta_project_node_get_node_type (root) != ANJUTA_PROJECT_ROOT))
return;
@@ -750,7 +748,7 @@ add_root (GbfProjectModel *model,
static void
project_updated_cb (IAnjutaProject *project, GbfProjectModel *model)
{
- gbf_project_model_update_tree (model, NULL, NULL, NULL);
+ gbf_project_model_update_tree (model, NULL, NULL);
}
static void
@@ -844,14 +842,14 @@ recursive_find_tree_data (GtkTreeModel *model,
}
void
-gbf_project_model_update_shortcut (GbfProjectModel *model, GtkTreeIter *iter, GHashTable *map)
+gbf_project_model_update_shortcut (GbfProjectModel *model, AnjutaProjectNode *parent)
{
GtkTreeIter child;
gboolean valid;
- /* Get all children */
- valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &child, iter);
-
+ /* Get all root node */
+ valid = gtk_tree_model_iter_children (GTK_TREE_MODEL (model), &child, NULL);
+
while (valid)
{
GbfTreeData *data;
@@ -861,42 +859,23 @@ gbf_project_model_update_shortcut (GbfProjectModel *model, GtkTreeIter *iter, GH
gtk_tree_model_get (GTK_TREE_MODEL (model), &child,
GBF_PROJECT_MODEL_COLUMN_DATA, &data,
-1);
-
+
/* Shortcuts are always at the beginning */
- if ((iter == NULL) && (data->type != GBF_TREE_NODE_SHORTCUT)) break;
+ if (data->type != GBF_TREE_NODE_SHORTCUT) break;
old_node = gbf_tree_data_get_node (data);
- if (g_hash_table_lookup_extended (map, old_node, NULL, &new_node))
- {
- /* Find node */
- if (new_node != NULL)
- {
- /* Node has been changed */
- gbf_tree_data_replace_node (data, new_node);
-
- /* update recursively */
- gbf_project_model_update_tree (model, new_node, &child, map);
-
- valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
- }
- else
- {
- /* Node has been removed */
- valid = gbf_project_model_remove (model, &child);
- }
- }
- else
+ if (old_node == parent)
{
- /* Node has not changed */
- gbf_project_model_update_shortcut (model, &child, map);
-
- valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
+ /* 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, GHashTable *map)
+gbf_project_model_update_tree (GbfProjectModel *model, AnjutaProjectNode *parent, GtkTreeIter *iter)
{
GtkTreeIter child;
GList *node;
@@ -912,39 +891,35 @@ gbf_project_model_update_tree (GbfProjectModel *model, AnjutaProjectNode *parent
while (valid) {
GbfTreeData *data = NULL;
- AnjutaProjectNode* new_node = NULL;
- AnjutaProjectNode* old_node = NULL;
+ AnjutaProjectNode* data_node = NULL;
- if (map != NULL)
- {
- /* Look for old node */
+ /* Look for current node */
- gtk_tree_model_get (GTK_TREE_MODEL (model), &child,
- GBF_PROJECT_MODEL_COLUMN_DATA, &data,
- -1);
+ gtk_tree_model_get (GTK_TREE_MODEL (model), &child,
+ GBF_PROJECT_MODEL_COLUMN_DATA, &data,
+ -1);
- old_node = gbf_tree_data_get_node (data);
- new_node = g_hash_table_lookup (map, old_node);
- }
-
- if (new_node != NULL)
+ data_node = gbf_tree_data_get_node (data);
+
+ node = g_list_find (nodes, data_node);
+
+ if (node != NULL)
{
- /* Remove from the new node list */
- node = g_list_find (nodes, new_node);
- if (node != NULL)
- {
- nodes = g_list_delete_link (nodes, node);
- }
- gbf_tree_data_replace_node (data, new_node);
-
+ /* 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, new_node, &child, map);
+ gbf_project_model_update_tree (model, data_node, &child);
+
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (model), &child);
}
else
{
- /* update recursively */
+ /* Node has been deleted */
valid = gbf_project_model_remove (model, &child);
}
}
diff --git a/plugins/project-manager/project-model.h b/plugins/project-manager/project-model.h
index 1c179ba..35217bf 100644
--- a/plugins/project-manager/project-model.h
+++ b/plugins/project-manager/project-model.h
@@ -86,11 +86,7 @@ void gbf_project_model_add_shortcut (GbfProjectModel *model,
void gbf_project_model_update_tree (GbfProjectModel *model,
AnjutaProjectNode *parent,
- GtkTreeIter *iter,
- GHashTable *map);
-void gbf_project_model_update_shortcut (GbfProjectModel *model,
- GtkTreeIter *iter,
- GHashTable *map);
+ GtkTreeIter *iter);
#endif
diff --git a/plugins/project-manager/project.c b/plugins/project-manager/project.c
index 65add31..fb55277 100644
--- a/plugins/project-manager/project.c
+++ b/plugins/project-manager/project.c
@@ -32,106 +32,9 @@
#include "dialogs.h"
-/*
-
-2 Threads: GUI and Work
-
-Add new source.
-
-1. Work add new node
- + Obvious, because it has the parent node
- - Not possible, if the GUI has to get all child of the same node
-
-2. Work add new node, GUI use tree data
-
-3. Work create new node only but doesn't add it
-
-4. GUI create a new node and call the save function later
-
-
-The GUI cannot change links, else the Work cannot follow links when getting a
-node. The Work can even need parent links.
-=> GUI cannot read links except in particular case
-
-The GUI can read and write common part
-=> We need to copy the properties anyway when changing them
-
-The GUI can only read common part
-=>
-
-Have a proxy node for setting properties, this proxy will copy add common data
-and keep a link with the original node and reference count. The GUI can still
-read all data in the proxy without disturbing the Work which can change the
-underlines node. The proxy address is returned immediatly when the
-set_properties function is used. If another set_properties is done on the same
-node the proxy is reused, incrementing reference count.
-
-There is no need to proxy after add or remove functions, because the links are
-already copied in the module.
-
-After changing a property should we reload automatically ?
-
-
-Reloading a node can change its property, so we need a proxy for the load too.
-
-Proxy has to be created in GUI, because we need to update tree data.
-
-Instead of using a Proxy, we can copy all data everytime, this will allow
-automatic reload.
-
-
-
- Work has always a full access to link
- GUI read a special GNode tree created by thread
-
- Work can always read common data, and can write them before sending them to GUI
- or in when modification are requested by the GUI (the GUI get a proxy)
- GUI can only read common data
-
- Work has always a full access to specific data.
- GUI has no access to specific data
-
-
-*/
-
/* Types
*---------------------------------------------------------------------------*/
-typedef enum
-{
- LOAD = 0,
- RELOAD,
- SAVE,
- ADD,
- REMOVE,
- EXIT,
- LAST_COMMAND
-} PmCommand;
-
-typedef struct _PmJob PmJob;
-
-typedef gboolean (*PmCommandFunc) (AnjutaPmProject *project, PmJob *job);
-
-typedef struct _PmCommandWork
-{
- PmCommandFunc setup;
- PmCommandFunc worker;
- PmCommandFunc complete;
-} PmCommandWork;
-
-struct _PmJob
-{
- PmCommand command;
- AnjutaProjectNodeType type;
- GFile *file;
- gchar *name;
- AnjutaProjectNode *node;
- AnjutaProjectNode *sibling;
- GError *error;
- AnjutaProjectNode *proxy;
- GHashTable *map;
-};
-
/* Signal
*---------------------------------------------------------------------------*/
@@ -144,259 +47,6 @@ 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, AnjutaProjectNode *node, AnjutaProjectNode *sibling, AnjutaProjectNodeType type, GFile *file, const gchar *name)
-{
- PmJob *job;
-
- job = g_new0 (PmJob, 1);
- job->command = command;
- job->node = node;
- job->sibling = sibling;
- job->type = type;
- if (file != NULL) job->file = g_object_ref (file);
- if (name != NULL) job->name = g_strdup (name);
-
- return job;
-}
-
-static void
-pm_job_free (PmJob *job)
-{
- if (job->error != NULL) g_error_free (job->error);
- if (job->map != NULL) g_hash_table_destroy (job->map);
- if (job->file != NULL) g_object_unref (job->file);
- if (job->name != NULL) g_free (job->name);
-}
-
-/* Worker thread functions
- *---------------------------------------------------------------------------*/
-
-static gint
-pm_project_compare_node (AnjutaProjectNode *old_node, AnjutaProjectNode *new_node)
-{
- gchar *name1;
- gchar *name2;
- GFile *file1;
- GFile *file2;
-
- name1 = anjuta_project_node_get_name (old_node);
- name2 = anjuta_project_node_get_name (new_node);
- file1 = anjuta_project_node_get_file (old_node);
- file2 = anjuta_project_node_get_file (new_node);
-
- return (anjuta_project_node_get_node_type (old_node) == anjuta_project_node_get_node_type (new_node))
- && ((name1 == NULL) || (name2 == NULL) || (strcmp (name1, name2) == 0))
- && ((file1 == NULL) || (file2 == NULL) || g_file_equal (file1, file2)) ? 0 : 1;
-}
-
-static void
-pm_project_map_children (PmJob *job, AnjutaProjectNode *old_node, AnjutaProjectNode *new_node)
-{
- GList *children = NULL;
-
- if (new_node != NULL)
- {
- for (new_node = anjuta_project_node_first_child (new_node); new_node != NULL; new_node = anjuta_project_node_next_sibling (new_node))
- {
- children = g_list_prepend (children, new_node);
- }
- children = g_list_reverse (children);
- }
-
- for (old_node = anjuta_project_node_first_child (old_node); old_node != NULL; old_node = anjuta_project_node_next_sibling (old_node))
- {
- GList *same;
-
- same = g_list_find_custom (children, old_node, (GCompareFunc)pm_project_compare_node);
-
- if (same != NULL)
- {
- g_hash_table_insert (job->map, old_node, (AnjutaProjectNode *)same->data);
-
- pm_project_map_children ((PmJob *)job, old_node, (AnjutaProjectNode *)same->data);
- children = g_list_delete_link (children, same);
- }
- else
- {
- /* Mark deleted node */
- g_hash_table_insert (job->map, old_node, NULL);
- pm_project_map_children ((PmJob *)job, old_node, NULL);
- }
- }
-
- g_list_free (children);
-}
-
-static void
-pm_project_map_node (PmJob *job)
-{
- if ((job->proxy != NULL) && (job->node != NULL))
- {
- AnjutaProjectNode *old_node;
- AnjutaProjectNode *new_node;
-
- job->map = g_hash_table_new (g_direct_hash, NULL);
- old_node = job->proxy;
- new_node = job->node;
-
- g_hash_table_insert (job->map, old_node, new_node);
-
- pm_project_map_children (job, old_node, new_node);
- }
-}
-
-static gboolean
-pm_command_load_work (AnjutaPmProject *project, PmJob *job)
-{
- AnjutaProjectNode *node;
-
-
- if (ianjuta_project_load_node (project->project, job->node, &(job->error)))
- {
- pm_project_map_node (job);
- }
-
- return TRUE;
-}
-
-static gboolean
-pm_command_save_work (AnjutaPmProject *project, PmJob *job)
-{
- return ianjuta_project_save_node (project->project, job->node, &(job->error));
-}
-
-static gboolean
-pm_command_exit_work (AnjutaPmProject *project, PmJob *job)
-{
- g_return_val_if_fail (job != 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 (;;)
- {
- PmJob *job;
- PmCommandFunc func;
-
- /* Get new job */
- job = (PmJob *)g_async_queue_pop (project->work_queue);
-
- /* Get work function and call it if possible */
- func = PmCommands[job->command].worker;
- if (func != NULL)
- {
- 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)
-{
- project->done_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->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;
- }
- else
- {
- project->idle_func = g_idle_add ((GSourceFunc) pm_project_idle_func, project);
- project->stopping = FALSE;
-
- return TRUE;
- }
-}
-
-static gboolean
-pm_project_stop_thread (AnjutaPmProject *project)
-{
- if (project->job_queue)
- {
- PmJob *job;
-
- project->stopping = TRUE;
-
- // Remove idle function
- g_idle_remove_by_data (project);
- project->idle_func = 0;
-
- // Request to terminate thread
- job = pm_job_new (EXIT, NULL, NULL, 0, NULL, NULL);
- g_async_queue_push (project->work_queue, job);
- g_thread_join (project->worker);
- project->worker = NULL;
-
- // Free queue
- g_async_queue_unref (project->work_queue);
- project->work_queue = NULL;
- g_queue_foreach (project->job_queue, (GFunc)pm_job_free, project->project);
- g_queue_free (project->job_queue);
- project->job_queue = NULL;
- for (;;)
- {
- job = g_async_queue_try_pop (project->done_queue);
- if (job == NULL) break;
- pm_job_free (job);
- }
- project->done_queue = NULL;
- }
-
- return TRUE;
-}
-
-static void
-pm_project_push_command (AnjutaPmProject *project, PmCommand command, AnjutaProjectNode *node, AnjutaProjectNode *sibling, AnjutaProjectNodeType type, GFile *file, const gchar *name)
-{
- PmJob *job;
-
- job = pm_job_new (command, node, sibling, type, file, name);
- g_queue_push_tail (project->job_queue, job);
-
- pm_project_run_command (project);
-}
-
static void
on_pm_project_load_incomplete (AnjutaProjectNode *node, AnjutaPmProject *project)
{
@@ -408,287 +58,83 @@ on_pm_project_load_incomplete (AnjutaProjectNode *node, AnjutaPmProject *project
project->incomplete_node++;
anjuta_project_node_set_state (node, ANJUTA_PROJECT_LOADING);
//g_message ("load incomplete %p", node);
- pm_project_push_command (project, RELOAD, node, NULL, 0, NULL, NULL);
- }
-}
-
-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);
- anjuta_project_node_replace (job->node, job->proxy);
- /*anjuta_project_proxy_exchange_data (job->node, job->proxy);*/
-
- return TRUE;
-}
-
-static void
-check_queue (GQueue *queue, GHashTable *map)
-{
- guint i;
-
- //g_message ("check queue size %d", g_queue_get_length (queue));
- for (i = 0;; i++)
- {
- PmJob *job = (PmJob *)g_queue_peek_nth (queue, i);
-
- if (job == NULL) break;
- if (job->node != NULL)
- {
- AnjutaProjectNode *replace;
- AnjutaProjectNode *node;
-
- /* Get original node if we have a proxy here */
- node = anjuta_project_proxy_get_node (job->node);
-
- if (g_hash_table_lookup_extended (map, node, NULL, (gpointer *)&replace))
- {
- //g_message ("*** delete node %p used ***", job->node);
- if (replace != NULL)
- {
- /* Replaced node */
- job->node = replace;
- }
- else
- {
- /* node has been deleted */
- g_warning ("Node %s has been delete before executing command %d", anjuta_project_node_get_name (job->node), job->command);
- job = g_queue_pop_nth (queue, i);
- pm_job_free (job);
- i--;
- }
- }
- }
+ ianjuta_project_load_node (project->project, node, NULL);
}
}
static gboolean
-pm_command_load_complete (AnjutaPmProject *project, PmJob *job)
+pm_command_load_complete (AnjutaPmProject *project, AnjutaProjectNode *node, GError *error)
{
- //anjuta_project_proxy_exchange (job->proxy, job->node);
- anjuta_project_node_exchange (job->proxy, job->node);
-
g_message ("pm_command_load_complete");
- if (job->error != NULL)
+
+ if (error != NULL)
{
g_warning ("unable to load node");
- g_signal_emit (G_OBJECT (project), signals[job->command == LOAD ? LOADED : UPDATED], 0, job->node, job->error);
+ g_signal_emit (G_OBJECT (project), project->loaded ? LOADED : UPDATED, 0, node, error);
}
else
{
- gboolean load = job->command == LOAD;
-
- if (job->command == LOAD)
+ if (project->root == node)
{
g_object_set (G_OBJECT (project->model), "project", project, NULL);
project->incomplete_node = 0;
- }
-
- if (project->root == job->node)
- {
- gbf_project_model_update_tree (project->model, job->node, NULL, job->map);
- gbf_project_model_update_shortcut (project->model, NULL, job->map);
+ gbf_project_model_update_tree (project->model, node, NULL);
}
else
{
GtkTreeIter iter;
gboolean found;
- found = gbf_project_model_find_node (project->model, &iter, NULL, job->node);
- gbf_project_model_update_tree (project->model, job->node, found ? &iter : NULL, job->map);
- gbf_project_model_update_shortcut (project->model, NULL, job->map);
+ found = gbf_project_model_find_node (project->model, &iter, NULL, node);
+ gbf_project_model_update_tree (project->model, node, found ? &iter : NULL);
}
-
// Check for incompletely loaded object and load them
- if (anjuta_project_node_get_state (job->node) & ANJUTA_PROJECT_INCOMPLETE)
+ if (anjuta_project_node_get_state (node) & ANJUTA_PROJECT_INCOMPLETE)
{
project->incomplete_node--;
//g_message ("remaining node %d", project->incomplete_node);
- if (project->incomplete_node == 0) load = TRUE;
}
- anjuta_project_node_clear_state (job->node, ANJUTA_PROJECT_LOADING | ANJUTA_PROJECT_INCOMPLETE);
- anjuta_project_node_foreach (job->node, G_POST_ORDER, (AnjutaProjectNodeForeachFunc)on_pm_project_load_incomplete, project);
+ anjuta_project_node_clear_state (node, ANJUTA_PROJECT_LOADING | ANJUTA_PROJECT_INCOMPLETE);
+ anjuta_project_node_foreach (node, G_POST_ORDER, (AnjutaProjectNodeForeachFunc)on_pm_project_load_incomplete, project);
- g_message ("emit node %p", job->node);
- if (load && (project->incomplete_node == 0))
+ g_message ("emit node %p", node);
+ if (!project->loaded && (project->incomplete_node == 0))
{
- g_signal_emit (G_OBJECT (project), signals[LOADED], 0, job->node, NULL);
+ g_signal_emit (G_OBJECT (project), signals[LOADED], 0, node, NULL);
+ project->loaded = TRUE;
}
else
{
- g_signal_emit (G_OBJECT (project), signals[UPDATED], 0, job->node, NULL);
+ g_signal_emit (G_OBJECT (project), signals[UPDATED], 0, node, NULL);
}
- check_queue (project->job_queue, job->map);
}
-
- anjuta_project_proxy_unref (job->proxy);
- //anjuta_project_node_foreach (job->proxy, G_POST_ORDER, (AnjutaProjectNodeForeachFunc)pm_free_node, project->project);
-
- return TRUE;
-}
-
-static gboolean
-pm_command_add_setup (AnjutaPmProject *project, PmJob *job)
-{
- AnjutaProjectNode *node;
-
- g_return_val_if_fail (job != NULL, FALSE);
- g_return_val_if_fail (job->node != NULL, FALSE);
-
- node = ianjuta_project_add_node_before (project->project, job->node, job->sibling, job->type, NULL, job->name, NULL);
- job->node = node;
return TRUE;
}
-static gboolean
-pm_command_remove_setup (AnjutaPmProject *project, PmJob *job)
+static void
+on_node_updated (IAnjutaProject *sender, AnjutaProjectNode *node, AnjutaPmProject *project)
{
- GtkTreeIter iter;
-
- g_return_val_if_fail (job != NULL, FALSE);
- g_return_val_if_fail (job->node != NULL, FALSE);
-
- /* Remove node from project tree */
- if (gbf_project_model_find_node (project->model, &iter, NULL, job->node))
- {
- gbf_project_model_remove (project->model, &iter);
- ianjuta_project_remove_node (project->project, job->node, NULL);
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ ianjuta_project_load_node (project->project, node, NULL);
}
-static gboolean
-pm_command_remove_complete (AnjutaPmProject *project, PmJob *job)
-{
- g_return_val_if_fail (job != NULL, FALSE);
- g_return_val_if_fail (job->node != NULL, FALSE);
-
- /* Remove node from node tree */
- //anjuta_project_node_remove (job->node);
- //pm_free_node (job->node, project->project);
- //anjuta_project_node_foreach (job->node, G_POST_ORDER, (AnjutaProjectNodeForeachFunc)pm_free_node, project->project);
-
- 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},
- {NULL,
- pm_command_save_work,
- NULL},
- {pm_command_add_setup,
- pm_command_save_work,
- NULL},
- {pm_command_remove_setup,
- pm_command_save_work,
- pm_command_remove_complete},
- {NULL,
- pm_command_exit_work,
- NULL}};
-
-/* Run a command in job queue */
-static gboolean
-pm_project_run_command (AnjutaPmProject *project)
+static void
+on_node_loaded (IAnjutaProject *sender, AnjutaProjectNode *node, GError *error, AnjutaPmProject *project)
{
- gboolean running = TRUE;
-
- if (project->busy == 0)
- {
- /* 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;
+ pm_command_load_complete (project, node, error);
}
-static gboolean
-pm_project_idle_func (AnjutaPmProject *project)
+static void
+on_node_changed (IAnjutaProject *sender, AnjutaProjectNode *node, GError *error, AnjutaPmProject *project)
{
- gboolean running;
-
- for (;;)
- {
- PmCommandFunc func;
- PmJob *job;
-
- /* 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)
- {
- running = func (project, job);
- }
- pm_job_free (job);
- project->busy--;
- }
-
- running = pm_project_run_command (project);
- if (!running) project->idle_func = 0;
-
- return running;
+ ianjuta_project_save_node (project->project, node, NULL);
}
/* Public functions
*---------------------------------------------------------------------------*/
-static void
-on_node_updated (IAnjutaProject *sender, AnjutaProjectNode *node, AnjutaPmProject *project)
-{
- pm_project_push_command (project, RELOAD, node, NULL, 0, NULL, NULL);
-}
-
+
gboolean
anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
{
@@ -696,7 +142,6 @@ anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
GList *desc;
IAnjutaProjectBackend *backend;
gint found = 0;
- GError *err = NULL;
g_return_val_if_fail (file != NULL, FALSE);
@@ -704,6 +149,7 @@ anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
{
g_object_unref (project->project);
project->project = NULL;
+ project->loaded = FALSE;
}
DEBUG_PRINT ("loading gbf backendâ?¦\n");
@@ -767,17 +213,21 @@ anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
return FALSE;
}
- if (!pm_project_start_thread(project, &err))
- {
- return FALSE;
- }
g_signal_connect (G_OBJECT (project->project),
"node-updated",
G_CALLBACK (on_node_updated),
project);
+ g_signal_connect (G_OBJECT (project->project),
+ "node-loaded",
+ G_CALLBACK (on_node_loaded),
+ project);
+ g_signal_connect (G_OBJECT (project->project),
+ "node-changed",
+ G_CALLBACK (on_node_changed),
+ project);
project->root = ianjuta_project_get_root (project->project, NULL);
- pm_project_push_command (project, LOAD, project->root, NULL, 0, NULL, NULL);
+ ianjuta_project_load_node (project->project, project->root, NULL);
return TRUE;
}
@@ -785,7 +235,7 @@ anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
static gboolean
anjuta_pm_project_reload_node (AnjutaPmProject *project, AnjutaProjectNode *node, GError **error)
{
- pm_project_push_command (project, RELOAD, node, NULL, 0, NULL, NULL);
+ ianjuta_project_load_node (project->project, project->root, NULL);
return TRUE;
}
@@ -793,11 +243,10 @@ anjuta_pm_project_reload_node (AnjutaPmProject *project, AnjutaProjectNode *node
gboolean
anjuta_pm_project_unload (AnjutaPmProject *project, GError **error)
{
- pm_project_stop_thread (project);
-
g_object_set (G_OBJECT (project->model), "project", NULL, NULL);
g_object_unref (project->project);
project->project = NULL;
+ project->loaded = FALSE;
/* Remove project properties dialogs */
if (project->properties_dialog != NULL) gtk_widget_destroy (project->properties_dialog);
@@ -809,9 +258,7 @@ anjuta_pm_project_unload (AnjutaPmProject *project, GError **error)
gboolean
anjuta_pm_project_refresh (AnjutaPmProject *project, GError **error)
{
- //g_message ("reload project %p", project->root);
-
- pm_project_push_command (project, RELOAD, project->root, NULL, 0, NULL, NULL);
+ ianjuta_project_load_node (project->project, project->root, NULL);
return TRUE;
}
@@ -909,7 +356,7 @@ anjuta_pm_project_add_group (AnjutaPmProject *project, AnjutaProjectNode *parent
g_return_val_if_fail (project->project != NULL, NULL);
- pm_project_push_command (project, ADD, parent, sibling, ANJUTA_PROJECT_GROUP, NULL, name);
+ node = ianjuta_project_add_node_before (project->project, parent, sibling, ANJUTA_PROJECT_GROUP, NULL, name, NULL);
return node;
}
@@ -921,7 +368,7 @@ anjuta_pm_project_add_target (AnjutaPmProject *project, AnjutaProjectNode *paren
g_return_val_if_fail (project->project != NULL, NULL);
- pm_project_push_command (project, ADD, parent, sibling, ANJUTA_PROJECT_TARGET | type, NULL, name);
+ node = ianjuta_project_add_node_before (project->project, parent, sibling, ANJUTA_PROJECT_TARGET | type, NULL, name, NULL);
return node;
}
@@ -933,7 +380,7 @@ anjuta_pm_project_add_source (AnjutaPmProject *project, AnjutaProjectNode *paren
g_return_val_if_fail (project->project != NULL, NULL);
- pm_project_push_command (project, ADD, parent, sibling, ANJUTA_PROJECT_SOURCE, NULL, name);
+ node = ianjuta_project_add_node_before (project->project, parent, sibling, ANJUTA_PROJECT_SOURCE, NULL, name, NULL);
return node;
}
@@ -941,7 +388,7 @@ anjuta_pm_project_add_source (AnjutaPmProject *project, AnjutaProjectNode *paren
gboolean
anjuta_pm_project_remove (AnjutaPmProject *project, AnjutaProjectNode *node, GError **error)
{
- pm_project_push_command (project, REMOVE, node, NULL, 0, NULL, NULL);
+ ianjuta_project_remove_node (project->project, node, NULL);
return TRUE;
}
@@ -960,8 +407,6 @@ anjuta_pm_project_set_properties (AnjutaPmProject *project, AnjutaProjectNode *n
if (!valid) break;
}
- if (valid) pm_project_push_command (project, SAVE, node, NULL, 0, NULL, NULL);
-
return valid;
}
@@ -982,7 +427,6 @@ anjuta_pm_project_remove_data (AnjutaPmProject *project, GbfTreeData *data, GErr
}
}
-
gboolean
anjuta_pm_project_is_open (AnjutaPmProject *project)
{
@@ -1088,7 +532,7 @@ anjuta_pm_project_show_properties_dialog (AnjutaPmProject *project, GbfTreeData
node);
if (*dialog_ptr != NULL)
{
- g_object_add_weak_pointer (*dialog_ptr, dialog_ptr);
+ g_object_add_weak_pointer (G_OBJECT (*dialog_ptr), (gpointer *)dialog_ptr);
}
}
@@ -1105,16 +549,9 @@ anjuta_pm_project_init (AnjutaPmProject *project)
{
project->model = gbf_project_model_new (NULL);
project->plugin = NULL;
+ project->loaded = FALSE;
project->properties_dialog = 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 462ef31..f86e674 100644
--- a/plugins/project-manager/project.h
+++ b/plugins/project-manager/project.h
@@ -63,18 +63,11 @@ struct _AnjutaPmProject
AnjutaProjectNode *root;
guint incomplete_node;
+
+ gboolean loaded;
/* project properties dialog */
GtkWidget *properties_dialog;
-
- /* Thread 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]