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
_fetch(Evry_Plugin * plugin,const char * input)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 = NULL;
24    int top_level = 0, subj_sel = 0, cnt = 0;
25    size_t inp_len = 0;
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, n;
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 > -1.0)
96                     evry_history_item_usage_set(it, input, context);
97 
98                   if (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(itp, pp);
110 
111              itp->hi = NULL;
112              /* TODO get better usage estimate */
113              evry_history_item_usage_set(itp, NULL, NULL);
114              itp->usage /= 100.0;
115 
116              if ((!eina_dbl_exact(itp->usage, 0)) && (!eina_dbl_exact(max_usage, 0)) && (itp->usage < max_usage))
117                itp->usage = max_usage;
118              itp->fuzzy_match = min_fuzz;
119 
120              IF_RELEASE(itp->detail);
121              n = eina_list_count(pp->items);
122              snprintf(buf, sizeof(buf), P_("%d item", "%d items", n), n);
123              itp->detail = eina_stringshare_add(buf);
124 
125              items = eina_list_append(items, itp);
126           }
127 
128         /* only one plugin: show items */
129         if ((eina_list_count(s->cur_plugins)) == 1 && items &&
130             (pp = eina_list_data_get(items)) && (pp->config->aggregate))
131           {
132              eina_list_free(items);
133              items = NULL;
134              EINA_LIST_FOREACH (pp->items, l, it)
135                {
136                   if (it->usage >= 0)
137                     evry_history_item_usage_set(it, input, context);
138                   if (it->fuzzy_match == 0)
139                     it->fuzzy_match = evry_fuzzy_match(it->label, input);
140 
141                   items = eina_list_append(items, it);
142                }
143           }
144 
145 #if 0
146         /* append all plugins as items (which were not added above) */
147         if (inp_len >= plugin->config->min_query)
148           {
149              EINA_LIST_FOREACH (s->plugins, l, pp)
150                {
151                   if (!strcmp(pp->name, "Actions"))
152                     continue;
153 
154                   /* items MUST only contain plugins here ! */
155                   EINA_LIST_FOREACH (items, ll, pp2)
156                     if (pp2->name == pp->name) break;
157                   if (pp2)
158                     continue;
159 
160                   GET_ITEM(it, pp);
161 
162                   if ((!input) ||
163                       (it->fuzzy_match = evry_fuzzy_match(it->label, input)))
164                     {
165                        evry_history_item_usage_set(it, input, NULL);
166                        it->usage /= 100.0;
167 
168                        EVRY_ITEM(pp)->plugin->state = s;
169                        items = eina_list_append(items, pp);
170                     }
171                }
172           }
173 #endif
174         if (!lp && (eina_list_count(items) < 2))
175           {
176              if (items) eina_list_free(items);
177              return 0;
178           }
179      }
180 
181    if (!lp && !items)
182      return 0;
183 
184    /* if there is input append all items that match */
185    if (input)
186      {
187         EINA_LIST_FOREACH (lp, l, pp)
188           {
189              EINA_LIST_FOREACH (pp->items, ll, it)
190                {
191                   if (it->fuzzy_match == 0)
192                     it->fuzzy_match = evry_fuzzy_match(it->label, input);
193 
194                   if (it->usage >= 0)
195                     evry_history_item_usage_set(it, input, context);
196 
197                   if ((subj_sel) && (top_level) &&
198                       eina_dbl_exact(it->usage, 0) && ((int) inp_len < plugin->config->min_query))
199                     continue;
200 
201                   items = eina_list_append(items, it);
202                }
203           }
204      }
205    /* no input: append all items that are in history */
206    else
207      {
208         EINA_LIST_FOREACH (lp, l, pp)
209           {
210              cnt = 1;
211              EINA_LIST_FOREACH (pp->items, ll, it)
212                {
213                   if ((!subj_sel) || (it->usage < 0) ||
214                       (evry_history_item_usage_set(it, input, context)))
215                     {
216                        it->fuzzy_match = 0;
217                        items = eina_list_append(items, it);
218                        if (++cnt > MAX_PLUGIN) break;
219                     }
220                }
221           }
222      }
223 
224    if ((!top_level) && (eina_list_count(items) < MAX_ITEMS))
225      {
226         EINA_LIST_FOREACH (lp, l, pp)
227           {
228              EINA_LIST_FOREACH (pp->items, ll, it)
229                {
230                   if (eina_list_data_find_list(items, it))
231                     continue;
232 
233                   items = eina_list_append(items, it);
234                }
235           }
236      }
237 
238    evry_util_items_sort(&items, 0 /* !input */);
239 
240    EINA_LIST_FOREACH (items, l, it)
241      {
242         /* remove duplicates provided by different plugins. e.g.
243            files / places and tracker can find the same files */
244         if (it->id)
245           {
246              EINA_LIST_FOREACH (p->base.items, ll, it2)
247                {
248                   if ((it->plugin->name != it2->plugin->name) &&
249                       (it->type == it2->type) &&
250                       (it->id == it2->id))
251                     break;
252                }
253           }
254 
255         if (!it->id || !it2)
256           {
257              evry_item_ref(it);
258              EVRY_PLUGIN_ITEM_APPEND(p, it);
259           }
260 
261         if (cnt++ > MAX_ITEMS)
262           break;
263      }
264 
265    if (lp) eina_list_free(lp);
266 
267    if (items)
268      {
269         eina_list_free(items);
270         return EVRY_PLUGIN_HAS_ITEMS(p);
271      }
272    /* 'text' and 'actions' are always loaded */
273    else if ((subj_sel) && (eina_list_count(s->plugins) == 2))
274      {
275         evry_item_ref(p->warning);
276         EVRY_PLUGIN_ITEM_APPEND(p, p->warning);
277      }
278 
279    return 0;
280 }
281 
282 static void
_finish(Evry_Plugin * plugin)283 _finish(Evry_Plugin *plugin)
284 {
285    GET_PLUGIN(p, plugin);
286 
287    EVRY_PLUGIN_ITEMS_FREE(p);
288 
289    evry_item_free(p->warning);
290 
291    E_FREE(p);
292 }
293 
294 static Evry_Plugin *
_begin(Evry_Plugin * plugin,const Evry_Item * it EINA_UNUSED)295 _begin(Evry_Plugin *plugin, const Evry_Item *it EINA_UNUSED)
296 {
297    Plugin *p;
298 
299    /* GET_PLUGIN(base, plugin); */
300    EVRY_PLUGIN_INSTANCE(p, plugin);
301 
302    p->warning = evry_item_new(NULL, EVRY_PLUGIN(p), N_("No plugins loaded"), NULL, NULL);
303    p->warning->type = EVRY_TYPE_NONE;
304 
305    return EVRY_PLUGIN(p);
306 }
307 
308 Evry_Plugin *
evry_aggregator_new(int type)309 evry_aggregator_new(int type)
310 {
311    Evry_Plugin *p;
312 
313    p = EVRY_PLUGIN_BASE(N_("All"), NULL, 0, _begin, _finish, _fetch);
314 
315    if (evry_plugin_register(p, type, -1))
316      {
317         p->config->view_mode = VIEW_MODE_THUMB;
318      }
319 
320    return p;
321 }
322 
323