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