Merge lp:~jamesh/unity-lens-applications/scope-previews into lp:~unity-team/unity-lens-applications/libunity7-compatible

Proposed by James Henstridge
Status: Merged
Approved by: Michal Hruby
Approved revision: 348
Merged at revision: 344
Proposed branch: lp:~jamesh/unity-lens-applications/scope-previews
Merge into: lp:~unity-team/unity-lens-applications/libunity7-compatible
Diff against target: 615 lines (+313/-256)
1 file modified
src/daemon.vala (+313/-256)
To merge this branch: bzr merge lp:~jamesh/unity-lens-applications/scope-previews
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michal Hruby (community) Approve
Review via email: mp+161534@code.launchpad.net

Commit message

Add screenshots to local scope previews with information obtained from the software center, escape markup characters in descriptions and don't allow the user to disable the applications scope.

Description of the change

When creating previews for local scopes, look up the package name in the software center index (requires scopes to be included in the app-install data) and then query the data provider for screenshots to include in the preview. This

As the preview() method was getting quite long, I also took the opportunity to split it into the app preview and scope preview cases into their own methods.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
344. By James Henstridge

Escape special characters in the scope description when producing
previews.

345. By James Henstridge

Don't include scope description in comment field of search results.

346. By James Henstridge

Don't show the enable/disable buttons in the preview of the applications
scope.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
347. By James Henstridge

Merge from libunity7-compatible, fixing conflict

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
348. By James Henstridge

Also remove the disable action for the home scope.

Revision history for this message
Michal Hruby (mhr3) wrote :

LGTM

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

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 2013-04-30 18:46:48 +0000
3+++ src/daemon.vala 2013-05-01 19:21:29 +0000
4@@ -1080,7 +1080,6 @@
5 var uri = @"scope://$(info.desktop_file)";
6 var name = info.application_name;
7 var icon_hint = info.icon;
8- var comment = info.description;
9 var category = info.desktop_file in disabled_scope_ids ?
10 Category.AVAILABLE : Category.INSTALLED;
11
12@@ -1103,7 +1102,7 @@
13 ResultType.DEFAULT,
14 "application/x-unity-scope",
15 name != "" ? name : uri,
16- comment,
17+ "",
18 "", // dnd_uri ?!
19 empty_asv);
20 }
21@@ -1310,282 +1309,340 @@
22
23 public Unity.Preview preview (string uri)
24 {
25- Unity.ApplicationPreview? preview = null;
26-
27- string pkgname = "";
28- string appname = "";
29+ Unity.Preview? preview = null;
30 bool installed = uri.has_prefix ("application://");
31 bool is_scope = uri.has_prefix ("scope://");
32
33 if (installed || uri.has_prefix ("unity-install://"))
34 {
35- string desktopfile = null;
36- if (installed)
37- {
38- desktopfile = uri.substring (14); //remove "application://" prefix
39-
40- // de-mangle desktop file names back to what S-C expects
41- if (sc_mangler.contains (desktopfile))
42- {
43- desktopfile = sc_mangler.get (desktopfile);
44- }
45-
46- Unity.Package.PackageInfo pkginfo = pkgsearcher.get_by_desktop_file (desktopfile);
47- if (pkginfo != null)
48- {
49- appname = pkginfo.application_name;
50- pkgname = pkginfo.package_name;
51- }
52- }
53- else // unity-install
54- {
55- string app = uri.substring (16); //remove "unity-install://" prefix
56- string[] parts = app.split ("/");
57- if (parts.length > 1)
58- {
59- pkgname = parts[0];
60- appname = parts[1];
61- }
62- }
63-
64- if (pkgname != "")
65- {
66+ preview = make_app_preview (uri, installed);
67+ }
68+ else if (is_scope)
69+ {
70+ preview = make_scope_preview (uri);
71+ }
72+ return preview;
73+ }
74+
75+ private SoftwareCenterData.AppDetailsData get_app_details (string appname, string pkgname) throws Error
76+ {
77+ if (sc_data_provider == null)
78+ {
79+ sc_data_provider = new SoftwareCenterDataCache (TOP_RATED_ITEMS_CACHE_LIFETIME);
80+ sc_data_provider.connect_to ();
81+ }
82+
83+ debug ("Requesting pkg info: %s, %s\n", pkgname, appname);
84+ return sc_data_provider.get_app_details (appname, pkgname);
85+ }
86+
87+ private Unity.Preview make_app_preview (string uri, bool installed)
88+ {
89+ Unity.ApplicationPreview? preview = null;
90+ string desktopfile = null;
91+ string pkgname = "";
92+ string appname = "";
93+
94+ if (installed)
95+ {
96+ desktopfile = uri.substring (14); //remove "application://" prefix
97+
98+ // de-mangle desktop file names back to what S-C expects
99+ if (sc_mangler.contains (desktopfile))
100+ {
101+ desktopfile = sc_mangler.get (desktopfile);
102+ }
103+
104+ Unity.Package.PackageInfo pkginfo = pkgsearcher.get_by_desktop_file (desktopfile);
105+ if (pkginfo != null)
106+ {
107+ appname = pkginfo.application_name;
108+ pkgname = pkginfo.package_name;
109+ }
110+ }
111+ else // unity-install
112+ {
113+ string app = uri.substring (16); //remove "unity-install://" prefix
114+ string[] parts = app.split ("/");
115+ if (parts.length > 1)
116+ {
117+ pkgname = parts[0];
118+ appname = parts[1];
119+ }
120+ }
121+
122+ if (pkgname != "")
123+ {
124+ try {
125+ var details = get_app_details (appname, pkgname);
126+
127+ Icon? icon = null;
128+ if (installed)
129+ icon = new GLib.ThemedIcon (details.icon);
130+ else
131+ {
132+ icon = find_pkg_icon (null, details.icon);
133+ if (icon.to_string () == GENERIC_APP_ICON && details.icon_url != null && details.icon_url != "")
134+ {
135+ icon = new GLib.FileIcon (File.new_for_uri (details.icon_url));
136+ }
137+ }
138+
139+ Icon? screenshot = null;
140+
141+ if (details.screenshot != null)
142+ {
143+ File scr_file = File.new_for_uri (details.screenshot);
144+ screenshot = new FileIcon (scr_file);
145+ }
146+
147+ string subtitle = "";
148+ if (details.version != "")
149+ subtitle = _("Version %s").printf (details.version);
150+ if (details.size > 0)
151+ {
152+ if (subtitle != "")
153+ subtitle += ", ";
154+ subtitle += ("Size %s").printf (GLib.format_size (details.size));
155+ }
156+ preview = new Unity.ApplicationPreview (details.name, subtitle, details.description, icon, screenshot);
157+ preview.license = details.license;
158+
159+ init_ratings_db ();
160+ if (ratings != null)
161+ {
162+ Unity.Ratings.Result result;
163+ ratings.query (pkgname, out result);
164+ preview.set_rating (result.average_rating / 5.0f, result.total_rating);
165+ }
166+
167+ if (details.hardware_requirements != "")
168+ preview.add_info (new InfoHint ("hardware-requirements", _("Hardware requirements"), null, details.hardware_requirements));
169+
170+ if (uri.has_prefix ("unity-install://")) // application needs to be purchased/installed
171+ {
172+ // uninstalled and not purchased before
173+ if (details.pkg_state == SoftwareCenterData.PackageState.NEEDS_PURCHASE)
174+ {
175+ var buy_action = new Unity.PreviewAction ("buy", _("Buy"), null);
176+ if (details.price != null && details.price != "")
177+ {
178+ buy_action.extra_text = details.price;
179+ }
180+
181+ buy_action.activated.connect (start_software_center);
182+ preview.add_action (buy_action);
183+ }
184+ else // uninstalled, purchased before
185+ {
186+
187+ Unity.PreviewAction install_action = null;
188+ if (details.raw_price == null || details.raw_price == "")
189+ {
190+ install_action = new Unity.PreviewAction ("install", _("Free Download"), null);
191+ install_action.activated.connect (app_preview_install);
192+ }
193+ else
194+ {
195+ install_action = new Unity.PreviewAction ("install", _("Install"), null);
196+ install_action.activated.connect (start_software_center);
197+ }
198+ preview.add_action (install_action);
199+ }
200+
201+ if (details.website != null && details.website != "")
202+ {
203+ preview_developer_website = details.website;
204+ var website_action = new Unity.PreviewAction ("website", _("Developer Site"), null);
205+ website_action.activated.connect (app_preview_website);
206+ preview.add_action (website_action);
207+ }
208+ }
209+ else // application is already installed
210+ {
211+ preview.add_info (new InfoHint ("date-installed", _("Installed on"), null, details.installation_date));
212+ var launch_action = new Unity.PreviewAction ("launch", _("Launch"), null);
213+ preview.add_action (launch_action);
214+ if (!details.is_desktop_dependency)
215+ {
216+ var uninstall_action = new Unity.PreviewAction ("uninstall", _("Uninstall"), null);
217+ uninstall_action.activated.connect (app_preview_uninstall);
218+ preview.add_action (uninstall_action);
219+ }
220+ }
221+
222+ preview_installable_desktop_file = details.desktop_file;
223+ preview_installable_icon_file = details.icon;
224+ }
225+ catch (Error e)
226+ {
227+ warning ("Failed to get package details for '%s': %s", uri, e.message);
228+ preview = null;
229+ }
230+ }
231+
232+ // xapian db doesn't know this .desktop file or S-C dbus data provider fails,
233+ // fallback to DesktopAppInfo (based on installed .desktop file) if available
234+ if (preview == null && desktopfile != null)
235+ {
236+ var app_info = new DesktopAppInfo (desktopfile);
237+ if (app_info != null)
238+ {
239+ preview = new Unity.ApplicationPreview (app_info.get_display_name (), "", app_info.get_description () ?? "", app_info.get_icon (), null);
240+ var launch_action = new Unity.PreviewAction ("launch", _("Launch"), null);
241+ preview.add_action (launch_action);
242+ }
243+ }
244+
245+ if (preview == null)
246+ {
247+ warning ("No pksearcher nor desktop app info for '%s'", uri);
248+ }
249+ return preview;
250+ }
251+
252+ private Unity.Preview make_scope_preview(string uri)
253+ {
254+ Unity.ApplicationPreview? preview = null;
255+ var scope_id = uri.substring (8);
256+ bool scope_disabled = scope_id in disabled_scope_ids;
257+
258+ // figure out if the scope is remote
259+ bool is_remote_scope = false;
260+ var info = scopesearcher.get_by_desktop_file (scope_id);
261+
262+ Dee.ModelIter found_iter = null;
263+ if (info == null)
264+ {
265+ var iter = remote_scopes_model.get_first_iter ();
266+ var end_iter = remote_scopes_model.get_last_iter ();
267+ while (iter != end_iter)
268+ {
269+ if (remote_scopes_model.get_string (iter, 0) == scope_id)
270+ {
271+ is_remote_scope = true;
272+ found_iter = iter;
273+ break;
274+ }
275+ iter = remote_scopes_model.next (iter);
276+ }
277+ }
278+
279+ if (is_remote_scope)
280+ {
281+ var name = remote_scopes_model.get_string (found_iter, 1);
282+ if (name == null || name == "")
283+ name = remote_scopes_model.get_string (found_iter, 0);
284+ var description = remote_scopes_model.get_string (found_iter, 2);
285+ if (description != null)
286+ description = Markup.escape_text(description);
287+ Icon? icon = null;
288+ Icon? screenshot = null;
289+ var icon_hint = remote_scopes_model.get_string (found_iter, 3);
290+ var screenshot_url = remote_scopes_model.get_string (found_iter, 4);
291+ try
292+ {
293+ if (icon_hint != "") icon = Icon.new_for_string (icon_hint);
294+ if (screenshot_url != "") screenshot = Icon.new_for_string (screenshot_url);
295+ }
296+ catch (Error err)
297+ {
298+ warning ("%s", err.message);
299+ }
300+
301+ if (icon == null) icon = get_default_scope_icon ();
302+
303+ preview = new Unity.ApplicationPreview (name,
304+ "",
305+ description,
306+ icon,
307+ screenshot);
308+ }
309+ else if (info != null)
310+ {
311+ var name = info.application_name;
312+ if (name == null || name == "")
313+ name = info.desktop_file;
314+ var subtitle = "";
315+ var description = info.description;
316+ if (description != null)
317+ description = Markup.escape_text(description);
318+ Icon? icon = null;
319+ Icon? screenshot = null;
320+ try
321+ {
322+ if (info.icon != null && info.icon != "")
323+ icon = Icon.new_for_string (info.icon);
324+ }
325+ catch (Error err)
326+ {
327+ warning ("%s", err.message);
328+ }
329+ if (icon == null)
330+ icon = get_default_scope_icon ();
331+
332+ // de-mangle desktop file names back to what S-C expects
333+ string mangled_id;
334+ if (sc_mangler.contains (scope_id))
335+ {
336+ mangled_id = sc_mangler.get (scope_id);
337+ }
338+ else
339+ {
340+ mangled_id = scope_id;
341+ }
342+
343+ Unity.Package.PackageInfo pkginfo = pkgsearcher.get_by_desktop_file (mangled_id);
344+ if (pkginfo != null)
345+ {
346+ SoftwareCenterData.AppDetailsData? details;
347 try {
348- if (sc_data_provider == null)
349- {
350- sc_data_provider = new SoftwareCenterDataCache (TOP_RATED_ITEMS_CACHE_LIFETIME);
351- sc_data_provider.connect_to ();
352- }
353-
354- debug ("Requesting pkg info: %s, %s\n", pkgname, appname);
355- var details = sc_data_provider.get_app_details (appname, pkgname);
356-
357- Icon? icon = null;
358- if (installed)
359- icon = new GLib.ThemedIcon (details.icon);
360- else
361- {
362- icon = find_pkg_icon (null, details.icon);
363- if (icon.to_string () == GENERIC_APP_ICON && details.icon_url != null && details.icon_url != "")
364- {
365- icon = new GLib.FileIcon (File.new_for_uri (details.icon_url));
366- }
367- }
368-
369- Icon? screenshot = null;
370-
371+ details = get_app_details(pkginfo.application_name,
372+ pkginfo.package_name);
373+ } catch (Error e) {
374+ details = null;
375+ }
376+ if (details != null) {
377+ if (details.version != "")
378+ subtitle = _("Version %s").printf (details.version);
379 if (details.screenshot != null)
380 {
381 File scr_file = File.new_for_uri (details.screenshot);
382 screenshot = new FileIcon (scr_file);
383 }
384-
385- string subtitle = "";
386- if (details.version != "")
387- subtitle = _("Version %s").printf (details.version);
388- if (details.size > 0)
389- {
390- if (subtitle != "")
391- subtitle += ", ";
392- subtitle += ("Size %s").printf (GLib.format_size (details.size));
393- }
394- preview = new Unity.ApplicationPreview (details.name, subtitle, details.description, icon, screenshot);
395- preview.license = details.license;
396-
397- init_ratings_db ();
398- if (ratings != null)
399- {
400- Unity.Ratings.Result result;
401- ratings.query (pkgname, out result);
402- preview.set_rating (result.average_rating / 5.0f, result.total_rating);
403- }
404-
405- if (details.hardware_requirements != "")
406- preview.add_info (new InfoHint ("hardware-requirements", _("Hardware requirements"), null, details.hardware_requirements));
407-
408- if (uri.has_prefix ("unity-install://")) // application needs to be purchased/installed
409- {
410- // uninstalled and not purchased before
411- if (details.pkg_state == SoftwareCenterData.PackageState.NEEDS_PURCHASE)
412- {
413- var buy_action = new Unity.PreviewAction ("buy", _("Buy"), null);
414- if (details.price != null && details.price != "")
415- {
416- buy_action.extra_text = details.price;
417- }
418-
419- buy_action.activated.connect (start_software_center);
420- preview.add_action (buy_action);
421- }
422- else // uninstalled, purchased before
423- {
424-
425- Unity.PreviewAction install_action = null;
426- if (details.raw_price == null || details.raw_price == "")
427- {
428- install_action = new Unity.PreviewAction ("install", _("Free Download"), null);
429- install_action.activated.connect (app_preview_install);
430- }
431- else
432- {
433- install_action = new Unity.PreviewAction ("install", _("Install"), null);
434- install_action.activated.connect (start_software_center);
435- }
436- preview.add_action (install_action);
437- }
438-
439- if (details.website != null && details.website != "")
440- {
441- preview_developer_website = details.website;
442- var website_action = new Unity.PreviewAction ("website", _("Developer Site"), null);
443- website_action.activated.connect (app_preview_website);
444- preview.add_action (website_action);
445- }
446- }
447- else // application is already installed
448- {
449- preview.add_info (new InfoHint ("date-installed", _("Installed on"), null, details.installation_date));
450- var launch_action = new Unity.PreviewAction ("launch", _("Launch"), null);
451- preview.add_action (launch_action);
452- if (!details.is_desktop_dependency)
453- {
454- var uninstall_action = new Unity.PreviewAction ("uninstall", _("Uninstall"), null);
455- uninstall_action.activated.connect (app_preview_uninstall);
456- preview.add_action (uninstall_action);
457- }
458- }
459-
460- preview_installable_desktop_file = details.desktop_file;
461- preview_installable_icon_file = details.icon;
462- }
463- catch (Error e)
464- {
465- warning ("Failed to get package details for '%s': %s", uri, e.message);
466- preview = null;
467- }
468- }
469-
470- // xapian db doesn't know this .desktop file or S-C dbus data provider fails,
471- // fallback to DesktopAppInfo (based on installed .desktop file) if available
472- if (preview == null && desktopfile != null)
473- {
474- var app_info = new DesktopAppInfo (desktopfile);
475- if (app_info != null)
476- {
477- preview = new Unity.ApplicationPreview (app_info.get_display_name (), "", app_info.get_description () ?? "", app_info.get_icon (), null);
478- var launch_action = new Unity.PreviewAction ("launch", _("Launch"), null);
479- preview.add_action (launch_action);
480- }
481- }
482-
483- if (preview == null)
484- {
485- warning ("No pksearcher nor desktop app info for '%s'", uri);
486- }
487+ }
488+ }
489+
490+ preview = new Unity.ApplicationPreview (name,
491+ subtitle,
492+ description,
493+ icon,
494+ screenshot);
495 }
496- else if (is_scope)
497+ if (preview != null && scope_id != "home.scope" &&
498+ scope_id != "applications.scope")
499 {
500- var scope_id = uri.substring (8);
501- bool scope_disabled = scope_id in disabled_scope_ids;
502-
503- // figure out if the scope is remote
504- bool is_remote_scope = false;
505- var info = scopesearcher.get_by_desktop_file (scope_id);
506-
507- Dee.ModelIter found_iter = null;
508- if (info == null)
509- {
510- var iter = remote_scopes_model.get_first_iter ();
511- var end_iter = remote_scopes_model.get_last_iter ();
512- while (iter != end_iter)
513- {
514- if (remote_scopes_model.get_string (iter, 0) == scope_id)
515- {
516- is_remote_scope = true;
517- found_iter = iter;
518- break;
519- }
520- iter = remote_scopes_model.next (iter);
521- }
522- }
523-
524- if (is_remote_scope)
525- {
526- var name = remote_scopes_model.get_string (found_iter, 1);
527- if (name == null || name == "")
528- name = remote_scopes_model.get_string (found_iter, 0);
529- var description = remote_scopes_model.get_string (found_iter, 2);
530- Icon? icon = null;
531- Icon? screenshot = null;
532- var icon_hint = remote_scopes_model.get_string (found_iter, 3);
533- var screenshot_url = remote_scopes_model.get_string (found_iter, 4);
534- try
535- {
536- if (icon_hint != "") icon = Icon.new_for_string (icon_hint);
537- if (screenshot_url != "") screenshot = Icon.new_for_string (screenshot_url);
538- }
539- catch (Error err)
540- {
541- warning ("%s", err.message);
542- }
543-
544- if (icon == null) icon = get_default_scope_icon ();
545-
546- preview = new Unity.ApplicationPreview (name,
547- "",
548- description,
549- icon,
550- screenshot);
551- }
552- else if (info != null)
553- {
554- var name = info.application_name;
555- if (name == null || name == "")
556- name = info.desktop_file;
557- // XXX: add this to package info.
558- var description = info.description;
559- Icon? icon = null;
560- try
561- {
562- if (info.icon != null && info.icon != "")
563- icon = Icon.new_for_string (info.icon);
564- }
565- catch (Error err)
566- {
567- warning ("%s", err.message);
568- }
569- if (icon == null)
570- icon = get_default_scope_icon ();
571-
572- preview = new Unity.ApplicationPreview (name,
573- "",
574- description,
575- icon,
576- null);
577- }
578- if (preview != null) {
579- PreviewAction action;
580- preview.set_rating(-1.0f, 0);
581- if (scope_disabled)
582- {
583- action = new Unity.PreviewAction ("enable-scope", _("Enable"), null);
584- action.activated.connect (() =>
585+ PreviewAction action;
586+ preview.set_rating(-1.0f, 0);
587+ if (scope_disabled)
588+ {
589+ action = new Unity.PreviewAction ("enable-scope", _("Enable"), null);
590+ action.activated.connect (() =>
591 {
592 enable_scope (scope_id);
593 return new ActivationResponse.with_preview (this.preview (uri));
594 });
595- }
596- else
597- {
598- action = new Unity.PreviewAction ("disable-scope", _("Disable"), null);
599- action.activated.connect (() =>
600+ }
601+ else
602+ {
603+ action = new Unity.PreviewAction ("disable-scope", _("Disable"), null);
604+ action.activated.connect (() =>
605 {
606 disable_scope (scope_id);
607 return new ActivationResponse.with_preview (this.preview (uri));
608 });
609- }
610- preview.add_action (action);
611 }
612+ preview.add_action (action);
613 }
614 return preview;
615 }

Subscribers

People subscribed via source and target branches

to all changes: