[geany/geany] 6bc43f: Merge pull request #1203 from codebrainz/document-data
Matthew Brush
git-noreply at xxxxx
Sun Sep 11 02:40:38 UTC 2016
Branch: refs/heads/master
Author: Matthew Brush <mbrush at codebrainz.ca>
Committer: GitHub <noreply at github.com>
Date: Sun, 11 Sep 2016 02:40:38 UTC
Commit: 6bc43f745e27a45a7fd1b981ca452e8b97929c0e
https://github.com/geany/geany/commit/6bc43f745e27a45a7fd1b981ca452e8b97929c0e
Log Message:
-----------
Merge pull request #1203 from codebrainz/document-data
Document data
Modified Paths:
--------------
src/document.c
src/document.h
src/documentprivate.h
src/plugins.c
src/pluginutils.c
src/pluginutils.h
Modified: src/document.c
23 lines changed, 23 insertions(+), 0 deletions(-)
===================================================================
@@ -657,6 +657,8 @@ static GeanyDocument *document_create(const gchar *utf8_filename)
doc->priv->last_check = time(NULL);
#endif
+ g_datalist_init(&doc->priv->data);
+
sidebar_openfiles_add(doc); /* sets doc->iter */
notebook_new_tab(doc);
@@ -712,6 +714,8 @@ static gboolean remove_page(guint page_num)
if (! main_status.closing_all && doc->real_path != NULL)
ui_add_recent_document(doc);
+ g_datalist_clear(&doc->priv->data);
+
doc->is_valid = FALSE;
doc->id = 0;
@@ -3839,3 +3843,22 @@ GEANY_API_SYMBOL
GType document_get_type (void);
G_DEFINE_BOXED_TYPE(GeanyDocument, document, copy_, free_);
+
+
+gpointer document_get_data(const GeanyDocument *doc, const gchar *key)
+{
+ return g_datalist_get_data(&doc->priv->data, key);
+}
+
+
+void document_set_data(GeanyDocument *doc, const gchar *key, gpointer data)
+{
+ g_datalist_set_data(&doc->priv->data, key, data);
+}
+
+
+void document_set_data_full(GeanyDocument *doc, const gchar *key,
+ gpointer data, GDestroyNotify free_func)
+{
+ g_datalist_set_data_full(&doc->priv->data, key, data, free_func);
+}
Modified: src/document.h
7 lines changed, 7 insertions(+), 0 deletions(-)
===================================================================
@@ -316,6 +316,13 @@ void document_grab_focus(GeanyDocument *doc);
GeanyDocument *document_clone(GeanyDocument *old_doc);
+gpointer document_get_data(const GeanyDocument *doc, const gchar *key);
+
+void document_set_data(GeanyDocument *doc, const gchar *key, gpointer data);
+
+void document_set_data_full(GeanyDocument *doc, const gchar *key,
+ gpointer data, GDestroyNotify free_func);
+
#endif /* GEANY_PRIVATE */
G_END_DECLS
Modified: src/documentprivate.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -111,6 +111,8 @@ typedef struct GeanyDocumentPrivate
gint protected;
/* Save pointer to info bars allowing to cancel them programatically (to avoid multiple ones) */
GtkWidget *info_bars[NUM_MSG_TYPES];
+ /* Keyed Data List to attach arbitrary data to the document */
+ GData *data;
}
GeanyDocumentPrivate;
Modified: src/plugins.c
39 lines changed, 39 insertions(+), 0 deletions(-)
===================================================================
@@ -31,6 +31,7 @@
#include "app.h"
#include "dialogs.h"
+#include "documentprivate.h"
#include "encodings.h"
#include "geanyobject.h"
#include "geanywraplabel.h"
@@ -59,6 +60,14 @@
#include <string.h>
+typedef struct
+{
+ gchar *prefix;
+ GeanyDocument *document;
+}
+ForEachDocData;
+
+
GList *active_plugin_list = NULL; /* list of only actually loaded plugins, always valid */
@@ -850,6 +859,35 @@ static gboolean is_active_plugin(Plugin *plugin)
}
+static void remove_each_doc_data(GQuark key_id, gpointer data, gpointer user_data)
+{
+ const ForEachDocData *doc_data = user_data;
+ const gchar *key = g_quark_to_string(key_id);
+ if (g_str_has_prefix(key, doc_data->prefix))
+ g_datalist_remove_data(&doc_data->document->priv->data, key);
+}
+
+
+static void remove_doc_data(Plugin *plugin)
+{
+ ForEachDocData data;
+
+ data.prefix = g_strdup_printf("geany/plugins/%s/", plugin->public.info->name);
+
+ for (guint i = 0; i < documents_array->len; i++)
+ {
+ GeanyDocument *doc = documents_array->pdata[i];
+ if (DOC_VALID(doc))
+ {
+ data.document = doc;
+ g_datalist_foreach(&doc->priv->data, remove_each_doc_data, &data);
+ }
+ }
+
+ g_free(data.prefix);
+}
+
+
/* Clean up anything used by an active plugin */
static void
plugin_cleanup(Plugin *plugin)
@@ -859,6 +897,7 @@ plugin_cleanup(Plugin *plugin)
/* With geany_register_plugin cleanup is mandatory */
plugin->cbs.cleanup(&plugin->public, plugin->cb_data);
+ remove_doc_data(plugin);
remove_callbacks(plugin);
remove_sources(plugin);
Modified: src/pluginutils.c
153 lines changed, 153 insertions(+), 0 deletions(-)
===================================================================
@@ -44,6 +44,14 @@
#include "utils.h"
+typedef struct
+{
+ gpointer data;
+ GDestroyNotify free_func;
+}
+PluginDocDataProxy;
+
+
/** Inserts a toolbar item before the Quit button, or after the previous plugin toolbar item.
* A separator is added on the first call to this function, and will be shown when @a item is
* shown; hidden when @a item is hidden.
@@ -599,4 +607,149 @@ void geany_plugin_set_data(GeanyPlugin *plugin, gpointer pdata, GDestroyNotify f
}
+static void plugin_doc_data_proxy_free(gpointer pdata)
+{
+ PluginDocDataProxy *prox = pdata;
+ if (prox != NULL)
+ {
+ if (prox->free_func)
+ prox->free_func(prox->data);
+ g_slice_free(PluginDocDataProxy, prox);
+ }
+}
+
+
+/**
+ * Retrieve plugin-specific data attached to a document.
+ *
+ * @param plugin The plugin who attached the data.
+ * @param doc The document which the data was attached to.
+ * @param key The key name of the attached data.
+ *
+ * @return The attached data pointer or `NULL` if the key is not found
+ * for the given plugin.
+ *
+ * @since 1.29 (Plugin API 228)
+ * @see plugin_set_document_data plugin_set_document_data_full
+ */
+GEANY_API_SYMBOL
+gpointer plugin_get_document_data(struct GeanyPlugin *plugin,
+ struct GeanyDocument *doc, const gchar *key)
+{
+ gchar *real_key;
+ PluginDocDataProxy *data;
+
+ g_return_val_if_fail(plugin != NULL, NULL);
+ g_return_val_if_fail(doc != NULL, NULL);
+ g_return_val_if_fail(key != NULL && *key != '\0', NULL);
+
+ real_key = g_strdup_printf("geany/plugins/%s/%s", plugin->info->name, key);
+ data = document_get_data(doc, real_key);
+ g_free(real_key);
+
+ return (data != NULL) ? data->data : NULL;
+}
+
+
+/**
+ * Attach plugin-specific data to a document.
+ *
+ * @param plugin The plugin attaching data to the document.
+ * @param doc The document to attach the data to.
+ * @param key The key name for the data.
+ * @param data The pointer to attach to the document.
+ *
+ * @since 1.29 (Plugin API 228)
+ * @see plugin_get_document_data plugin_set_document_data_full
+ */
+GEANY_API_SYMBOL
+void plugin_set_document_data(struct GeanyPlugin *plugin, struct GeanyDocument *doc,
+ const gchar *key, gpointer data)
+{
+ plugin_set_document_data_full(plugin, doc, key, data, NULL);
+}
+
+
+/**
+ * Attach plugin-specific data and a free function to a document.
+ *
+ * This is useful for plugins who want to keep some additional data with
+ * the document and even have it auto-released appropriately (see below).
+ *
+ * This is a simple example showing how a plugin might use this to
+ * attach a string to each document and print it when the document is
+ * saved:
+ *
+ * @code
+ * void on_document_open(GObject *unused, GeanyDocument *doc, GeanyPlugin *plugin)
+ * {
+ * plugin_set_document_data_full(plugin, doc, "my-data",
+ * g_strdup("some-data"), g_free);
+ * }
+ *
+ * void on_document_save(GObject *unused, GeanyDocument *doc, GeanyPlugin *plugin)
+ * {
+ * const gchar *some_data = plugin_get_document_data(plugin, doc, "my-data");
+ * g_print("my-data: %s", some_data);
+ * }
+ *
+ * gboolean plugin_init(GeanyPlugin *plugin, gpointer unused)
+ * {
+ * plugin_signal_connect(plugin, NULL, "document-open", TRUE,
+ * G_CALLBACK(on_document_open), plugin);
+ * plugin_signal_connect(plugin, NULL, "document-new", TRUE,
+ * G_CALLBACK(on_document_open), plugin);
+ * plugin_signal_connect(plugin, NULL, "document-save", TRUE,
+ * G_CALLBACK(on_document_save), plugin);
+ * return TRUE;
+ * }
+ *
+ * void geany_load_module(GeanyPlugin *plugin)
+ * {
+ * // ...
+ * plugin->funcs->init = plugin_init;
+ * // ...
+ * }
+ * @endcode
+ *
+ * The @a free_func can be used to tie the lifetime of the data to that
+ * of the @a doc and/or the @a plugin. The @a free_func will be called
+ * in any of the following cases:
+ *
+ * - When a document is closed.
+ * - When the plugin is unloaded.
+ * - When the document data is set again using the same key.
+ *
+ * @param plugin The plugin attaching data to the document.
+ * @param doc The document to attach the data to.
+ * @param key The key name for the data.
+ * @param data The pointer to attach to the document.
+ * @param free_func The function to call with data when removed.
+ *
+ * @since 1.29 (Plugin API 228)
+ * @see plugin_get_document_data plugin_set_document_data
+ */
+GEANY_API_SYMBOL
+void plugin_set_document_data_full(struct GeanyPlugin *plugin,
+ struct GeanyDocument *doc, const gchar *key, gpointer data,
+ GDestroyNotify free_func)
+{
+ PluginDocDataProxy *prox;
+
+ g_return_if_fail(plugin != NULL);
+ g_return_if_fail(doc != NULL);
+ g_return_if_fail(key != NULL);
+
+ prox = g_slice_new(PluginDocDataProxy);
+ if (prox != NULL)
+ {
+ gchar *real_key = g_strdup_printf("geany/plugins/%s/%s", plugin->info->name, key);
+ prox->data = data;
+ prox->free_func = free_func;
+ document_set_data_full(doc, real_key, prox, plugin_doc_data_proxy_free);
+ g_free(real_key);
+ }
+}
+
+
#endif
Modified: src/pluginutils.h
11 lines changed, 11 insertions(+), 0 deletions(-)
===================================================================
@@ -33,6 +33,7 @@ G_BEGIN_DECLS
/* avoid including plugindata.h otherwise this redefines the GEANY() macro */
struct GeanyPlugin;
+struct GeanyDocument;
void plugin_add_toolbar_item(struct GeanyPlugin *plugin, GtkToolItem *item);
@@ -62,6 +63,16 @@ void plugin_show_configure(struct GeanyPlugin *plugin);
void plugin_builder_connect_signals(struct GeanyPlugin *plugin,
GtkBuilder *builder, gpointer user_data);
+gpointer plugin_get_document_data(struct GeanyPlugin *plugin,
+ struct GeanyDocument *doc, const gchar *key);
+
+void plugin_set_document_data(struct GeanyPlugin *plugin, struct GeanyDocument *doc,
+ const gchar *key, gpointer data);
+
+void plugin_set_document_data_full(struct GeanyPlugin *plugin,
+ struct GeanyDocument *doc, const gchar *key, gpointer data,
+ GDestroyNotify free_func);
+
G_END_DECLS
#endif /* HAVE_PLUGINS */
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list