Merge lp:~jeremywootten/pantheon-files/fix-1604300-merge-find-functionalities-part2 into lp:~elementary-apps/pantheon-files/trunk
- fix-1604300-merge-find-functionalities-part2
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Danielle Foré |
Proposed branch: | lp:~jeremywootten/pantheon-files/fix-1604300-merge-find-functionalities-part2 |
Merge into: | lp:~elementary-apps/pantheon-files/trunk |
Prerequisite: | lp:~jeremywootten/pantheon-files/fix-1604300-merge-find-functionalities-part1 |
Diff against target: |
573 lines (+242/-117) 1 file modified
libwidgets/View/SearchResults.vala (+242/-117) |
To merge this branch: | bzr merge lp:~jeremywootten/pantheon-files/fix-1604300-merge-find-functionalities-part2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
elementary Apps team | Pending | ||
Review via email: mp+313862@code.launchpad.net |
Commit message
Description of the change
This branch adds multi-level sorting to the search results as well as introducing categories to distinguish files in the current folder, below the current folder, in the bookmarks and in zeitgeist. Within categories the results are sorted with those starting with the search term coming first and then sorting by name.
Zeitgeist searching is fixed so more matches are found.
Each category is counted separately so a large number of hits in one category does not hide all the results in another category.
Hover-select is reverted as the search window is now likely to overlap the mouse cursor and result in a random initial selection otherwise.
- 2415. By Jeremy Wootten
-
Merge changes in parent branch
- 2416. By Jeremy Wootten
-
No hover-select; no select headers
Danielle Foré (danrabbit) wrote : | # |
- 2417. By Jeremy Wootten
-
Merge trunk to r2470
Danielle Foré (danrabbit) wrote : | # |
Pushed a branch under elementary-apps with merged trunk https:/
Danielle Foré (danrabbit) wrote : | # |
Gonna reject this proposal since the other branch supersedes it
Unmerged revisions
Preview Diff
1 | === modified file 'libwidgets/View/SearchResults.vala' |
2 | --- libwidgets/View/SearchResults.vala 2017-01-13 13:31:06 +0000 |
3 | +++ libwidgets/View/SearchResults.vala 2017-02-04 13:36:24 +0000 |
4 | @@ -20,6 +20,40 @@ |
5 | { |
6 | public class SearchResults : Gtk.Window, Searchable |
7 | { |
8 | + /* The order of these categories governs the order in which matches appear in the search view. |
9 | + * The category represents a first level sort. Within a category the matches sort alphabetically on name */ |
10 | + private enum Category { |
11 | + CURRENT_HEADER, |
12 | + CURRENT_BEGINS, |
13 | + CURRENT_CONTAINS, |
14 | + CURRENT_ELLIPSIS, |
15 | + DEEP_HEADER, |
16 | + DEEP_BEGINS, |
17 | + DEEP_CONTAINS, |
18 | + DEEP_ELLIPSIS, |
19 | + ZEITGEIST_HEADER, |
20 | + ZEITGEIST_BEGINS, |
21 | + ZEITGEIST_CONTAINS, |
22 | + ZEITGEIST_ELLIPSIS, |
23 | + BOOKMARK_HEADER, |
24 | + BOOKMARK_BEGINS, |
25 | + BOOKMARK_CONTAINS, |
26 | + BOOKMARK_ELLIPSIS |
27 | + } |
28 | + |
29 | + /* This function converts a Category enum to a letter which can be prefixed to the match |
30 | + * name to form a sort key. This ensures that the categories appear in the list in the |
31 | + * desired order - that is within each class of results (current folder, deep search, |
32 | + * zeitgeist search and bookmark search), after the header, the matches appear with the |
33 | + * "begins with" ones first, then the "contains" and finally an "ellipsis" pseudo-match |
34 | + * appears if MAX_RESULTS is exceeded for that category. |
35 | + */ |
36 | + /* The constant "sort_string" serves as an array of characters indexed by the enum. */ |
37 | + private const string sort_string = "ABCDEFGHIJKLMN"; |
38 | + private static string category_to_string (Category category) { |
39 | + return (sort_string.get_char ((uint)category)).to_string (); |
40 | + } |
41 | + |
42 | class Match : Object |
43 | { |
44 | public string name { get; construct; } |
45 | @@ -27,32 +61,34 @@ |
46 | public string path_string { get; construct; } |
47 | public Icon icon { get; construct; } |
48 | public File? file { get; construct; } |
49 | + public string sortkey { get; construct; } |
50 | |
51 | - public Match (FileInfo info, string path_string, File parent) |
52 | - { |
53 | - Object (name: info.get_display_name (), |
54 | + public Match (FileInfo info, string path_string, File parent, SearchResults.Category category) { |
55 | + var _name = info.get_display_name (); |
56 | + Object (name: Markup.escape_text (_name), |
57 | mime: info.get_content_type (), |
58 | icon: info.get_icon (), |
59 | path_string: path_string, |
60 | - file: parent.resolve_relative_path (info.get_name ())); |
61 | + file: parent.resolve_relative_path (info.get_name ()), |
62 | + sortkey: category_to_string (category) + _name); |
63 | } |
64 | |
65 | - public Match.from_bookmark (Bookmark bookmark) |
66 | - { |
67 | - Object (name: bookmark.label, |
68 | + public Match.from_bookmark (Bookmark bookmark, SearchResults.Category category) { |
69 | + Object (name: Markup.escape_text (bookmark.label), |
70 | mime: "inode/directory", |
71 | icon: bookmark.get_icon (), |
72 | path_string: "", |
73 | - file: bookmark.get_location ()); |
74 | + file: bookmark.get_location (), |
75 | + sortkey: SearchResults.category_to_string (category) + bookmark.label); |
76 | } |
77 | |
78 | - public Match.ellipsis () |
79 | - { |
80 | + public Match.ellipsis (SearchResults.Category category) { |
81 | Object (name: "...", |
82 | mime: "", |
83 | icon: null, |
84 | path_string: "", |
85 | - file: null); |
86 | + file: null, |
87 | + sortkey: SearchResults.category_to_string (category)); |
88 | } |
89 | } |
90 | |
91 | @@ -79,7 +115,8 @@ |
92 | Zeitgeist.Index zg_index; |
93 | GenericArray<Zeitgeist.Event> templates; |
94 | |
95 | - int display_count; |
96 | + int current_count; |
97 | + int deep_count; |
98 | |
99 | bool local_search_finished = false; |
100 | bool global_search_finished = false; |
101 | @@ -87,10 +124,11 @@ |
102 | bool is_grabbing = false; |
103 | Gdk.Device? device = null; |
104 | |
105 | - Gtk.TreeIter local_results; |
106 | - Gtk.TreeIter global_results; |
107 | - Gtk.TreeIter bookmark_results; |
108 | - Gtk.TreeIter no_results_label; |
109 | + Gtk.TreeIter? current_results = null; |
110 | + Gtk.TreeIter? deep_results = null; |
111 | + Gtk.TreeIter? zeitgeist_results = null; |
112 | + Gtk.TreeIter? bookmark_results = null; |
113 | + |
114 | Gtk.TreeView view; |
115 | Gtk.TreeStore list; |
116 | Gtk.TreeModelFilter filter; |
117 | @@ -126,10 +164,15 @@ |
118 | |
119 | view = new Gtk.TreeView (); |
120 | view.get_selection ().set_mode (Gtk.SelectionMode.BROWSE); |
121 | + /* Do not select category headers */ |
122 | + view.get_selection ().set_select_function ((selection, list, path, path_selected) => { |
123 | + return path.get_depth () != 0; |
124 | + }); |
125 | view.headers_visible = false; |
126 | view.show_expanders = false; |
127 | view.level_indentation = 12; |
128 | - view.set_hover_selection (true); |
129 | + /* Revert to no hover select as the search window is now much larger */ |
130 | + view.set_hover_selection (false); |
131 | |
132 | get_style_context ().add_class ("completion-popup"); |
133 | |
134 | @@ -153,16 +196,21 @@ |
135 | |
136 | view.append_column (column); |
137 | |
138 | - list = new Gtk.TreeStore (5, typeof (string), typeof (GLib.Icon), |
139 | - typeof (string), typeof (File), typeof (bool)); |
140 | + list = new Gtk.TreeStore (6, |
141 | + typeof (string), /*0 file basename or category name */ |
142 | + typeof (GLib.Icon), /*1 file icon */ |
143 | + typeof (string?), /*2 file location */ |
144 | + typeof (File?), /*3 file object */ |
145 | + typeof (bool), /*4 icon is visible */ |
146 | + typeof (string)); /*5 Sort key */ |
147 | + |
148 | filter = new Gtk.TreeModelFilter (list, null); |
149 | + |
150 | filter.set_visible_func ((model, iter) => { |
151 | - if (iter == no_results_label) |
152 | - return n_results < 1; |
153 | - |
154 | /* hide empty category headers */ |
155 | return list.iter_depth (iter) != 0 || list.iter_has_child (iter); |
156 | }); |
157 | + |
158 | view.model = filter; |
159 | |
160 | list.row_changed.connect ((path, iter) => { |
161 | @@ -174,12 +222,27 @@ |
162 | } |
163 | }); |
164 | |
165 | - list.append (out local_results, null); |
166 | - list.@set (local_results, 0, get_category_header (_("In This Folder"))); |
167 | + list.set_sort_column_id (5, Gtk.SortType.ASCENDING); |
168 | + |
169 | + list.append (out current_results, null); |
170 | + list.@set (current_results, |
171 | + 0, get_category_header (_("In This Folder")), |
172 | + 5, SearchResults.category_to_string (Category.CURRENT_HEADER)); |
173 | + |
174 | + list.append (out deep_results, null); |
175 | + list.@set (deep_results, |
176 | + 0, get_category_header (_("Below This Folder")), |
177 | + 5, SearchResults.category_to_string (Category.CURRENT_HEADER)); |
178 | + |
179 | list.append (out bookmark_results, null); |
180 | - list.@set (bookmark_results, 0, get_category_header (_("Bookmarks"))); |
181 | - list.append (out global_results, null); |
182 | - list.@set (global_results, 0, get_category_header (_("Everywhere Else"))); |
183 | + list.@set (bookmark_results, |
184 | + 0, get_category_header (_("Bookmarks")), |
185 | + 5, SearchResults.category_to_string (Category.CURRENT_HEADER)); |
186 | + |
187 | + list.append (out zeitgeist_results, null); |
188 | + list.@set (zeitgeist_results, |
189 | + 0, get_category_header (_("Recently used")), |
190 | + 5, SearchResults.category_to_string (Category.CURRENT_HEADER)); |
191 | |
192 | scroll.add (view); |
193 | frame.add (scroll); |
194 | @@ -242,8 +305,8 @@ |
195 | } |
196 | |
197 | var include_hidden = GOF.Preferences.get_default ().pref_show_hidden_files; |
198 | - |
199 | - display_count = 0; |
200 | + current_count = 0; |
201 | + deep_count = 0; |
202 | directory_queue = new Gee.LinkedList<File> (); |
203 | waiting_results = new Gee.HashMap<Gtk.TreeIter?,Gee.List> (); |
204 | current_root = folder; |
205 | @@ -277,7 +340,7 @@ |
206 | new Thread<void*> (null, () => { |
207 | local_search_finished = false; |
208 | while (!file_search_operation.is_cancelled () && directory_queue.size > 0) { |
209 | - visit (search_term, include_hidden, file_search_operation); |
210 | + visit (search_term, include_hidden, file_search_operation, folder); |
211 | } |
212 | |
213 | local_search_finished = true; |
214 | @@ -286,17 +349,17 @@ |
215 | return null; |
216 | }); |
217 | |
218 | - get_zg_results.begin (search_term); |
219 | - |
220 | - var bookmarks_matched = new Gee.LinkedList<Match> (); |
221 | - |
222 | - foreach (var bookmark in BookmarkList.get_instance ().list) { |
223 | - if (term_matches (search_term, bookmark.label)) { |
224 | - bookmarks_matched.add (new Match.from_bookmark (bookmark)); |
225 | - } |
226 | + get_zg_results.begin (search_term); |
227 | + |
228 | + var bookmarks_matched = new Gee.LinkedList<Match> (); |
229 | + var begins_with = false; |
230 | + foreach (var bookmark in BookmarkList.get_instance ().list) { |
231 | + if (term_matches (search_term, bookmark.label, out begins_with)) { |
232 | + bookmarks_matched.add (new Match.from_bookmark (bookmark, begins_with ? Category.BOOKMARK_BEGINS : Category.BOOKMARK_CONTAINS)); |
233 | } |
234 | + } |
235 | |
236 | - add_results (bookmarks_matched, bookmark_results); |
237 | + add_results (bookmarks_matched, bookmark_results); |
238 | } |
239 | |
240 | /** Signal handlers **/ |
241 | @@ -648,15 +711,14 @@ |
242 | return; |
243 | } |
244 | |
245 | - Gtk.TreeIter iter; |
246 | - File file; |
247 | - |
248 | foreach (var match in new_results) { |
249 | - /* prevent results from showing in both global and local results */ |
250 | - if (parent == global_results) { |
251 | + Gtk.TreeIter? iter = null; |
252 | + File file; |
253 | + /* do not add global result if already in local results */ |
254 | + if (parent == zeitgeist_results) { |
255 | var already_added = false; |
256 | |
257 | - for (var valid = list.iter_nth_child (out iter, local_results, 0); valid; |
258 | + for (var valid = list.iter_nth_child (out iter, current_results, 0); valid; |
259 | valid = list.iter_next (ref iter)) { |
260 | |
261 | list.@get (iter, 3, out file); |
262 | @@ -667,10 +729,25 @@ |
263 | } |
264 | } |
265 | |
266 | - if (already_added) |
267 | + if (!already_added) { |
268 | + for (var valid = list.iter_nth_child (out iter, deep_results, 0); valid; |
269 | + valid = list.iter_next (ref iter)) { |
270 | + |
271 | + list.@get (iter, 3, out file); |
272 | + |
273 | + if (file != null && match.file != null && file.equal (match.file)) { |
274 | + already_added = true; |
275 | + break; |
276 | + } |
277 | + } |
278 | + } |
279 | + |
280 | + if (already_added) { |
281 | continue; |
282 | - } else if (parent == local_results) { |
283 | - for (var valid = list.iter_nth_child (out iter, global_results, 0); valid; |
284 | + } |
285 | + } else if (parent == current_results) { |
286 | + /* remove current search result from global if in global results */ |
287 | + for (var valid = list.iter_nth_child (out iter, zeitgeist_results, 0); valid; |
288 | valid = list.iter_next (ref iter)) { |
289 | |
290 | list.@get (iter, 3, out file); |
291 | @@ -680,13 +757,25 @@ |
292 | break; |
293 | } |
294 | } |
295 | - } |
296 | + } else if (parent == deep_results) { |
297 | + /* remove deep search result from from global if in global results */ |
298 | + for (var valid = list.iter_nth_child (out iter, zeitgeist_results, 0); valid; |
299 | + valid = list.iter_next (ref iter)) { |
300 | + |
301 | + list.@get (iter, 3, out file); |
302 | + |
303 | + if (file != null && match.file != null && file.equal (match.file)) { |
304 | + list.remove (ref iter); |
305 | + break; |
306 | + } |
307 | + } |
308 | + } |
309 | |
310 | var location = "<span %s>%s</span>".printf (get_pango_grey_color_string (), |
311 | - Markup.escape_text (match.path_string)); |
312 | + Markup.escape_text (match.path_string)); |
313 | |
314 | list.append (out iter, parent); |
315 | - list.@set (iter, 0, Markup.escape_text (match.name), 1, match.icon, 2, location, 3, match.file, 4, true); |
316 | + list.@set (iter, 0, match.name, 1, match.icon, 2, location, 3, match.file, 4, true, 5, match.sortkey); |
317 | n_results++; |
318 | |
319 | view.expand_all (); |
320 | @@ -804,21 +893,23 @@ |
321 | FileAttribute.STANDARD_TYPE + "," + |
322 | FileAttribute.STANDARD_ICON; |
323 | |
324 | - void visit (string term, bool include_hidden, Cancellable cancel) |
325 | - { |
326 | - |
327 | - FileEnumerator enumerator; |
328 | + void visit (string term, bool include_hidden, Cancellable cancel, File root_folder) { |
329 | var folder = directory_queue.poll (); |
330 | |
331 | if (folder == null) { |
332 | return; |
333 | } |
334 | |
335 | + bool in_root = folder.equal (root_folder); |
336 | + var category_count = in_root ? current_count : deep_count; |
337 | + |
338 | var depth = 0; |
339 | |
340 | File f = folder; |
341 | var path_string = ""; |
342 | - while (!f.equal (current_root)) { |
343 | + |
344 | + |
345 | + while (f != null && !f.equal (current_root)) { |
346 | path_string = f.get_basename () + (path_string == "" ? "" : Path.DIR_SEPARATOR_S + path_string); |
347 | f = f.get_parent (); |
348 | depth++; |
349 | @@ -828,6 +919,7 @@ |
350 | return; |
351 | } |
352 | |
353 | + FileEnumerator enumerator; |
354 | try { |
355 | enumerator = folder.enumerate_children (ATTRIBUTES, 0, cancel); |
356 | } catch (Error e) { |
357 | @@ -837,8 +929,13 @@ |
358 | var new_results = new Gee.LinkedList<Match> (); |
359 | |
360 | FileInfo info = null; |
361 | + Category cat; |
362 | + |
363 | try { |
364 | - while (!cancel.is_cancelled () && (info = enumerator.next_file (null)) != null) { |
365 | + while (!cancel.is_cancelled () && |
366 | + (info = enumerator.next_file (null)) != null && |
367 | + category_count < MAX_RESULTS) { |
368 | + |
369 | if (info.get_is_hidden () && !include_hidden) { |
370 | continue; |
371 | } |
372 | @@ -847,43 +944,47 @@ |
373 | directory_queue.add (folder.resolve_relative_path (info.get_name ())); |
374 | } |
375 | |
376 | - if (term_matches (term, info.get_display_name ())) { |
377 | - new_results.add (new Match (info, path_string, folder)); |
378 | - } |
379 | + var begins_with = false; |
380 | + if (term_matches (term, info.get_display_name (), out begins_with)) { |
381 | + if (in_root) { |
382 | + cat = begins_with ? Category.CURRENT_BEGINS : Category.CURRENT_CONTAINS; |
383 | + } else { |
384 | + cat = begins_with ? Category.DEEP_BEGINS : Category.DEEP_CONTAINS; |
385 | + } |
386 | + new_results.add (new Match (info, path_string, folder, cat)); |
387 | + category_count++; |
388 | + } |
389 | } |
390 | } catch (Error e) {warning ("Error enumerating in visit");} |
391 | |
392 | if (new_results.size < 1) { |
393 | + cat = in_root ? Category.CURRENT_ELLIPSIS : Category.DEEP_ELLIPSIS; |
394 | + new_results.add (new Match.ellipsis (cat)); |
395 | return; |
396 | - } |
397 | - |
398 | - if (!cancel.is_cancelled ()) { |
399 | - var new_count = display_count + new_results.size; |
400 | - if (new_count > MAX_RESULTS) { |
401 | - cancel.cancel (); |
402 | - |
403 | - var num_ok = MAX_RESULTS - display_count; |
404 | - if (num_ok < new_results.size) { |
405 | - var count = 0; |
406 | - var it = new_results.iterator (); |
407 | - while (it.next ()) { |
408 | - count++; |
409 | - if (count > num_ok) |
410 | - it.remove (); |
411 | - } |
412 | - } |
413 | - |
414 | - new_results.add (new Match.ellipsis ()); |
415 | - |
416 | - display_count = MAX_RESULTS; |
417 | - } else |
418 | - display_count = new_count; |
419 | + } else if (!cancel.is_cancelled ()) { |
420 | + if (in_root) { |
421 | + current_count = category_count; |
422 | + } else { |
423 | + deep_count = category_count; |
424 | + } |
425 | |
426 | /* use a closure here to get vala to pass the userdata that we actually want */ |
427 | Idle.add (() => { |
428 | - add_results (new_results, local_results); |
429 | + add_results (new_results, in_root ? current_results : deep_results); |
430 | return false; |
431 | }); |
432 | + |
433 | + |
434 | + if (category_count >= MAX_RESULTS) { |
435 | + cat = in_root ? Category.CURRENT_ELLIPSIS : Category.DEEP_ELLIPSIS; |
436 | + new_results.add (new Match.ellipsis (cat)); |
437 | + return; |
438 | + } |
439 | + |
440 | + |
441 | + if (current_count >= MAX_RESULTS && deep_count >= MAX_RESULTS) { |
442 | + cancel.cancel (); |
443 | + } |
444 | } |
445 | } |
446 | |
447 | @@ -893,11 +994,11 @@ |
448 | |
449 | Zeitgeist.ResultSet results; |
450 | try { |
451 | - results = yield zg_index.search (term, |
452 | + results = yield zg_index.search ("name:" + term + "*", |
453 | new Zeitgeist.TimeRange.anytime (), |
454 | templates, |
455 | 0, /* offset */ |
456 | - MAX_RESULTS + 1, |
457 | + MAX_RESULTS * 3, |
458 | Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS, |
459 | current_operation); |
460 | } catch (IOError.CANCELLED e) { |
461 | @@ -911,57 +1012,81 @@ |
462 | return; |
463 | } |
464 | |
465 | - var i = 0; |
466 | - |
467 | var matches = new Gee.LinkedList<Match> (); |
468 | var home = File.new_for_path (Environment.get_home_dir ()); |
469 | - while (results.has_next () && !current_operation.is_cancelled ()) { |
470 | + Category cat; |
471 | + var i = 0; |
472 | + while (results.has_next () && !current_operation.is_cancelled () && !global_search_finished) { |
473 | + |
474 | var result = results.next_value (); |
475 | foreach (var subject in result.subjects.data) { |
476 | if (i == MAX_RESULTS) { |
477 | - matches.add (new Match.ellipsis ()); |
478 | + matches.add (new Match.ellipsis (Category.ZEITGEIST_ELLIPSIS)); |
479 | + global_search_finished = true; |
480 | break; |
481 | } |
482 | |
483 | try { |
484 | var file = File.new_for_uri (subject.uri); |
485 | - var path_string = ""; |
486 | - var parent = file; |
487 | - while ((parent = parent.get_parent ()) != null) { |
488 | - if (parent.equal (current_root)) |
489 | - break; |
490 | - |
491 | - if (parent.equal (home)) { |
492 | - path_string = "~/" + path_string; |
493 | - break; |
494 | - } |
495 | - |
496 | - if (path_string == "") |
497 | - path_string = parent.get_basename (); |
498 | - else |
499 | - path_string = parent.get_basename () + Path.DIR_SEPARATOR_S + path_string; |
500 | - } |
501 | - |
502 | - var info = yield file.query_info_async (ATTRIBUTES, 0, Priority.DEFAULT, current_operation); |
503 | - matches.add (new Match (info, path_string, file.get_parent ())); |
504 | - |
505 | - i++; |
506 | + /* Zeitgeist search finds search term anywhere in path. We are only interested |
507 | + * when the search term is in the basename */ |
508 | + while (file != null && !file.get_basename ().contains (term)) { |
509 | + file = file.get_parent (); |
510 | + } |
511 | + if (file != null) { |
512 | + var path_string = ""; |
513 | + var parent = file; |
514 | + while ((parent = parent.get_parent ()) != null) { |
515 | + if (parent.equal (current_root)) { |
516 | + break; |
517 | + } |
518 | + |
519 | + if (parent.equal (home)) { |
520 | + path_string = "~/" + path_string; |
521 | + break; |
522 | + } |
523 | + |
524 | + if (path_string == "") { |
525 | + path_string = parent.get_basename (); |
526 | + } else { |
527 | + path_string = parent.get_basename () + Path.DIR_SEPARATOR_S + path_string; |
528 | + } |
529 | + } |
530 | + |
531 | + /* Eliminate duplicate matches */ |
532 | + bool found = false; |
533 | + foreach (Match m in matches) { |
534 | + if (m.path_string == path_string) { |
535 | + found = true; |
536 | + break; |
537 | + } |
538 | + } |
539 | + |
540 | + if (!found) { |
541 | + var info = yield file.query_info_async (ATTRIBUTES, 0, Priority.DEFAULT, current_operation); |
542 | + var name = info.get_display_name (); |
543 | + cat = name.has_prefix (term) ? Category.ZEITGEIST_BEGINS : Category.ZEITGEIST_CONTAINS; |
544 | + matches.add (new Match (info, path_string, file.get_parent (), cat)); |
545 | + i++; |
546 | + } |
547 | + } |
548 | } catch (Error e) {} |
549 | } |
550 | } |
551 | |
552 | - if (!current_operation.is_cancelled ()) |
553 | - add_results (matches, global_results); |
554 | + if (!current_operation.is_cancelled ()) { |
555 | + add_results (matches, zeitgeist_results); |
556 | + } |
557 | |
558 | global_search_finished = true; |
559 | Idle.add (send_search_finished); |
560 | } |
561 | |
562 | - bool term_matches (string term, string name) |
563 | - { |
564 | - /**TODO** improve */ |
565 | + bool term_matches (string term, string name, out bool begins_with ) { |
566 | /* term is assumed to be down */ |
567 | - return name.normalize ().casefold ().contains (term); |
568 | + var n = name.normalize ().casefold (); |
569 | + begins_with = n.has_prefix (term); |
570 | + return n.contains (term); |
571 | } |
572 | |
573 | string get_category_header (string title) |
I agree with removing the hover select. It causes some unintended behavior when searching.