1 #include "e_mod_main.h"
3 #define HISTORY_VERSION 2
5 #define SEVEN_DAYS 604800.0
7 #define TIME_FACTOR(_now) (1.0 - (evry_hist->begin / _now)) / 1000000000000000.0
9 typedef struct _Cleanup_Data Cleanup_Data;
19 static E_Config_DD *hist_entry_edd = NULL;
20 static E_Config_DD *hist_item_edd = NULL;
21 static E_Config_DD *hist_types_edd = NULL;
22 static E_Config_DD *hist_edd = NULL;
24 Evry_History *evry_hist = NULL;
27 evry_history_init(void)
31 hist_item_edd = E_CONFIG_DD_NEW("History_Item", History_Item);
32 #define T History_Item
33 #define D hist_item_edd
34 E_CONFIG_VAL(D, T, plugin, STR);
35 E_CONFIG_VAL(D, T, context, STR);
36 E_CONFIG_VAL(D, T, input, STR);
37 E_CONFIG_VAL(D, T, last_used, DOUBLE);
38 E_CONFIG_VAL(D, T, usage, DOUBLE);
39 E_CONFIG_VAL(D, T, count, INT);
40 E_CONFIG_VAL(D, T, transient, INT);
41 E_CONFIG_VAL(D, T, data, STR);
44 hist_entry_edd = E_CONFIG_DD_NEW("History_Entry", History_Entry);
45 #define T History_Entry
46 #define D hist_entry_edd
47 E_CONFIG_LIST(D, T, items, hist_item_edd);
50 hist_types_edd = E_CONFIG_DD_NEW("History_Types", History_Types);
51 #define T History_Types
52 #define D hist_types_edd
53 E_CONFIG_HASH(D, T, types, hist_entry_edd);
56 hist_edd = E_CONFIG_DD_NEW("History", Evry_History);
57 #define T Evry_History
59 E_CONFIG_VAL(D, T, version, INT);
60 E_CONFIG_VAL(D, T, begin, DOUBLE);
61 E_CONFIG_HASH(D, T, subjects, hist_types_edd);
67 _hist_entry_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
69 History_Entry *he = data;
72 EINA_LIST_FREE(he->items, hi)
75 eina_stringshare_del(hi->input);
77 eina_stringshare_del(hi->plugin);
79 eina_stringshare_del(hi->context);
81 eina_stringshare_del(hi->data);
91 _hist_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
93 History_Types *ht = data;
97 eina_hash_foreach(ht->types, _hist_entry_free_cb, NULL);
98 eina_hash_free(ht->types);
107 _hist_entry_cleanup_cb(const Eina_Hash *hash __UNUSED__, const void *key, void *data, void *fdata)
109 History_Entry *he = data;
110 Cleanup_Data *d = fdata;
114 EINA_LIST_FOREACH_SAFE(he->items, l, ll, hi)
116 if (hi->last_used < d->time - SEVEN_DAYS)
119 hi->last_used = d->time - SEVEN_DAYS/2.0;
122 /* item is transient or too old */
123 if ((hi->count < 1) || hi->transient)
126 eina_stringshare_del(hi->input);
128 eina_stringshare_del(hi->plugin);
130 eina_stringshare_del(hi->context);
132 eina_stringshare_del(hi->data);
135 he->items = eina_list_remove_list(he->items, l);
142 d->keys = eina_list_append(d->keys, key);
149 _hist_cleanup_cb(const Eina_Hash *hash __UNUSED__, const void *key, void *data, void *fdata)
151 History_Types *ht = data;
152 Cleanup_Data *d = fdata;
156 eina_hash_foreach(ht->types, _hist_entry_cleanup_cb, fdata);
158 EINA_LIST_FREE(d->keys, key)
159 eina_hash_del_by_key(ht->types, key);
165 evry_history_free(void)
169 evry_hist = e_config_domain_load("module.everything.cache", hist_edd);
172 d = E_NEW(Cleanup_Data, 1);
173 d->time = ecore_time_unix_get();
175 if (evry_hist->subjects)
177 eina_hash_foreach(evry_hist->subjects, _hist_cleanup_cb, d);
181 evry_history_unload();
184 E_CONFIG_DD_FREE(hist_item_edd);
185 E_CONFIG_DD_FREE(hist_entry_edd);
186 E_CONFIG_DD_FREE(hist_types_edd);
187 E_CONFIG_DD_FREE(hist_edd);
191 evry_history_load(void)
193 if (evry_hist) return;
195 evry_hist = e_config_domain_load("module.everything.cache", hist_edd);
197 if (evry_hist && evry_hist->version != HISTORY_VERSION)
199 eina_hash_foreach(evry_hist->subjects, _hist_free_cb, NULL);
200 eina_hash_free(evry_hist->subjects);
208 evry_hist = E_NEW(Evry_History, 1);
209 evry_hist->version = HISTORY_VERSION;
210 evry_hist->begin = ecore_time_unix_get() - SEVEN_DAYS;
212 if (!evry_hist->subjects)
213 evry_hist->subjects = eina_hash_string_superfast_new(NULL);
218 evry_history_unload(void)
220 if (!evry_hist) return;
222 e_config_domain_save("module.everything.cache", hist_edd, evry_hist);
224 eina_hash_foreach(evry_hist->subjects, _hist_free_cb, NULL);
225 eina_hash_free(evry_hist->subjects);
232 evry_history_types_get(Evry_Type _type)
235 const char *type = evry_type_get(_type);
243 ht = eina_hash_find(evry_hist->subjects, type);
247 ht = E_NEW(History_Types, 1);
248 eina_hash_add(evry_hist->subjects, type, ht);
252 ht->types = eina_hash_string_superfast_new(NULL);
258 evry_history_item_add(Evry_Item *it, const char *ctxt, const char *input)
262 History_Item *hi = NULL;
273 if ((!it->plugin->history) && (!CHECK_TYPE(it, EVRY_TYPE_PLUGIN)))
276 if (it->type == EVRY_TYPE_ACTION)
279 if (!act->remember_context)
285 /* keep hi when context didn't change */
286 if ((!rem_ctxt) || (!it->hi->context && !ctxt) ||
287 (it->hi->context && ctxt && !strcmp(it->hi->context, ctxt)))
293 id = (it->id ? it->id : it->label);
294 ht = evry_history_types_get(it->type);
298 he = eina_hash_find(ht->types, id);
302 he = E_NEW(History_Entry, 1);
303 eina_hash_add(ht->types, id, he);
307 EINA_LIST_FOREACH(he->items, l, hi)
308 if ((hi->plugin == it->plugin->name) &&
309 (!rem_ctxt || (ctxt == hi->context)))
316 hi = E_NEW(History_Item, 1);
317 hi->plugin = eina_stringshare_ref(it->plugin->name);
318 he->items = eina_list_append(he->items, hi);
325 hi->last_used = ecore_time_unix_get();
327 hi->usage += TIME_FACTOR(hi->last_used);
328 hi->transient = it->plugin->transient;
331 if (ctxt && !hi->context && rem_ctxt)
333 hi->context = eina_stringshare_ref(ctxt);
336 if (input && hi->input)
338 if (strncmp(hi->input, input, strlen(input)))
340 eina_stringshare_del(hi->input);
341 hi->input = eina_stringshare_add(input);
346 hi->input = eina_stringshare_add(input);
357 evry_history_item_usage_set(Evry_Item *it, const char *input, const char *ctxt)
361 History_Item *hi = NULL;
366 if ((!it->plugin->history) && (!CHECK_TYPE(it, EVRY_TYPE_PLUGIN)))
371 /* keep hi when context didn't change */
372 if ((!rem_ctxt) || (!it->hi->context && !ctxt) ||
373 (it->hi->context && ctxt && !strcmp(it->hi->context, ctxt)))
379 ht = evry_history_types_get(it->type);
384 if (!(he = eina_hash_find(ht->types, (it->id ? it->id : it->label))))
387 if (it->type == EVRY_TYPE_ACTION)
390 if (!act->remember_context)
394 EINA_LIST_FOREACH(he->items, l, hi)
396 if (hi->plugin != it->plugin->name)
399 if (rem_ctxt && ctxt && (hi->context != ctxt))
412 if (evry_conf->history_sort_mode == 0)
414 if (!input || !hi->input)
416 it->usage += hi->usage * hi->count;
420 /* higher priority for exact matches */
421 if (!strncmp(input, hi->input, strlen(input)))
423 it->usage += hi->usage * hi->count;
425 if (!strncmp(input, hi->input, strlen(hi->input)))
427 it->usage += hi->usage * hi->count;
431 if (ctxt && hi->context && (hi->context == ctxt))
433 it->usage += hi->usage * hi->count * 10.0;
436 else if (evry_conf->history_sort_mode == 1)
438 it->usage = hi->count * (hi->last_used / 10000000000.0);
440 if (ctxt && hi->context && (hi->context == ctxt))
442 it->usage += hi->usage * hi->count * 10.0;
445 else if (evry_conf->history_sort_mode == 2)
447 if (hi->last_used > it->usage)
448 it->usage = hi->last_used;
450 if (it->fuzzy_match > 0)
451 it->usage /= (double) it->fuzzy_match;