From 2a0b25fca5f6d4bef7edd4d618e420559209e8ec Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Mon, 21 Feb 2022 00:22:59 +0100
Subject: Translate enumerations before PyGObject using internal definitions
 when needed.

---
 plugins/pychrysalide/helpers.c | 104 +++++++++++++++++++++++++++++++++++++++--
 plugins/pychrysalide/helpers.h |  54 +++++++++++++++------
 2 files changed, 139 insertions(+), 19 deletions(-)

diff --git a/plugins/pychrysalide/helpers.c b/plugins/pychrysalide/helpers.c
index 92a5db9..320e40a 100644
--- a/plugins/pychrysalide/helpers.c
+++ b/plugins/pychrysalide/helpers.c
@@ -1440,15 +1440,15 @@ int convert_to_gdk_rgba(PyObject *arg, void *dst)
 *                                                                             *
 *  Description : Officialise un groupe de constantes avec sémentique.         *
 *                                                                             *
-*  Retour      : true en cas de succès de l'opération, false sinon.           *
+*  Retour      : Groupe de constantes mis en place ou NULL en cas d'échec.    *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc)
+PyObject *_attach_constants_group(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc)
 {
-    bool result;                            /* Bilan à retourner           */
+    PyObject *result;                       /* Instance à retourner        */
     PyObject *enum_mod;                     /* Module Python enum          */
     PyObject *class;                        /* Classe "Enum*"              */
     PyObject *str_obj;                      /* Conversion en Python        */
@@ -1462,7 +1462,7 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons
     PyObject *features;                     /* Module à recompléter        */
     PyObject *features_dict;                /* Dictionnaire à compléter    */
 
-    result = false;
+    result = NULL;
 
     /* Recherche de la classe Python */
 
@@ -1539,7 +1539,8 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons
     ret = PyDict_SetItemString(features_dict, name, new);
     if (ret != 0) goto register_1_error;
 
-    result = true;
+    result = new;
+    Py_INCREF(result);
 
     /* Sortie propre */
 
@@ -1570,6 +1571,99 @@ bool _attach_constants_group(const char *owner, PyObject *dict, bool flags, cons
 
 }
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : owner  = désignation du propriétaire du dictionnaire visé.   *
+*                dict   = dictionnaire dont le contenu est à compléter.       *
+*                flags  = indique le type d'énumération ciblée.               *
+*                name   = désignation humaine du groupe à constituer.         *
+*                values = noms et valeurs associées.                          *
+*                doc    = documentation à associer au groupe.                 *
+*                gtype  = énumération GLib à lier.                            *
+*                                                                             *
+*  Description : Officialise un groupe de constantes avec lien GLib.          *
+*                                                                             *
+*  Retour      : Groupe de constantes mis en place ou NULL en cas d'échec.    *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+PyObject *_attach_constants_group_with_pyg_enum(const char *owner, PyObject *dict, bool flags, const char *name, PyObject *values, const char *doc, GType gtype)
+{
+    PyObject *result;                       /* Instance à retourner        */
+    PyObject *values_set;                   /* Zone pour nouvelles valeurs */
+    int ret;                                /* Bilan d'une insertion       */
+    PyObject *new;                          /* Nouvelle instance en place  */
+    PyObject *values_src;                   /* Source de nouvelles valeurs */
+    PyObject *values_dest;                  /* Destination des valeurs     */
+
+    static GQuark pygenum_class_key = 0;    /* Clef d'accès au marquage    */
+
+    result = NULL;
+
+    /**
+     * Le seul intérêt d'un tel enregistrement en bonne et due forme est de
+     * permettre une impression, via str() ou repr(), de l'énumération
+     * transcrite en GLib via g_enum_register_static() et potentiellement
+     * convertie de façon brusque par _pygi_argument_to_object(), lors d'une
+     * émission de signal par exemple.
+     *
+     * La satisfaction de la fonction pyg_enum_from_gtype() est ainsi recherchée.
+     * Tous les éléments sont normalement mis en place à partir de la fonction
+     * pyg_enum_add().
+     */
+
+    /* Préparation du réceptacle */
+
+    values_set = PyDict_New();
+
+    ret = PyDict_SetItemString(values, "__enum_values__", values_set);
+
+    Py_DECREF(values_set);
+
+    if (ret != 0) goto exit;
+
+    /* Création */
+
+    new = _attach_constants_group(owner, dict, flags, name, values, doc);
+    if (new == NULL) goto exit;
+
+    /* Actualisation des valeurs */
+
+    values_src = PyDict_GetItemString(((PyTypeObject *)new)->tp_dict, "_value2member_map_");
+    if (values_src == NULL) goto exit_without_src;
+
+    values_dest = PyDict_GetItemString(((PyTypeObject *)new)->tp_dict, "__enum_values__");
+    if (values_dest == NULL) goto exit_without_dest;
+
+    assert(values_dest == values_set);
+
+    ret = PyDict_Merge(values_dest, values_src, true);
+
+    if (ret == 0)
+    {
+        result = new;
+        Py_INCREF(result);
+
+        if (pygenum_class_key == 0)
+            pygenum_class_key = g_quark_from_static_string("PyGEnum::class");
+
+        g_type_set_qdata(gtype, pygenum_class_key, result);
+
+    }
+
+ exit_without_dest:
+ exit_without_src:
+
+    Py_DECREF(new);
+
+ exit:
+
+    return result;
+
+}
+
 
 /******************************************************************************
 *                                                                             *
diff --git a/plugins/pychrysalide/helpers.h b/plugins/pychrysalide/helpers.h
index 931be95..0ef8adc 100644
--- a/plugins/pychrysalide/helpers.h
+++ b/plugins/pychrysalide/helpers.h
@@ -308,20 +308,46 @@ int convert_to_gdk_rgba(PyObject *, void *);
     })
 
 /* Officialise un groupe de constantes avec sémentique. */
-bool _attach_constants_group(const char *, PyObject *, bool, const char *, PyObject *, const char *);
-
-#define attach_constants_group_to_type(type, flags, name, values, doc) \
-    _attach_constants_group(type->tp_name, type->tp_dict, flags, name, values, doc)
-
-#define attach_constants_group_to_module(mod, flags, name, values, doc)                 \
-    ({                                                                                  \
-        bool __result;                                                                  \
-        const char *__owner;                                                            \
-        PyObject *__dict;                                                               \
-        __owner = PyModule_GetName(mod);                                                \
-        __dict = PyModule_GetDict(mod);                                                 \
-        __result = _attach_constants_group(__owner, __dict, flags, name, values, doc);  \
-        __result;                                                                       \
+PyObject *_attach_constants_group(const char *, PyObject *, bool, const char *, PyObject *, const char *);
+
+#define attach_constants_group_to_type(type, flags, name, values, doc)                      \
+    ({                                                                                      \
+        bool __result;                                                                      \
+        PyObject *__new;                                                                    \
+        __new = _attach_constants_group(type->tp_name, type->tp_dict, flags, name, values,  \
+                                        doc);                                               \
+        __result = (__new != NULL);                                                         \
+        Py_XDECREF(__new);                                                                  \
+        __result;                                                                           \
+    })
+
+#define attach_constants_group_to_module(mod, flags, name, values, doc)                     \
+    ({                                                                                      \
+        bool __result;                                                                      \
+        const char *__owner;                                                                \
+        PyObject *__dict;                                                                   \
+        PyObject *__new;                                                                    \
+        __owner = PyModule_GetName(mod);                                                    \
+        __dict = PyModule_GetDict(mod);                                                     \
+        __new = _attach_constants_group(__owner, __dict, flags, name, values, doc);         \
+        __result = (__new != NULL);                                                         \
+        Py_XDECREF(__new);                                                                  \
+        __result;                                                                           \
+    })
+
+/* Officialise un groupe de constantes avec lien GLib. */
+PyObject *_attach_constants_group_with_pyg_enum(const char *, PyObject *, bool, const char *, PyObject *, const char *, GType);
+
+
+#define attach_constants_group_to_type_with_pyg_enum(type, flags, name, values, doc, gtype) \
+    ({                                                                                      \
+        bool __result;                                                                      \
+        PyObject *__new;                                                                    \
+        __new = _attach_constants_group_with_pyg_enum(type->tp_name, type->tp_dict, flags,  \
+                                                      name, values, doc, gtype);            \
+        __result = (__new != NULL);                                                         \
+        Py_XDECREF(__new);                                                                  \
+        __result;                                                                           \
     })
 
 /* Traduit une valeur constante C en équivalent Python. */
-- 
cgit v0.11.2-87-g4458