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