Versioned config for Elementary.

This is not doing much now, just the version field in the struct,
some stuff stolen from E and a base to use when new things are added.
There are some comments in the code about what to do in certain cases
that E does not have, like a system update, new config and apps linked
to the old version still running when the config Atoms are updated. These
things we'll probably be addressed as they are needed, as well as come
clean up in quick code I ditched in there, but it would be good to do so
with more feedback from the good guys around that like to break SVN
every now and then.

Since the commit message is already long enough, I'm adding some more crap
just for the sake of doing so. I could go with some tl;dr thing as well,
but I don't feel like resuming what's up there.

Have a nice day.


SVN revision: 51843
This commit is contained in:
Iván Briano 2010-09-02 14:33:04 +00:00
parent 27298797f0
commit f2c8ba0fe6
5 changed files with 123 additions and 24 deletions

View File

@ -1,4 +1,5 @@
group "Elm_Config" struct {
value "config_version" int: 65537;
value "engine" int: 0;
value "thumbscroll_enable" int: 1;
value "thumbscroll_threshhold" int: 24;

View File

@ -1,4 +1,5 @@
group "Elm_Config" struct {
value "config_version" int: 65537;
value "engine" int: 0;
value "thumbscroll_enable" int: 1;
value "thumbscroll_threshhold" int: 24;

View File

@ -1,4 +1,5 @@
group "Elm_Config" struct {
value "config_version" int: 65537;
value "engine" int: 0;
value "thumbscroll_enable" int: 1;
value "thumbscroll_threshhold" int: 4;

View File

@ -18,7 +18,10 @@ static void _desc_shutdown(void);
static void _profile_get(void);
static void _config_free(void);
static void _config_apply(void);
static Elm_Config * _config_user_load(void);
static Elm_Config * _config_system_load(void);
static void _config_load(void);
static void _config_update(void);
static void _env_get(void);
#ifdef HAVE_ELEMENTARY_X
@ -79,6 +82,16 @@ _prop_config_get(void)
config_data = eet_data_descriptor_decode(_config_edd, data, size);
free(data);
if (!config_data) return EINA_FALSE;
/* What do we do on version mismatch when someone changes the
* config in the rootwindow? */
/* Most obvious case, new version and we are still linked to
* whatever was there before, we just ignore until user restarts us */
if (config_data->config_version > ELM_CONFIG_VERSION)
return EINA_TRUE;
/* What in the case the version is older? Do we even support those
* cases or we only check for equality above? */
_config_free();
_elm_config = config_data;
_config_apply();
@ -143,7 +156,6 @@ _prop_change(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
val = ecore_x_window_prop_string_get(event->win,
event->atom);
eina_stringshare_replace(&_elm_config->theme, val);
if (val)
{
int changed = 0;
@ -191,6 +203,7 @@ _desc_init(void)
printf("EEEK! eet_data_descriptor_file_new() failed\n");
return;
}
EET_DATA_DESCRIPTOR_ADD_BASIC(_config_edd, Elm_Config, "config_version", config_version, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_config_edd, Elm_Config, "engine", engine, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_config_edd, Elm_Config, "thumbscroll_enable", thumbscroll_enable, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(_config_edd, Elm_Config, "thumbscroll_threshhold", thumbscroll_threshhold, EET_T_INT);
@ -307,38 +320,70 @@ _config_apply(void)
edje_scale_set(_elm_config->scale);
}
static Elm_Config *
_config_user_load(void)
{
Elm_Config *cfg = NULL;
Eet_File *ef;
char buf[PATH_MAX];
const char *home;
home = getenv("HOME");
if (!home) home = "";
snprintf(buf, sizeof(buf), "%s/.elementary/config/%s/base.cfg", home,
_elm_profile);
ef = eet_open(buf, EET_FILE_MODE_READ);
if (ef)
{
cfg = eet_data_read(ef, _config_edd, "config");
eet_close(ef);
}
return cfg;
}
static Elm_Config *
_config_system_load(void)
{
Elm_Config *cfg = NULL;
Eet_File *ef;
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "%s/config/%s/base.cfg", _elm_data_dir,
_elm_profile);
ef = eet_open(buf, EET_FILE_MODE_READ);
if (ef)
{
cfg = eet_data_read(ef, _config_edd, "config");
eet_close(ef);
}
return cfg;
}
static void
_config_load(void)
{
Eet_File *ef = NULL;
char buf[PATH_MAX];
const char *home = NULL;
home = getenv("HOME");
if (!home) home = "/";
// user config
snprintf(buf, sizeof(buf), "%s/.elementary/config/%s/base.cfg", home, _elm_profile);
ef = eet_open(buf, EET_FILE_MODE_READ);
if (ef)
_elm_config = _config_user_load();
if (_elm_config)
{
_elm_config = eet_data_read(ef, _config_edd, "config");
eet_close(ef);
}
if (_elm_config) return;
// system config
snprintf(buf, sizeof(buf), "%s/config/%s/base.cfg", _elm_data_dir, _elm_profile);
ef = eet_open(buf, EET_FILE_MODE_READ);
if (ef)
{
_elm_config = eet_data_read(ef, _config_edd, "config");
eet_close(ef);
if (_elm_config->config_version < ELM_CONFIG_VERSION)
_config_update();
return;
}
/* no user config, fallback for system. No need to check version for
* this one, if it's not the right one, someone screwed up at the time
* of installing it */
_elm_config = _config_system_load();
if (_elm_config) return;
/* FIXME: config load could have failed because of a non-existent
* profile. Fallback to default before moving on */
// config load fail - defaults
/* XXX: do these make sense? Only if it's valid to install the lib
* without the config, but do we want that? */
_elm_config = ELM_NEW(Elm_Config);
_elm_config->config_version = ELM_CONFIG_VERSION;
_elm_config->engine = ELM_SOFTWARE_X11;
_elm_config->thumbscroll_enable = 1;
_elm_config->thumbscroll_threshhold = 24;
@ -362,6 +407,46 @@ _config_load(void)
_elm_config->modules = NULL;
}
static void
_config_update(void)
{
Elm_Config *tcfg;
tcfg = _config_system_load();
if (!tcfg)
{
/* weird profile or something? We should probably fill
* with hardcoded defaults, or get from default previx */
return;
}
#define IFCFG(v) if ((_elm_config->config_version & 0xffff) < (v)) {
#define IFCFGELSE } else {
#define IFCFGEND }
#define COPYVAL(x) do {_elm_config->x = tcfg->x;} while(0)
#define COPYPTR(x) do {_elm_config->x = tcfg->x; tcfg->x = NULL; } while(0)
#define COPYSTR(x) COPYPTR(x)
/* we also need to update for property changes in the root window
* if needed, but that will be dependant on new properties added
* with each version */
/* nothing here, just an example */
/*
IFCFG(0x0002);
COPYVAL(some_value);
IFCFGEND;
*/
#undef COPYSTR
#undef COPYPTR
#undef COPYVAL
#undef IFCFGEND
#undef IFCFGELSE
#undef IFCFG
/* after updating user config, we must save */
}
static void
_env_get(void)
{

View File

@ -50,8 +50,19 @@ typedef enum _Elm_Engine
typedef struct _Elm_Config Elm_Config;
/* increment this whenever we change config enough that you need new
* defaults for elm to work.
*/
#define ELM_CONFIG_EPOCH 0x0001
/* increment this whenever a new set of config values are added but the users
* config doesn't need to be wiped - simply new values need to be put in
*/
#define ELM_CONFIG_FILE_GENERATION 0x0001
#define ELM_CONFIG_VERSION ((ELM_CONFIG_EPOCH << 16) | ELM_CONFIG_FILE_GENERATION)
struct _Elm_Config
{
int config_version;
int engine;
int thumbscroll_enable;
int thumbscroll_threshhold;