update for beta release
[framework/uifw/e17.git] / src / modules / everything / evry_plug_aggregator.c
1 #include "e_mod_main.h"
2
3 //TODO min input for items not in history
4
5 #define MAX_ITEMS  100
6 #define MAX_PLUGIN 25
7
8 typedef struct _Plugin Plugin;
9
10 struct _Plugin
11 {
12    Evry_Plugin base;
13
14    Evry_Item  *warning;
15 };
16
17 static int
18 _fetch(Evry_Plugin *plugin, const char *input)
19 {
20    Plugin *p = (Plugin *)plugin;
21    Evry_Plugin *pp;
22    Eina_List *l, *ll, *lp = NULL;
23    Evry_Item *it, *it2;
24    int top_level = 0, subj_sel = 0, cnt = 0;
25    size_t inp_len;
26    Eina_List *items = NULL;
27    const char *context = NULL;
28    char buf[128];
29    Evry_State *s = plugin->state;
30    Evry_Selector *sel = s->selector;
31    Evry_Selector **sels = sel->win->selectors;
32
33    if (input && input[0])
34      inp_len = strlen(input);
35    else
36      input = NULL;
37
38    if ((eina_list_count(sel->states) == 1))
39      top_level = 1;
40
41    /* get current items' context, which is
42     * the previous selectors selected item */
43    if (sel == sels[0])
44      {
45         subj_sel = 1;
46      }
47    else if (sel == sels[1])
48      {
49         it = sels[0]->state->cur_item;
50         if (it) context = it->context;
51      }
52    else if (sel == sels[2])
53      {
54         it = sels[1]->state->cur_item;
55         if (it) context = it->context;
56      }
57
58    EVRY_PLUGIN_ITEMS_FREE(p);
59
60    /* collect plugins to be shown in aggregator */
61    EINA_LIST_FOREACH (s->cur_plugins, l, pp)
62      {
63         /* dont show in aggregator */
64         if (!pp->config->aggregate)
65           continue;
66         /* do not recurse */
67         if (pp == plugin)
68           continue;
69         /* dont show plugin in top-level */
70         if (top_level && !pp->config->top_level)
71           continue;
72         lp = eina_list_append(lp, pp);
73      }
74
75    /* show non-top-level plugins as item */
76    if ((top_level) && (!s->trigger_active))
77      {
78         EINA_LIST_FOREACH (s->plugins, l, pp)
79           {
80              int min_fuzz = 0;
81              double max_usage = 0.0;
82
83              if (pp->config->top_level)
84                continue;
85
86              if (pp == plugin)
87                continue;
88
89              if (!pp->items)
90                continue;
91
92              /* give plugin item the highest priority of its items */
93              EINA_LIST_FOREACH (pp->items, ll, it)
94                {
95                   if (it->usage >= 0)
96                     evry_history_item_usage_set(it, input, context);
97
98                   if (it->usage && (it->usage > max_usage))
99                     max_usage = it->usage;
100
101                   if (it->fuzzy_match == 0)
102                     it->fuzzy_match = evry_fuzzy_match(it->label, input);
103
104                   if ((!min_fuzz) || ((it->fuzzy_match > 0) &&
105                                       (it->fuzzy_match < min_fuzz)))
106                     min_fuzz = it->fuzzy_match;
107                }
108
109              GET_ITEM(it, pp);
110
111              it->hi = NULL;
112              /* TODO get better usage estimate */
113              evry_history_item_usage_set(it, NULL, NULL);
114              it->usage /= 100.0;
115
116              if ((it->usage && max_usage) && (it->usage < max_usage))
117                it->usage = max_usage;
118              it->fuzzy_match = min_fuzz;
119
120              IF_RELEASE(it->detail);
121              snprintf(buf, sizeof(buf), "%d %s", eina_list_count(pp->items), _("Items"));
122              it->detail = eina_stringshare_add(buf);
123
124              items = eina_list_append(items, it);
125           }
126
127         /* only one plugin: show items */
128         if ((eina_list_count(s->cur_plugins)) == 1 && items &&
129             (pp = eina_list_data_get(items)) && (pp->config->aggregate))
130           {
131              eina_list_free(items);
132              items = NULL;
133              EINA_LIST_FOREACH (pp->items, l, it)
134                {
135                   if (it->usage >= 0)
136                     evry_history_item_usage_set(it, input, context);
137                   if (it->fuzzy_match == 0)
138                     it->fuzzy_match = evry_fuzzy_match(it->label, input);
139
140                   items = eina_list_append(items, it);
141                }
142           }
143
144 #if 0
145         /* append all plugins as items (which were not added above) */
146         if (inp_len >= plugin->config->min_query)
147           {
148              EINA_LIST_FOREACH (s->plugins, l, pp)
149                {
150                   if (!strcmp(pp->name, "Actions"))
151                     continue;
152
153                   /* items MUST only conatin plugins here ! */
154                   EINA_LIST_FOREACH (items, ll, pp2)
155                     if (pp2->name == pp->name) break;
156                   if (pp2)
157                     continue;
158
159                   GET_ITEM(it, pp);
160
161                   if ((!input) ||
162                       (it->fuzzy_match = evry_fuzzy_match(it->label, input)))
163                     {
164                        evry_history_item_usage_set(it, input, NULL);
165                        it->usage /= 100.0;
166
167                        EVRY_ITEM(pp)->plugin->state = s;
168                        items = eina_list_append(items, pp);
169                     }
170                }
171           }
172 #endif
173         if (!lp && (eina_list_count(items) < 2))
174           {
175              if (items) eina_list_free(items);
176              return 0;
177           }
178      }
179
180    if (!lp && !items)
181      return 0;
182
183    /* if there is input append all items that match */
184    if (input)
185      {
186         EINA_LIST_FOREACH (lp, l, pp)
187           {
188              EINA_LIST_FOREACH (pp->items, ll, it)
189                {
190                   if (it->fuzzy_match == 0)
191                     it->fuzzy_match = evry_fuzzy_match(it->label, input);
192
193                   if (it->usage >= 0)
194                     evry_history_item_usage_set(it, input, context);
195
196                   if ((subj_sel) && (top_level) &&
197                       (!it->usage) && (inp_len < plugin->config->min_query))
198                     continue;
199
200                   items = eina_list_append(items, it);
201                }
202           }
203      }
204    /* no input: append all items that are in history */
205    else
206      {
207         EINA_LIST_FOREACH (lp, l, pp)
208           {
209              int cnt = 1;
210              EINA_LIST_FOREACH (pp->items, ll, it)
211                {
212                   if ((!subj_sel) || (it->usage < 0) ||
213                       (evry_history_item_usage_set(it, input, context)))
214                     {
215                        it->fuzzy_match = 0;
216                        items = eina_list_append(items, it);
217                        if (++cnt > MAX_PLUGIN) break;
218                     }
219                }
220           }
221      }
222
223    if ((!top_level) && (eina_list_count(items) < MAX_ITEMS))
224      {
225         EINA_LIST_FOREACH (lp, l, pp)
226           {
227              EINA_LIST_FOREACH (pp->items, ll, it)
228                {
229                   if (eina_list_data_find_list(items, it))
230                     continue;
231
232                   items = eina_list_append(items, it);
233                }
234           }
235      }
236
237    evry_util_items_sort(&items, 0 /* !input */);
238
239    EINA_LIST_FOREACH (items, l, it)
240      {
241         /* remove duplicates provided by different plugins. e.g.
242            files / places and tracker can find the same files */
243         if (it->id)
244           {
245              EINA_LIST_FOREACH (p->base.items, ll, it2)
246                {
247                   if ((it->plugin->name != it2->plugin->name) &&
248                       (it->type == it2->type) &&
249                       (it->id == it2->id))
250                     break;
251                }
252           }
253
254         if (!it->id || !it2)
255           {
256              evry_item_ref(it);
257              EVRY_PLUGIN_ITEM_APPEND(p, it);
258           }
259
260         if (cnt++ > MAX_ITEMS)
261           break;
262      }
263
264    if (lp) eina_list_free(lp);
265
266    if (items)
267      {
268         eina_list_free(items);
269         return EVRY_PLUGIN_HAS_ITEMS(p);
270      }
271    /* 'text' and 'actions' are always loaded */
272    else if ((subj_sel) && (eina_list_count(s->plugins) == 2))
273      {
274         evry_item_ref(p->warning);
275         EVRY_PLUGIN_ITEM_APPEND(p, p->warning);
276      }
277
278    return 0;
279 }
280
281 static void
282 _finish(Evry_Plugin *plugin)
283 {
284    GET_PLUGIN(p, plugin);
285
286    EVRY_PLUGIN_ITEMS_FREE(p);
287
288    evry_item_free(p->warning);
289
290    E_FREE(p);
291 }
292
293 static Evry_Plugin *
294 _begin(Evry_Plugin *plugin, const Evry_Item *it __UNUSED__)
295 {
296    Plugin *p;
297
298    GET_PLUGIN(base, plugin);
299    EVRY_PLUGIN_INSTANCE(p, plugin);
300
301    p->warning = evry_item_new(NULL, EVRY_PLUGIN(p), N_("No plugins loaded"), NULL, NULL);
302    p->warning->type = EVRY_TYPE_NONE;
303
304    return EVRY_PLUGIN(p);
305 }
306
307 Evry_Plugin *
308 evry_aggregator_new(int type)
309 {
310    Evry_Plugin *p;
311
312    p = EVRY_PLUGIN_BASE("All", NULL, 0, _begin, _finish, _fetch);
313
314    if (evry_plugin_register(p, type, -1))
315      {
316         p->config->view_mode = VIEW_MODE_THUMB;
317      }
318
319    return p;
320 }
321