Merge lp:~mhr3/unity-lens-music/home-lenses into lp:unity-lens-music
- home-lenses
- Merge into trunk
Proposed by
Michal Hruby
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Didier Roche-Tolomelli | ||||
Approved revision: | 76 | ||||
Merged at revision: | 69 | ||||
Proposed branch: | lp:~mhr3/unity-lens-music/home-lenses | ||||
Merge into: | lp:unity-lens-music | ||||
Diff against target: |
438 lines (+162/-92) 10 files modified
po/POTFILES.in (+1/-0) po/POTFILES.skip (+1/-1) src/Makefile.am (+1/-0) src/banshee-collection.vala (+45/-11) src/banshee-scope.vala (+14/-3) src/categories.vala (+29/-0) src/daemon.vala (+6/-0) src/musicstore-collection.vala (+12/-9) src/musicstore-scope.vala (+8/-6) src/simple-scope.vala (+45/-62) |
||||
To merge this branch: | bzr merge lp:~mhr3/unity-lens-music/home-lenses | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mikkel Kamstrup Erlandsen (community) | Approve | ||
Review via email: mp+89667@code.launchpad.net |
Commit message
Description of the change
Changes to the lens to suit new home lens view - collate Songs and Albums into one category (displaying Albums first)
To post a comment you must log in.
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote : | # |
review:
Needs Fixing
Revision history for this message
Michal Hruby (mhr3) wrote : | # |
Fixed.
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote : | # |
Awesome!
review:
Approve
Revision history for this message
Unity Merger (unity-merger) wrote : | # |
The Jenkins job https:/
Not merging it.
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) : | # |
review:
Approve
Revision history for this message
Unity Merger (unity-merger) wrote : | # |
The Jenkins job https:/
Not merging it.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'po/POTFILES.in' |
2 | --- po/POTFILES.in 2011-08-11 13:38:55 +0000 |
3 | +++ po/POTFILES.in 2012-01-23 14:02:32 +0000 |
4 | @@ -1,5 +1,6 @@ |
5 | [encoding: UTF-8] |
6 | src/daemon.vala |
7 | src/main.vala |
8 | +src/simple-scope.vala |
9 | [type: gettext/ini]music.lens.in.in |
10 | |
11 | |
12 | === modified file 'po/POTFILES.skip' |
13 | --- po/POTFILES.skip 2011-08-09 17:28:19 +0000 |
14 | +++ po/POTFILES.skip 2012-01-23 14:02:32 +0000 |
15 | @@ -1,4 +1,4 @@ |
16 | src/main.c |
17 | src/daemon.c |
18 | src/utils.c |
19 | - |
20 | +src/simple-scope.c |
21 | |
22 | === modified file 'src/Makefile.am' |
23 | --- src/Makefile.am 2011-09-15 18:08:53 +0000 |
24 | +++ src/Makefile.am 2012-01-23 14:02:32 +0000 |
25 | @@ -41,6 +41,7 @@ |
26 | banshee-filter-parser-decade.vala \ |
27 | banshee-filter-parser-genre.vala \ |
28 | banshee-scope.vala \ |
29 | + categories.vala \ |
30 | config.vala \ |
31 | daemon.vala \ |
32 | filter-parser.vala \ |
33 | |
34 | === modified file 'src/banshee-collection.vala' |
35 | --- src/banshee-collection.vala 2011-09-22 15:23:41 +0000 |
36 | +++ src/banshee-collection.vala 2012-01-23 14:02:32 +0000 |
37 | @@ -49,11 +49,12 @@ |
38 | /** |
39 | * Performs a search on the banshee db |
40 | */ |
41 | - public void search (LensSearch? search, |
42 | - Dee.Model results_model, |
43 | - GLib.List<FilterParser>? filters = null, |
44 | - int max_results = -1) |
45 | - { |
46 | + public void search (LensSearch search, |
47 | + SearchType search_type, |
48 | + GLib.List<FilterParser>? filters = null, |
49 | + int max_results = -1, |
50 | + int category_override = -1) |
51 | + { |
52 | const int TRACK_TITLE = 0; |
53 | const int TRACK_URI = 1; |
54 | const int TRACK_MIMETYPE = 2; |
55 | @@ -65,6 +66,14 @@ |
56 | Statement stmt; |
57 | string album_art_dir = "%s/media-art/".printf (Environment.get_user_cache_dir ()); |
58 | |
59 | + var results_model = search.results_model; |
60 | + var helper_model = results_model; |
61 | + if (category_override >= 0) |
62 | + { |
63 | + helper_model = new Dee.SequenceModel (); |
64 | + helper_model.set_schema_full (results_model.get_schema ()); |
65 | + } |
66 | + |
67 | // use a tree set to ensure we don't duplicate albums |
68 | TreeSet<string> albums = new TreeSet<string> (); |
69 | string filters_sql = build_sql_from_filters (filters); |
70 | @@ -93,7 +102,7 @@ |
71 | rc = execute_sql (sql, out stmt); |
72 | if (stmt == null) |
73 | return; |
74 | - |
75 | + |
76 | do { |
77 | rc = stmt.step (); |
78 | switch (rc) { |
79 | @@ -119,8 +128,14 @@ |
80 | album.uri = "album://%s/%s".printf (album.artist, album.title); |
81 | album.artwork_path = artwork_path; |
82 | |
83 | - results_model.append (track.uri, track.artwork_path, 0, track.mime_type, track.title, track.artist, track.uri); |
84 | - |
85 | + uint category_id = Category.SONGS; |
86 | + if (category_override >= 0) |
87 | + category_id = category_override; |
88 | + |
89 | + helper_model.append (track.uri, track.artwork_path, category_id, |
90 | + track.mime_type, track.title, track.artist, |
91 | + track.uri); |
92 | + |
93 | if (albums.add (album.artist + album.title)) { |
94 | StringBuilder uri_list_builder = new StringBuilder (); |
95 | foreach (string uri in get_track_uris (album)) { |
96 | @@ -128,15 +143,34 @@ |
97 | uri_list_builder.append (uri); |
98 | uri_list_builder.append ("' "); |
99 | } |
100 | - |
101 | - results_model.append (album.uri, album.artwork_path, 1, "audio/mp3", album.title, album.artist, uri_list_builder.str); |
102 | + |
103 | + category_id = Category.ALBUMS; |
104 | + if (category_override >= 0) |
105 | + category_id = category_override; |
106 | + |
107 | + results_model.append (album.uri, album.artwork_path, category_id, |
108 | + "audio/mp3", album.title, album.artist, |
109 | + uri_list_builder.str); |
110 | } |
111 | - |
112 | + |
113 | break; |
114 | default: |
115 | break; |
116 | } |
117 | } while (rc == Sqlite.ROW); |
118 | + |
119 | + if (helper_model == results_model) return; |
120 | + |
121 | + // we need to do this because the dash doesn't care about position |
122 | + // of a newly added row in the model - it just appends it |
123 | + var iter = helper_model.get_first_iter (); |
124 | + var last = helper_model.get_last_iter (); |
125 | + while (iter != last) |
126 | + { |
127 | + var row = helper_model.get_row (iter); |
128 | + results_model.append_row (row); |
129 | + iter = helper_model.next (iter); |
130 | + } |
131 | } |
132 | |
133 | /** |
134 | |
135 | === modified file 'src/banshee-scope.vala' |
136 | --- src/banshee-scope.vala 2011-09-21 18:52:49 +0000 |
137 | +++ src/banshee-scope.vala 2012-01-23 14:02:32 +0000 |
138 | @@ -91,10 +91,21 @@ |
139 | } |
140 | } |
141 | |
142 | - public override void perform_search (LensSearch? search, Dee.Model results_model, |
143 | - List<FilterParser> filters, int max_results = -1) |
144 | + public override async void perform_search (LensSearch search, |
145 | + SearchType search_type, |
146 | + owned List<FilterParser> filters, |
147 | + int max_results = -1) |
148 | { |
149 | - collection.search (search, results_model, filters, max_results); |
150 | + int category_override = -1; |
151 | + if (search_type == SearchType.GLOBAL) |
152 | + { |
153 | + category_override = Category.MUSIC; |
154 | + // the lens shouldn't display anything for empty search |
155 | + if (is_search_empty (search)) return; |
156 | + } |
157 | + |
158 | + collection.search (search, search_type, filters, |
159 | + max_results, category_override); |
160 | } |
161 | } |
162 | } |
163 | |
164 | === added file 'src/categories.vala' |
165 | --- src/categories.vala 1970-01-01 00:00:00 +0000 |
166 | +++ src/categories.vala 2012-01-23 14:02:32 +0000 |
167 | @@ -0,0 +1,29 @@ |
168 | +/* |
169 | + * Copyright (C) 2012 Canonical Ltd |
170 | + * |
171 | + * This program is free software: you can redistribute it and/or modify |
172 | + * it under the terms of the GNU General Public License version 3 as |
173 | + * published by the Free Software Foundation. |
174 | + * |
175 | + * This program is distributed in the hope that it will be useful, |
176 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
177 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
178 | + * GNU General Public License for more details. |
179 | + * |
180 | + * You should have received a copy of the GNU General Public License |
181 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
182 | + * |
183 | + * Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com> |
184 | + * |
185 | + */ |
186 | + |
187 | +namespace Unity.MusicLens { |
188 | + |
189 | + public enum Category { |
190 | + SONGS, |
191 | + ALBUMS, |
192 | + PURCHASE, |
193 | + MUSIC |
194 | + } |
195 | + |
196 | +} |
197 | |
198 | === modified file 'src/daemon.vala' |
199 | --- src/daemon.vala 2012-01-10 10:09:16 +0000 |
200 | +++ src/daemon.vala 2012-01-23 14:02:32 +0000 |
201 | @@ -102,6 +102,8 @@ |
202 | // FIXME icons |
203 | private void populate_categories () |
204 | { |
205 | + /* Offsets of categories must match up with the Category enum */ |
206 | + |
207 | var categories = new GLib.List<Unity.Category> (); |
208 | var icon_dir = File.new_for_path (ICON_PATH); |
209 | |
210 | @@ -116,6 +118,10 @@ |
211 | cat = new Unity.Category (_("Available for Purchase"), |
212 | new FileIcon (icon_dir.get_child ("group-purchase.svg"))); |
213 | categories.append (cat); |
214 | + |
215 | + cat = new Unity.Category (_("Music"), |
216 | + new FileIcon (icon_dir.get_child ("group-songs.svg"))); |
217 | + categories.append (cat); |
218 | |
219 | lens.categories = categories; |
220 | } |
221 | |
222 | === modified file 'src/musicstore-collection.vala' |
223 | --- src/musicstore-collection.vala 2011-09-29 07:24:40 +0000 |
224 | +++ src/musicstore-collection.vala 2012-01-23 14:02:32 +0000 |
225 | @@ -32,32 +32,35 @@ |
226 | { |
227 | } |
228 | |
229 | - public void search (LensSearch? search, Dee.Model results_model, |
230 | - List<FilterParser> filters, int max_results = -1) throws IOError |
231 | + public async void search (LensSearch search, SearchType search_type, |
232 | + owned List<FilterParser> filters, int max_results = -1) throws IOError |
233 | { |
234 | // helps cut down on number of requests we send out to u1 |
235 | if (cancellable != null) |
236 | - cancellable.cancel (); |
237 | + cancellable.cancel (); |
238 | |
239 | cancellable = new Cancellable (); |
240 | string? uri = build_search_uri (search.search_string, filters); |
241 | |
242 | if (uri == null) |
243 | - return; |
244 | - |
245 | + return; |
246 | + |
247 | + var results_model = search.results_model; |
248 | File file = File.new_for_uri (uri); |
249 | - read_musicstore_search_result_async.begin (file, results_model); |
250 | + |
251 | + yield read_musicstore_search_result_async (file, results_model); |
252 | } |
253 | |
254 | private async void read_musicstore_search_result_async (File file, Dee.Model model) |
255 | { |
256 | var timer = new Timer (); |
257 | debug ("Searching %s", file.get_uri ()); |
258 | - |
259 | + |
260 | try { |
261 | - var dis = new DataInputStream (file.read (cancellable)); |
262 | + var stream = yield file.read_async (Priority.DEFAULT, cancellable); |
263 | + var dis = new DataInputStream (stream); |
264 | var parser = new Json.Parser (); |
265 | - parser.load_from_stream (dis, cancellable); |
266 | + yield parser.load_from_stream_async (dis, cancellable); |
267 | var root_object = parser.get_root ().get_object (); |
268 | |
269 | foreach (var r in root_object.get_array_member ("results").get_elements ()) { |
270 | |
271 | === modified file 'src/musicstore-scope.vala' |
272 | --- src/musicstore-scope.vala 2011-09-22 00:12:38 +0000 |
273 | +++ src/musicstore-scope.vala 2012-01-23 14:02:32 +0000 |
274 | @@ -59,16 +59,18 @@ |
275 | return new Unity.ActivationResponse (Unity.HandledType.HIDE_DASH); |
276 | } |
277 | |
278 | - public override void perform_search (LensSearch? search, Dee.Model results_model, |
279 | - List<FilterParser> filters, int max_results = -1) |
280 | + public override async void perform_search (LensSearch search, |
281 | + SearchType search_type, |
282 | + owned List<FilterParser> filters, |
283 | + int max_results = -1) |
284 | { |
285 | - if (search_is_invalid (search)) |
286 | + if (is_search_empty (search)) |
287 | return; |
288 | |
289 | try { |
290 | - debug ("model has %u rows before search", results_model.get_n_rows ()); |
291 | - collection.search (search, results_model, filters, max_results); |
292 | - debug ("model has %u rows after search", results_model.get_n_rows ()); |
293 | + debug ("model has %u rows before search", search.results_model.get_n_rows ()); |
294 | + yield collection.search (search, search_type, (owned) filters, max_results); |
295 | + debug ("model has %u rows after search", search.results_model.get_n_rows ()); |
296 | } catch (IOError e) { |
297 | warning ("Failed to search for '%s': %s", search.search_string, e.message); |
298 | } |
299 | |
300 | === modified file 'src/simple-scope.vala' |
301 | --- src/simple-scope.vala 2012-01-19 12:21:04 +0000 |
302 | +++ src/simple-scope.vala 2012-01-23 14:02:32 +0000 |
303 | @@ -29,8 +29,11 @@ |
304 | protected abstract int num_results_global_search { get; } |
305 | protected abstract int num_results_lens_search { get; } |
306 | |
307 | - protected abstract void perform_search (LensSearch? search, Dee.Model results_model, List<FilterParser> filters, int max_results = -1); |
308 | - |
309 | + protected abstract async void perform_search (LensSearch search, |
310 | + SearchType search_type, |
311 | + owned List<FilterParser> filters, |
312 | + int max_results = -1); |
313 | + |
314 | public SimpleScope () |
315 | { |
316 | } |
317 | @@ -49,64 +52,50 @@ |
318 | |
319 | /* Listen for changes to the lens search entry */ |
320 | scope.search_changed.connect ((search, search_type, cancellable) => { |
321 | - if (search_type == SearchType.DEFAULT) |
322 | - update_search_async.begin (search); |
323 | - else |
324 | - update_global_search_async.begin (search); |
325 | + update_search_async.begin (search, search_type); |
326 | }); |
327 | } |
328 | - |
329 | - /* based on the filters(?) get the default results to show when the music lens is |
330 | - * just opened without filters, like when someone hits Super+M |
331 | - */ |
332 | - private async void update_without_search_async (LensSearch search) |
333 | - { |
334 | - yield perform_search_async (search, num_results_without_search); |
335 | - } |
336 | - |
337 | - /** |
338 | - * results for a global search from just hitting Super. here we want to return |
339 | - * a smaller number of results with 0 filters. |
340 | - */ |
341 | - private async void update_global_search_async (LensSearch search) |
342 | - { |
343 | - if (search_is_invalid (search)) |
344 | - { |
345 | - search.results_model.clear (); |
346 | - search.finished (); |
347 | - return; |
348 | - } |
349 | - |
350 | - yield perform_search_async (search, num_results_global_search); |
351 | - } |
352 | - |
353 | - private async void update_search_async (LensSearch search) |
354 | - { |
355 | - // just pretend like there's no search |
356 | - if (search_is_invalid (search)) |
357 | - { |
358 | - yield update_without_search_async (search); |
359 | - return; |
360 | - } |
361 | - |
362 | - yield perform_search_async (search, num_results_lens_search); |
363 | - } |
364 | - |
365 | - private async void perform_search_async (LensSearch search, int max_results) |
366 | + |
367 | + private async void update_search_async (LensSearch search, |
368 | + SearchType search_type) |
369 | + { |
370 | + int max_results; |
371 | + /* |
372 | + * results for a global search from just hitting Super. |
373 | + * Here we want to return a smaller number of results with 0 filters. |
374 | + */ |
375 | + if (search_type == SearchType.GLOBAL) |
376 | + max_results = num_results_global_search; |
377 | + else if (is_search_empty (search)) |
378 | + max_results = num_results_without_search; |
379 | + else |
380 | + max_results = num_results_lens_search; |
381 | + |
382 | + yield prepare_search (search, search_type, max_results); |
383 | + } |
384 | + |
385 | + private async void prepare_search (LensSearch search, |
386 | + SearchType search_type, |
387 | + int max_results) |
388 | { |
389 | var results_model = search.results_model; |
390 | |
391 | List<FilterParser> filters = new List<FilterParser> (); |
392 | - Filter filter = scope.get_filter ("genre"); |
393 | - if (filter.filtering) |
394 | - filters.append (new GenreFilterParser (filter as CheckOptionFilterCompact)); |
395 | - |
396 | - filter = scope.get_filter ("decade"); |
397 | - if (filter.filtering) |
398 | - filters.append (new DecadeFilterParser (filter as MultiRangeFilter)); |
399 | - |
400 | + // don't apply filters to global searches |
401 | + if (search_type != SearchType.GLOBAL) |
402 | + { |
403 | + Filter filter = scope.get_filter ("genre"); |
404 | + if (filter.filtering) |
405 | + filters.append (new GenreFilterParser (filter as CheckOptionFilterCompact)); |
406 | + |
407 | + filter = scope.get_filter ("decade"); |
408 | + if (filter.filtering) |
409 | + filters.append (new DecadeFilterParser (filter as MultiRangeFilter)); |
410 | + } |
411 | + |
412 | results_model.clear (); |
413 | - perform_search (search, results_model, filters, max_results); |
414 | + |
415 | + yield perform_search (search, search_type, (owned) filters, max_results); |
416 | |
417 | if (results_model.get_n_rows () == 0) |
418 | { |
419 | @@ -117,16 +106,10 @@ |
420 | search.finished (); |
421 | } |
422 | |
423 | - protected bool search_is_invalid (LensSearch? search) |
424 | + protected bool is_search_empty (LensSearch search) |
425 | + requires (search.search_string != null) |
426 | { |
427 | - /* This boolean expression is unfolded as we seem to get |
428 | - * some null dereference if we join them in a big || expression */ |
429 | - if (search == null) |
430 | - return true; |
431 | - else if (search.search_string == null) |
432 | - return true; |
433 | - |
434 | - return search.search_string.strip() == ""; |
435 | + return search.search_string.strip () == ""; |
436 | } |
437 | } |
438 | } |
There appears to be a merge conflict?
While you resolve it you might want to look at this nitpick:
102 + var iter = helper_ model.get_ first_iter (); model.get_ last_iter ())
103 + while (iter != helper_
I usually add a helper variable 'var end = helper_ model.get_ last_iter ()' and do 'while (iter != end)'. This saves quite a bit of type checking.