From 0c526f66448360f6c4aa737d0e4aefd61d2c0feb Mon Sep 17 00:00:00 2001 From: Michael Gratton Date: Mon, 2 Mar 2020 12:08:31 +1100 Subject: [PATCH] Plugins: Support loading optional plugins Add optional-plugins GSetting, automatically load any plugins specified there at startup, and allow getting, loading and unloading optional plugins via Application.PluginManager. --- desktop/org.gnome.Geary.gschema.xml | 6 ++ .../application-configuration.vala | 15 +++++ .../application-plugin-manager.vala | 61 +++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/desktop/org.gnome.Geary.gschema.xml b/desktop/org.gnome.Geary.gschema.xml index e23e26a9..ac477a43 100644 --- a/desktop/org.gnome.Geary.gschema.xml +++ b/desktop/org.gnome.Geary.gschema.xml @@ -141,6 +141,12 @@ be displayed. + + [] + List of optional plugins + Plugins listed here will be loaded on startup. + + false Whether we migrated the old settings diff --git a/src/client/application/application-configuration.vala b/src/client/application/application-configuration.vala index 6cce6a7d..170c98ee 100644 --- a/src/client/application/application-configuration.vala +++ b/src/client/application/application-configuration.vala @@ -25,6 +25,7 @@ public class Application.Configuration : Geary.BaseObject { public const string FOLDER_LIST_PANE_POSITION_VERTICAL_KEY = "folder-list-pane-position-vertical"; public const string FORMATTING_TOOLBAR_VISIBLE = "formatting-toolbar-visible"; public const string MESSAGES_PANE_POSITION_KEY = "messages-pane-position"; + public const string OPTIONAL_PLUGINS = "optional-plugins"; public const string SEARCH_STRATEGY_KEY = "search-strategy"; public const string SINGLE_KEY_SHORTCUTS = "single-key-shortcuts"; public const string SPELL_CHECK_LANGUAGES = "spell-check-languages"; @@ -204,6 +205,20 @@ public class Application.Configuration : Geary.BaseObject { this.settings.set_value(COMPOSER_WINDOW_SIZE_KEY, value); } + /** + * Returns list of optional plugins to load by default + */ + public string[] get_optional_plugins() { + return this.settings.get_strv(OPTIONAL_PLUGINS); + } + + /** + * Sets the list of optional plugins to load by default + */ + public void set_optional_plugins(string[] value) { + this.settings.set_strv(OPTIONAL_PLUGINS, value); + } + /** * Returns enabled spell checker languages. * diff --git a/src/client/application/application-plugin-manager.vala b/src/client/application/application-plugin-manager.vala index ffcc256d..fd2c7caf 100644 --- a/src/client/application/application-plugin-manager.vala +++ b/src/client/application/application-plugin-manager.vala @@ -47,6 +47,7 @@ public class Application.PluginManager : GLib.Object { } }); + string[] optional_names = application.config.get_optional_plugins(); foreach (Peas.PluginInfo info in this.engine.get_plugin_list()) { string name = info.get_module_name(); try { @@ -55,6 +56,9 @@ public class Application.PluginManager : GLib.Object { info.get_module_dir().has_prefix(builtin_path)) { debug("Loading built-in plugin: %s", name); this.engine.load_plugin(info); + } else if (name in optional_names) { + debug("Loading optional plugin: %s", name); + this.engine.load_plugin(info); } } } catch (GLib.Error err) { @@ -63,4 +67,61 @@ public class Application.PluginManager : GLib.Object { } } + public Gee.List get_optional_plugins() { + var plugins = new Gee.LinkedList(); + foreach (Peas.PluginInfo plugin in this.engine.get_plugin_list()) { + try { + plugin.is_available(); + if (!plugin.is_builtin()) { + plugins.add(plugin); + } + } catch (GLib.Error err) { + warning( + "Plugin %s not available: %s", + plugin.get_module_name(), err.message + ); + } + } + return plugins; + } + + public bool load_optional(Peas.PluginInfo plugin) throws GLib.Error { + bool loaded = false; + if (plugin.is_available() && + !plugin.is_loaded() && + !plugin.is_builtin()) { + this.engine.load_plugin(plugin); + loaded = true; + string name = plugin.get_module_name(); + string[] optional_names = + this.application.config.get_optional_plugins(); + if (!(name in optional_names)) { + optional_names += name; + this.application.config.set_optional_plugins(optional_names); + } + } + return loaded; + } + + public bool unload_optional(Peas.PluginInfo plugin) throws GLib.Error { + bool unloaded = false; + if (plugin.is_available() && + plugin.is_loaded() && + !plugin.is_builtin()) { + this.engine.unload_plugin(plugin); + unloaded = true; + string name = plugin.get_module_name(); + string[] old_names = + this.application.config.get_optional_plugins(); + string[] new_names = new string[0]; + for (int i = 0; i < old_names.length; i++) { + if (old_names[i] != name) { + new_names += old_names[i]; + } + } + this.application.config.set_optional_plugins(new_names); + } + return unloaded; + } + }