From 13ec6ffbea8155f563a8a6b5a86a5b674684697a Mon Sep 17 00:00:00 2001 From: Matthew Brush Date: Sun, 9 Jun 2013 15:16:54 -0700 Subject: [PATCH] Add new API function plugin_builder_connect_signals() --- plugins/geanyfunctions.h | 2 ++ src/plugindata.h | 3 +- src/plugins.c | 3 +- src/pluginutils.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ src/pluginutils.h | 3 ++ 5 files changed, 91 insertions(+), 2 deletions(-) diff --git a/plugins/geanyfunctions.h b/plugins/geanyfunctions.h index beaf6fb9f..6f70e9251 100644 --- a/plugins/geanyfunctions.h +++ b/plugins/geanyfunctions.h @@ -32,6 +32,8 @@ geany_functions->p_plugin->plugin_timeout_add_seconds #define plugin_idle_add \ geany_functions->p_plugin->plugin_idle_add +#define plugin_builder_connect_signals \ + geany_functions->p_plugin->plugin_builder_connect_signals #define document_new_file \ geany_functions->p_document->document_new_file #define document_get_current \ diff --git a/src/plugindata.h b/src/plugindata.h index 0e3f2b73b..d7e681fda 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -55,7 +55,7 @@ G_BEGIN_DECLS * @warning You should not test for values below 200 as previously * @c GEANY_API_VERSION was defined as an enum value, not a macro. */ -#define GEANY_API_VERSION 216 +#define GEANY_API_VERSION 217 /* hack to have a different ABI when built with GTK3 because loading GTK2-linked plugins * with GTK3-linked Geany leads to crash */ @@ -666,6 +666,7 @@ typedef struct PluginFuncs guint (*plugin_timeout_add_seconds) (GeanyPlugin *plugin, guint interval, GSourceFunc function, gpointer data); guint (*plugin_idle_add) (GeanyPlugin *plugin, GSourceFunc function, gpointer data); + void (*plugin_builder_connect_signals) (GeanyPlugin *plugin, GtkBuilder *builder, gpointer user_data); } PluginFuncs; diff --git a/src/plugins.c b/src/plugins.c index 56e16f152..f8c71e3c2 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -86,7 +86,8 @@ static PluginFuncs plugin_funcs = { &plugin_show_configure, &plugin_timeout_add, &plugin_timeout_add_seconds, - &plugin_idle_add + &plugin_idle_add, + &plugin_builder_connect_signals }; static DocumentFuncs doc_funcs = { diff --git a/src/pluginutils.c b/src/pluginutils.c index 0c26ab192..102369f02 100644 --- a/src/pluginutils.c +++ b/src/pluginutils.c @@ -395,4 +395,86 @@ void plugin_show_configure(GeanyPlugin *plugin) } +struct BuilderConnectData +{ + gpointer user_data; + GeanyPlugin *plugin; +}; + + +static void connect_plugin_signals(GtkBuilder *builder, GObject *object, + const gchar *signal_name, const gchar *handler_name, + GObject *connect_object, GConnectFlags flags, gpointer user_data) +{ + gpointer symbol = NULL; + struct BuilderConnectData *data = user_data; + + if (!g_module_symbol(data->plugin->priv->module, handler_name, &symbol)) + { + g_warning("Failed to locate signal handler for '%s': %s", + signal_name, g_module_error()); + return; + } + + plugin_signal_connect(data->plugin, object, signal_name, FALSE, + G_CALLBACK(symbol) /*ub?*/, data->user_data); +} + + +/** + * Allows auto-connecting Glade/GtkBuilder signals in plugins. + * + * When a plugin uses GtkBuilder to load some UI from file/string, + * the gtk_builder_connect_signals() function is unable to automatically + * connect to the plugin's signal handlers. A plugin could itself use + * the gtk_builder_connect_signals_full() function to automatically + * connect to the signal handler functions by loading it's GModule + * and retrieving pointers to the handler functions, but rather than + * each plugin having to do that, this function handles it automatically. + * + * @code + * ... + * GeanyPlugin *geany_plugin; + * + * G_MODULE_EXPORT void + * myplugin_button_clicked(GtkButton *button, gpointer user_data) + * { + * g_print("Button pressed\n"); + * } + * + * void plugin_init(GeanyData *data) + * { + * GtkBuilder *builder = gtk_builder_new(); + * gtk_builder_add_from_file(builder, "gui.glade", NULL); + * plugin_builder_connect_signals(geany_plugin, builder, NULL); + * ... + * } + * @endcode + * + * @note It's important that you prefix your callback handlers with + * a plugin-specific prefix to avoid clashing with other plugins since + * the function symbols will be exported process-wide. + * + * @param plugin Must be @ref geany_plugin. + * @param builder The GtkBuilder to connect signals with. + * @param user_data User data to pass to the connected signal handlers. + * + * @since 1.24, plugin API 217. + */ +void plugin_builder_connect_signals(GeanyPlugin *plugin, + GtkBuilder *builder, gpointer user_data) +{ + struct BuilderConnectData data = { NULL }; + + g_return_if_fail(plugin != NULL && plugin->priv != NULL); + g_return_if_fail(plugin->priv->module != NULL); + g_return_if_fail(GTK_IS_BUILDER(builder)); + + data.user_data = user_data; + data.plugin = plugin; + + gtk_builder_connect_signals_full(builder, connect_plugin_signals, &data); +} + + #endif diff --git a/src/pluginutils.h b/src/pluginutils.h index 852581507..8bd1ae0f0 100644 --- a/src/pluginutils.h +++ b/src/pluginutils.h @@ -53,5 +53,8 @@ struct GeanyKeyGroup *plugin_set_key_group(struct GeanyPlugin *plugin, void plugin_show_configure(struct GeanyPlugin *plugin); +void plugin_builder_connect_signals(struct GeanyPlugin *plugin, + GtkBuilder *builder, gpointer user_data); + #endif /* HAVE_PLUGINS */ #endif /* GEANY_PLUGINUTILS_H */ -- 2.11.4.GIT