From 8965133f188c817cbdf4fcf9d1f1b60462bbfe7d Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Thu, 31 Dec 2020 12:40:42 +0100 Subject: Offered a custom configuration facility to each plugin. --- plugins/pychrysalide/constants.c | 3 +- plugins/pychrysalide/core.c | 41 ++++-- plugins/pychrysalide/glibext/configuration.c | 25 ++-- plugins/pychrysalide/plugin.c | 127 +++++++++++++++++- plugins/python/scripting/core.py | 8 +- src/glibext/configuration.c | 22 +++- src/plugins/pglist.c | 2 +- src/plugins/pglist.h | 4 +- src/plugins/plugin-def.h | 9 +- src/plugins/plugin-int.h | 7 + src/plugins/plugin.c | 184 +++++++++++++++++++++++---- src/plugins/plugin.h | 7 + 12 files changed, 375 insertions(+), 64 deletions(-) diff --git a/plugins/pychrysalide/constants.c b/plugins/pychrysalide/constants.c index 53d4375..97cf43b 100644 --- a/plugins/pychrysalide/constants.c +++ b/plugins/pychrysalide/constants.c @@ -55,9 +55,10 @@ bool define_plugin_module_constants(PyTypeObject *type) if (result) result = add_const_to_group(values, "BASIC_NONE", PGA_BASIC_NONE); if (result) result = add_const_to_group(values, "PLUGIN_INIT", PGA_PLUGIN_INIT); + if (result) result = add_const_to_group(values, "PLUGIN_LOADED", PGA_PLUGIN_LOADED); if (result) result = add_const_to_group(values, "PLUGIN_EXIT", PGA_PLUGIN_EXIT); if (result) result = add_const_to_group(values, "NATIVE_PLUGINS_LOADED", PGA_NATIVE_PLUGINS_LOADED); - if (result) result = add_const_to_group(values, "PLUGINS_LOADED", PGA_PLUGINS_LOADED); + if (result) result = add_const_to_group(values, "ALL_PLUGINS_LOADED", PGA_ALL_PLUGINS_LOADED); if (result) result = add_const_to_group(values, "TYPE_BUILDING", PGA_TYPE_BUILDING); if (result) result = add_const_to_group(values, "GUI_THEME", PGA_GUI_THEME); if (result) result = add_const_to_group(values, "PANEL_CREATION", PGA_PANEL_CREATION); diff --git a/plugins/pychrysalide/core.c b/plugins/pychrysalide/core.c index ee88521..a148654 100644 --- a/plugins/pychrysalide/core.c +++ b/plugins/pychrysalide/core.c @@ -665,6 +665,8 @@ static void load_python_plugins(GPluginModule *plugin) char *modname; /* Nom du module pour Python */ char *filename; /* Chemin d'accès reconstruit */ GPluginModule *pyplugin; /* Lien vers un grffon Python */ + bool status; /* Bilan d'une opération */ + GGenConfig *config; /* Configuration à charger */ /* Définition des zones d'influence */ @@ -744,25 +746,42 @@ static void load_python_plugins(GPluginModule *plugin) pyplugin = g_python_plugin_new(modname, filename); if (pyplugin == NULL) + { g_plugin_module_log_variadic_message(plugin, LMT_ERROR, _("No suitable Python plugin found in '%s'"), filename); - else - { - g_plugin_module_log_variadic_message(plugin, LMT_PROCESS, - _("Loaded the Python plugin found in the '%s' directory"), - filename); + goto done_with_plugin; + } - /** - * Comme le greffon n'est pas passé par la résolution des dépendances, - * on simule l'effet attendu. - */ - g_object_ref(G_OBJECT(plugin)); + g_plugin_module_create_config(pyplugin); - _register_plugin(pyplugin); + status = g_plugin_module_manage(pyplugin, PGA_PLUGIN_LOADED); + if (!status) + { + g_plugin_module_log_variadic_message(plugin, LMT_ERROR, + _("Plugin '%s' failed to complete loading..."), filename); + goto done_with_plugin; } + config = g_plugin_module_get_config(pyplugin); + g_generic_config_read(config); + g_object_unref(G_OBJECT(config)); + + g_plugin_module_log_variadic_message(plugin, LMT_PROCESS, + _("Loaded the Python plugin found in the '%s' directory"), + filename); + + /** + * Comme le greffon n'est pas passé par la résolution des dépendances, + * on simule l'effet attendu. + */ + g_object_ref(G_OBJECT(plugin)); + + _register_plugin(pyplugin); + + done_with_plugin: + free(filename); free(modname); diff --git a/plugins/pychrysalide/glibext/configuration.c b/plugins/pychrysalide/glibext/configuration.c index b7d8f82..235662d 100644 --- a/plugins/pychrysalide/glibext/configuration.c +++ b/plugins/pychrysalide/glibext/configuration.c @@ -515,28 +515,27 @@ static PyObject *py_config_param_get_value(PyObject *self, void *closure) ) param = G_CFG_PARAM(pygobject_get(self)); + type = g_config_param_get_ptype(param); + g_config_param_get_value(param, &value); + switch (type) { case CPT_BOOLEAN: - g_config_param_get_value(param, &value.boolean); result = (value.boolean ? Py_True : Py_False); Py_INCREF(result); break; case CPT_INTEGER: - g_config_param_get_value(param, &value.integer); result = PyLong_FromLong(value.integer); break; case CPT_ULONG: - g_config_param_get_value(param, &value.ulong); result = PyLong_FromUnsignedLong(value.ulong); break; case CPT_STRING: - g_config_param_get_value(param, &value.string); if (value.string != NULL) result = PyUnicode_FromString(value.string); else @@ -547,7 +546,6 @@ static PyObject *py_config_param_get_value(PyObject *self, void *closure) break; case CPT_COLOR: - g_config_param_get_value(param, &value.color); result = create_gdk_rgba(&value.color); break; @@ -602,7 +600,8 @@ static int py_config_param_set_value(PyObject *self, PyObject *value, void *clos case CPT_BOOLEAN: if (PyBool_Check(value)) { - pvalue.boolean = (value == Py_True); + pvalue.integer = (value == Py_True); + g_config_param_set_value(param, pvalue.integer); result = 0; } break; @@ -611,6 +610,7 @@ static int py_config_param_set_value(PyObject *self, PyObject *value, void *clos if (PyLong_Check(value)) { pvalue.integer = PyLong_AsLong(value); + g_config_param_set_value(param, pvalue.integer); result = 0; } break; @@ -619,6 +619,7 @@ static int py_config_param_set_value(PyObject *self, PyObject *value, void *clos if (PyLong_Check(value)) { pvalue.ulong = PyLong_AsUnsignedLong(value); + g_config_param_set_value(param, pvalue.ulong); result = 0; } break; @@ -627,13 +628,17 @@ static int py_config_param_set_value(PyObject *self, PyObject *value, void *clos if (PyUnicode_Check(value)) { pvalue.string = PyUnicode_DATA(value); + g_config_param_set_value(param, pvalue.string); result = 0; } break; case CPT_COLOR: if (convert_to_gdk_rgba(value, &pvalue.color) == 1) + { + g_config_param_set_value(param, &pvalue.color); result = 0; + } break; default: @@ -642,9 +647,6 @@ static int py_config_param_set_value(PyObject *self, PyObject *value, void *clos } - if (result == 0) - g_config_param_set_value(param, &pvalue); - } return result; @@ -1303,7 +1305,7 @@ static PyObject *py_generic_config_search(PyObject *self, PyObject *args) else { result = pygobject_new(G_OBJECT(param)); - g_object_unref(G_OBJECT(param)); + //g_object_unref(G_OBJECT(param)); } return result; @@ -1359,6 +1361,7 @@ static PyObject *py_generic_config_add(PyObject *self, PyObject *args) config = G_GEN_CONFIG(pygobject_get(self)); + g_object_ref(G_OBJECT(param)); added = _g_generic_config_add_param(config, param, lock); if (added == NULL) @@ -1369,7 +1372,7 @@ static PyObject *py_generic_config_add(PyObject *self, PyObject *args) else { result = pygobject_new(G_OBJECT(added)); - g_object_unref(G_OBJECT(added)); + //g_object_unref(G_OBJECT(added)); } return result; diff --git a/plugins/pychrysalide/plugin.c b/plugins/pychrysalide/plugin.c index 495cecf..aa91fb8 100644 --- a/plugins/pychrysalide/plugin.c +++ b/plugins/pychrysalide/plugin.c @@ -57,6 +57,9 @@ static void py_plugin_module_init_gclass(GPluginModuleClass *, gpointer); /* Initialise une instance sur la base du dérivé de GObject. */ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds); +/* Encadre une étape de la vie d'un greffon. */ +static bool py_plugin_module_manage_wrapper(GPluginModule *); + /* Accompagne la fin du chargement des modules natifs. */ static void py_plugin_module_notify_plugins_loaded_wrapper(GPluginModule *, PluginAction); @@ -229,6 +232,7 @@ static PyObject *py_plugin_module_new(PyTypeObject *type, PyObject *args, PyObje static void py_plugin_module_init_gclass(GPluginModuleClass *class, gpointer unused) { class->init = NULL; + class->manage = py_plugin_module_manage_wrapper; class->exit = NULL; class->plugins_loaded = py_plugin_module_notify_plugins_loaded_wrapper; @@ -293,6 +297,7 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds) "\n" \ "Depending on the implemented actions, some of the following methods" \ " have to be defined for new classes:\n" \ + "* pychrysalide.PluginModule._init_config();\n" \ "* pychrysalide.PluginModule._notify_plugins_loaded();\n" \ "* pychrysalide.PluginModule._include_theme();\n" \ "* pychrysalide.PluginModule._on_panel_creation;\n" \ @@ -395,8 +400,71 @@ static int py_plugin_module_init(PyObject *self, PyObject *args, PyObject *kwds) /****************************************************************************** * * * Paramètres : plugin = greffon à manipuler. * +* * +* Description : Encadre une étape de la vie d'un greffon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_plugin_module_manage_wrapper(GPluginModule *plugin) +{ + bool result; /* Bilan à faire remonter */ + PyGILState_STATE gstate; /* Sauvegarde d'environnement */ + PyObject *pyobj; /* Objet Python concerné */ + PyObject *args; /* Arguments pour l'appel */ + PyObject *pyret; /* Bilan d'exécution */ + +#define PLUGIN_MODULE_MANAGE_WRAPPER PYTHON_WRAPPER_DEF \ +( \ + _manage, "$self, action, /", \ + METH_VARARGS, \ + "Abstract method called to react to several steps of the plugin" \ + " life.\n" \ + "\n" \ + "The expected action is a pychrysalide.PluginModule.PluginAction" \ + " value.\n" \ + "\n" \ + "This method has to be defined in order to handle actions such as" \ + " *PLUGIN_LOADED*." \ +) + + result = true; + + gstate = PyGILState_Ensure(); + + pyobj = pygobject_new(G_OBJECT(plugin)); + + if (has_python_method(pyobj, "_manage")) + { + args = PyTuple_New(1); + + PyTuple_SetItem(args, 0, PyLong_FromUnsignedLong(PGA_PLUGIN_LOADED)); + + pyret = run_python_method(pyobj, "_manage", args); + + result = (pyret == Py_True); + + Py_XDECREF(pyret); + Py_DECREF(args); + + } + + Py_DECREF(pyobj); + + PyGILState_Release(gstate); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * * action = type d'action attendue. * -* unused = variable non utilisé pour l'usage de __VA_ARGS__. * * * * Description : Accompagne la fin du chargement des modules natifs. * * * @@ -1629,6 +1697,61 @@ static PyObject *py_plugin_module_get_filename(PyObject *self, void *closure) /****************************************************************************** * * +* Paramètres : self = objet Python concerné par l'appel. * +* closure = non utilisé ici. * +* * +* Description : Fournit la configuration mise en place pour le greffon. * +* * +* Retour : Configuration dédiée à l'extension. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_plugin_module_get_config(PyObject *self, void *closure) +{ + PyObject *result; /* Valeur à retourner */ + GPluginModule *plugin; /* Version native du greffon */ + GGenConfig *config; /* Configuration associée */ + +#define PLUGIN_MODULE_CONFIG_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + config, py_plugin_module, \ + "Dedicated configuration for the plugin." \ + "\n" \ + "The value is a pychrysalide.glibext.GenConfig instance" \ + " or None if the configuration is not yet created.\n" \ + "\n" \ + "As configuration storage path depends on the plugin name," \ + " all plugin properties have to get fully loaded by the" \ + " core before the configuration can be setup." \ + "automatically" \ +) + + plugin = G_PLUGIN_MODULE(pygobject_get(self)); + config = g_plugin_module_get_config(plugin); + + if (config == NULL) + { + result = Py_None; + Py_INCREF(result); + } + + else + { + result = pygobject_new(G_OBJECT(config)); + + g_object_unref(G_OBJECT(config)); + + } + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -1642,6 +1765,7 @@ static PyObject *py_plugin_module_get_filename(PyObject *self, void *closure) PyTypeObject *get_python_plugin_module_type(void) { static PyMethodDef py_plugin_module_methods[] = { + PLUGIN_MODULE_MANAGE_WRAPPER, PLUGIN_MODULE_NOTIFY_PLUGINS_LOADED_WRAPPER, PLUGIN_MODULE_INCLUDE_THEME_WRAPPER, PLUGIN_MODULE_ON_PANEL_CREATION_WRAPPER, @@ -1661,6 +1785,7 @@ PyTypeObject *get_python_plugin_module_type(void) static PyGetSetDef py_plugin_module_getseters[] = { PLUGIN_MODULE_MODNAME_ATTRIB, PLUGIN_MODULE_FILENAME_ATTRIB, + PLUGIN_MODULE_CONFIG_ATTRIB, { NULL } }; diff --git a/plugins/python/scripting/core.py b/plugins/python/scripting/core.py index c46ef07..1b91688 100644 --- a/plugins/python/scripting/core.py +++ b/plugins/python/scripting/core.py @@ -19,7 +19,7 @@ class ScriptingEngine(PluginModule): _version = '0.1' _url = 'https://www.chrysalide.re/' - _actions = ( PluginModule.PluginAction.PLUGINS_LOADED, PluginModule.PluginAction.PANEL_CREATION ) + _actions = ( PluginModule.PluginAction.PLUGIN_LOADED, PluginModule.PluginAction.PANEL_CREATION ) _manager = None @@ -64,15 +64,17 @@ class ScriptingEngine(PluginModule): file_menu.insert(item, index) - def _notify_plugins_loaded(self, action): + def _manage(self, action): """Ack the full loading of all plugins.""" - if action == PluginModule.PluginAction.PLUGINS_LOADED: + if action == PluginModule.PluginAction.PLUGIN_LOADED: xbel = self.build_config_filename('recents.xbel', True) ScriptingEngine._manager = Gtk.RecentManager(filename=xbel) + return True + def _on_panel_creation(self, action, item): """Get notified of a new panel creation.""" diff --git a/src/glibext/configuration.c b/src/glibext/configuration.c index 1fa2968..8746bfd 100644 --- a/src/glibext/configuration.c +++ b/src/glibext/configuration.c @@ -1323,14 +1323,21 @@ void g_generic_config_build(GGenConfig *config, const char *name) { char *suffix; /* Fin du nom de fichier */ - suffix = strdup("chrysalide"); - suffix = stradd(suffix, G_DIR_SEPARATOR_S); - suffix = stradd(suffix, name); - suffix = stradd(suffix, ".xml"); + if (g_path_is_absolute(name)) + config->filename = strdup(name); - config->filename = get_xdg_config_dir(suffix); + else + { + suffix = strdup("chrysalide"); + suffix = stradd(suffix, G_DIR_SEPARATOR_S); + suffix = stradd(suffix, name); + suffix = stradd(suffix, ".xml"); + + config->filename = get_xdg_config_dir(suffix); - free(suffix); + free(suffix); + + } } @@ -1468,7 +1475,8 @@ bool g_generic_config_write(GGenConfig *config) g_generic_config_runlock(config); - save_xml_file(xdoc, config->filename); + if (result) + result = save_xml_file(xdoc, config->filename); close_xml_file(xdoc, context); diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c index ffcda63..c1d96ed 100644 --- a/src/plugins/pglist.c +++ b/src/plugins/pglist.c @@ -472,7 +472,7 @@ void load_remaning_plugins(void) notify_native_plugins_loaded(); - notify_plugins_loaded(); + notify_all_plugins_loaded(); } diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h index d6c539d..a380844 100644 --- a/src/plugins/pglist.h +++ b/src/plugins/pglist.h @@ -110,8 +110,8 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); #define notify_native_plugins_loaded() \ process_all_plugins_for(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL) -#define notify_plugins_loaded() \ - process_all_plugins_for(PGA_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL) +#define notify_all_plugins_loaded() \ + process_all_plugins_for(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL) #define build_type_instance(t) \ process_plugins_while_null(PGA_TYPE_BUILDING, g_plugin_module_build_type_instance, t) diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index 0c25a7a..1118140 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -113,8 +113,11 @@ typedef enum _PluginAction /* Chargement */ PGA_PLUGIN_INIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(0), + /* Chargement des paramètres */ + PGA_PLUGIN_LOADED = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(1), + /* Déchargement */ - PGA_PLUGIN_EXIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(1), + PGA_PLUGIN_EXIT = DPC_BASIC | DPS_PG_MANAGEMENT | DEFINE_PLUGIN_ACTION(2), /** * DPC_BASIC | DPS_CORE_MANAGEMENT @@ -124,10 +127,10 @@ typedef enum _PluginAction PGA_NATIVE_PLUGINS_LOADED = DPC_BASIC | DPS_CORE_MANAGEMENT | DEFINE_PLUGIN_ACTION(0), /* Fin du chargement de tous greffons */ - PGA_PLUGINS_LOADED = DPC_BASIC | DPS_CORE_MANAGEMENT | DEFINE_PLUGIN_ACTION(1), + PGA_ALL_PLUGINS_LOADED = DPC_BASIC | DPS_CORE_MANAGEMENT | DEFINE_PLUGIN_ACTION(1), /* Mise en place de type à partir de code externe */ - PGA_TYPE_BUILDING = DPC_BASIC | DPS_CORE_MANAGEMENT | DEFINE_PLUGIN_ACTION(2), + PGA_TYPE_BUILDING = DPC_BASIC | DPS_CORE_MANAGEMENT | DEFINE_PLUGIN_ACTION(2), /** * DPC_GUI | DPS_SETUP diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index 98a07bb..88e0fbb 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -96,6 +96,8 @@ struct _GPluginModule bitfield_t *dependencies; /* Cartographie des dépendances*/ + GGenConfig *config; /* Configuration dédiée */ + }; @@ -105,6 +107,7 @@ struct _GPluginModuleClass GObjectClass parent; /* A laisser en premier */ pg_management_fc init; /* Procédure d'initialisation */ + pg_management_fc manage; /* Etape dans la vie du greffon*/ pg_management_fc exit; /* Procédure d'extinction */ pg_plugins_loaded_fc plugins_loaded; /* Fin des chargements */ @@ -130,5 +133,9 @@ struct _GPluginModuleClass }; +/* Met en place la configuration dédiée au greffon. */ +void g_plugin_module_create_config(GPluginModule *); + + #endif /* _PLUGINS_PLUGIN_INT_H */ diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 23ef34c..e563817 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -112,6 +112,7 @@ static void g_plugin_module_class_init(GPluginModuleClass *class) static void g_plugin_module_init(GPluginModule *plugin) { + plugin->config = NULL; } @@ -167,6 +168,14 @@ static void g_plugin_module_dispose(GPluginModule *plugin) if (class->exit != NULL) class->exit(plugin); + if (plugin->config != NULL) + { + g_generic_config_write(plugin->config); + + g_clear_object(&plugin->config); + + } + if (plugin->module != NULL) { g_module_close(plugin->module); @@ -306,6 +315,10 @@ GPluginModule *g_plugin_module_new(const gchar *filename) valid = check_plugin_symbol(module, "chrysalide_plugin_init"); break; + case PGA_PLUGIN_LOADED: + valid = check_plugin_symbol(module, "chrysalide_plugin_manage"); + break; + case PGA_PLUGIN_EXIT: valid = check_plugin_symbol(module, "chrysalide_plugin_exit"); break; @@ -325,7 +338,7 @@ GPluginModule *g_plugin_module_new(const gchar *filename) switch (action) { case PGA_NATIVE_PLUGINS_LOADED: - case PGA_PLUGINS_LOADED: + case PGA_ALL_PLUGINS_LOADED: valid = check_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded"); break; @@ -600,6 +613,10 @@ static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *modu load_plugin_symbol(module, "chrysalide_plugin_init", &class->init); break; + case PGA_PLUGIN_LOADED: + load_plugin_symbol(module, "chrysalide_plugin_manage", &class->manage); + break; + case PGA_PLUGIN_EXIT: load_plugin_symbol(module, "chrysalide_plugin_exit", &class->exit); break; @@ -617,7 +634,7 @@ static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *modu switch (action) { case PGA_NATIVE_PLUGINS_LOADED: - case PGA_PLUGINS_LOADED: + case PGA_ALL_PLUGINS_LOADED: load_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded", &class->plugins_loaded); break; @@ -1039,6 +1056,7 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co size_t i; /* Boucle de parcours */ GPluginModule *dependency; /* Module nécessaire */ GPluginModuleClass *class; /* Classe de l'instance active */ + GGenConfig *config; /* Configuration à charger */ char *dir; /* Répertoire modifiable */ /* Si un essai précédent a déjà échoué ou réussi... */ @@ -1067,47 +1085,63 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co } if (!result) + { log_variadic_message(LMT_ERROR, _("Some dependencies failed to load for plugin '%s'"), plugin->filename); + goto failure; + } /* Chargement du greffon courant */ - if (result) + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + if (class->init != NULL) { - class = G_PLUGIN_MODULE_GET_CLASS(plugin); + result = class->init(plugin); - if (class->init != NULL) + if (!result) { - result = class->init(plugin); + log_variadic_message(LMT_ERROR, + _("Plugin '%s' failed to load itself..."), plugin->filename); - if (!result) - { - log_variadic_message(LMT_ERROR, - _("Plugin '%s' failed to load itself..."), plugin->filename); - - plugin->flags |= PSF_FAILURE; - - } + plugin->flags |= PSF_FAILURE; + goto failure; } - if (result) - { - dir = strdup(plugin->filename); - dir = dirname(dir); + } - log_variadic_message(LMT_PROCESS, - _("Loaded the '%s' file as plugin from the '%s' directory"), - strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir); + g_plugin_module_create_config(plugin); - free(dir); + result = g_plugin_module_manage(plugin, PGA_PLUGIN_LOADED); - plugin->flags |= PSF_LOADED; + if (!result) + { + log_variadic_message(LMT_ERROR, + _("Plugin '%s' failed to complete loading..."), plugin->filename); - } + plugin->flags |= PSF_FAILURE; + goto failure; } + config = g_plugin_module_get_config(plugin); + g_generic_config_read(config); + g_object_unref(G_OBJECT(config)); + + dir = strdup(plugin->filename); + dir = dirname(dir); + + log_variadic_message(LMT_PROCESS, + _("Loaded the '%s' file as plugin from the '%s' directory"), + strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir); + + free(dir); + + plugin->flags |= PSF_LOADED; + + failure: + return result; } @@ -1168,6 +1202,57 @@ char *g_plugin_module_build_config_filename(const GPluginModule *plugin, const c /****************************************************************************** * * +* Paramètres : plugin = greffon à compléter. * +* * +* Description : Met en place la configuration dédiée au greffon. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_plugin_module_create_config(GPluginModule *plugin) +{ + char *filename; /* Chemin d'accès particulier */ + + filename = g_plugin_module_build_config_filename(plugin, "config.xml", false); + + plugin->config = g_generic_config_new_from_file(filename); + + free(filename); + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à consulter. * +* * +* Description : Fournit la configuration mise en place pour le greffon. * +* * +* Retour : Configuration dédiée à l'extension. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGenConfig *g_plugin_module_get_config(const GPluginModule *plugin) +{ + GGenConfig *result; /* Configuration à faire suivre*/ + + result = plugin->config; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : plugin = greffon à consulter. * * msg = message à faire apparaître à l'écran. * * * @@ -1238,6 +1323,57 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag * * * Paramètres : plugin = greffon à manipuler. * * action = type d'action attendue. * +* * +* Description : Encadre une étape de la vie d'un greffon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_plugin_module_manage(GPluginModule *plugin, PluginAction action) +{ + bool result; /* Bilan à faire remonter */ + GPluginModuleClass *class; /* Classe de l'instance active */ + const plugin_interface *pg_iface; /* Informations à consulter */ + size_t i; /* Boucle de parcours */ + bool handle_action; /* Action supportée ? */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + if (class->manage == NULL) + result = true; + + else + { + handle_action = false; + + pg_iface = g_plugin_module_get_interface(plugin); + + for (i = 0; i < pg_iface->actions_count; i++) + if (pg_iface->actions[i] == PGA_PLUGIN_LOADED) + { + handle_action = true; + break; + } + + if (handle_action) + result = class->manage(plugin/*, action*/); + else + result = true; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à manipuler. * +* action = type d'action attendue. * * unused = variable non utilisé pour l'usage de __VA_ARGS__. * * * * Description : Accompagne la fin du chargement des modules. * diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index fc54aee..ff456b3 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -35,6 +35,7 @@ #include "../format/format.h" #include "../format/known.h" #include "../format/preload.h" +#include "../glibext/configuration.h" #include "../gtkext/gtkstatusstack.h" #include "../gui/panel.h" @@ -100,12 +101,18 @@ bool g_plugin_module_load(GPluginModule *, GPluginModule **, size_t); /* Construit le nom d'un fichier de configuration du greffon. */ char *g_plugin_module_build_config_filename(const GPluginModule *, const char *, bool); +/* Fournit la configuration mise en place pour le greffon. */ +GGenConfig *g_plugin_module_get_config(const GPluginModule *); + /* Présente dans le journal un message simple. */ void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, const char *); /* Présente dans le journal un message complexe. */ void g_plugin_module_log_variadic_message(const GPluginModule *, LogMessageType, const char *, ...); +/* Encadre une étape de la vie d'un greffon. */ +bool g_plugin_module_manage(GPluginModule *, PluginAction); + /* Accompagne la fin du chargement des modules natifs. */ void g_plugin_module_notify_plugins_loaded(GPluginModule *, PluginAction, void *); -- cgit v0.11.2-87-g4458