Merge lp:~mhr3/unity-lens-files/fix-947856 into lp:unity-lens-files

Proposed by Michal Hruby
Status: Merged
Approved by: Neil J. Patel
Approved revision: no longer in the source branch.
Merged at revision: 220
Proposed branch: lp:~mhr3/unity-lens-files/fix-947856
Merge into: lp:unity-lens-files
Diff against target: 362 lines (+99/-112)
3 files modified
src/daemon.vala (+88/-111)
src/url-checker.vala (+1/-1)
tests/manual/downloads.txt (+10/-0)
To merge this branch: bzr merge lp:~mhr3/unity-lens-files/fix-947856
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Approve
Siegfried Gevatter (community) Approve
Review via email: mp+97440@code.launchpad.net

Commit message

Use Zeitgeist's data to list files from Downloads directory.

This makes sure that search is consistent and privacy settings are honored.

Description of the change

Use Zeitgeist for downloads directory listing and searching, so we make sure the privacy settings are honored.

To post a comment you must log in.
Revision history for this message
Siegfried Gevatter (rainct) wrote :

Nice :).

review: Approve
Revision history for this message
Neil J. Patel (njpatel) wrote :

Looks good

review: Approve
lp:~mhr3/unity-lens-files/fix-947856 updated
219. By Michal Hruby

Monitor Zeitgeist's blacklist to make sure locate search respects privacy settings.. Fixes: https://bugs.launchpad.net/bugs/955229. Approved by Neil J. Patel, Siegfried Gevatter.

220. By Michal Hruby

Use Zeitgeist's data to list files from Downloads directory.

This makes sure that search is consistent and privacy settings are honored.. Fixes: https://bugs.launchpad.net/bugs/947856. Approved by Neil J. Patel, Siegfried Gevatter.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/daemon.vala'
2--- src/daemon.vala 2012-03-12 23:23:48 +0000
3+++ src/daemon.vala 2012-03-15 12:01:17 +0000
4@@ -42,6 +42,7 @@
5 /* For each section we have a set of Zeitgeist.Event templates that
6 * we use to query Zeitgeist */
7 private HashTable<string, Event> type_templates;
8+ private HashTable<string, Event> download_dir_type_templates;
9
10 private const string SCHEMA_NAME = "com.canonical.Unity.FilesLens";
11 private const string USE_LOCATE_KEY = "use-locate";
12@@ -213,65 +214,65 @@
13 lens.categories = categories;
14 }
15
16- private void prepare_type_templates ()
17+ private void init_templates (HashTable<string, Event> templates,
18+ string manifestation, string uri_prefix)
19 {
20- type_templates = new HashTable<string, Event> (str_hash, str_equal);
21 Event event;
22
23 /* Section.ALL_FILES */
24- event = new Event.full("", ZG_USER_ACTIVITY, "",
25- new Subject.full ("file:*",
26+ event = new Event.full("", manifestation, "",
27+ new Subject.full (uri_prefix,
28 "", "", "", "", "", ""));
29- type_templates["all"] = event;
30+ templates["all"] = event;
31
32 /* Section.DOCUMENTS */
33- event = new Event.full("", ZG_USER_ACTIVITY, "",
34- new Subject.full ("file:*",
35+ event = new Event.full("", manifestation, "",
36+ new Subject.full (uri_prefix,
37 NFO_DOCUMENT,
38 "", "", "", "", ""),
39- new Subject.full ("file:*",
40+ new Subject.full ("",
41 "!"+NFO_PRESENTATION,
42 "", "", "", "", ""));
43- type_templates["documents"] = event;
44+ templates["documents"] = event;
45
46 /* Section.FOLDERS
47 * - we're using special ORIGIN queries here */
48- event = new Event.full("", ZG_USER_ACTIVITY, "",
49- new Subject.full ("file:*",
50+ event = new Event.full("", manifestation, "",
51+ new Subject.full (uri_prefix,
52 "", "", "", "", "", ""));
53- type_templates["folders"] = event;
54+ templates["folders"] = event;
55
56 /* Section.IMAGES */
57- event = new Event.full("", ZG_USER_ACTIVITY, "",
58- new Subject.full ("file:*",
59+ event = new Event.full("", manifestation, "",
60+ new Subject.full (uri_prefix,
61 NFO_IMAGE, "", "", "", "", ""));
62- type_templates["images"] = event;
63+ templates["images"] = event;
64
65 /* Section.AUDIO */
66- event = new Event.full("", ZG_USER_ACTIVITY, "",
67- new Subject.full ("file:*",
68+ event = new Event.full("", manifestation, "",
69+ new Subject.full (uri_prefix,
70 NFO_AUDIO, "", "", "", "", ""));
71- type_templates["audio"] = event;
72+ templates["audio"] = event;
73
74 /* Section.VIDEOS */
75- event = new Event.full("", ZG_USER_ACTIVITY, "",
76- new Subject.full ("file:*",
77+ event = new Event.full("", manifestation, "",
78+ new Subject.full (uri_prefix,
79 NFO_VIDEO, "", "", "", "", ""));
80- type_templates["videos"] = event;
81+ templates["videos"] = event;
82
83 /* Section.PRESENTATIONS
84 * FIXME: Zeitgeist logger needs to user finer granularity
85 * on classification as I am not sure it uses
86 * NFO_PRESENTATION yet */
87- event = new Event.full("", ZG_USER_ACTIVITY, "",
88- new Subject.full ("file:*",
89+ event = new Event.full("", manifestation, "",
90+ new Subject.full (uri_prefix,
91 NFO_PRESENTATION, "", "", "", "", ""));
92- type_templates["presentations"] = event;
93+ templates["presentations"] = event;
94
95 /* Section.OTHER
96 * Note that subject templates are joined with logical AND */
97- event = new Event.full("", ZG_USER_ACTIVITY, "");
98- event.add_subject (new Subject.full ("file:*",
99+ event = new Event.full("", manifestation, "");
100+ event.add_subject (new Subject.full (uri_prefix,
101 "!"+NFO_DOCUMENT, "", "", "", "", ""));
102 event.add_subject (new Subject.full ("",
103 "!"+NFO_IMAGE,
104@@ -289,7 +290,23 @@
105 "!"+NFO_PRESENTATION,
106 "",
107 "", "", "", ""));
108- type_templates["other"] = event;
109+ templates["other"] = event;
110+ }
111+
112+ private void prepare_type_templates ()
113+ {
114+ type_templates = new HashTable<string, Event> (str_hash, str_equal);
115+ init_templates (type_templates, ZG_USER_ACTIVITY, "file:*");
116+
117+ unowned string download_path;
118+ download_path = Environment.get_user_special_dir (UserDirectory.DOWNLOAD);
119+ if (download_path != null)
120+ {
121+ download_dir_type_templates = new HashTable<string, Event> (str_hash,
122+ str_equal);
123+ string download_uri = File.new_for_path (download_path).get_uri ();
124+ init_templates (download_dir_type_templates, "", download_uri + "/*");
125+ }
126 }
127
128 private const string[] ALL_TYPES =
129@@ -303,14 +320,19 @@
130 "other"
131 };
132
133- private GenericArray<Event> create_template (OptionsFilter? filter)
134+ private GenericArray<Event>? create_template (OptionsFilter? filter,
135+ bool downloads_templates)
136 {
137 var templates = new GenericArray<Event> ();
138
139+ HashTable<string, Event>? prepared_templates = downloads_templates ?
140+ download_dir_type_templates : type_templates;
141+ if (prepared_templates == null) return null;
142+
143 if (filter == null || !filter.filtering)
144 {
145 /* Section.ALL_FILES */
146- templates.add (type_templates["all"]);
147+ templates.add (prepared_templates["all"]);
148 return templates;
149 }
150
151@@ -327,7 +349,7 @@
152 if (types.length == ALL_TYPES.length)
153 {
154 /* Section.ALL_FILES */
155- templates.add (type_templates["all"]);
156+ templates.add (prepared_templates["all"]);
157 return templates;
158 }
159
160@@ -336,7 +358,7 @@
161 // we need to handle folders separately
162 if (type_id == "folders") continue;
163
164- templates.add (type_templates[type_id]);
165+ templates.add (prepared_templates[type_id]);
166 }
167
168 return templates;
169@@ -413,8 +435,17 @@
170 /* Add downloads catagory if we don't have a search */
171 if (has_search == false)
172 {
173- yield update_downloads_async (results_model, cancellable,
174- search.search_string);
175+ results = yield run_zg_query (search,
176+ new Zeitgeist.TimeRange.anytime (),
177+ ResultType.MOST_RECENT_SUBJECTS,
178+ null,
179+ 20,
180+ cancellable,
181+ true);
182+
183+ Unity.FilesLens.append_events_sorted (results, results_model,
184+ 0, int64.MAX, ResultFlags.NONE,
185+ null, Categories.DOWNLOADS);
186 }
187
188 if (has_search && use_locate)
189@@ -487,8 +518,18 @@
190 }
191
192 /* get recently downloaded files */
193- yield update_downloads_async (txn, cancellable,
194- search.search_string);
195+ results = yield run_zg_query (search,
196+ get_current_timerange (),
197+ ResultType.MOST_RECENT_SUBJECTS,
198+ filter,
199+ 50,
200+ cancellable,
201+ true);
202+
203+ Unity.FilesLens.append_events_sorted (results, txn,
204+ min_size, max_size,
205+ ResultFlags.NONE,
206+ null, Categories.DOWNLOADS);
207
208 /* commit if the origin query is taking too long, if we committed right
209 * away, we'd cause flicker */
210@@ -670,16 +711,19 @@
211 }
212 }
213
214- private async ResultSet run_zg_query (LensSearch search,
215- TimeRange time_range,
216- ResultType result_type,
217- OptionsFilter? filters,
218- uint num_results,
219- Cancellable cancellable) throws Error
220+ private async ResultSet? run_zg_query (LensSearch search,
221+ TimeRange time_range,
222+ ResultType result_type,
223+ OptionsFilter? filters,
224+ uint num_results,
225+ Cancellable cancellable,
226+ bool downloads_only = false)
227+ throws Error
228 {
229 ResultSet results;
230 var timer = new Timer ();
231- var templates = create_template (filters);
232+ var templates = create_template (filters, downloads_only);
233+ if (templates == null) return null;
234
235 /* Copy the templates to a PtrArray which libzg expects */
236 var ptr_arr = new PtrArray ();
237@@ -730,74 +774,6 @@
238 }
239 }
240
241- private async void update_downloads_async (Dee.Model results_model,
242- Cancellable cancellable,
243- string? name_filter = null,
244- int category_override = -1) throws IOError
245- {
246- // FIXME: Store the Downloads folder and update on changes
247- unowned string download_path =
248- Environment.get_user_special_dir (UserDirectory.DOWNLOAD);
249- if (download_path == null) {
250- warning ("Download directory unknown, skipping.");
251- return;
252- }
253- var download_dir = File.new_for_path (download_path);
254- SList<FileInfo> downloads;
255-
256- try {
257- if (name_filter != null && name_filter != "")
258- downloads = yield Utils.list_dir_filtered (download_dir, name_filter);
259- else
260- downloads = yield Utils.list_dir (download_dir);
261- } catch (GLib.Error e) {
262- warning ("Failed to list downloads from directory '%s': %s",
263- download_path, e.message);
264- return;
265- }
266-
267- cancellable.set_error_if_cancelled (); // throws IOError
268-
269- /* Sort files by mtime, we do an ugly nested ternary
270- * to avoid potential long/int overflow */
271- downloads.sort ((CompareFunc) Utils.cmp_file_info_by_mtime);
272-
273- var timerange = get_current_timerange ();
274- int64 min_size, max_size;
275- get_current_size_limits (out min_size, out max_size);
276- var types = get_current_types ();
277-
278- foreach (var info in downloads)
279- {
280- var uri = download_dir.get_child (info.get_name ()).get_uri ();
281- var mimetype = info.get_content_type ();
282- var icon_hint = Utils.check_icon_string (uri, mimetype, info);
283-
284- // check if we match the timerange
285- uint64 atime = info.get_attribute_uint64 (FILE_ATTRIBUTE_TIME_ACCESS) * 1000;
286-
287- if (atime < timerange.get_start() || atime > timerange.get_end ())
288- continue;
289-
290- // check if type matches
291- if (types != null && !Utils.file_info_matches_any (info, types))
292- continue;
293-
294- // check if size is within bounds
295- int64 size = info.get_size ();
296- if (size < min_size || size > max_size)
297- continue;
298-
299- uint category_id = Categories.DOWNLOADS;
300-
301- if (category_override >= 0)
302- category_id = category_override;
303-
304- results_model.append (uri, icon_hint, category_id,
305- mimetype, info.get_display_name (), uri);
306- }
307- }
308-
309 private async void perform_locate (uint timeout,
310 string query,
311 Dee.Model results_model,
312@@ -908,13 +884,14 @@
313
314 /* Appends a set of Zeitgeist.Events to our Dee.Model assuming that
315 * these events are already sorted with descending timestamps */
316- public void append_events_sorted (Zeitgeist.ResultSet events,
317+ public void append_events_sorted (Zeitgeist.ResultSet? events,
318 Dee.Model results,
319 int64 min_size, int64 max_size,
320 ResultFlags flags,
321 Gee.Set<string>? excluded_uris = null,
322 int category_override = -1)
323 {
324+ if (events == null) return;
325 foreach (var ev in events)
326 {
327 if (ev.num_subjects() > 0)
328
329=== modified file 'src/url-checker.vala'
330--- src/url-checker.vala 2012-03-13 08:53:24 +0000
331+++ src/url-checker.vala 2012-03-15 12:01:17 +0000
332@@ -68,6 +68,7 @@
333 */
334 public string? check_url (string sample, out UrlType url_type)
335 {
336+ url_type = UrlType.UNKNOWN;
337 if (sample.strip () == "") return null;
338
339 if (mountable_regex.match (sample))
340@@ -80,7 +81,6 @@
341 url_type = UrlType.WEB;
342 return sample.has_prefix ("http") ? sample : ("http://" + sample);
343 }
344- url_type = UrlType.UNKNOWN;
345 return null;
346 }
347
348
349=== added file 'tests/manual/downloads.txt'
350--- tests/manual/downloads.txt 1970-01-01 00:00:00 +0000
351+++ tests/manual/downloads.txt 2012-03-15 12:01:17 +0000
352@@ -0,0 +1,10 @@
353+Downloads
354+=========
355+Tests that the downloads category shows files from your ~/Downloads directory.
356+
357+#. Create a file in the ~/Downloads category (or equivalent for your locale).
358+#. Search for this file with files lens.
359+
360+Outcome
361+ The file you created in the first step should show up as a result in the Downloads category of files lens.
362+

Subscribers

People subscribed via source and target branches