Merge lp:~elementary-apps/pantheon-files/find-function-part2 into lp:~elementary-apps/pantheon-files/trunk

Proposed by Danielle Foré
Status: Merged
Approved by: Danielle Foré
Approved revision: 2426
Merged at revision: 2582
Proposed branch: lp:~elementary-apps/pantheon-files/find-function-part2
Merge into: lp:~elementary-apps/pantheon-files/trunk
Diff against target: 516 lines (+203/-98)
1 file modified
libwidgets/View/SearchResults.vala (+203/-98)
To merge this branch: bzr merge lp:~elementary-apps/pantheon-files/find-function-part2
Reviewer Review Type Date Requested Status
Adam Bieńkowski (community) code Approve
Danielle Foré Abstain
Review via email: mp+323718@code.launchpad.net

Commit message

* Add multi-level sorting to the search results
* Categories to distinguish files in the current folder, below the current folder, in the bookmarks and in zeitgeist
* Zeitgeist searching fixed
* Each category is counted separately so a large number of hits in one category does not hide all the results in another category

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.

To post a comment you must log in.
Revision history for this message
Danielle Foré (danrabbit) wrote :

I don't think I like the use of "current" here instead of "local". To me "current" implies time as in Gdk.CURRENT_TIME but what we really mean here isn't results we have currently but results for the pwd.

review: Needs Fixing
Revision history for this message
Danielle Foré (danrabbit) wrote :

there's a spot that refers to the headers but it looks like it assigns CURRENT_HEADER for everything. Seems unintentional?

Revision history for this message
Danielle Foré (danrabbit) :
Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

For me "LOCAL" sounds like the opposite to "REMOTE", i.e. referring to results on the local, native file system - this is in line with usage in Gtk filechooser, recent, sidebar etc. "CURRENT" in this context means the folder currently being displayed. It could be changed to "PWD_HEADER" etc if you think that is clearer?

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Regarding the header sort keys - yes you are right - good spot! These should be changed to the appropriate Category.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

See inline responses

Revision history for this message
Danielle Foré (danrabbit) wrote :

If there is already a convention for Files that CURRENT means present working directory, that's probably fine :)

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Made correction to headers.

Revision history for this message
Danielle Foré (danrabbit) wrote :

While this branch renames things like "local_results" to "current_results", it doesn't rename things like "local_search" so you end up with some inconsistency there. I think I would like to see variable name changes in their own branch

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Removed last variable name change revision

2423. By Jeremy Wootten

Revert other variable name changes

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Reverted "current_results" to "local_results" and "zeitgeist_results" to "global_results", as requested.

Revision history for this message
Adam Bieńkowski (donadigo) wrote :

I've tested this branch, and so far it looks good, although I'm not sure about this "sort_string". Could you explain how this works in detail? I left some comments in the diff.

review: Needs Information (code / testing)
2424. By Jeremy Wootten

Improve code style

Revision history for this message
Danielle Foré (danrabbit) wrote :

I'm changing my review to abstain on this branch so that it doesn't appear that it still needs fixing on my account :)

review: Abstain
Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

From Slack discussion re sort_string:

I need to have alphabetic sort of the filenames (within categories) so the whole key has to be alphabetic (I think?) How else to combine an integer order and an alphabetic order?

The only slight concern I have is whether it works in other locales.

Revision history for this message
Adam Bieńkowski (donadigo) wrote :

Couple of additional diff comments. I'm still not sure about the hole Category.to_string (). Those comments are the last thing I want to see addressed in this branch. I won't be pointing anything out afterwards since this is the last branch to migrate Files to GitHub.

review: Needs Fixing (code)
Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Addressed code style issues identified and merged latest trunk.

2425. By Jeremy Wootten

Code style improvements

2426. By Jeremy Wootten

Merge trunk to r2581

Revision history for this message
Adam Bieńkowski (donadigo) wrote :

Thanks, looks good to me now.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libwidgets/View/SearchResults.vala'
--- libwidgets/View/SearchResults.vala 2017-05-07 16:16:18 +0000
+++ libwidgets/View/SearchResults.vala 2017-06-17 09:54:37 +0000
@@ -20,6 +20,38 @@
20{20{
21 public class SearchResults : Gtk.Window, Searchable21 public class SearchResults : Gtk.Window, Searchable
22 {22 {
23 /* The order of these categories governs the order in which matches appear in the search view.
24 * The category represents a first level sort. Within a category the matches sort alphabetically on name */
25 private enum Category {
26 CURRENT_HEADER,
27 CURRENT_BEGINS,
28 CURRENT_CONTAINS,
29 CURRENT_ELLIPSIS,
30 DEEP_HEADER,
31 DEEP_BEGINS,
32 DEEP_CONTAINS,
33 DEEP_ELLIPSIS,
34 ZEITGEIST_HEADER,
35 ZEITGEIST_BEGINS,
36 ZEITGEIST_CONTAINS,
37 ZEITGEIST_ELLIPSIS,
38 BOOKMARK_HEADER,
39 BOOKMARK_BEGINS,
40 BOOKMARK_CONTAINS,
41 BOOKMARK_ELLIPSIS;
42
43 /* This function converts a Category enum to a letter which can be prefixed to the match
44 * name to form a sort key. This ensures that the categories appear in the list in the
45 * desired order - that is within each class of results (current folder, deep search,
46 * zeitgeist search and bookmark search), after the header, the matches appear with the
47 * "begins with" ones first, then the "contains" and finally an "ellipsis" pseudo-match
48 * appears if MAX_RESULTS is exceeded for that category.
49 */
50 public string to_string () {
51 return CharacterSet.A_2_Z.get_char ((uint)this).to_string ();
52 }
53 }
54
23 class Match : Object55 class Match : Object
24 {56 {
25 public string name { get; construct; }57 public string name { get; construct; }
@@ -27,29 +59,34 @@
27 public string path_string { get; construct; }59 public string path_string { get; construct; }
28 public Icon icon { get; construct; }60 public Icon icon { get; construct; }
29 public File? file { get; construct; }61 public File? file { get; construct; }
62 public string sortkey { get; construct; }
3063
31 public Match (FileInfo info, string path_string, File parent) {64 public Match (FileInfo info, string path_string, File parent, SearchResults.Category category) {
32 Object (name: info.get_display_name (),65 var _name = info.get_display_name ();
66 Object (name: Markup.escape_text (_name),
33 mime: info.get_content_type (),67 mime: info.get_content_type (),
34 icon: info.get_icon (),68 icon: info.get_icon (),
35 path_string: path_string,69 path_string: path_string,
36 file: parent.resolve_relative_path (info.get_name ()));70 file: parent.resolve_relative_path (info.get_name ()),
71 sortkey: category.to_string () + _name);
37 }72 }
3873
39 public Match.from_bookmark (Bookmark bookmark) {74 public Match.from_bookmark (Bookmark bookmark, SearchResults.Category category) {
40 Object (name: bookmark.label,75 Object (name: Markup.escape_text (bookmark.label),
41 mime: "inode/directory",76 mime: "inode/directory",
42 icon: bookmark.get_icon (),77 icon: bookmark.get_icon (),
43 path_string: "",78 path_string: "",
44 file: bookmark.get_location ());79 file: bookmark.get_location (),
80 sortkey: category.to_string () + bookmark.label);
45 }81 }
4682
47 public Match.ellipsis () {83 public Match.ellipsis (SearchResults.Category category) {
48 Object (name: "...",84 Object (name: "...",
49 mime: "",85 mime: "",
50 icon: null,86 icon: null,
51 path_string: "",87 path_string: "",
52 file: null);88 file: null,
89 sortkey: category.to_string ());
53 }90 }
54 }91 }
5592
@@ -76,7 +113,8 @@
76 Zeitgeist.Index zg_index;113 Zeitgeist.Index zg_index;
77 GenericArray<Zeitgeist.Event> templates;114 GenericArray<Zeitgeist.Event> templates;
78115
79 int display_count;116 int current_count;
117 int deep_count;
80118
81 bool local_search_finished = false;119 bool local_search_finished = false;
82 bool global_search_finished = false;120 bool global_search_finished = false;
@@ -84,10 +122,11 @@
84 bool is_grabbing = false;122 bool is_grabbing = false;
85 Gdk.Device? device = null;123 Gdk.Device? device = null;
86124
87 Gtk.TreeIter local_results;125 Gtk.TreeIter? local_results = null;
88 Gtk.TreeIter global_results;126 Gtk.TreeIter? deep_results = null;
89 Gtk.TreeIter bookmark_results;127 Gtk.TreeIter? zeitgeist_results = null;
90 Gtk.TreeIter no_results_label;128 Gtk.TreeIter? bookmark_results = null;
129
91 Gtk.TreeView view;130 Gtk.TreeView view;
92 Gtk.TreeStore list;131 Gtk.TreeStore list;
93 Gtk.TreeModelFilter filter;132 Gtk.TreeModelFilter filter;
@@ -154,19 +193,17 @@
154193
155 view.append_column (column);194 view.append_column (column);
156195
157 list = new Gtk.TreeStore (5,196 list = new Gtk.TreeStore (6,
158 typeof (string), /*0 file basename or category name */197 typeof (string), /*0 file basename or category name */
159 typeof (GLib.Icon), /*1 file icon */198 typeof (GLib.Icon), /*1 file icon */
160 typeof (string), /*2 file location */199 typeof (string?), /*2 file location */
161 typeof (File), /*3 file object */200 typeof (File?), /*3 file object */
162 typeof (bool)); /*4 icon is visible */201 typeof (bool), /*4 icon is visible */
202 typeof (string)); /*5 Sort key */
163203
164 filter = new Gtk.TreeModelFilter (list, null);204 filter = new Gtk.TreeModelFilter (list, null);
165205
166 filter.set_visible_func ((model, iter) => {206 filter.set_visible_func ((model, iter) => {
167 if (iter == no_results_label)
168 return n_results < 1;
169
170 /* hide empty category headers */207 /* hide empty category headers */
171 return list.iter_depth (iter) != 0 || list.iter_has_child (iter);208 return list.iter_depth (iter) != 0 || list.iter_has_child (iter);
172 });209 });
@@ -182,17 +219,27 @@
182 }219 }
183 });220 });
184221
222 list.set_sort_column_id (5, Gtk.SortType.ASCENDING);
223
185 list.append (out local_results, null);224 list.append (out local_results, null);
186 list.@set (local_results,225 list.@set (local_results,
187 0, get_category_header (_("In This Folder")));226 0, get_category_header (_("In This Folder")),
227 5, Category.CURRENT_HEADER.to_string ());
228
229 list.append (out deep_results, null);
230 list.@set (deep_results,
231 0, get_category_header (_("Below This Folder")),
232 5, Category.CURRENT_HEADER.to_string ());
188233
189 list.append (out bookmark_results, null);234 list.append (out bookmark_results, null);
190 list.@set (bookmark_results,235 list.@set (bookmark_results,
191 0, get_category_header (_("Bookmarks")));236 0, get_category_header (_("Bookmarks")),
237 5, Category.CURRENT_HEADER.to_string ());
192238
193 list.append (out global_results, null);239 list.append (out zeitgeist_results, null);
194 list.@set (global_results,240 list.@set (zeitgeist_results,
195 0, get_category_header (_("Everywhere Else")));241 0, get_category_header (_("Recently used")),
242 5, Category.CURRENT_HEADER.to_string ());
196243
197 scroll.add (view);244 scroll.add (view);
198 frame.add (scroll);245 frame.add (scroll);
@@ -255,8 +302,8 @@
255 }302 }
256303
257 var include_hidden = GOF.Preferences.get_default ().show_hidden_files;304 var include_hidden = GOF.Preferences.get_default ().show_hidden_files;
258305 current_count = 0;
259 display_count = 0;306 deep_count = 0;
260 directory_queue = new Gee.LinkedList<File> ();307 directory_queue = new Gee.LinkedList<File> ();
261 waiting_results = new Gee.HashMap<Gtk.TreeIter?,Gee.List> ();308 waiting_results = new Gee.HashMap<Gtk.TreeIter?,Gee.List> ();
262 current_root = folder;309 current_root = folder;
@@ -290,7 +337,7 @@
290 new Thread<void*> (null, () => {337 new Thread<void*> (null, () => {
291 local_search_finished = false;338 local_search_finished = false;
292 while (!file_search_operation.is_cancelled () && directory_queue.size > 0) {339 while (!file_search_operation.is_cancelled () && directory_queue.size > 0) {
293 visit (search_term, include_hidden, file_search_operation);340 visit (search_term, include_hidden, file_search_operation, folder);
294 }341 }
295342
296 local_search_finished = true;343 local_search_finished = true;
@@ -302,10 +349,10 @@
302 get_zg_results.begin (search_term);349 get_zg_results.begin (search_term);
303350
304 var bookmarks_matched = new Gee.LinkedList<Match> ();351 var bookmarks_matched = new Gee.LinkedList<Match> ();
305352 var begins_with = false;
306 foreach (var bookmark in BookmarkList.get_instance ().list) {353 foreach (var bookmark in BookmarkList.get_instance ().list) {
307 if (term_matches (search_term, bookmark.label)) {354 if (term_matches (search_term, bookmark.label, out begins_with)) {
308 bookmarks_matched.add (new Match.from_bookmark (bookmark));355 bookmarks_matched.add (new Match.from_bookmark (bookmark, begins_with ? Category.BOOKMARK_BEGINS : Category.BOOKMARK_CONTAINS));
309 }356 }
310 }357 }
311358
@@ -662,10 +709,10 @@
662 }709 }
663710
664 foreach (var match in new_results) {711 foreach (var match in new_results) {
665 Gtk.TreeIter iter;712 Gtk.TreeIter? iter = null;
666 File file;713 File file;
667 /* prevent results from showing in both global and local results */714 /* do not add global result if already in local results */
668 if (parent == global_results) {715 if (parent == zeitgeist_results) {
669 var already_added = false;716 var already_added = false;
670717
671 for (var valid = list.iter_nth_child (out iter, local_results, 0); valid;718 for (var valid = list.iter_nth_child (out iter, local_results, 0); valid;
@@ -679,11 +726,25 @@
679 }726 }
680 }727 }
681728
729 if (!already_added) {
730 for (var valid = list.iter_nth_child (out iter, deep_results, 0); valid;
731 valid = list.iter_next (ref iter)) {
732
733 list.@get (iter, 3, out file);
734
735 if (file != null && match.file != null && file.equal (match.file)) {
736 already_added = true;
737 break;
738 }
739 }
740 }
741
682 if (already_added) {742 if (already_added) {
683 continue;743 continue;
684 }744 }
685 } else if (parent == local_results) {745 } else if (parent == local_results) {
686 for (var valid = list.iter_nth_child (out iter, global_results, 0); valid;746 /* remove current search result from global if in global results */
747 for (var valid = list.iter_nth_child (out iter, zeitgeist_results, 0); valid;
687 valid = list.iter_next (ref iter)) {748 valid = list.iter_next (ref iter)) {
688749
689 list.@get (iter, 3, out file);750 list.@get (iter, 3, out file);
@@ -693,13 +754,25 @@
693 break;754 break;
694 }755 }
695 }756 }
696 }757 } else if (parent == deep_results) {
758 /* remove deep search result from from global if in global results */
759 for (var valid = list.iter_nth_child (out iter, zeitgeist_results, 0); valid;
760 valid = list.iter_next (ref iter)) {
761
762 list.@get (iter, 3, out file);
763
764 if (file != null && match.file != null && file.equal (match.file)) {
765 list.remove (ref iter);
766 break;
767 }
768 }
769 }
697770
698 var location = "<span %s>%s</span>".printf (get_pango_grey_color_string (),771 var location = "<span %s>%s</span>".printf (get_pango_grey_color_string (),
699 Markup.escape_text (match.path_string));772 Markup.escape_text (match.path_string));
700773
701 list.append (out iter, parent);774 list.append (out iter, parent);
702 list.@set (iter, 0, Markup.escape_text (match.name), 1, match.icon, 2, location, 3, match.file, 4, true);775 list.@set (iter, 0, match.name, 1, match.icon, 2, location, 3, match.file, 4, true, 5, match.sortkey);
703 n_results++;776 n_results++;
704777
705 view.expand_all ();778 view.expand_all ();
@@ -823,21 +896,22 @@
823 FileAttribute.STANDARD_TYPE + "," +896 FileAttribute.STANDARD_TYPE + "," +
824 FileAttribute.STANDARD_ICON;897 FileAttribute.STANDARD_ICON;
825898
826 void visit (string term, bool include_hidden, Cancellable cancel) {899 void visit (string term, bool include_hidden, Cancellable cancel, File root_folder) {
827
828 FileEnumerator enumerator;
829 var folder = directory_queue.poll ();900 var folder = directory_queue.poll ();
830901
831 if (folder == null) {902 if (folder == null) {
832 return;903 return;
833 }904 }
834905
906 bool in_root = folder.equal (root_folder);
907 var category_count = in_root ? current_count : deep_count;
908
835 var depth = 0;909 var depth = 0;
836910
837 File f = folder;911 File f = folder;
838 var path_string = "";912 var path_string = "";
839913
840 while (!f.equal (current_root)) {914 while (f != null && !f.equal (current_root)) {
841 path_string = f.get_basename () + (path_string == "" ? "" : Path.DIR_SEPARATOR_S + path_string);915 path_string = f.get_basename () + (path_string == "" ? "" : Path.DIR_SEPARATOR_S + path_string);
842 f = f.get_parent ();916 f = f.get_parent ();
843 depth++;917 depth++;
@@ -847,6 +921,7 @@
847 return;921 return;
848 }922 }
849923
924 FileEnumerator enumerator;
850 try {925 try {
851 enumerator = folder.enumerate_children (ATTRIBUTES, 0, cancel);926 enumerator = folder.enumerate_children (ATTRIBUTES, 0, cancel);
852 } catch (Error e) {927 } catch (Error e) {
@@ -856,10 +931,12 @@
856 var new_results = new Gee.LinkedList<Match> ();931 var new_results = new Gee.LinkedList<Match> ();
857932
858 FileInfo info = null;933 FileInfo info = null;
934 Category cat;
859935
860 try {936 try {
861 while (!cancel.is_cancelled () &&937 while (!cancel.is_cancelled () &&
862 (info = enumerator.next_file (null)) != null) {938 (info = enumerator.next_file (null)) != null &&
939 category_count < MAX_RESULTS) {
863940
864 if (info.get_is_hidden () && !include_hidden) {941 if (info.get_is_hidden () && !include_hidden) {
865 continue;942 continue;
@@ -869,43 +946,45 @@
869 directory_queue.add (folder.resolve_relative_path (info.get_name ()));946 directory_queue.add (folder.resolve_relative_path (info.get_name ()));
870 }947 }
871948
872 if (term_matches (term, info.get_display_name ())) {949 bool begins_with;
873 new_results.add (new Match (info, path_string, folder));950 if (term_matches (term, info.get_display_name (), out begins_with)) {
874 }951 if (in_root) {
952 cat = begins_with ? Category.CURRENT_BEGINS : Category.CURRENT_CONTAINS;
953 } else {
954 cat = begins_with ? Category.DEEP_BEGINS : Category.DEEP_CONTAINS;
955 }
956 new_results.add (new Match (info, path_string, folder, cat));
957 category_count++;
958 }
875 }959 }
876 } catch (Error e) {warning ("Error enumerating in visit");}960 } catch (Error e) {warning ("Error enumerating in visit");}
877961
878 if (new_results.size < 1) {962 if (new_results.size < 1) {
963 cat = in_root ? Category.CURRENT_ELLIPSIS : Category.DEEP_ELLIPSIS;
964 new_results.add (new Match.ellipsis (cat));
879 return;965 return;
880 }966 } else if (!cancel.is_cancelled ()) {
881967 if (in_root) {
882 if (!cancel.is_cancelled ()) {968 current_count = category_count;
883 var new_count = display_count + new_results.size;969 } else {
884 if (new_count > MAX_RESULTS) {970 deep_count = category_count;
885 cancel.cancel ();971 }
886
887 var num_ok = MAX_RESULTS - display_count;
888 if (num_ok < new_results.size) {
889 var count = 0;
890 var it = new_results.iterator ();
891 while (it.next ()) {
892 count++;
893 if (count > num_ok)
894 it.remove ();
895 }
896 }
897
898 new_results.add (new Match.ellipsis ());
899
900 display_count = MAX_RESULTS;
901 } else
902 display_count = new_count;
903972
904 /* use a closure here to get vala to pass the userdata that we actually want */973 /* use a closure here to get vala to pass the userdata that we actually want */
905 Idle.add (() => {974 Idle.add (() => {
906 add_results (new_results, local_results);975 add_results (new_results, in_root ? local_results : deep_results);
907 return false;976 return false;
908 });977 });
978
979 if (category_count >= MAX_RESULTS) {
980 cat = in_root ? Category.CURRENT_ELLIPSIS : Category.DEEP_ELLIPSIS;
981 new_results.add (new Match.ellipsis (cat));
982 return;
983 }
984
985 if (current_count >= MAX_RESULTS && deep_count >= MAX_RESULTS) {
986 cancel.cancel ();
987 }
909 }988 }
910 }989 }
911990
@@ -915,11 +994,11 @@
915994
916 Zeitgeist.ResultSet results;995 Zeitgeist.ResultSet results;
917 try {996 try {
918 results = yield zg_index.search (term,997 results = yield zg_index.search ("name:" + term + "*",
919 new Zeitgeist.TimeRange.anytime (),998 new Zeitgeist.TimeRange.anytime (),
920 templates,999 templates,
921 0, /* offset */1000 0, /* offset */
922 MAX_RESULTS + 1,1001 MAX_RESULTS * 3,
923 Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,1002 Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,
924 current_operation);1003 current_operation);
925 } catch (IOError.CANCELLED e) {1004 } catch (IOError.CANCELLED e) {
@@ -935,54 +1014,80 @@
9351014
936 var matches = new Gee.LinkedList<Match> ();1015 var matches = new Gee.LinkedList<Match> ();
937 var home = File.new_for_path (Environment.get_home_dir ());1016 var home = File.new_for_path (Environment.get_home_dir ());
1017 Category cat;
938 var i = 0;1018 var i = 0;
939 while (results.has_next () && !current_operation.is_cancelled ()) {1019
1020 while (results.has_next () && !current_operation.is_cancelled () && !global_search_finished) {
940 var result = results.next_value ();1021 var result = results.next_value ();
941 foreach (var subject in result.subjects.data) {1022 foreach (var subject in result.subjects.data) {
942 if (i == MAX_RESULTS) {1023 if (i == MAX_RESULTS) {
943 matches.add (new Match.ellipsis ());1024 matches.add (new Match.ellipsis (Category.ZEITGEIST_ELLIPSIS));
1025 global_search_finished = true;
944 break;1026 break;
945 }1027 }
9461028
947 try {1029 try {
948 var file = File.new_for_uri (subject.uri);1030 var file = File.new_for_uri (subject.uri);
949 var path_string = "";1031 /* Zeitgeist search finds search term anywhere in path. We are only interested
950 var parent = file;1032 * when the search term is in the basename */
951 while ((parent = parent.get_parent ()) != null) {1033 while (file != null && !file.get_basename ().contains (term)) {
952 if (parent.equal (current_root))1034 file = file.get_parent ();
953 break;1035 }
9541036
955 if (parent.equal (home)) {1037 if (file != null) {
956 path_string = "~/" + path_string;1038 var path_string = "";
957 break;1039 var parent = file;
958 }1040 while ((parent = parent.get_parent ()) != null) {
9591041 if (parent.equal (current_root)) {
960 if (path_string == "")1042 break;
961 path_string = parent.get_basename ();1043 }
962 else1044
963 path_string = parent.get_basename () + Path.DIR_SEPARATOR_S + path_string;1045 if (parent.equal (home)) {
964 }1046 path_string = "~/" + path_string;
9651047 break;
966 var info = yield file.query_info_async (ATTRIBUTES, 0, Priority.DEFAULT, current_operation);1048 }
967 matches.add (new Match (info, path_string, file.get_parent ()));1049
9681050 if (path_string == "") {
969 i++;1051 path_string = parent.get_basename ();
1052 } else {
1053 path_string = Path.build_path (Path.DIR_SEPARATOR_S, parent.get_basename (), path_string);
1054 }
1055 }
1056
1057 /* Eliminate duplicate matches */
1058 bool found = false;
1059 foreach (Match m in matches) {
1060 if (m.path_string == path_string) {
1061 found = true;
1062 break;
1063 }
1064 }
1065
1066 if (!found) {
1067 var info = yield file.query_info_async (ATTRIBUTES, 0, Priority.DEFAULT, current_operation);
1068 var name = info.get_display_name ();
1069 cat = name.has_prefix (term) ? Category.ZEITGEIST_BEGINS : Category.ZEITGEIST_CONTAINS;
1070 matches.add (new Match (info, path_string, file.get_parent (), cat));
1071 i++;
1072 }
1073 }
970 } catch (Error e) {}1074 } catch (Error e) {}
971 }1075 }
972 }1076 }
9731077
974 if (!current_operation.is_cancelled ()) {1078 if (!current_operation.is_cancelled ()) {
975 add_results (matches, global_results);1079 add_results (matches, zeitgeist_results);
976 }1080 }
9771081
978 global_search_finished = true;1082 global_search_finished = true;
979 Idle.add (send_search_finished);1083 Idle.add (send_search_finished);
980 }1084 }
9811085
982 bool term_matches (string term, string name) {1086 bool term_matches (string term, string name, out bool begins_with ) {
983 /**TODO** improve */
984 /* term is assumed to be down */1087 /* term is assumed to be down */
985 return name.normalize ().casefold ().contains (term);1088 var n = name.normalize ().casefold ();
1089 begins_with = n.has_prefix (term);
1090 return n.contains (term);
986 }1091 }
9871092
988 string get_category_header (string title)1093 string get_category_header (string title)

Subscribers

People subscribed via source and target branches