diff options
Diffstat (limited to 'src/eom-plugin-engine.c')
-rw-r--r-- | src/eom-plugin-engine.c | 841 |
1 files changed, 62 insertions, 779 deletions
diff --git a/src/eom-plugin-engine.c b/src/eom-plugin-engine.c index b55b0d0..0c55731 100644 --- a/src/eom-plugin-engine.c +++ b/src/eom-plugin-engine.c @@ -26,833 +26,116 @@ #include <config.h> #endif -#include <string.h> - #include "eom-plugin-engine.h" -#include "eom-plugin.h" -#include "eom-module.h" #include "eom-debug.h" -#include "eom-application.h" #include "eom-config-keys.h" #include "eom-util.h" #include <glib/gi18n.h> #include <glib.h> #include <gio/gio.h> +#include <girepository.h> #define USER_EOM_PLUGINS_LOCATION "plugins/" -#define PLUGIN_EXT ".eom-plugin" - -typedef enum { - EOM_PLUGIN_LOADER_C, -} EomPluginLoader; - -struct _EomPluginInfo -{ - gchar *file; - - gchar *location; - EomPluginLoader loader; - GTypeModule *module; +G_DEFINE_TYPE (EomPluginEngine, eom_plugin_engine, PEAS_TYPE_ENGINE) - gchar *name; - gchar *desc; - gchar *icon_name; - gchar **authors; - gchar *copyright; - gchar *website; - - EomPlugin *plugin; - - gint active : 1; - - /* A plugin is unavailable if it is not possible to activate it - due to an error loading the plugin module */ - gint available : 1; +struct _EomPluginEnginePrivate { + GSettings *plugins_settings; }; -static void eom_plugin_engine_active_plugins_changed (GSettings *settings, - gchar *key, - gpointer user_data); - -static GList *eom_plugins_list = NULL; - -static GSettings *eom_plugin_engine_settings = NULL; - -static GSList *active_plugins = NULL; - -static void -eom_plugin_info_free (EomPluginInfo *info) -{ - if (info->plugin != NULL) { - eom_debug_message (DEBUG_PLUGINS, "Unref plugin %s", info->name); - - g_object_unref (info->plugin); - } - - g_free (info->file); - g_free (info->location); - g_free (info->name); - g_free (info->desc); - g_free (info->icon_name); - g_free (info->website); - g_free (info->copyright); - g_strfreev (info->authors); - - g_free (info); -} - -static EomPluginInfo * -eom_plugin_engine_load (const gchar *file) -{ - EomPluginInfo *info; - GKeyFile *plugin_file = NULL; - gchar *str; - - g_return_val_if_fail (file != NULL, NULL); - - eom_debug_message (DEBUG_PLUGINS, "Loading plugin: %s", file); - - info = g_new0 (EomPluginInfo, 1); - info->file = g_strdup (file); - - plugin_file = g_key_file_new (); - - if (!g_key_file_load_from_file (plugin_file, file, G_KEY_FILE_NONE, NULL)) { - g_warning ("Bad plugin file: %s", file); - - goto error; - } - - if (!g_key_file_has_key (plugin_file, - "Eom Plugin", - "IAge", - NULL)) { - eom_debug_message (DEBUG_PLUGINS, - "IAge key does not exist in file: %s", file); - - goto error; - } - - /* Check IAge=2 */ - if (g_key_file_get_integer (plugin_file, - "Eom Plugin", - "IAge", - NULL) != 2) { - eom_debug_message (DEBUG_PLUGINS, - "Wrong IAge in file: %s", file); - - goto error; - } - - /* Get Location */ - str = g_key_file_get_string (plugin_file, - "Eom Plugin", - "Module", - NULL); - - if ((str != NULL) && (*str != '\0')) { - info->location = str; - } else { - g_warning ("Could not find 'Module' in %s", file); - - goto error; - } - - /* Get the loader for this plugin */ - str = g_key_file_get_string (plugin_file, - "Eom Plugin", - "Loader", - NULL); - - info->loader = EOM_PLUGIN_LOADER_C; - - g_free (str); - - /* Get Name */ - str = g_key_file_get_locale_string (plugin_file, - "Eom Plugin", - "Name", - NULL, NULL); - if (str) { - info->name = str; - } else { - g_warning ("Could not find 'Name' in %s", file); - - goto error; - } - - /* Get Description */ - str = g_key_file_get_locale_string (plugin_file, - "Eom Plugin", - "Description", - NULL, NULL); - if (str) { - info->desc = str; - } else { - eom_debug_message (DEBUG_PLUGINS, "Could not find 'Description' in %s", file); - } - - /* Get Icon */ - str = g_key_file_get_locale_string (plugin_file, - "Eom Plugin", - "Icon", - NULL, NULL); - if (str) { - info->icon_name = str; - } else { - eom_debug_message (DEBUG_PLUGINS, "Could not find 'Icon' in %s, " - "using 'eom-plugin'", file); - } - - /* Get Authors */ - info->authors = g_key_file_get_string_list (plugin_file, - "Eom Plugin", - "Authors", - NULL, - NULL); - - if (info->authors == NULL) - eom_debug_message (DEBUG_PLUGINS, "Could not find 'Authors' in %s", file); - - - /* Get Copyright */ - str = g_key_file_get_string (plugin_file, - "Eom Plugin", - "Copyright", - NULL); - if (str) { - info->copyright = str; - } else { - eom_debug_message (DEBUG_PLUGINS, "Could not find 'Copyright' in %s", file); - } - - /* Get Website */ - str = g_key_file_get_string (plugin_file, - "Eom Plugin", - "Website", - NULL); - if (str) { - info->website = str; - } else { - eom_debug_message (DEBUG_PLUGINS, "Could not find 'Website' in %s", file); - } - - g_key_file_free (plugin_file); - - /* If we know nothing about the availability of the plugin, - set it as available */ - info->available = TRUE; - - return info; - -error: - g_free (info->file); - g_free (info->location); - g_free (info->name); - g_free (info); - g_key_file_free (plugin_file); - - return NULL; -} - -static gint -compare_plugin_info (EomPluginInfo *info1, - EomPluginInfo *info2) -{ - return strcmp (info1->location, info2->location); -} - -static void -eom_plugin_engine_load_dir (const gchar *dir) -{ - GError *error = NULL; - GDir *d; - const gchar *dirent; - - if (!g_file_test (dir, G_FILE_TEST_IS_DIR)) { - return; - } - - g_return_if_fail (eom_plugin_engine_settings != NULL); - - eom_debug_message (DEBUG_PLUGINS, "DIR: %s", dir); - - d = g_dir_open (dir, 0, &error); - - if (!d) { - g_warning ("%s", error->message); - g_error_free (error); - - return; - } - - while ((dirent = g_dir_read_name (d))) { - if (g_str_has_suffix (dirent, PLUGIN_EXT)) { - gchar *plugin_file; - EomPluginInfo *info; - - plugin_file = g_build_filename (dir, dirent, NULL); - info = eom_plugin_engine_load (plugin_file); - g_free (plugin_file); - - if (info == NULL) - continue; - - /* If a plugin with this name has already been loaded - * drop this one (user plugins override system plugins) */ - if (g_list_find_custom (eom_plugins_list, - info, - (GCompareFunc)compare_plugin_info) != NULL) { - g_warning ("Two or more plugins named '%s'. " - "Only the first will be considered.\n", - info->location); - - eom_plugin_info_free (info); - - continue; - } - - /* Actually, the plugin will be activated when reactivate_all - * will be called for the first time. */ - info->active = (g_slist_find_custom (active_plugins, - info->location, - (GCompareFunc)strcmp) != NULL); - - eom_plugins_list = g_list_prepend (eom_plugins_list, info); - - eom_debug_message (DEBUG_PLUGINS, "Plugin %s loaded", info->name); - } - } - - eom_plugins_list = g_list_reverse (eom_plugins_list); - - g_dir_close (d); -} - static void -eom_plugin_engine_load_all (void) -{ - gchar *pdir; - - pdir = g_build_filename (eom_util_dot_dir (), - USER_EOM_PLUGINS_LOCATION, NULL); - - /* Load user's plugins */ - eom_plugin_engine_load_dir (pdir); - - g_free (pdir); - - /* Load system plugins */ - eom_plugin_engine_load_dir (EOM_PLUGIN_DIR "/"); -} - -static void -eom_plugin_engine_get_active_plugins (void) -{ - gchar **array; - gint i; - - active_plugins = NULL; - array = g_settings_get_strv (eom_plugin_engine_settings, EOM_CONF_PLUGINS_ACTIVE_PLUGINS); - if (array != NULL) { - for (i = 0; array[i]; i++) { - active_plugins = g_slist_append (active_plugins, g_strdup (array[i])); - } - } - g_strfreev (array); -} - -gboolean -eom_plugin_engine_init (void) +eom_plugin_engine_init (EomPluginEngine *engine) { eom_debug (DEBUG_PLUGINS); - g_return_val_if_fail (eom_plugins_list == NULL, FALSE); + engine->priv = G_TYPE_INSTANCE_GET_PRIVATE (engine, + EOM_TYPE_PLUGIN_ENGINE, + EomPluginEnginePrivate); - if (!g_module_supported ()) { - g_warning ("eom is not able to initialize the plugins engine."); - - return FALSE; - } - - eom_plugin_engine_settings = g_settings_new (EOM_CONF_PLUGINS); - - g_signal_connect (eom_plugin_engine_settings, - "changed::" EOM_CONF_PLUGINS_ACTIVE_PLUGINS, - G_CALLBACK (eom_plugin_engine_active_plugins_changed), - NULL); - - eom_plugin_engine_get_active_plugins (); - - eom_plugin_engine_load_all (); - - return TRUE; -} - -void -eom_plugin_engine_shutdown (void) -{ - GList *pl; - - eom_debug (DEBUG_PLUGINS); - - g_return_if_fail (eom_plugin_engine_settings != NULL); - - for (pl = eom_plugins_list; pl; pl = pl->next) { - EomPluginInfo *info = (EomPluginInfo*) pl->data; - - eom_plugin_info_free (info); - } - - g_slist_foreach (active_plugins, (GFunc)g_free, NULL); - g_slist_free (active_plugins); - - active_plugins = NULL; - - g_list_free (eom_plugins_list); - eom_plugins_list = NULL; - - g_object_unref (eom_plugin_engine_settings); - eom_plugin_engine_settings = NULL; -} - -const GList * -eom_plugin_engine_get_plugins_list (void) -{ - eom_debug (DEBUG_PLUGINS); - - return eom_plugins_list; -} - -static gboolean -load_plugin_module (EomPluginInfo *info) -{ - gchar *path; - gchar *dirname; - - eom_debug (DEBUG_PLUGINS); - - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (info->file != NULL, FALSE); - g_return_val_if_fail (info->location != NULL, FALSE); - g_return_val_if_fail (info->plugin == NULL, FALSE); - g_return_val_if_fail (info->available, FALSE); - - switch (info->loader) { - case EOM_PLUGIN_LOADER_C: - dirname = g_path_get_dirname (info->file); - g_return_val_if_fail (dirname != NULL, FALSE); - - path = g_module_build_path (dirname, info->location); - - g_free (dirname); - - g_return_val_if_fail (path != NULL, FALSE); - - info->module = G_TYPE_MODULE (eom_module_new (path)); - - g_free (path); - - break; - - default: - g_return_val_if_reached (FALSE); - } - - if (!g_type_module_use (info->module)) { - switch (info->loader) { - case EOM_PLUGIN_LOADER_C: - g_warning ("Cannot load plugin '%s' since file '%s' cannot be read.", - info->name, - eom_module_get_path (EOM_MODULE (info->module))); - break; - - default: - g_return_val_if_reached (FALSE); - } - - g_object_unref (G_OBJECT (info->module)); - - info->module = NULL; - - /* Mark plugin as unavailable and fails */ - info->available = FALSE; - - return FALSE; - } - - switch (info->loader) { - case EOM_PLUGIN_LOADER_C: - info->plugin = - EOM_PLUGIN (eom_module_new_object (EOM_MODULE (info->module))); - break; - - default: - g_return_val_if_reached (FALSE); - } - - g_type_module_unuse (info->module); - - eom_debug_message (DEBUG_PLUGINS, "End"); - - return TRUE; -} - -static gboolean -eom_plugin_engine_activate_plugin_real (EomPluginInfo *info) -{ - gboolean res = TRUE; - - /* Plugin is not available, don't try to activate/load it */ - if (!info->available) { - return FALSE; - } - - if (info->plugin == NULL) - res = load_plugin_module (info); - - if (res) { - const GList *wins = eom_application_get_windows (EOM_APP); - - while (wins != NULL) { - eom_plugin_activate (info->plugin, - EOM_WINDOW (wins->data)); - - wins = g_list_next (wins); - } - } else { - g_warning ("Error activating plugin '%s'", info->name); - } - - return res; -} - -gboolean -eom_plugin_engine_activate_plugin (EomPluginInfo *info) -{ - eom_debug (DEBUG_PLUGINS); - - g_return_val_if_fail (info != NULL, FALSE); - - if (!info->available) - return FALSE; - - if (info->active) - return TRUE; - - if (eom_plugin_engine_activate_plugin_real (info)) { - GSList *list; - - /* Update plugin state */ - info->active = TRUE; - - list = active_plugins; - - while (list != NULL) { - if (strcmp (info->location, (gchar *)list->data) == 0) { - g_warning ("Plugin '%s' is already active.", info->name); - - return TRUE; - } - - list = g_slist_next (list); - } - - active_plugins = g_slist_insert_sorted (active_plugins, - g_strdup (info->location), - (GCompareFunc)strcmp); - - GArray *array; - GSList *l; - array = g_array_new (TRUE, TRUE, sizeof (gchar *)); - for (l = active_plugins; l; l = l->next) { - array = g_array_append_val (array, l->data); - } - g_settings_set_strv (eom_plugin_engine_settings, EOM_CONF_PLUGINS_ACTIVE_PLUGINS, - (const gchar **) array->data); - g_array_free (array, TRUE); - - return TRUE; - } - - return FALSE; + engine->priv->plugins_settings = g_settings_new (EOM_CONF_PLUGINS); } static void -eom_plugin_engine_deactivate_plugin_real (EomPluginInfo *info) -{ - const GList *wins = eom_application_get_windows (EOM_APP); - - while (wins != NULL) { - eom_plugin_deactivate (info->plugin, - EOM_WINDOW (wins->data)); - - wins = g_list_next (wins); - } -} - -gboolean -eom_plugin_engine_deactivate_plugin (EomPluginInfo *info) +eom_plugin_engine_dispose (GObject *object) { - gboolean res; - GSList *list; - - eom_debug (DEBUG_PLUGINS); - - g_return_val_if_fail (info != NULL, FALSE); - - if (!info->active || !info->available) - return TRUE; - - eom_plugin_engine_deactivate_plugin_real (info); - - /* Update plugin state */ - info->active = FALSE; + EomPluginEngine *engine = EOM_PLUGIN_ENGINE (object); - list = active_plugins; - res = (list == NULL); - - while (list != NULL) { - if (strcmp (info->location, (gchar *)list->data) == 0) { - g_free (list->data); - active_plugins = g_slist_delete_link (active_plugins, list); - list = NULL; - res = TRUE; - } else { - list = g_slist_next (list); - } - } - - if (!res) { - g_warning ("Plugin '%s' is already deactivated.", info->name); - - return TRUE; + if (engine->priv->plugins_settings != NULL) + { + g_object_unref (engine->priv->plugins_settings); + engine->priv->plugins_settings = NULL; } - GArray *array; - GSList *l; - array = g_array_new (TRUE, TRUE, sizeof (gchar *)); - for (l = active_plugins; l; l = l->next) { - array = g_array_append_val (array, l->data); - } - g_settings_set_strv (eom_plugin_engine_settings, EOM_CONF_PLUGINS_ACTIVE_PLUGINS, - (const gchar **) array->data); - g_array_free (array, TRUE); - - return TRUE; -} - -gboolean -eom_plugin_engine_plugin_is_active (EomPluginInfo *info) -{ - g_return_val_if_fail (info != NULL, FALSE); - - return (info->available && info->active); -} - -gboolean -eom_plugin_engine_plugin_is_available (EomPluginInfo *info) -{ - g_return_val_if_fail (info != NULL, FALSE); - - return (info->available != FALSE); + G_OBJECT_CLASS (eom_plugin_engine_parent_class)->dispose (object); } static void -reactivate_all (EomWindow *window) +eom_plugin_engine_class_init (EomPluginEngineClass *klass) { - GList *pl; - - eom_debug (DEBUG_PLUGINS); - - for (pl = eom_plugins_list; pl; pl = pl->next) { - gboolean res = TRUE; + GObjectClass *object_class = G_OBJECT_CLASS (klass); - EomPluginInfo *info = (EomPluginInfo*)pl->data; + object_class->dispose = eom_plugin_engine_dispose; - /* If plugin is not available, don't try to activate/load it */ - if (info->available && info->active) { - if (info->plugin == NULL) - res = load_plugin_module (info); - - if (res) - eom_plugin_activate (info->plugin, - window); - } - } - - eom_debug_message (DEBUG_PLUGINS, "End"); + g_type_class_add_private (klass, sizeof (EomPluginEnginePrivate)); } -void -eom_plugin_engine_update_plugins_ui (EomWindow *window, - gboolean new_window) +EomPluginEngine * +eom_plugin_engine_new (void) { - GList *pl; - - eom_debug (DEBUG_PLUGINS); - - g_return_if_fail (EOM_IS_WINDOW (window)); - - if (new_window) - reactivate_all (window); - - /* Updated ui of all the plugins that implement update_ui */ - for (pl = eom_plugins_list; pl; pl = pl->next) { - EomPluginInfo *info = (EomPluginInfo*)pl->data; - - if (!info->available || !info->active) - continue; + EomPluginEngine *engine; + gchar *user_plugin_path; + gchar *private_path; + GError *error = NULL; - eom_debug_message (DEBUG_PLUGINS, "Updating UI of %s", info->name); + private_path = g_build_filename (LIBDIR, "girepository-1.0", NULL); - eom_plugin_update_ui (info->plugin, window); + /* This should be moved to libpeas */ + if (g_irepository_require (g_irepository_get_default (), + "Peas", "1.0", 0, &error) == NULL) + { + g_warning ("Error loading Peas typelib: %s\n", + error->message); + g_clear_error (&error); } -} - -gboolean -eom_plugin_engine_plugin_is_configurable (EomPluginInfo *info) { - eom_debug (DEBUG_PLUGINS); - - g_return_val_if_fail (info != NULL, FALSE); - - if ((info->plugin == NULL) || !info->active || !info->available) - return FALSE; - - return eom_plugin_is_configurable (info->plugin); -} - -void -eom_plugin_engine_configure_plugin (EomPluginInfo *info, - GtkWindow *parent) -{ - GtkWidget *conf_dlg; - - GtkWindowGroup *wg; - - eom_debug (DEBUG_PLUGINS); - - g_return_if_fail (info != NULL); - - conf_dlg = eom_plugin_create_configure_dialog (info->plugin); - - g_return_if_fail (conf_dlg != NULL); - gtk_window_set_transient_for (GTK_WINDOW (conf_dlg), - parent); - - // Will return a default group if no group is set - wg = gtk_window_get_group (parent); - - // For now assign a dedicated window group if it is - // the default one until we know if this is really needed - if (wg == gtk_window_get_group (NULL)) { - wg = gtk_window_group_new (); - gtk_window_group_add_window (wg, parent); + if (g_irepository_require (g_irepository_get_default (), + "PeasGtk", "1.0", 0, &error) == NULL) + { + g_warning ("Error loading PeasGtk typelib: %s\n", + error->message); + g_clear_error (&error); } - gtk_window_group_add_window (wg, - GTK_WINDOW (conf_dlg)); - - gtk_window_set_modal (GTK_WINDOW (conf_dlg), TRUE); - - gtk_widget_show (conf_dlg); -} - -static void -eom_plugin_engine_active_plugins_changed (GSettings *settings, - gchar *key, - gpointer user_data) -{ - GList *pl; - gboolean to_activate; - - eom_debug (DEBUG_PLUGINS); - - g_return_if_fail (settings != NULL); - g_return_if_fail (key != NULL); - - eom_plugin_engine_get_active_plugins (); - - for (pl = eom_plugins_list; pl; pl = pl->next) { - EomPluginInfo *info = (EomPluginInfo*)pl->data; - - if (!info->available) - continue; - - to_activate = (g_slist_find_custom (active_plugins, - info->location, - (GCompareFunc)strcmp) != NULL); - - if (!info->active && to_activate) { - /* Activate plugin */ - if (eom_plugin_engine_activate_plugin_real (info)) - /* Update plugin state */ - info->active = TRUE; - } else { - if (info->active && !to_activate) { - eom_plugin_engine_deactivate_plugin_real (info); - - /* Update plugin state */ - info->active = FALSE; - } - } + if (g_irepository_require_private (g_irepository_get_default (), + private_path, "Eom", "1.0", 0, + &error) == NULL) + { + g_warning ("Error loading Eom typelib: %s\n", + error->message); + g_clear_error (&error); } -} - -const gchar * -eom_plugin_engine_get_plugin_name (EomPluginInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - return info->name; -} - -const gchar * -eom_plugin_engine_get_plugin_description (EomPluginInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - return info->desc; -} -const gchar * -eom_plugin_engine_get_plugin_icon_name (EomPluginInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); + g_free (private_path); - /* Use the eom-plugin icon as a default if the plugin does not - have its own */ - if (info->icon_name != NULL && - gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), - info->icon_name)) - return info->icon_name; - else - return "eom-plugin"; -} + engine = EOM_PLUGIN_ENGINE (g_object_new (EOM_TYPE_PLUGIN_ENGINE, NULL)); -const gchar ** -eom_plugin_engine_get_plugin_authors (EomPluginInfo *info) -{ - g_return_val_if_fail (info != NULL, (const gchar **)NULL); + user_plugin_path = g_build_filename (eom_util_dot_dir (), + USER_EOM_PLUGINS_LOCATION, NULL); - return (const gchar **) info->authors; -} + peas_engine_add_search_path (PEAS_ENGINE (engine), + user_plugin_path, user_plugin_path); -const gchar * -eom_plugin_engine_get_plugin_website (EomPluginInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); + peas_engine_add_search_path (PEAS_ENGINE (engine), + EOM_PLUGIN_DIR, EOM_PLUGIN_DIR); - return info->website; -} + g_settings_bind (engine->priv->plugins_settings, + EOM_CONF_PLUGINS_ACTIVE_PLUGINS, + engine, + "loaded-plugins", + G_SETTINGS_BIND_DEFAULT); -const gchar * -eom_plugin_engine_get_plugin_copyright (EomPluginInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); + g_free (user_plugin_path); - return info->copyright; + return engine; } |