From 8965133f188c817cbdf4fcf9d1f1b60462bbfe7d Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
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 '<b>%s</b>' 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 '<b>%s</b>' 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 '<b>%s</b>' file as plugin from the '<b>%s</b>' 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 '<b>%s</b>' file as plugin from the '<b>%s</b>' 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