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.
This commit is contained in:
Michael Gratton 2020-03-02 12:08:31 +11:00 committed by Michael James Gratton
parent 627bfb7c89
commit 0c526f6644
3 changed files with 82 additions and 0 deletions

View file

@ -141,6 +141,12 @@
be displayed.</description>
</key>
<key name="optional-plugins" type="as">
<default>[]</default>
<summary>List of optional plugins</summary>
<description>Plugins listed here will be loaded on startup.</description>
</key>
<key name="migrated-config" type="b">
<default>false</default>
<summary>Whether we migrated the old settings</summary>

View file

@ -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.
*

View file

@ -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<Peas.PluginInfo> get_optional_plugins() {
var plugins = new Gee.LinkedList<Peas.PluginInfo>();
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;
}
}