From dcd5e0b104143b110997029aa0728731f4087ad8 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 2 Jan 2021 00:20:42 +0100 Subject: Managed GObject references each time a configuration parameter is accessed. --- plugins/pychrysalide/glibext/configuration.c | 42 ++++++------ src/analysis/cattribs.c | 4 ++ src/core/params.c | 98 ++++++++++++++-------------- src/glibext/configuration.c | 78 +++++++++++++++------- src/glibext/configuration.h | 44 +++++++++---- src/gui/panel.c | 19 ++---- tests/glibext/configuration.py | 37 ++++++++++- 7 files changed, 201 insertions(+), 121 deletions(-) diff --git a/plugins/pychrysalide/glibext/configuration.c b/plugins/pychrysalide/glibext/configuration.c index 235662d..b0586af 100644 --- a/plugins/pychrysalide/glibext/configuration.c +++ b/plugins/pychrysalide/glibext/configuration.c @@ -856,10 +856,8 @@ static PyObject *py_config_param_iterator_next(PyObject *self) iterator->last = item; if (item != NULL) - { result = pygobject_new(G_OBJECT(item->data)); - Py_INCREF(result); - } + else { PyErr_SetNone(PyExc_StopIteration); @@ -1098,7 +1096,7 @@ static int py_generic_config_init(PyObject *self, PyObject *args, PyObject *kwds name = NULL; - ret = PyArg_ParseTuple(args, "s", &name); + ret = PyArg_ParseTuple(args, "|s", &name); if (!ret) return -1; /* Initialisation d'un objet GLib */ @@ -1110,7 +1108,8 @@ static int py_generic_config_init(PyObject *self, PyObject *args, PyObject *kwds config = G_GEN_CONFIG(pygobject_get(self)); - g_generic_config_build(config, name); + if (name != NULL) + g_generic_config_build(config, name); return 0; @@ -1305,7 +1304,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; @@ -1333,7 +1332,7 @@ static PyObject *py_generic_config_add(PyObject *self, PyObject *args) GCfgParam *param; /* Paramètre GLib transmis */ int ret; /* Bilan de lecture des args. */ GGenConfig *config; /* Version GLib de la config. */ - GCfgParam *added; /* Elément ajouté ou NULL */ + bool status; /* Bilan de l'opération */ #define GENERIC_CONFIG_ADD_METHOD PYTHON_METHOD_DEF \ ( \ @@ -1361,19 +1360,10 @@ 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); + status = _g_generic_config_add_param(config, param, lock); - if (added == NULL) - { - result = Py_None; - Py_INCREF(result); - } - else - { - result = pygobject_new(G_OBJECT(added)); - //g_object_unref(G_OBJECT(added)); - } + result = status ? Py_True : Py_False; + Py_INCREF(result); return result; @@ -1436,6 +1426,7 @@ static PyObject *py_generic_config_delete(PyObject *self, PyObject *args) static PyObject *py_generic_config_get_filename(PyObject *self, void *closure) { + PyObject *result; /* Chemin à retourner */ GGenConfig *config; /* Version GLib de la config. */ const char *filename; /* Chemin d'accès au fichier */ @@ -1446,14 +1437,23 @@ static PyObject *py_generic_config_get_filename(PyObject *self, void *closure) " configuration.\n" \ "\n" \ "The result is a string pointing to a file which may not" \ - " (yet) exist." \ + " (yet) exist or None if not defined." \ ) config = G_GEN_CONFIG(pygobject_get(self)); filename = g_generic_config_get_filename(config); - return PyUnicode_FromString(filename); + if (filename == NULL) + { + result = Py_None; + Py_INCREF(result); + } + + else + result = PyUnicode_FromString(filename); + + return result; } diff --git a/src/analysis/cattribs.c b/src/analysis/cattribs.c index ebebb83..704e665 100644 --- a/src/analysis/cattribs.c +++ b/src/analysis/cattribs.c @@ -297,6 +297,8 @@ const char **g_content_attributes_get_keys(const GContentAttributes *attribs, si result = NULL; *count = 0; + g_generic_config_rlock(attribs->configs[0]); + list = g_generic_config_list_params(attribs->configs[0]); for (iter = g_list_first(list); iter != NULL; iter = g_list_next(iter)) @@ -311,6 +313,8 @@ const char **g_content_attributes_get_keys(const GContentAttributes *attribs, si } + g_generic_config_runlock(attribs->configs[0]); + return result; } diff --git a/src/core/params.c b/src/core/params.c index 25f8991..c05ce68 100644 --- a/src/core/params.c +++ b/src/core/params.c @@ -38,87 +38,89 @@ bool load_main_config_parameters(void) { + bool result; /* Bilan à retourner */ GGenConfig *config; /* Configuration à charger */ - GCfgParam *param; /* Paramètre chargé */ config = g_generic_config_new_from_file("main"); set_main_configuration(config); - param = g_generic_config_create_param(config, MPK_FORMAT_NO_NAME, CPT_BOOLEAN, false); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_FORMAT_NO_NAME, CPT_BOOLEAN, false); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_INTERNAL_THEME, CPT_STRING, "Adwaita"); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_INTERNAL_THEME, CPT_STRING, "Adwaita"); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_TITLE_BAR, CPT_BOOLEAN, true); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_TITLE_BAR, CPT_BOOLEAN, true); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_LAST_PROJECT, CPT_STRING, NULL); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_LAST_PROJECT, CPT_STRING, NULL); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_SKIP_EXIT_MSG, CPT_BOOLEAN, false); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_SKIP_EXIT_MSG, CPT_BOOLEAN, false); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_MAXIMIZED, CPT_BOOLEAN, true); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_MAXIMIZED, CPT_BOOLEAN, true); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_ELLIPSIS_HEADER, CPT_INTEGER, 54); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_ELLIPSIS_HEADER, CPT_INTEGER, 54); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_ELLIPSIS_TAB, CPT_INTEGER, 35); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_ELLIPSIS_TAB, CPT_INTEGER, 35); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_WELCOME_STARTUP, CPT_BOOLEAN, true); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_WELCOME_STARTUP, CPT_BOOLEAN, true); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_WELCOME_CHECK, CPT_BOOLEAN, false); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_WELCOME_CHECK, CPT_BOOLEAN, false); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_LABEL_OFFSET, CPT_INTEGER, 10); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_LABEL_OFFSET, CPT_INTEGER, 10); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_HEX_PADDING, CPT_INTEGER, 10); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_HEX_PADDING, CPT_INTEGER, 10); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_SELECTION_LINE, CPT_BOOLEAN, true); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_SELECTION_LINE, CPT_BOOLEAN, true); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_TOOLTIP_MAX_CALLS, CPT_INTEGER, 5); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_TOOLTIP_MAX_CALLS, CPT_INTEGER, 5); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_TOOLTIP_MAX_STRINGS, CPT_INTEGER, 5); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_TOOLTIP_MAX_STRINGS, CPT_INTEGER, 5); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_HEX_UPPER_CASE, CPT_BOOLEAN, true); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_HEX_UPPER_CASE, CPT_BOOLEAN, true); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_LINK_DEFAULT, CPT_COLOR, ((GdkRGBA []) { { 0, 0, 0, 1.0 } })); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_LINK_DEFAULT, CPT_COLOR, ((GdkRGBA []) { { 0, 0, 0, 1.0 } })); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_LINK_BRANCH_TRUE, CPT_COLOR, ((GdkRGBA []) { { 0, 0.6, 0, 1.0 } })); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_LINK_BRANCH_TRUE, CPT_COLOR, ((GdkRGBA []) { { 0, 0.6, 0, 1.0 } })); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_LINK_BRANCH_FALSE, CPT_COLOR, ((GdkRGBA []) { { 0.8, 0, 0, 1.0 } })); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_LINK_BRANCH_FALSE, CPT_COLOR, ((GdkRGBA []) { { 0.8, 0, 0, 1.0 } })); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_LINK_LOOP, CPT_COLOR, ((GdkRGBA []) { { 0, 0, 0.8, 1.0 } })); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_LINK_LOOP, CPT_COLOR, ((GdkRGBA []) { { 0, 0, 0.8, 1.0 } })); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_KEYBINDINGS_EDIT, CPT_STRING, "F2"); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_KEYBINDINGS_EDIT, CPT_STRING, "F2"); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_TMPDIR, CPT_STRING, "/tmp/chrysalide"); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_TMPDIR, CPT_STRING, "/tmp/chrysalide"); + if (!result) goto exit; - param = g_generic_config_create_param(config, MPK_AUTO_SAVE, CPT_BOOLEAN, true); - if (param == NULL) return false; + result = g_generic_config_create_param(config, MPK_AUTO_SAVE, CPT_BOOLEAN, true); + if (!result) goto exit; g_generic_config_create_group(config, "gui.panels.positions", CPT_INTEGER); g_generic_config_create_group(config, "gui.panels.dock_at_startup", CPT_BOOLEAN); g_generic_config_create_group(config, "gui.panels.path", CPT_STRING); - return true; + exit: + + return result; } diff --git a/src/glibext/configuration.c b/src/glibext/configuration.c index b4eb784..5bc94a7 100644 --- a/src/glibext/configuration.c +++ b/src/glibext/configuration.c @@ -942,7 +942,7 @@ void g_config_param_set_value(GCfgParam *param, ...) * * ******************************************************************************/ -void g_config_param_get_value(GCfgParam *param, ...) +void g_config_param_get_value(const GCfgParam *param, ...) { va_list ap; /* Liste d'arguments */ @@ -1135,6 +1135,7 @@ static void g_config_group_load(GCfgGroup *group, GGenConfig *config, xmlXPathCo param = g_config_param_new_empty(key, group->type); _g_generic_config_add_param(config, param, false); + g_object_unref(G_OBJECT(param)); free(key); @@ -1358,7 +1359,11 @@ void g_generic_config_build(GGenConfig *config, const char *name) const char *g_generic_config_get_filename(const GGenConfig *config) { - return config->filename; + char *result; /* Chemin à retourner */ + + result = config->filename; + + return result; } @@ -1463,24 +1468,33 @@ bool g_generic_config_write(GGenConfig *config) xmlXPathContextPtr context; /* Contexte de recherche XPath */ GList *iter; /* Boucle de parcours */ - if (!create_new_xml_file(&xdoc, &context)) - return false; - - g_generic_config_rlock(config); + if (config->filename == NULL) + result = false; - for (result = true, iter = g_list_first(config->params); - result && iter != NULL; - iter = g_list_next(iter)) + else { - result = g_config_param_write(G_CFG_PARAM(iter->data), xdoc, context); - } + result = create_new_xml_file(&xdoc, &context); + if (!result) goto exit; - g_generic_config_runlock(config); + g_generic_config_rlock(config); - if (result) - result = save_xml_file(xdoc, config->filename); + for (iter = g_list_first(config->params); + result && iter != NULL; + iter = g_list_next(iter)) + { + result = g_config_param_write(G_CFG_PARAM(iter->data), xdoc, context); + } - close_xml_file(xdoc, context); + g_generic_config_runlock(config); + + if (result) + result = save_xml_file(xdoc, config->filename); + + close_xml_file(xdoc, context); + + } + + exit: return result; @@ -1504,6 +1518,8 @@ void g_generic_config_add_group(GGenConfig *config, GCfgGroup *group) { g_generic_config_wlock(config); + g_object_ref(G_OBJECT(group)); + config->groups = g_list_append(config->groups, group); g_generic_config_wunlock(config); @@ -1527,6 +1543,7 @@ void g_generic_config_add_group(GGenConfig *config, GCfgGroup *group) GCfgParam *_g_generic_config_search(GGenConfig *config, const char *path, bool lock) { + GCfgParam *result; /* Instance à retourner */ GList *item; /* Elément générique de liste */ GCfgParam fake; /* Faux élément partiel */ @@ -1538,10 +1555,15 @@ GCfgParam *_g_generic_config_search(GGenConfig *config, const char *path, bool l item = g_list_find_custom(config->params, &fake, (GCompareFunc)g_config_param_compare); + result = item ? item->data : NULL; + + if (result != NULL) + g_object_ref(G_OBJECT(result)); + if (lock) g_generic_config_runlock(config); - return item ? item->data : NULL; + return result; } @@ -1554,14 +1576,15 @@ GCfgParam *_g_generic_config_search(GGenConfig *config, const char *path, bool l * * * Description : Ajoute un paramètre à une configuration. * * * -* Retour : Elément mis en place ou NULL en cas d'erreur. * +* Retour : Validation de l'ajout : true ou false. * * * * Remarques : - * * * ******************************************************************************/ -GCfgParam *_g_generic_config_add_param(GGenConfig *config, GCfgParam *param, bool lock) +bool _g_generic_config_add_param(GGenConfig *config, GCfgParam *param, bool lock) { + bool result; /* Bilan à retourner */ const char *path; /* Chemin d'accès unique */ GCfgParam *old; /* Test de présence */ @@ -1573,20 +1596,25 @@ GCfgParam *_g_generic_config_add_param(GGenConfig *config, GCfgParam *param, boo old = _g_generic_config_search(config, path, false); if (old != NULL) { - g_clear_object(¶m); + g_object_unref(G_OBJECT(old)); + result = false; goto exit; } + g_object_ref(G_OBJECT(param)); + config->params = g_list_append(config->params, param); g_signal_connect(param, "modified", G_CALLBACK(on_config_param_modified), config); + result = true; + exit: if (lock) g_generic_config_wunlock(config); - return param; + return result; } @@ -1632,12 +1660,16 @@ void g_generic_config_delete_param(GGenConfig *config, const char *path) old = _g_generic_config_search(config, path, false); - g_signal_handlers_disconnect_by_func(old, G_CALLBACK(on_config_param_modified), config); - if (old != NULL) + { + g_signal_handlers_disconnect_by_func(old, G_CALLBACK(on_config_param_modified), config); + config->params = g_list_remove(config->params, old); - g_object_unref(G_OBJECT(old)); + g_object_unref(G_OBJECT(old)); + g_object_unref(G_OBJECT(old)); + + } g_generic_config_wunlock(config); diff --git a/src/glibext/configuration.h b/src/glibext/configuration.h index afefed1..aac6dc7 100644 --- a/src/glibext/configuration.h +++ b/src/glibext/configuration.h @@ -105,7 +105,7 @@ void g_config_param_reset(GCfgParam *); void g_config_param_set_value(GCfgParam *, ...); /* Indique la valeur courante d'un paramètre de configuration. */ -void g_config_param_get_value(GCfgParam *, ...); +void g_config_param_get_value(const GCfgParam *, ...); @@ -191,6 +191,7 @@ void g_generic_config_add_group(GGenConfig *, GCfgGroup *); GCfgGroup *__group; \ __group = g_config_group_new(p, t); \ g_generic_config_add_group(c, __group); \ + g_object_unref(G_OBJECT(__group)); \ }) @@ -205,7 +206,10 @@ GCfgParam *_g_generic_config_search(GGenConfig *, const char *, bool); GCfgParam *__param; \ __param = g_generic_config_search(c, p); \ if (__param != NULL) \ + { \ g_config_param_set_value(__param, v); \ + g_object_unref(G_OBJECT(__param)); \ + } \ __param != NULL ? true : false; \ }) @@ -214,51 +218,63 @@ GCfgParam *_g_generic_config_search(GGenConfig *, const char *, bool); GCfgParam *__param; \ __param = g_generic_config_search(c, p); \ if (__param != NULL) \ + { \ g_config_param_get_value(__param, v); \ + g_object_unref(G_OBJECT(__param)); \ + } \ __param != NULL ? true : false; \ }) /* Ajoute un paramètre à une configuration. */ -GCfgParam *_g_generic_config_add_param(GGenConfig *, GCfgParam *, bool); +bool _g_generic_config_add_param(GGenConfig *, GCfgParam *, bool); #define g_generic_config_add_param(c, p) _g_generic_config_add_param(c, p, true) #define g_generic_config_create_param(c, p, t, d) \ ({ \ - GCfgParam *__result; \ - __result = g_config_param_new(p, t, d); \ - __result = g_generic_config_add_param(c, __result); \ + bool __result; \ + GCfgParam *__param; \ + __param = g_config_param_new(p, t, d); \ + __result = g_generic_config_add_param(c, __param); \ + g_object_unref(G_OBJECT(__param)); \ __result; \ }) #define g_generic_config_create_param_if_not_exist(c, p, t, d) \ ({ \ - GCfgParam *__result; \ - __result = g_generic_config_search(c, p); \ - if (__result == NULL) \ + bool __result; \ + GCfgParam *__param; \ + __param = g_generic_config_search(c, p); \ + if (__param == NULL) \ { \ - __result = g_config_param_new(p, t, d); \ - __result = g_generic_config_add_param(c, __result); \ + __param = g_config_param_new(p, t, d); \ + __result = g_generic_config_add_param(c, __param); \ } \ + else \ + __result = true; \ + g_object_unref(G_OBJECT(__param)); \ __result; \ }) #define g_generic_config_create_or_udpdate_param(c, p, t, d, v) \ ({ \ + bool __result; \ GCfgParam *__param; \ __param = g_generic_config_search(c, p); \ if (__param == NULL) \ { \ __param = g_config_param_new(p, t, d); \ - __param = g_generic_config_add_param(c, __param); \ + __result = g_generic_config_add_param(c, __param); \ } \ - if (__param != NULL) \ - g_config_param_set_value(__param, v); \ - __param != NULL ? true : false; \ + else \ + __result = true; \ + g_config_param_set_value(__param, v); \ + g_object_unref(G_OBJECT(__param)); \ + __result; \ }) diff --git a/src/gui/panel.c b/src/gui/panel.c index 976a2d7..5b21620 100644 --- a/src/gui/panel.c +++ b/src/gui/panel.c @@ -516,40 +516,31 @@ bool gtk_panel_item_class_setup_configuration(const GPanelItemClass *class, GGen bool result; /* Bilan à retourner */ char *key; /* Clef d'accès à un paramètre */ bool dock_at_startup; /* Affichage dès le départ ? */ - GCfgParam *param; /* Paramètre chargé */ char *path; /* Localisation du panneau */ - result = true; - key = gtk_panel_item_class_build_configuration_key(class, "dock_at_startup"); dock_at_startup = class->dock_at_startup(class); - param = g_generic_config_create_param_if_not_exist(config, key, CPT_BOOLEAN, dock_at_startup); + result = g_generic_config_create_param_if_not_exist(config, key, CPT_BOOLEAN, dock_at_startup); free(key); - if (param == NULL) - { - result = false; + if (!result) goto exit; - } key = gtk_panel_item_class_build_configuration_key(class, "path"); path = class->get_path(class); - param = g_generic_config_create_param_if_not_exist(config, key, CPT_STRING, path); - - if (param == NULL) - result = false; + result = g_generic_config_create_param_if_not_exist(config, key, CPT_STRING, path); free(path); - exit: - free(key); + exit: + return result; } diff --git a/tests/glibext/configuration.py b/tests/glibext/configuration.py index 786fc9e..880b445 100644 --- a/tests/glibext/configuration.py +++ b/tests/glibext/configuration.py @@ -4,7 +4,7 @@ gi.require_version('Gdk', '3.0') from gi.repository import Gdk from chrysacase import ChrysalideTestCase -from pychrysalide.glibext import ConfigParam +from pychrysalide.glibext import ConfigParam, GenConfig class TestConfiguration(ChrysalideTestCase): @@ -69,3 +69,38 @@ class TestConfiguration(ChrysalideTestCase): self.assertTrue('|' in str(param.state)) self.assertTrue('.' in str(param.type)) + + + def testConfiguration(self): + """Feed and browse a basic configuration.""" + + config = GenConfig() + self.assertIsNotNone(config) + self.assertIsNone(config.filename) + + for i in range(5): + param = ConfigParam('config.int.%u' % i, ConfigParam.ConfigParamType.INTEGER, i) + config.add(param) + + chain = '' + + for p in config.params: + chain += '%u' % p.value + + self.assertTrue(chain == ''.join([ '%u' % i for i in range(5) ])) + + found = config.search('config.int.3') + self.assertTrue(found.value == 3) + + found = config.search('config.int.33') + self.assertIsNone(found) + + for p in config.params: + p.value *= 10 + + chain = '' + + for p in config.params: + chain += '%u' % p.value + + self.assertTrue(chain == ''.join([ '%u' % (i * 10) for i in range(5) ])) -- cgit v0.11.2-87-g4458