summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2016-01-04 17:58:18 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2016-01-05 22:24:58 +0900
commit1056b6ed01475817da2439012057d11865d2c5d8 (patch)
tree2f2cbcbceebdee3c67b503141c45fc5c5224fe41
parent6d448760f374638af69590d60bc8f896895240f8 (diff)
downloadelementary-1056b6ed01475817da2439012057d11865d2c5d8.tar.gz
elm config - add the ability to have derived configurations from others
this adds the ability to have one profile automatically be derived from another with modifications applied. right now it only can do a very limited modification - multiple scale. over time this will expand. this is only inteded otbe sued by a DE like enlightenment, so it's not going to be documented fully at this point. @feature
-rw-r--r--src/lib/elm_config.c300
-rw-r--r--src/lib/elm_config.h41
-rw-r--r--src/lib/elm_priv.h2
3 files changed, 336 insertions, 7 deletions
diff --git a/src/lib/elm_config.c b/src/lib/elm_config.c
index 00723514d..ccf64985b 100644
--- a/src/lib/elm_config.c
+++ b/src/lib/elm_config.c
@@ -665,6 +665,285 @@ _elm_config_user_dir_snprintf(char *dst,
return 0;
}
+typedef struct _Elm_Config_Derived Elm_Config_Derived;
+typedef struct _Elm_Config_Derived_Profile Elm_Config_Derived_Profile;
+
+struct _Elm_Config_Derived
+{
+ Eina_List *profiles;
+};
+
+struct _Elm_Config_Derived_Profile
+{
+ const char *profile;
+ const char *derive_options;
+};
+
+static Eet_Data_Descriptor *_config_derived_edd = NULL;
+static Eet_Data_Descriptor *_config_derived_profile_edd = NULL;
+
+static void
+_elm_config_profile_derived_init(void)
+{
+ Eet_Data_Descriptor_Class eddc;
+
+ EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Config_Derived);
+ eddc.func.str_direct_alloc = NULL;
+ eddc.func.str_direct_free = NULL;
+ _config_derived_edd = eet_data_descriptor_file_new(&eddc);
+
+ memset(&eddc, 0, sizeof(eddc)); /* just in case... */
+ EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Config_Derived_Profile);
+ eddc.func.str_direct_alloc = NULL;
+ eddc.func.str_direct_free = NULL;
+ _config_derived_profile_edd = eet_data_descriptor_file_new(&eddc);
+
+#define T Elm_Config_Derived_Profile
+#define D _config_derived_profile_edd
+ ELM_CONFIG_VAL(D, T, profile, EET_T_STRING);
+ ELM_CONFIG_VAL(D, T, derive_options, EET_T_STRING);
+#undef T
+#undef D
+
+#define T Elm_Config_Derived
+#define D _config_derived_edd
+ ELM_CONFIG_LIST(D, T, profiles, _config_derived_profile_edd);
+#undef T
+#undef D
+}
+
+static void
+_elm_config_profile_derived_shutdown(void)
+{
+ if (_config_derived_profile_edd)
+ {
+ eet_data_descriptor_free(_config_derived_profile_edd);
+ _config_derived_profile_edd = NULL;
+ }
+ if (_config_derived_edd)
+ {
+ eet_data_descriptor_free(_config_derived_edd);
+ _config_derived_edd = NULL;
+ }
+}
+
+static Elm_Config_Derived *
+_elm_config_derived_load(const char *profile)
+{
+ char buf[PATH_MAX];
+ Eet_File *ef;
+ Elm_Config_Derived *derived;
+
+ if (!profile) profile = _elm_profile;
+ _elm_config_user_dir_snprintf(buf, sizeof(buf), "config/%s/derived.cfg",
+ profile);
+ ef = eet_open(buf, EET_FILE_MODE_READ);
+ if (ef)
+ {
+ derived = eet_data_read(ef, _config_derived_edd, "config");
+ eet_close(ef);
+ if (derived) return derived;
+ }
+ snprintf(buf, sizeof(buf), "%s/config/%s/derived.cfg",
+ _elm_data_dir, profile);
+ ef = eet_open(buf, EET_FILE_MODE_READ);
+ if (ef)
+ {
+ derived = eet_data_read(ef, _config_derived_edd, "config");
+ eet_close(ef);
+ if (derived) return derived;
+ }
+ return NULL;
+}
+
+static void
+_elm_config_profile_derived_save(const char *profile, Elm_Config_Derived *derived)
+{
+ Eet_File *ef;
+ char buf[PATH_MAX], buf2[PATH_MAX];
+
+ _elm_config_user_dir_snprintf(buf, sizeof(buf), "config/%s",
+ profile ? profile : _elm_profile);
+ ecore_file_mkpath(buf);
+ _elm_config_user_dir_snprintf(buf, sizeof(buf), "config/%s/derived.cfg.tmp",
+ profile ? profile : _elm_profile);
+ _elm_config_user_dir_snprintf(buf2, sizeof(buf2), "config/%s/derived.cfg",
+ profile ? profile : _elm_profile);
+ ef = eet_open(buf, EET_FILE_MODE_WRITE);
+ if (ef)
+ {
+ eet_data_write(ef, _config_derived_edd, "config", derived, 1);
+ eet_close(ef);
+ ecore_file_mv(buf, buf2);
+ }
+}
+
+static void
+_elm_config_derived_free(Elm_Config_Derived *derived)
+{
+ Elm_Config_Derived_Profile *dp;
+
+ if (!derived) return;
+ EINA_LIST_FREE(derived->profiles, dp)
+ {
+ eina_stringshare_del(dp->profile);
+ eina_stringshare_del(dp->derive_options);
+ free(dp);
+ }
+ free(derived);
+}
+
+static void
+_elm_config_derived_option_op_apply(Elm_Config *cfg, const char *op, const char *params)
+{
+ if (!strcmp(op, "scale-mul"))
+ {
+ int multiplier = atoi(params);
+ if (multiplier > 0)
+ {
+ cfg->scale = cfg->scale * (((double)multiplier) / 100.0);
+ }
+ }
+ // Add more derivation commands here
+}
+
+static void
+_elm_config_derived_option_apply(Elm_Config *cfg, const char *option)
+{
+ const char *p;
+ char *buf = alloca(strlen(option) + 1);
+ char *bp = buf;
+
+ p = option;
+ bp = buf;
+ for (;;)
+ {
+ if ((*p == 0) || (*p == ' '))
+ {
+ if (*p == ' ') p++;
+ *bp = 0;
+ _elm_config_derived_option_op_apply(cfg, buf, p);
+ return;
+ }
+ else
+ {
+ *bp = *p;
+ bp++;
+ }
+ if (*p == 0) break;
+ p++;
+ }
+}
+
+static void
+_elm_config_derived_apply(Elm_Config *cfg, const char *derive_options)
+{
+ // derive_options = "option1 param param2 ...; option2 param1 ..."
+ const char *p;
+ char *buf = alloca(strlen(derive_options) + 1);
+ char *bp = buf;
+
+ p = derive_options;
+ for (;;)
+ {
+ if ((*p == 0) || (*p == ';'))
+ {
+ if (*p == ';') p++;
+ *bp = 0;
+ _elm_config_derived_option_apply(cfg, buf);
+ bp = buf;
+ }
+ else
+ {
+ *bp = *p;
+ bp++;
+ }
+ if (*p == 0) break;
+ p++;
+ }
+}
+
+static void
+_elm_config_derived_save(Elm_Config *cfg, Elm_Config_Derived *derived)
+{
+ Elm_Config_Derived_Profile *dp;
+ Eina_List *l;
+
+ if (!derived) return;
+ EINA_LIST_FOREACH(derived->profiles, l, dp)
+ {
+ if ((dp->profile) && (dp->derive_options))
+ {
+ Elm_Config *cfg2;
+
+ cfg2 = malloc(sizeof(Elm_Config));
+ if (cfg2)
+ {
+ memcpy(cfg2, cfg, sizeof(Elm_Config));
+ _elm_config_derived_apply(cfg2, dp->derive_options);
+ _elm_config_save(cfg2, dp->profile);
+ free(cfg2);
+ }
+ }
+ }
+}
+
+EAPI void
+elm_config_profile_derived_add(const char *profile, const char *derive_options)
+{
+ Elm_Config_Derived *derived;
+
+ derived = _elm_config_derived_load(_elm_profile);
+ if (!derived) derived = calloc(1, sizeof(derived));
+ if (derived)
+ {
+ Elm_Config_Derived_Profile *dp = calloc(1, sizeof(Elm_Config_Derived_Profile));
+
+ if (dp)
+ {
+ dp->profile = eina_stringshare_add(profile);
+ dp->derive_options = eina_stringshare_add(derive_options);
+ derived->profiles = eina_list_append(derived->profiles, dp);
+ _elm_config_profile_derived_save(_elm_profile, derived);
+ _elm_config_derived_save(_elm_config, derived);
+ }
+ _elm_config_derived_free(derived);
+ }
+}
+
+EAPI void
+elm_config_profile_derived_del(const char *profile)
+{
+ Elm_Config_Derived *derived;
+ Elm_Config_Derived_Profile *dp;
+ Eina_List *l;
+
+ if (!profile) return;
+ derived = _elm_config_derived_load(_elm_profile);
+ if (derived)
+ {
+ EINA_LIST_FOREACH(derived->profiles, l, dp)
+ {
+ if ((dp->profile) && (!strcmp(dp->profile, profile)))
+ {
+ char buf[PATH_MAX];
+
+ _elm_config_user_dir_snprintf(buf, sizeof(buf), "config/%s",
+ profile);
+ ecore_file_recursive_rm(buf);
+ derived->profiles = eina_list_remove_list(derived->profiles, l);
+ eina_stringshare_del(dp->profile);
+ eina_stringshare_del(dp->derive_options);
+ free(dp);
+ _elm_config_profile_derived_save(_elm_profile, derived);
+ _elm_config_derived_free(derived);
+ return;
+ }
+ }
+ _elm_config_derived_free(derived);
+ }
+}
+
const char *
_elm_config_profile_dir_get(const char *prof,
Eina_Bool is_user)
@@ -1688,6 +1967,13 @@ _elm_config_profile_save(void)
}
ecore_file_unlink(buf2);
+
+ derived = _elm_config_derived_load(profile ? profile : _elm_profile);
+ if (derived)
+ {
+ _elm_config_derived_save(cfg, derived);
+ _elm_config_derived_free(derived);
+ }
return EINA_TRUE;
err:
@@ -1696,8 +1982,9 @@ err:
}
Eina_Bool
-_elm_config_save(const char *profile)
+_elm_config_save(Elm_Config *cfg, const char *profile)
{
+ Elm_Config_Derived *derived;
char buf[4096], buf2[4096];
int ok = 0, ret;
const char *err;
@@ -1754,7 +2041,7 @@ _elm_config_save(const char *profile)
if (!ef)
return EINA_FALSE;
- ok = eet_data_write(ef, _config_edd, "config", _elm_config, 1);
+ ok = eet_data_write(ef, _config_edd, "config", cfg, 1);
if (!ok)
goto err;
@@ -1888,7 +2175,7 @@ _config_update(void)
_elm_config->config_version = ELM_CONFIG_VERSION;
/* after updating user config, we must save */
_config_free(tcfg);
- _elm_config_save(NULL);
+ _elm_config_save(_elm_config, NULL);
}
static void
@@ -2386,7 +2673,7 @@ elm_config_password_show_last_timeout_set(double password_show_last_timeout)
EAPI Eina_Bool
elm_config_save(void)
{
- return _elm_config_save(NULL);
+ return _elm_config_save(_elm_config, NULL);
}
EAPI void
@@ -2465,10 +2752,9 @@ EAPI void
elm_config_profile_save(const char *profile)
{
EINA_SAFETY_ON_NULL_RETURN(profile);
- _elm_config_save(profile);
+ _elm_config_save(_elm_config, profile);
}
-
EAPI const char *
elm_config_engine_get(void)
{
@@ -3441,6 +3727,7 @@ _elm_config_init(void)
if (!ELM_EVENT_CONFIG_ALL_CHANGED)
ELM_EVENT_CONFIG_ALL_CHANGED = ecore_event_type_new();
_desc_init();
+ _elm_config_profile_derived_init();
_profile_fetch_from_conf();
_config_load();
_env_get();
@@ -3821,6 +4108,7 @@ _elm_config_shutdown(void)
ELM_SAFE_FREE(_elm_profile, free);
_elm_font_overlays_del_free();
+ _elm_config_profile_derived_shutdown();
_desc_shutdown();
ELM_SAFE_FREE(_elm_key_bindings, eina_hash_free);
diff --git a/src/lib/elm_config.h b/src/lib/elm_config.h
index 1d106153b..1c74b653d 100644
--- a/src/lib/elm_config.h
+++ b/src/lib/elm_config.h
@@ -179,6 +179,47 @@ EAPI void elm_config_profile_set(const char *profile);
EAPI void elm_config_profile_save(const char *profile);
/**
+ * Add a new profile of the given name to be derived from the current profile
+ *
+ * This creates a new profile of name @p profile that will be derived from
+ * the currently used profile using the modification commands encoded in the
+ * @p derive_options string.
+ *
+ * At this point it is not expected that anyone would generally use this API
+ * except if you are a destktop environment and so the user base of this API
+ * will be enlightenment itself.
+ *
+ * @param profile The new profile's name
+ * @param derive_options A string of derive options detailing how to modify
+ *
+ * @see elm_config_profile_derived_del
+ * @ingroup Profile
+ *
+ * @since 1.17
+ */
+EAPI void elm_config_profile_derived_add(const char *profile, const char *derive_options);
+
+/**
+ * Deletes a profile that is derived from the current one
+ *
+ * This deletes a derived profile added by elm_config_profile_derived_add().
+ * This will delete the profile of the given name @p profile that is derived
+ * from the current profile.
+ *
+ * At this point it is not expected that anyone would generally use this API
+ * except if you are a destktop environment and so the user base of this API
+ * will be enlightenment itself.
+ *
+ * @param profile The profile's name that is to be deleted
+ *
+ * @see elm_config_profile_derived_add
+ * @ingroup Profile
+ *
+ * @since 1.17
+ */
+EAPI void elm_config_profile_derived_del(const char *profile);
+
+/**
* @}
*/
diff --git a/src/lib/elm_priv.h b/src/lib/elm_priv.h
index f5f1cde38..7bd39cb92 100644
--- a/src/lib/elm_priv.h
+++ b/src/lib/elm_priv.h
@@ -433,7 +433,7 @@ void _elm_config_init(void);
void _elm_config_sub_init(void);
void _elm_config_shutdown(void);
void _elm_config_sub_shutdown(void);
-Eina_Bool _elm_config_save(const char *profile);
+Eina_Bool _elm_config_save(Elm_Config *cfg, const char *profile);
void _elm_config_reload(void);
size_t _elm_config_user_dir_snprintf(char *dst, size_t size,
const char *fmt, ...)