GNOME Bugzilla – Bug 371370
GKeyFile should allow loading of key files into non-empty structures
Last modified: 2018-02-02 11:29:44 UTC
Hi developers, In my application I wanted to use GKeyFiles to store user preferences (I'd rather not depend on GConf). I thought it might be useful to be able to load the defaults from a system-wide configuration file, and then have the user preferences override those defaults, by doing something like this: g_key_file_load_from_file (keyfile, "system-wide-default.cfg", NULL); g_key_file_load_from_file (keyfile, "user-preferences.cfg", NULL); Unfortunately, this doesn't work; loading keys from a file clears all the previous data. Is there a reason for this, or was this just an arbitrary decision? Commenting out "g_key_file_clear" and "g_key_file_init" from g_key_file_load_from_fd and g_key_file_load_from_data works for me, but this might have unknown regressions. Thanks a lot, Samuel Cormier-Iijima
I'm using keyfiles to serialize a dictionary for on-the-fly spelling changes, and having this feature would be useful for me -- we'd load the system dictionary, then the one to which the user has added customizations.
I wanted to use keyfiles for presets in gstreamer and need something like this too. It could be added by providing g_key_file_merge_from_file(GKeyfile *, char *file_name, GKeyfileMergeMode) which would not clear the keyfile before. The merge mode would be: tyepdef enum { G_KEYFILE_MERGE_NEW_GROUPS, // replace full groups G_KEYFILE_MERGE_NEW_KEYS, // repleace only keys } GKeyfileMergeMode; if G_KEYFILE_MERGE_NEW_GROUPS is not specified and G_KEYFILE_MERGE_NEW_KEYS the keys are merged like if the appear multiple times in one keyfile. if G_KEYFILE_MERGE_NEW_KEYS, then the new keys replace the old keys. if G_KEYFILE_MERGE_NEW_GROUPS, then a new groups would clear the old groups and all new keys are added.
What I do in my code is loading both key files (presets and actual values) separately and using wrapper functions for access: const char* my_config_get_string (const char *group, const char *key) { char *value; value = g_key_file_get_string (user_settings, group, key, NULL); if (!value) value = g_key_file_get_string (default_settings, group, key, NULL); return value; }
Thanks for the idea, but that is not what I am looking for. I want to keep only one keyfile in memory. Adding g_key_file_merge_from_file as it could share some parts with the load variant. It would not call g_key_file_clear() and _init(). The merge-mode need either be set in the instance of being propagated through all the g_key_file_parse() calls.
Matthias, one more issue with your approach is saving. Once you want to modify a key, you need to copy the group manually from the system keyfile to the user keyfile.
But if you merge all key files in memory, then you end up saving redundant keys to the user’s key file. I think there are too many options here for the policy which the application applies to how keys/groups override each other between the files, and how the results of that are saved. This is something which best exists at a higher level, as an array of GKeyFiles. I’ve got an implementation here which people are free to cargo cult: https://github.com/endlessm/eos-updater/blob/master/libeos-updater-util/config.c In addition to supporting multiple key files from various paths, it supports a base GKeyFile in a GResource which provides the defaults for all the options. ⇒ WONTFIX