SF.net SVN: geany-plugins:[2096] trunk/geany-plugins/gproject/src/ gproject-project.c

techet at users.sourceforge.net techet at xxxxx
Sun Jun 19 22:30:57 UTC 2011


Revision: 2096
          http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=2096&view=rev
Author:   techet
Date:     2011-06-19 22:30:57 +0000 (Sun, 19 Jun 2011)

Log Message:
-----------
Fix an issue with tag add/remove not working properly

Thanks to Josh Pschorr for this patch

Modified Paths:
--------------
    trunk/geany-plugins/gproject/src/gproject-project.c

Modified: trunk/geany-plugins/gproject/src/gproject-project.c
===================================================================
--- trunk/geany-plugins/gproject/src/gproject-project.c	2011-06-19 19:14:03 UTC (rev 2095)
+++ trunk/geany-plugins/gproject/src/gproject-project.c	2011-06-19 22:30:57 UTC (rev 2096)
@@ -20,11 +20,12 @@
 #include <gdk/gdkkeysyms.h>
 #include <glib/gstdio.h>
 
-#include <geanyplugin.h>
+#include <geany/geanyplugin.h>
 
 #include "gproject-utils.h"
 #include "gproject-project.h"
 
+extern GeanyPlugin *geany_plugin;
 extern GeanyData *geany_data;
 extern GeanyFunctions *geany_functions;
 
@@ -40,17 +41,34 @@
 
 static PropertyDialogElements *e;
 
+typedef enum {DeferredTagOpAdd, DeferredTagOpRemove} DeferredTagOpType;
 
-static void workspace_remove_tag(gchar *filename, TagObject *obj, gpointer foo)
+typedef struct
 {
-	if (obj->tag)
-	{
-		tm_workspace_remove_object(obj->tag, TRUE, TRUE);
-		obj->tag = NULL;
-	}
+	gchar * filename;
+	DeferredTagOpType type;
+} DeferredTagOp;
+
+static GSList *file_tag_deferred_op_queue = NULL;
+static gboolean flush_queued = FALSE;
+
+
+static void deferred_op_free(DeferredTagOp* op, G_GNUC_UNUSED gpointer user_data)
+{
+	g_free(op->filename);
+	g_free(op);
 }
 
 
+static void deferred_op_queue_clean()
+{
+	g_slist_foreach(file_tag_deferred_op_queue, (GFunc)deferred_op_free, NULL);
+	g_slist_free(file_tag_deferred_op_queue);
+	file_tag_deferred_op_queue = NULL;
+        flush_queued = FALSE;
+}
+
+
 static void workspace_add_tag(gchar *filename, TagObject *obj, gpointer foo)
 {
 	TMWorkObject *tm_obj = NULL;
@@ -74,6 +92,74 @@
 }
 
 
+static void workspace_add_file_tag(gchar *filename)
+{
+	TagObject *obj;
+
+	obj = g_hash_table_lookup(g_prj->file_tag_table, filename);
+	if (obj)
+		workspace_add_tag(filename, obj, NULL);
+}
+
+
+static void workspace_remove_tag(gchar *filename, TagObject *obj, gpointer foo)
+{
+	if (obj->tag)
+	{
+		tm_workspace_remove_object(obj->tag, TRUE, TRUE);
+		obj->tag = NULL;
+	}
+}
+
+
+static void workspace_remove_file_tag(gchar *filename)
+{
+	TagObject *obj;
+
+	obj = g_hash_table_lookup(g_prj->file_tag_table, filename);
+	if (obj)
+		workspace_remove_tag(filename, obj, NULL);
+}
+
+
+static void deferred_op_queue_dispatch(DeferredTagOp* op, G_GNUC_UNUSED gpointer user_data)
+{
+	if (op->type == DeferredTagOpAdd)
+		workspace_add_file_tag(op->filename);
+	else if (op->type == DeferredTagOpRemove)
+		workspace_remove_file_tag(op->filename);
+}
+
+
+static gboolean deferred_op_queue_flush(G_GNUC_UNUSED gpointer data)
+{
+	g_slist_foreach(file_tag_deferred_op_queue,
+					(GFunc)deferred_op_queue_dispatch, NULL);
+	deferred_op_queue_clean();
+	flush_queued = FALSE;
+
+	return FALSE; // returning false removes this callback; it is a one-shot
+}
+
+
+static void deferred_op_queue_enqueue(gchar* filename, DeferredTagOpType type)
+{
+	DeferredTagOp * op;
+
+	op = (DeferredTagOp *) g_new0(DeferredTagOp, 1);
+	op->type = type;
+	op->filename = g_strdup(filename);
+
+	file_tag_deferred_op_queue = g_slist_prepend(file_tag_deferred_op_queue,op);
+
+	if (!flush_queued)
+	{
+		flush_queued = TRUE;
+		plugin_idle_add(geany_plugin, (GSourceFunc)deferred_op_queue_flush, NULL);
+	}
+}
+
+
 /* path - absolute path in locale, returned list in locale */
 static GSList *get_file_list(const gchar * path, GSList *patterns, GSList *ignored_dirs_patterns)
 {
@@ -140,6 +226,8 @@
 	g_hash_table_destroy(g_prj->file_tag_table);
 	g_prj->file_tag_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 
+	deferred_op_queue_clean();
+
 	pattern_list = get_precompiled_patterns(geany_data->app->project->file_patterns);
 
 	ignored_dirs_list = get_precompiled_patterns(g_prj->ignored_dirs_patterns);
@@ -229,6 +317,8 @@
 
 	g_prj->file_tag_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 
+	deferred_op_queue_clean();
+
 	source_patterns = g_key_file_get_string_list(key_file, "gproject", "source_patterns", NULL, NULL);
 	if (!source_patterns)
 		source_patterns = g_strsplit("*.c *.C *.cpp *.cxx *.c++ *.cc", " ", -1);
@@ -368,6 +458,8 @@
 	if (g_prj->generate_tags)
 		g_hash_table_foreach(g_prj->file_tag_table, (GHFunc)workspace_remove_tag, NULL);
 
+	deferred_op_queue_clean();
+
 	g_free(g_prj->source_patterns);
 	g_free(g_prj->header_patterns);
 	g_free(g_prj->ignored_dirs_patterns);
@@ -381,21 +473,13 @@
 
 void gprj_project_add_file_tag(gchar *filename)
 {
-	TagObject *obj;
-
-	obj = g_hash_table_lookup(g_prj->file_tag_table, filename);
-	if (obj)
-		workspace_add_tag(filename, obj, NULL);
+	deferred_op_queue_enqueue(filename, DeferredTagOpAdd);
 }
 
 
 void gprj_project_remove_file_tag(gchar *filename)
 {
-	TagObject *obj;
-
-	obj = g_hash_table_lookup(g_prj->file_tag_table, filename);
-	if (obj)
-		workspace_remove_tag(filename, obj, NULL);
+	deferred_op_queue_enqueue(filename, DeferredTagOpRemove);
 }
 
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Plugins-Commits mailing list