Merge lp:~stolowski/unity-lens-applications/results-ribbons into lp:unity-lens-applications

Proposed by Paweł Stołowski
Status: Merged
Approved by: Neil J. Patel
Approved revision: 308
Merged at revision: 303
Proposed branch: lp:~stolowski/unity-lens-applications/results-ribbons
Merge into: lp:unity-lens-applications
Prerequisite: lp:~stolowski/unity-lens-applications/show-more-apps-on-no-query
Diff against target: 429 lines (+233/-22)
7 files modified
configure.ac (+1/-1)
src/Makefile.am (+1/-0)
src/daemon.vala (+58/-13)
src/purchase-info-helper.vala (+80/-0)
src/unity-package-search.cc (+81/-3)
src/unity-package-search.h (+4/-0)
vapi/unity-package-search.vapi (+8/-5)
To merge this branch: bzr merge lp:~stolowski/unity-lens-applications/results-ribbons
Reviewer Review Type Date Requested Status
Neil J. Patel (community) Approve
Review via email: mp+124734@code.launchpad.net

Commit message

Implemented price ribbons for Application Lens search results.

Description of the change

Implemented price ribbons for Application Lens search results.

Requires lp:~mvo/software-center-make-currency-part-of-the-db !

To post a comment you must log in.
Revision history for this message
Neil J. Patel (njpatel) wrote :

Approved, works well. Leaving as needs-review as waiting for other things to land before this can be merged.

DO NOT MARK AS APPROVED UNTIL SOFTWARE CENTER BRANCHES HAVE LANDED.

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

Attempt to merge into lp:unity-lens-applications failed due to conflicts:

text conflict in src/daemon.vala

308. By Paweł Stołowski

Merged trunk.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'configure.ac'
2--- configure.ac 2012-08-22 18:57:14 +0000
3+++ configure.ac 2012-09-18 14:08:19 +0000
4@@ -65,7 +65,7 @@
5 gee-1.0
6 dee-1.0 >= 0.5.16
7 zeitgeist-1.0 >= 0.3.8
8- unity >= 4.99.0
9+ unity >= 6.5.1
10 libgnome-menu)
11
12 AC_SUBST(LENS_DAEMON_CFLAGS)
13
14=== modified file 'src/Makefile.am'
15--- src/Makefile.am 2012-09-12 14:48:25 +0000
16+++ src/Makefile.am 2012-09-18 14:08:19 +0000
17@@ -60,6 +60,7 @@
18 schemas.vala \
19 utils.vala \
20 aptd-client.vala \
21+ purchase-info-helper.vala \
22 software-center-data-provider.vala \
23 software-center-data-cache.vala \
24 $(NULL)
25
26=== modified file 'src/daemon.vala'
27--- src/daemon.vala 2012-09-18 12:57:06 +0000
28+++ src/daemon.vala 2012-09-18 14:08:19 +0000
29@@ -120,6 +120,8 @@
30 public bool display_recent_apps { get; set; default = true; }
31 public bool display_available_apps { get; set; default = true; }
32
33+ private PurchaseInfoHelper purchase_info = null;
34+
35 construct
36 {
37 populate_type_queries ();
38@@ -564,6 +566,8 @@
39
40 transaction.commit ();
41
42+ purchase_info = new PurchaseInfoHelper ();
43+
44 /* If we don't have a search we display 6 random apps */
45 if (usc_apps_active () && display_available_apps && pkgsearcher != null)
46 {
47@@ -585,6 +589,7 @@
48 string? filter_query = prepare_pkg_search_string (search, filter);
49
50 var pkgresults = pkgsearcher.get_apps (filter_query, MAX_APP_FOR_DOWNLOAD_FOR_EMPTY_QUERY, filter_cb);
51+ purchase_info.from_pkgresults (pkgresults);
52 add_pkg_search_result (pkgresults, installed_uris, available_uris, model, Category.AVAILABLE, MAX_APP_FOR_DOWNLOAD_FOR_EMPTY_QUERY);
53 timer.stop ();
54 debug ("Entry search listed %i Available apps in %fms",
55@@ -603,9 +608,15 @@
56 sc_data_provider = new SoftwareCenterDataCache (TOP_RATED_ITEMS_CACHE_LIFETIME);
57
58 var whats_new = sc_data_provider.get_items_for_category ("unity-whats-new");
59+ var query = purchase_info.create_pkgsearch_query (whats_new);
60+ var tmpresults = pkgsearcher.get_by_exact_names (query);
61+ purchase_info.from_pkgresults (tmpresults);
62 hits = add_sc_category_results (whats_new, model, Category.AVAILABLE, ref duplicates_lookup, MAX_WHATS_NEW_APPS_FOR_EMPTY_QUERY);
63
64 var top_rated = sc_data_provider.get_items_for_category ("unity-top-rated");
65+ query = purchase_info.create_pkgsearch_query (top_rated);
66+ tmpresults = pkgsearcher.get_by_exact_names (query);
67+ purchase_info.from_pkgresults (tmpresults);
68 hits += add_sc_category_results (top_rated, model, Category.AVAILABLE, ref duplicates_lookup, MAX_TOP_RATED_APPS_FOR_EMPTY_QUERY);
69 }
70 catch (GLib.Error e)
71@@ -930,6 +941,25 @@
72 return GLib.Path.get_basename (name);
73 }
74
75+ private string get_annotated_icon (Icon app_icon, string price, bool paid)
76+ {
77+ var annotated_icon = new AnnotatedIcon (app_icon);
78+ annotated_icon.category = CategoryType.APPLICATION;
79+ if (price != null && price != "")
80+ {
81+ if (paid)
82+ annotated_icon.ribbon = _("Paid");
83+ else
84+ annotated_icon.ribbon = price;
85+ }
86+ else
87+ {
88+ annotated_icon.ribbon = _("Free");
89+ }
90+
91+ return annotated_icon.to_string ();
92+ }
93+
94 /**
95 * Add all results obtained from SoftwareCenterDataProvider
96 */
97@@ -943,15 +973,24 @@
98 foreach (SoftwareCenterDataProviderService.AppInfo app in results)
99 {
100 string uri = @"unity-install://$(app.package_name)/$(app.application_name)";
101-
102 if (uri in duplicates_lookup)
103- {
104 continue;
105- }
106-
107- Icon icon = find_pkg_icon (app.desktop_file, app.icon);
108-
109- model.append (uri, icon.to_string (),
110+
111+ string icon_obj;
112+ Icon app_icon = find_pkg_icon (app.desktop_file, app.icon);
113+ var pinfo = purchase_info.find (app.application_name, app.package_name);
114+ if (pinfo != null)
115+ {
116+ var annotated_icon = get_annotated_icon (app_icon, pinfo.formatted_price, pinfo.paid);
117+ icon_obj = annotated_icon.to_string ();
118+ }
119+ else
120+ {
121+ warning ("No purchase info for: %s, %s", app.application_name, app.package_name);
122+ icon_obj = app_icon.to_string ();
123+ }
124+
125+ model.append (uri, icon_obj,
126 category,
127 "application/x-desktop",
128 app.application_name,
129@@ -1021,6 +1060,8 @@
130 if (app != null && !app.should_show ())
131 continue;
132
133+ Icon icon = find_pkg_icon (pkginfo.desktop_file, pkginfo.icon);
134+ string icon_str;
135 if (category == Category.AVAILABLE)
136 {
137 /* If we have an available item, which is not a dupe, but is
138@@ -1035,12 +1076,16 @@
139 * but only use that after we've de-duped the results.
140 * But only change the URI *after* we've de-duped the results! */
141 uri = @"unity-install://$(pkginfo.package_name)/$(pkginfo.application_name)";
142- available_uris.add (uri);
143- }
144-
145- Icon icon = find_pkg_icon (pkginfo.desktop_file, pkginfo.icon);
146-
147- model.append (uri, icon.to_string (),
148+ available_uris.add (uri);
149+
150+ icon_str = get_annotated_icon (icon, pkginfo.price, !pkginfo.needs_purchase);
151+ }
152+ else
153+ {
154+ icon_str = icon.to_string ();
155+ }
156+
157+ model.append (uri, icon_str,
158 category,"application/x-desktop",
159 display_name != null ? display_name : "",
160 comment != null ? comment : "",
161
162=== added file 'src/purchase-info-helper.vala'
163--- src/purchase-info-helper.vala 1970-01-01 00:00:00 +0000
164+++ src/purchase-info-helper.vala 2012-09-18 14:08:19 +0000
165@@ -0,0 +1,80 @@
166+/*
167+ * Copyright (C) 2012 Canonical Ltd
168+ *
169+ * This program is free software: you can redistribute it and/or modify
170+ * it under the terms of the GNU General Public License version 3 as
171+ * published by the Free Software Foundation.
172+ *
173+ * This program is distributed in the hope that it will be useful,
174+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
175+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
176+ * GNU General Public License for more details.
177+ *
178+ * You should have received a copy of the GNU General Public License
179+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
180+ *
181+ * Authored by Pawel Stolowski <pawel.stolowski@canonical.com>
182+ */
183+
184+namespace Unity.ApplicationsLens {
185+
186+ class PurchaseInfoHelper
187+ {
188+ public struct AppInfo
189+ {
190+ string application_name;
191+ string package_name;
192+ string formatted_price;
193+ bool paid;
194+ }
195+
196+ private HashTable<string, AppInfo?> data;
197+
198+ public PurchaseInfoHelper ()
199+ {
200+ data = new HashTable<string, AppInfo?> (str_hash, str_equal);
201+ }
202+
203+ public void from_pkgresults (Unity.Package.SearchResult results)
204+ {
205+ foreach (var pkg in results.results)
206+ {
207+ var app_info = from_pkgresult (pkg);
208+ data.insert (pkg.application_name + "/" + pkg.package_name, app_info);
209+ }
210+ }
211+
212+ public AppInfo from_pkgresult (Unity.Package.PackageInfo pkg)
213+ {
214+ var app_info = AppInfo ()
215+ {
216+ package_name = pkg.package_name,
217+ application_name = pkg.application_name,
218+ formatted_price = pkg.price,
219+ paid = false
220+ };
221+ return app_info;
222+ }
223+
224+ public GLib.SList<string> create_pkgsearch_query (SoftwareCenterDataProviderService.AppInfo?[] results)
225+ {
226+ var params = new GLib.SList<string> ();
227+ foreach (var res in results)
228+ {
229+ params.append (res.application_name);
230+ params.append (res.package_name);
231+ }
232+ return params;
233+ }
234+
235+ public AppInfo? find (string application_name, string package_name)
236+ {
237+ string key = application_name + "/" + package_name;
238+ if (data.contains (key))
239+ {
240+ return data[key];
241+ }
242+ return null;
243+ }
244+ }
245+}
246\ No newline at end of file
247
248=== modified file 'src/unity-package-search.cc'
249--- src/unity-package-search.cc 2012-09-12 16:38:53 +0000
250+++ src/unity-package-search.cc 2012-09-18 14:08:19 +0000
251@@ -50,9 +50,12 @@
252 #define XAPIAN_VALUE_SUMMARY 177
253 #define XAPIAN_VALUE_ARCHIVE_CHANNEL 178
254 #define XAPIAN_VALUE_DESKTOP_FILE 179
255+#define XAPIAN_VALUE_PRICE 180
256+#define XAPIAN_VALUE_PURCHASED_DATE 184
257 #define XAPIAN_VALUE_SCREENSHOT_URLS 185
258 #define XAPIAN_VALUE_DESCRIPTION 188
259 #define XAPIAN_VALUE_VERSION_INFO 198
260+#define XAPIAN_VALUE_CURRENCY 201
261
262 #include "unity-package-search.h"
263
264@@ -368,6 +371,17 @@
265 string icon = doc.get_value (XAPIAN_VALUE_ICON);
266 pkginfo->icon = g_strdup (icon.c_str ());
267
268+ // FIXME: we may want to format it according to locales at some point
269+ string price = doc.get_value (XAPIAN_VALUE_CURRENCY);
270+ if (!price.empty ())
271+ {
272+ price += " " + doc.get_value (XAPIAN_VALUE_PRICE);
273+ }
274+ pkginfo->price = g_strdup (price.c_str ());
275+
276+ const string purchase_date = doc.get_value (XAPIAN_VALUE_PURCHASED_DATE);
277+ pkginfo->needs_purchase = purchase_date.empty ();
278+
279 return pkginfo;
280 }
281
282@@ -382,6 +396,7 @@
283 g_free (pkginfo->package_name);
284 g_free (pkginfo->application_name);
285 g_free (pkginfo->desktop_file);
286+ g_free (pkginfo->price);
287 g_free (pkginfo->icon);
288
289 g_slice_free (UnityPackageInfo, pkginfo);
290@@ -405,13 +420,13 @@
291 {
292 switch (search_type)
293 {
294- case UNITY_PACKAGE_SEARCHTYPE_PREFIX:
295+ case UNITY_PACKAGE_SEARCHTYPE_PREFIX:
296 query = searcher->query_parser->parse_query (_search_string, QUERY_PARSER_PREFIXSEARCH_FLAGS);
297 break;
298- case UNITY_PACKAGE_SEARCHTYPE_EXACT:
299+ case UNITY_PACKAGE_SEARCHTYPE_EXACT:
300 query = searcher->query_parser->parse_query (_search_string, QUERY_PARSER_EXACTSEARCH_FLAGS);
301 break;
302- default:
303+ default:
304 g_critical ("Unknown search type '%i'. Fallback to a prefix search", search_type);
305 query = searcher->query_parser->parse_query (_search_string, QUERY_PARSER_PREFIXSEARCH_FLAGS);
306 break;
307@@ -628,6 +643,69 @@
308 return result;
309 }
310
311+/**
312+ * Returns all apps that match exactly app+pkg names.
313+ * names must be a flat list of appname1, pkgname1, appname2, pkgname2... strings (must have even number of elements).
314+ */
315+UnityPackageSearchResult*
316+unity_package_searcher_get_by_exact_names (UnityPackageSearcher *searcher, GSList *names)
317+{
318+ g_return_val_if_fail (searcher != NULL, NULL);
319+
320+ vector<Xapian::Query> query_list;
321+ GSList *iter = names;
322+
323+ while (iter)
324+ {
325+ const string appname ((char *)iter->data);
326+ iter = g_slist_next (iter);
327+ if (iter == NULL)
328+ {
329+ g_warning ("List should have even list of arguments");
330+ return NULL;
331+ }
332+
333+ const string pkgname = ((char *)iter->data);
334+ Xapian::Query query1 ("AA" + appname);
335+ Xapian::Query query2 ("AP" + pkgname);
336+ Xapian::Query query (Xapian::Query::OP_AND, query1, query2);
337+ query_list.push_back (query);
338+
339+ iter = g_slist_next (iter);
340+ }
341+
342+ guint num_matches = 0;
343+ UnityPackageSearchResult *result;
344+
345+ result = g_slice_new0 (UnityPackageSearchResult);
346+
347+ try
348+ {
349+ Xapian::Query top_query = Xapian::Query (Xapian::Query::OP_OR, query_list.begin (), query_list.end ());
350+ searcher->enquire->set_sort_by_relevance ();
351+ searcher->enquire->set_query (top_query);
352+
353+ Xapian::MSet matches = searcher->enquire->get_mset(0, searcher->db->get_doccount ());
354+ Xapian::MSetIterator iter = matches.begin();
355+ while (iter != matches.end ())
356+ {
357+ Xapian::Document doc = iter.get_document ();
358+ UnityPackageInfo *pkginfo = _pkginfo_from_document (doc);
359+ result->results = g_slist_prepend (result->results, pkginfo);
360+ num_matches++;
361+ ++iter;
362+ }
363+ }
364+ catch (Xapian::Error e)
365+ {
366+ g_debug ("Error getting apps: %s", e.get_msg().c_str());
367+ return g_slice_new0 (UnityPackageSearchResult);
368+ }
369+
370+ result->num_hits = num_matches;
371+ return result;
372+}
373+
374 UnityPackageInfo *
375 unity_package_searcher_get_by_desktop_file (UnityPackageSearcher *searcher, const gchar *desktop_file)
376 {
377
378=== modified file 'src/unity-package-search.h'
379--- src/unity-package-search.h 2012-09-12 16:38:53 +0000
380+++ src/unity-package-search.h 2012-09-18 14:08:19 +0000
381@@ -46,6 +46,8 @@
382 gchar *application_name;
383 gchar *desktop_file;
384 gchar *icon;
385+ gchar *price;
386+ gboolean needs_purchase;
387 gint relevancy;
388 } UnityPackageInfo;
389
390@@ -82,6 +84,8 @@
391
392 void unity_package_package_info_free (UnityPackageInfo *pkginfo);
393
394+UnityPackageSearchResult* unity_package_searcher_get_by_exact_names (UnityPackageSearcher *searcher, GSList *names);
395+
396 UnityPackageInfo* unity_package_searcher_get_by_desktop_file (UnityPackageSearcher *searcher, const gchar *desktop_file);
397
398 #ifdef __cplusplus
399
400=== modified file 'vapi/unity-package-search.vapi'
401--- vapi/unity-package-search.vapi 2012-09-12 16:38:53 +0000
402+++ vapi/unity-package-search.vapi 2012-09-18 14:08:19 +0000
403@@ -30,6 +30,7 @@
404 public SearchResult search (string search_string, uint max_hits, Unity.Package.SearchType search_type, Unity.Package.Sort sort);
405 public SearchResult get_random_apps (string? filter_query, uint n_apps);
406 public SearchResult get_apps (string? filter_query, uint n_apps, AppFilterCallback cb);
407+ public SearchResult get_by_exact_names (GLib.SList<string> names);
408 public PackageInfo? get_by_desktop_file (string desktop_file);
409 }
410
411@@ -43,11 +44,13 @@
412 [Compact]
413 [CCode (cname = "UnityPackageInfo", free_function = "unity_package_package_info_free", cheader_filename = "unity-package-search.h")]
414 public class PackageInfo {
415- public string package_name;
416- public string application_name;
417- public string desktop_file;
418- public string icon;
419- public int relevancy;
420+ public string package_name;
421+ public string application_name;
422+ public string desktop_file;
423+ public string icon;
424+ public string price;
425+ public bool needs_purchase;
426+ public int relevancy;
427 }
428 }
429 }

Subscribers

People subscribed via source and target branches