Merge lp:~mhr3/unity-lens-music/home-lenses into lp:unity-lens-music

Proposed by Michal Hruby
Status: Merged
Approved by: Didier Roche
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
Reviewer Review Type Date Requested Status
Mikkel Kamstrup Erlandsen (community) Approve
Review via email: mp+89667@code.launchpad.net

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.

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 ();
103 + while (iter != helper_model.get_last_iter ())

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.

review: Needs Fixing
Michal Hruby (mhr3) wrote :

Fixed.

Awesome!

review: Approve
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity-lens-music/6/console reported an error when processing this lp:~mhr3/unity-lens-music/home-lenses branch.
Not merging it.

review: Approve
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity-lens-music/6/console reported an error when processing this lp:~mhr3/unity-lens-music/home-lenses branch.
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 }

Subscribers

People subscribed via source and target branches

to all changes: