Revision: 2096 http://geany-plugins.svn.sourceforge.net/geany-plugins/?rev=2096&view=re... 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.