Revision: 4041 http://geany.svn.sourceforge.net/geany/?rev=4041&view=rev Author: ntrel Date: 2009-07-29 17:40:20 +0000 (Wed, 29 Jul 2009)
Log Message: ----------- Add plugin_signal_connect() for connecting plugin signals at runtime and also for connecting to any GObject signal. Add 'Plugin Utility Functions' on main page. Add foreach_array() macro.
Modified Paths: -------------- trunk/ChangeLog trunk/doc/plugins.dox trunk/doc/pluginsymbols.c trunk/plugins/filebrowser.c trunk/plugins/geanyfunctions.h trunk/src/plugindata.h trunk/src/pluginprivate.h trunk/src/plugins.c trunk/src/pluginutils.c trunk/src/pluginutils.h trunk/src/stash.c trunk/src/utils.h
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/ChangeLog 2009-07-29 17:40:20 UTC (rev 4041) @@ -1,3 +1,15 @@ +2009-07-29 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com> + + * src/pluginprivate.h, src/utils.h, src/plugindata.h, + src/stash.c, src/pluginutils.c, src/plugins.c, src/pluginutils.h, + doc/pluginsymbols.c, doc/plugins.dox, plugins/geanyfunctions.h, + plugins/filebrowser.c: + Add plugin_signal_connect() for connecting plugin signals at + runtime and also for connecting to any GObject signal. + Add 'Plugin Utility Functions' on main page. + Add foreach_array() macro. + + 2009-07-28 Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
* wscript: Fix compiling error with waf.
Modified: trunk/doc/plugins.dox =================================================================== --- trunk/doc/plugins.dox 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/doc/plugins.dox 2009-07-29 17:40:20 UTC (rev 4041) @@ -42,9 +42,10 @@ * To get started, see the @link howto Plugin Howto @endlink. * * Other pages: + * - @link pluginsymbols.c Plugin Symbols @endlink * - @link plugindata.h Main Datatypes and Macros @endlink - * - @link pluginsymbols.c Plugin Symbols @endlink * - @link signals Plugin Signals @endlink + * - @link pluginutils.c Plugin Utility Functions @endlink * - @link guidelines Plugin Writing Guidelines @endlink * * @note Some of these pages are also listed in Related Pages. @@ -56,11 +57,14 @@ * * @section Usage * - * To use plugin signals in Geany, you simply create a PluginCallback array, list the signals - * you want to listen to and create the appropiate signal callbacks for each signal. - * The callback array is read @a after plugin_init() has been called. - * @note The PluginCallback array has to be ended with a final NULL entry. + * To use plugin signals in Geany, you have two options: * + * -# Create a PluginCallback array with the @ref plugin_callbacks symbol. List the signals + * you want to listen to and create the appropiate signal callbacks for each signal. + * The callback array is read @a after plugin_init() has been called. + * -# Use plugin_signal_connect(), which can be called at any time and can also connect + * to non-Geany signals (such as GTK widget signals). + * * The following code demonstrates how to use signals in Geany plugins. The code can be inserted * in your plugin code at any desired position. * @@ -76,6 +80,7 @@ { NULL, NULL, FALSE, NULL } }; * @endcode + * @note The PluginCallback array has to be ended with a final @c NULL entry. * * @section Signals *
Modified: trunk/doc/pluginsymbols.c =================================================================== --- trunk/doc/pluginsymbols.c 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/doc/pluginsymbols.c 2009-07-29 17:40:20 UTC (rev 4041) @@ -66,7 +66,8 @@ PluginFields *plugin_fields;
/** An array for connecting GeanyObject events, which should be terminated with - * @c {NULL, NULL, FALSE, NULL}. See @link signals Signal documentation @endlink. */ + * @c {NULL, NULL, FALSE, NULL}. See @link signals Signal documentation @endlink. + * @see plugin_signal_connect(). */ PluginCallback plugin_callbacks[];
/** Most plugins should use the PLUGIN_KEY_GROUP() macro to define it. However,
Modified: trunk/plugins/filebrowser.c =================================================================== --- trunk/plugins/filebrowser.c 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/plugins/filebrowser.c 2009-07-29 17:40:20 UTC (rev 4041) @@ -30,6 +30,7 @@ #include <gdk/gdkkeysyms.h>
+GeanyPlugin *geany_plugin; GeanyData *geany_data; GeanyFunctions *geany_functions;
@@ -87,12 +88,10 @@ } popup_items;
-static void document_activate_cb(GObject *obj, GeanyDocument *doc, gpointer data); static void project_change_cb(GObject *obj, GKeyFile *config, gpointer data);
PluginCallback plugin_callbacks[] = { - { "document-activate", (GCallback) &document_activate_cb, TRUE, NULL }, { "project-open", (GCallback) &project_change_cb, TRUE, NULL }, { "project-save", (GCallback) &project_change_cb, TRUE, NULL }, { NULL, NULL, FALSE, NULL } @@ -1020,6 +1019,9 @@ 0, 0, "focus_file_list", _("Focus File List"), NULL); keybindings_set_item(plugin_key_group, KB_FOCUS_PATH_ENTRY, kb_activate, 0, 0, "focus_path_entry", _("Focus Path Entry"), NULL); + + plugin_signal_connect(geany_plugin, NULL, "document-activate", TRUE, + (GCallback) &document_activate_cb, NULL); }
Modified: trunk/plugins/geanyfunctions.h =================================================================== --- trunk/plugins/geanyfunctions.h 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/plugins/geanyfunctions.h 2009-07-29 17:40:20 UTC (rev 4041) @@ -14,6 +14,8 @@ geany_functions->p_plugin->add_toolbar_item #define plugin_module_make_resident \ geany_functions->p_plugin->module_make_resident +#define plugin_signal_connect \ + geany_functions->p_plugin->signal_connect #define document_new_file \ geany_functions->p_document->new_file #define document_get_current \
Modified: trunk/src/plugindata.h =================================================================== --- trunk/src/plugindata.h 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/src/plugindata.h 2009-07-29 17:40:20 UTC (rev 4041) @@ -50,7 +50,7 @@ enum { /** The Application Programming Interface (API) version, incremented * whenever any plugin data types are modified or appended to. */ - GEANY_API_VERSION = 149, + GEANY_API_VERSION = 150,
/** The Application Binary Interface (ABI) version, incremented whenever * existing fields in the plugin data types have to be changed or reordered. */ @@ -138,7 +138,7 @@ };
-/** callback array entry */ +/** Callback array entry type used with the @ref plugin_callbacks symbol. */ typedef struct PluginCallback { /** The name of signal, must be an existing signal. For a list of available signals, @@ -546,6 +546,9 @@ { void (*add_toolbar_item)(GeanyPlugin *plugin, GtkToolItem *item); void (*module_make_resident) (GeanyPlugin *plugin); + void (*signal_connect) (GeanyPlugin *plugin, + GObject *object, gchar *signal_name, gboolean after, + GCallback callback, gpointer user_data); } PluginFuncs;
Modified: trunk/src/pluginprivate.h =================================================================== --- trunk/src/pluginprivate.h 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/src/pluginprivate.h 2009-07-29 17:40:20 UTC (rev 4041) @@ -32,6 +32,7 @@ { GeanyAutoSeparator toolbar_separator; gboolean resident; + GArray *signal_ids; /* gulong signal IDs to disconnect when unloading */ } GeanyPluginPrivate;
Modified: trunk/src/plugins.c =================================================================== --- trunk/src/plugins.c 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/src/plugins.c 2009-07-29 17:40:20 UTC (rev 4041) @@ -72,8 +72,6 @@ GeanyPlugin public; /* fields the plugin can read */ GeanyPluginPrivate priv; /* GeanyPlugin type private data, same as (*public.priv) */
- gulong *signal_ids; /* signal IDs to disconnect when unloading */ - gsize signal_ids_len; GeanyKeyGroup *key_group;
void (*init) (GeanyData *data); /* Called when the plugin is enabled */ @@ -100,7 +98,8 @@
static PluginFuncs plugin_funcs = { &plugin_add_toolbar_item, - &plugin_module_make_resident + &plugin_module_make_resident, + &plugin_signal_connect };
static DocumentFuncs doc_funcs = { @@ -455,16 +454,12 @@ if (len == 0) return;
- plugin->signal_ids_len = len; - plugin->signal_ids = g_new(gulong, len); - for (i = 0; i < len; i++) { cb = &callbacks[i];
- plugin->signal_ids[i] = (cb->after) ? - g_signal_connect_after(geany_object, cb->signal_name, cb->callback, cb->user_data) : - g_signal_connect(geany_object, cb->signal_name, cb->callback, cb->user_data); + plugin_signal_connect(&plugin->public, NULL, cb->signal_name, cb->after, + cb->callback, cb->user_data); } }
@@ -686,14 +681,16 @@
static void remove_callbacks(Plugin *plugin) { - guint i; + GArray *signal_ids = plugin->priv.signal_ids; + gulong *i;
- if (plugin->signal_ids == NULL) + if (signal_ids == NULL) return;
- for (i = 0; i < plugin->signal_ids_len; i++) - g_signal_handler_disconnect(geany_object, plugin->signal_ids[i]); - g_free(plugin->signal_ids); + foreach_array(gulong, i, signal_ids) + g_signal_handler_disconnect(geany_object, *i); + + g_array_free(signal_ids, TRUE); }
Modified: trunk/src/pluginutils.c =================================================================== --- trunk/src/pluginutils.c 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/src/pluginutils.c 2009-07-29 17:40:20 UTC (rev 4041) @@ -92,3 +92,33 @@ }
+/** Connect a signal which will be disconnected on unloading the plugin, to prevent a possible segfault. + * @param plugin Must be @ref geany_plugin. + * @param object Object to connect to, or @c NULL when using @link signals Geany signals @endlink. + * @param signal_name The name of the signal. For a list of available + * signals, please see the @link signals Signal documentation @endlink. + * @param after Set to @c TRUE to call your handler after the main signal handlers have been called + * (if supported by @a signal_name). + * @param callback The function to call when the signal is emitted. + * @param user_data The user data passed to the signal handler. + * @see plugin_callbacks. */ +void plugin_signal_connect(GeanyPlugin *plugin, + GObject *object, gchar *signal_name, gboolean after, + GCallback callback, gpointer user_data) +{ + gulong id; + + if (!object) + object = geany_object; + + id = after ? + g_signal_connect_after(object, signal_name, callback, user_data) : + g_signal_connect(object, signal_name, callback, user_data); + + if (!plugin->priv->signal_ids) + plugin->priv->signal_ids = g_array_new(FALSE, FALSE, sizeof(gulong)); + + g_array_append_val(plugin->priv->signal_ids, id); +} + +
Modified: trunk/src/pluginutils.h =================================================================== --- trunk/src/pluginutils.h 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/src/pluginutils.h 2009-07-29 17:40:20 UTC (rev 4041) @@ -32,4 +32,8 @@
void plugin_module_make_resident(GeanyPlugin *plugin);
+void plugin_signal_connect(GeanyPlugin *plugin, + GObject *object, gchar *signal_name, gboolean after, + GCallback callback, gpointer user_data); + #endif /* PLUGINUTILS_H */
Modified: trunk/src/stash.c =================================================================== --- trunk/src/stash.c 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/src/stash.c 2009-07-29 17:40:20 UTC (rev 4041) @@ -62,12 +62,9 @@ #include <gtk/gtk.h>
#include "stash.h" -#include "utils.h" /* only for utils_get_setting_*(). Stash should not depend on Geany. */ +#include "utils.h" /* only for foreach_*, utils_get_setting_*(). Stash should not depend on Geany. */
-#define foreach_array(type, item, array) \ - foreach_c_array(item, ((type*)(gpointer)array->data), array->len)
- struct GeanyPrefEntry { GType setting_type; /* e.g. G_TYPE_INT */
Modified: trunk/src/utils.h =================================================================== --- trunk/src/utils.h 2009-07-29 02:28:26 UTC (rev 4040) +++ trunk/src/utils.h 2009-07-29 17:40:20 UTC (rev 4041) @@ -64,6 +64,13 @@ #define foreach_c_array(item, array, len) \ for (item = array; item < &array[len]; item++)
+/** Iterates all items in @a array. + * @param type Type of @a item. + * @param item pointer to item in @a array. + * @param array @c GArray to traverse. */ +#define foreach_array(type, item, array) \ + foreach_c_array(item, ((type*)(gpointer)array->data), array->len) + /** Iterates all the pointers in @a ptr_array. * @param item pointer in @a ptr_array. * @param idx @c guint index into @a ptr_array.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.