enlightenment/src/modules/everything/evry_history.c

334 lines
6.8 KiB
C
Raw Normal View History

#include "e_mod_main.h"
#define HISTORY_VERSION 6
#define TIME_NOW (1.0 - (evry_hist->begin / ecore_time_get())) / 1000000000000.0
typedef struct _Cleanup_Data Cleanup_Data;
struct _Cleanup_Data
{
double time;
Eina_List *keys;
Eina_Bool normalize;
};
static E_Config_DD *hist_entry_edd = NULL;
static E_Config_DD *hist_item_edd = NULL;
static E_Config_DD *hist_edd = NULL;
History *evry_hist = NULL;
void
evry_history_init(void)
{
#undef T
#undef D
hist_item_edd = E_CONFIG_DD_NEW("History_Item", History_Item);
#define T History_Item
#define D hist_item_edd
E_CONFIG_VAL(D, T, plugin, STR);
E_CONFIG_VAL(D, T, context, STR);
E_CONFIG_VAL(D, T, input, STR);
E_CONFIG_VAL(D, T, last_used, DOUBLE);
E_CONFIG_VAL(D, T, count, INT);
E_CONFIG_VAL(D, T, transient, INT);
#undef T
#undef D
hist_entry_edd = E_CONFIG_DD_NEW("History_Entry", History_Entry);
#define T History_Entry
#define D hist_entry_edd
E_CONFIG_LIST(D, T, items, hist_item_edd);
#undef T
#undef D
hist_edd = E_CONFIG_DD_NEW("History", History);
#define T History
#define D hist_edd
E_CONFIG_VAL(D, T, version, INT);
E_CONFIG_HASH(D, T, subjects, hist_entry_edd);
E_CONFIG_HASH(D, T, actions, hist_entry_edd);
E_CONFIG_VAL(D, T, begin, DOUBLE);
#undef T
#undef D
}
static Eina_Bool
_hist_free_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
History_Entry *he = data;
History_Item *hi;
EINA_LIST_FREE(he->items, hi)
{
if (hi->input)
eina_stringshare_del(hi->input);
if (hi->plugin)
eina_stringshare_del(hi->plugin);
if (hi->context)
eina_stringshare_del(hi->context);
E_FREE(hi);
}
E_FREE(he);
return 1;
}
static Eina_Bool
_hist_cleanup_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata)
{
History_Entry *he = data;
Cleanup_Data *d = fdata;
History_Item *hi;
Eina_List *l, *ll;
EINA_LIST_FOREACH_SAFE(he->items, l, ll, hi)
{
/* item is transient or too old */
if (!hi->count || hi->transient)
{
if (hi->input)
eina_stringshare_del(hi->input);
if (hi->plugin)
eina_stringshare_del(hi->plugin);
if (hi->context)
eina_stringshare_del(hi->context);
E_FREE(hi);
he->items = eina_list_remove_list(he->items, l);
}
}
if (!he->items)
{
E_FREE(he);
d->keys = eina_list_append(d->keys, key);
}
return 1;
}
void
evry_history_free(void)
{
Cleanup_Data *d;
char *key;
evry_hist = e_config_domain_load("module.everything.history", hist_edd);
if (evry_hist)
{
d = E_NEW(Cleanup_Data, 1);
/* d->time = ecore_time_get() - SOME_YEARS; */
if (evry_hist->subjects)
{
eina_hash_foreach(evry_hist->subjects, _hist_cleanup_cb, d);
EINA_LIST_FREE(d->keys, key)
eina_hash_del_by_key(evry_hist->subjects, key);
}
if (evry_hist->subjects)
{
eina_hash_foreach(evry_hist->actions, _hist_cleanup_cb, d);
EINA_LIST_FREE(d->keys, key)
eina_hash_del_by_key(evry_hist->actions, key);
}
E_FREE(d);
evry_history_unload();
}
E_CONFIG_DD_FREE(hist_item_edd);
E_CONFIG_DD_FREE(hist_entry_edd);
E_CONFIG_DD_FREE(hist_edd);
}
void
evry_history_load(void)
{
evry_hist = e_config_domain_load("module.everything.history", hist_edd);
if (evry_hist && evry_hist->version != HISTORY_VERSION)
{
eina_hash_foreach(evry_hist->subjects, _hist_free_cb, NULL);
eina_hash_foreach(evry_hist->actions, _hist_free_cb, NULL);
eina_hash_free(evry_hist->subjects);
eina_hash_free(evry_hist->actions);
E_FREE(evry_hist);
evry_hist = NULL;
}
if (!evry_hist)
{
evry_hist = E_NEW(History, 1);
evry_hist->version = HISTORY_VERSION;
evry_hist->begin = ecore_time_get();
}
if (!evry_hist->subjects)
evry_hist->subjects = eina_hash_string_superfast_new(NULL);
if (!evry_hist->actions)
evry_hist->actions = eina_hash_string_superfast_new(NULL);
}
void
evry_history_unload(void)
{
if (!evry_hist) return;
e_config_domain_save("module.everything.history", hist_edd, evry_hist);
eina_hash_foreach(evry_hist->subjects, _hist_free_cb, NULL);
eina_hash_foreach(evry_hist->actions, _hist_free_cb, NULL);
E_FREE(evry_hist);
evry_hist = NULL;
}
void
evry_history_add(Eina_Hash *hist, Evry_State *s)
{
History_Entry *he;
History_Item *hi = NULL;
Evry_Item *it;
Eina_List *l;
const char *id;
if (!s) return;
it = s->cur_item;
if (!it) return;
if (it->id)
id = it->id;
else
id = it->label;
he = eina_hash_find(hist, id);
if (!he)
{
he = E_NEW(History_Entry, 1);
eina_hash_add(hist, id, he);
}
else
{
/* found history entry */
EINA_LIST_FOREACH(he->items, l, hi)
if (hi->plugin == it->plugin->name) break;
if (hi)
{
/* found history item */
if (hi->input)
{
if (!s->input || !strncmp (hi->input, s->input, strlen(s->input)))
{
/* s->input matches hi->input and is equal or shorter */
hi->last_used = TIME_NOW;
hi->count++;
hi->transient = it->transient;
if (it->transient)
hi->count++;
}
else if (s->input)
{
if (!strncmp (hi->input, s->input, strlen(hi->input)))
{
/* s->input matches hi->input but is longer */
eina_stringshare_del(hi->input);
hi->input = eina_stringshare_add(s->input);
}
else
{
/* s->input is different from hi->input
-> create new item */
hi = NULL;
}
}
}
else
{
/* remember input for item */
hi->count++;
if (it->transient)
hi->count++;
/* hi->last_used /= 2.0; */
hi->last_used = TIME_NOW;
if (s->input)
hi->input = eina_stringshare_add(s->input);
}
}
}
if (!hi)
{
hi = E_NEW(History_Item, 1);
hi->plugin = eina_stringshare_ref(it->plugin->name);
hi->last_used = TIME_NOW;
hi->count = 1;
if (it->transient)
hi->count++;
if (s->input)
hi->input = eina_stringshare_add(s->input);
he->items = eina_list_append(he->items, hi);
}
}
int
evry_history_item_usage_set(Eina_Hash *hist, Evry_Item *it, const char *input)
{
History_Entry *he;
History_Item *hi;
const char *id;
Eina_List *l;
int cnt;
if (it->id)
id = it->id;
else
id = it->label;
it->usage = 0;
if (!(he = eina_hash_find(hist, id)))
return 0;
EINA_LIST_FOREACH(he->items, l, hi)
{
if (hi->plugin != it->plugin->name)
continue;
cnt = 0;
if (!input || !hi->input)
{
cnt = hi->count;
}
else
{
/* higher priority for exact matches */
if (!strncmp(input, hi->input, strlen(input)))
{
cnt += hi->count*2;
}
if (!strncmp(input, hi->input, strlen(hi->input)))
{
cnt += hi->count*2;
}
}
it->usage += (cnt * hi->last_used);
}
if (it->usage) return 1;
return 0;
}