Merge lp:~jamesh/unity-lens-applications/index-local-scopes into lp:~unity-team/unity-lens-applications/libunity7-compatible

Proposed by James Henstridge
Status: Merged
Approved by: Michal Hruby
Approved revision: 346
Merged at revision: 341
Proposed branch: lp:~jamesh/unity-lens-applications/index-local-scopes
Merge into: lp:~unity-team/unity-lens-applications/libunity7-compatible
Diff against target: 574 lines (+254/-35)
11 files modified
configure.ac (+7/-0)
src/Makefile.am (+2/-1)
src/config.vala.in (+3/-1)
src/daemon.vala (+116/-17)
src/unity-package-search.cc (+106/-5)
src/unity-package-search.h (+3/-0)
src/xapian-utils.vala (+4/-4)
tests/unit/Makefile.am (+2/-0)
tests/unit/test-xapian-utils.vala (+7/-7)
vapi/unity-package-search.deps (+1/-0)
vapi/unity-package-search.vapi (+3/-0)
To merge this branch: bzr merge lp:~jamesh/unity-lens-applications/index-local-scopes
Reviewer Review Type Date Requested Status
Michal Hruby (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+160598@code.launchpad.net

Commit message

Index local scopes and include them in the search results.

Description of the change

Index local scopes and include them in the search results.

This branch adds locally installed scopes to the search results from the applications scope.

If the software-center index includes scopes, it will also remove installed scopes from the "more suggestions" category of the results.

Most of the preview code is shared between local and remote scopes, with the enable/disable preview action updating the same dconf key (from chats with mhr3, this is the way we want to handle disabling of local scopes too).

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

Merge from libunity7-compatible

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

There seem to be missing features here (local scopes are not displayed in "installed" category when doing empty search, sorting with the rest of the scopes, disabled local scopes in "more suggestions" category, etc), but what's in seems to work. +1

review: Approve

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 2013-03-13 10:13:14 +0000
3+++ configure.ac 2013-04-24 12:06:28 +0000
4@@ -77,6 +77,7 @@
5 zeitgeist-1.0 >= 0.3.8
6 libcolumbus0 >= 0.4.0
7 unity >= 6.7.0
8+ unity-protocol-private
9 libgnome-menu-3.0 >= 3.6.0)
10
11 AC_SUBST(LENS_DAEMON_CFLAGS)
12@@ -138,6 +139,12 @@
13 AS_AC_EXPAND(DATADIR, $datarootdir)
14 AC_SUBST(DATADIR)
15
16+#####################################################
17+# Look for protocol-private lib dir
18+#####################################################
19+PROTOCOLPRIVATELIBDIR="`$PKG_CONFIG --variable=libdir unity-protocol-private`/libunity"
20+AC_SUBST(PROTOCOLPRIVATELIBDIR)
21+
22 #############################################
23 # look for dbus service dir
24 #############################################
25
26=== modified file 'src/Makefile.am'
27--- src/Makefile.am 2013-02-22 12:05:05 +0000
28+++ src/Makefile.am 2013-04-24 12:06:28 +0000
29@@ -35,6 +35,7 @@
30 --pkg dee-1.0 \
31 --pkg zeitgeist-1.0 \
32 --pkg unity \
33+ --pkg unity-protocol \
34 --pkg gee-1.0 \
35 --pkg libgnome-menu-3.0 \
36 --pkg unity-package-search \
37@@ -54,7 +55,7 @@
38 unity-ratings-db.o \
39 $(NULL)
40
41-unity_applications_daemon_LDFLAGS = $(COVERAGE_LDFLAGS)
42+unity_applications_daemon_LDFLAGS = -rpath $(PROTOCOLPRIVATELIBDIR) $(COVERAGE_LDFLAGS)
43
44 unity_applications_daemon_VALASOURCES = \
45 app-watcher.vala \
46
47=== modified file 'src/config.vala.in'
48--- src/config.vala.in 2010-06-22 07:36:19 +0000
49+++ src/config.vala.in 2013-04-24 12:06:28 +0000
50@@ -4,6 +4,8 @@
51
52 const string DATADIR = "@DATADIR@";
53
54+ const string PKGDATADIR = "@DATADIR@/unity";
55+
56 const string BINDIR = "@prefix@/bin";
57
58 const string LOCALEDIR = "@DATADIR@/locale";
59@@ -11,4 +13,4 @@
60 const string PACKAGE = "@PACKAGE@";
61
62 const string VERSION = "@VERSION@";
63-}
64\ No newline at end of file
65+}
66
67=== modified file 'src/daemon.vala'
68--- src/daemon.vala 2013-04-23 15:01:12 +0000
69+++ src/daemon.vala 2013-04-24 12:06:28 +0000
70@@ -59,6 +59,7 @@
71 /* The searcher for online material may be null if it fails to load
72 * the Xapian index from the Software Center */
73 private Unity.Package.Searcher? pkgsearcher;
74+ private Unity.Package.Searcher? scopesearcher;
75 public Unity.Package.Searcher appsearcher;
76
77 /* Read the app ratings dumped by the Software Center */
78@@ -167,6 +168,7 @@
79 image_extensions.add ("jpg");
80
81 build_app_menu_index ();
82+ build_scope_index.begin ();
83
84 file_icon_cache = new HashTable<string,Icon>(str_hash, str_equal);
85 sc_mangler = new SoftwareCenterUtils.MangledDesktopFileLookup ();
86@@ -434,6 +436,15 @@
87 return false;
88 }
89
90+ private async void build_scope_index ()
91+ {
92+ var scope_registry = yield Unity.Protocol.ScopeRegistry.find_scopes (
93+ Config.PKGDATADIR + "/scopes");
94+
95+ debug ("Indexing scopes");
96+ scopesearcher = new Unity.Package.Searcher.for_scopes (scope_registry);
97+ }
98+
99 private void populate_zg_templates ()
100 {
101 /* Create a template that activation of applications */
102@@ -575,6 +586,13 @@
103
104 transaction.commit ();
105
106+ // add scopes (if filter is active)
107+ if (!has_filter || type_filter.get_option ("scopes").active)
108+ {
109+ add_local_scopes_results (search_string, model, installed_uris);
110+ add_remote_scopes_results (search_string, model);
111+ }
112+
113 purchase_info = new PurchaseInfoHelper ();
114
115 /* If we don't have a search we display 6 random apps */
116@@ -639,12 +657,6 @@
117 }
118 }
119
120- // add scopes (if filter is active)
121- if (!has_filter || type_filter.get_option ("scopes").active)
122- {
123- add_remote_scopes_results (search_string, model);
124- }
125-
126 if (model.get_n_rows () == 0)
127 {
128 search.set_reply_hint ("no-results-hint",
129@@ -1032,6 +1044,61 @@
130 return null;
131 }
132
133+ private void add_local_scopes_results (string search_string,
134+ Dee.Model model,
135+ Set<string> installed_uris)
136+ {
137+ // If the local scopes Xapian index hasn't been built, return.
138+ if (scopesearcher == null)
139+ return;
140+
141+ bool has_search = !Utils.is_search_empty (search_string);
142+
143+ var results = scopesearcher.search (search_string, 0,
144+ Unity.Package.SearchType.PREFIX,
145+ has_search ?
146+ Unity.Package.Sort.BY_RELEVANCY :
147+ Unity.Package.Sort.BY_NAME);
148+
149+ foreach (unowned Unity.Package.PackageInfo info in results.results)
150+ {
151+ /* De-dupe by "application://foo.scope", since that is what is
152+ * used for software-center results. */
153+ string dedup_key = @"application://$(info.desktop_file)";
154+ if (dedup_key in installed_uris)
155+ continue;
156+ installed_uris.add(dedup_key);
157+
158+ var uri = @"scope://$(info.desktop_file)";
159+ var name = info.application_name;
160+ var icon_hint = info.icon;
161+ var comment = info.description;
162+
163+ try
164+ {
165+ Icon base_icon = icon_hint == null || icon_hint == "" ?
166+ get_default_scope_icon () : Icon.new_for_string (icon_hint);
167+ var anno_icon = new AnnotatedIcon (base_icon);
168+ anno_icon.size_hint = IconSizeHint.SMALL;
169+ icon_hint = anno_icon.to_string ();
170+ }
171+ catch (Error err)
172+ {
173+ icon_hint = "";
174+ }
175+
176+ model.append (uri,
177+ icon_hint,
178+ Category.INSTALLED,
179+ ResultType.DEFAULT,
180+ "application/x-unity-scope",
181+ name != "" ? name : uri,
182+ comment,
183+ "", // dnd_uri ?!
184+ empty_asv);
185+ }
186+ }
187+
188 private void add_remote_scopes_results (string search_string,
189 Dee.Model model)
190 {
191@@ -1040,7 +1107,7 @@
192 {
193 unowned string scope_id =
194 remote_scopes_model.get_string (iter, RemoteScopesColumn.SCOPE_ID);
195- var uri = "scope://%s".printf (scope_id);
196+ var uri = @"scope://$(scope_id)";
197 var name =
198 remote_scopes_model.get_string (iter, RemoteScopesColumn.NAME);
199 var icon_hint =
200@@ -1413,18 +1480,23 @@
201
202 // figure out if the scope is remote
203 bool is_remote_scope = false;
204+ var info = scopesearcher.get_by_desktop_file (scope_id);
205+
206 Dee.ModelIter found_iter = null;
207- var iter = remote_scopes_model.get_first_iter ();
208- var end_iter = remote_scopes_model.get_last_iter ();
209- while (iter != end_iter)
210+ if (info == null)
211 {
212- if (remote_scopes_model.get_string (iter, 0) == scope_id)
213+ var iter = remote_scopes_model.get_first_iter ();
214+ var end_iter = remote_scopes_model.get_last_iter ();
215+ while (iter != end_iter)
216 {
217- is_remote_scope = true;
218- found_iter = iter;
219- break;
220+ if (remote_scopes_model.get_string (iter, 0) == scope_id)
221+ {
222+ is_remote_scope = true;
223+ found_iter = iter;
224+ break;
225+ }
226+ iter = remote_scopes_model.next (iter);
227 }
228- iter = remote_scopes_model.next (iter);
229 }
230
231 if (is_remote_scope)
232@@ -1454,9 +1526,36 @@
233 description,
234 icon,
235 screenshot);
236+ }
237+ else if (info != null)
238+ {
239+ var name = info.application_name;
240+ if (name == null || name == "")
241+ name = info.desktop_file;
242+ // XXX: add this to package info.
243+ var description = info.description;
244+ Icon? icon = null;
245+ try
246+ {
247+ if (info.icon != null && info.icon != "")
248+ icon = Icon.new_for_string (info.icon);
249+ }
250+ catch (Error err)
251+ {
252+ warning ("%s", err.message);
253+ }
254+ if (icon == null)
255+ icon = get_default_scope_icon ();
256+
257+ preview = new Unity.ApplicationPreview (name,
258+ "",
259+ description,
260+ icon,
261+ null);
262+ }
263+ if (preview != null) {
264+ PreviewAction action;
265 preview.set_rating(-1.0f, 0);
266-
267- PreviewAction action;
268 if (scope_disabled)
269 {
270 action = new Unity.PreviewAction ("enable-scope", _("Enable"), null);
271
272=== modified file 'src/unity-package-search.cc'
273--- src/unity-package-search.cc 2013-04-16 12:13:32 +0000
274+++ src/unity-package-search.cc 2013-04-24 12:06:28 +0000
275@@ -239,6 +239,9 @@
276 if (g_app_info_get_display_name (app_info))
277 doc.add_value (XAPIAN_VALUE_APPNAME, g_app_info_get_display_name (app_info));
278
279+ if (g_app_info_get_description (app_info))
280+ doc.add_value (XAPIAN_VALUE_DESCRIPTION, g_app_info_get_description (app_info));
281+
282 if (g_app_info_get_icon (app_info))
283 {
284 gchar *icon_str = g_icon_to_string (g_app_info_get_icon (app_info));
285@@ -383,6 +386,95 @@
286 return searcher;
287 }
288
289+/* Recursively traverse the set of scopes */
290+static void
291+index_scope (Xapian::WritableDatabase *db,
292+ Xapian::TermGenerator *indexer,
293+ UnityProtocolScopeRegistryScopeMetadata *info)
294+{
295+ Xapian::Document doc;
296+ char *dum1;
297+
298+ if (info->name != NULL)
299+ doc.add_value (XAPIAN_VALUE_APPNAME, info->name);
300+ if (info->description != NULL)
301+ doc.add_value (XAPIAN_VALUE_DESCRIPTION, info->description);
302+ if (info->icon != NULL)
303+ doc.add_value (XAPIAN_VALUE_ICON, info->icon);
304+ if (info->id != NULL)
305+ doc.add_value (XAPIAN_VALUE_DESKTOP_FILE, info->id);
306+
307+ indexer->set_document (doc);
308+ if (info->name != NULL)
309+ {
310+ dum1 = unity_applications_lens_utils_preprocess_string (info->name);
311+ indexer->index_text (dum1, 5);
312+ g_free (dum1);
313+ }
314+ if (info->description != NULL)
315+ {
316+ dum1 = unity_applications_lens_utils_preprocess_string (info->description);
317+ indexer->index_text (dum1, 5);
318+ g_free (dum1);
319+ }
320+ for (GSList *l = info->keywords; l != NULL; l = l->next)
321+ {
322+ dum1 = unity_applications_lens_utils_preprocess_string ((char *)l->data);
323+ indexer->index_text (dum1, 0);
324+ indexer->index_text (dum1, 0, "KW");
325+ g_free (dum1);
326+ }
327+
328+ /* Always assume Type=Scope for scopes... */
329+ doc.add_term ("ATscope");
330+
331+ /* Index application name */
332+ dum1 = g_strconcat ("AA", info->name, NULL);
333+ doc.add_term (dum1);
334+ g_free (dum1);
335+
336+ db->add_document (doc);
337+}
338+
339+UnityPackageSearcher*
340+unity_package_searcher_new_for_scopes (UnityProtocolScopeRegistry *scope_registry)
341+{
342+ UnityPackageSearcher *searcher;
343+ Xapian::WritableDatabase *db;
344+
345+ searcher = new UnityPackageSearcher;
346+ db = new Xapian::WritableDatabase ();
347+ searcher->db = db;
348+ searcher->db->add_database (Xapian::InMemory::open ());
349+
350+ init_searcher (searcher);
351+
352+ /* Index the menu recursively */
353+ searcher->db_merged = false;
354+ Xapian::TermGenerator *indexer = new Xapian::TermGenerator ();
355+
356+ GSList *scopes = unity_protocol_scope_registry_get_scopes (scope_registry);
357+ for (GSList *l = scopes; l != NULL; l = l->next)
358+ {
359+ UnityProtocolScopeRegistryScopeRegistryNode *node = (UnityProtocolScopeRegistryScopeRegistryNode *)l->data;
360+ index_scope (db, indexer, node->scope_info);
361+
362+ // Also index any sub-scopes
363+ for (GSList *sl = node->sub_scopes; sl != NULL; sl = sl->next)
364+ {
365+ UnityProtocolScopeRegistryScopeMetadata *info = (UnityProtocolScopeRegistryScopeMetadata *)sl->data;
366+ index_scope (db, indexer, info);
367+ }
368+ }
369+ delete indexer;
370+ db->flush ();
371+
372+ searcher->matcher = new Columbus::Matcher();
373+ buildMatcher(searcher);
374+
375+ return searcher;
376+}
377+
378 /* Create a new searcher that searches into the Xapian index
379 * provided by the Software Center */
380 UnityPackageSearcher*
381@@ -452,6 +544,9 @@
382 string appname = doc.get_value (XAPIAN_VALUE_APPNAME);
383 pkginfo->application_name = g_strdup (appname.c_str ());
384
385+ string description = doc.get_value (XAPIAN_VALUE_DESCRIPTION);
386+ pkginfo->description = g_strdup (description.c_str ());
387+
388 string desktop_file = doc.get_value (XAPIAN_VALUE_DESKTOP_FILE);
389 pkginfo->desktop_file = g_strdup (desktop_file.c_str ());
390
391@@ -892,14 +987,20 @@
392 Xapian::Document doc = searcher->db->get_document (*it);
393 string value = doc.get_value (XAPIAN_VALUE_DESKTOP_FILE);
394
395+ bool matches = false;
396 size_t sep = value.find (':');
397 if (sep != string::npos)
398 {
399- if (value.compare (sep+1, value.size() - sep, query) == 0)
400- {
401- pkginfo = _pkginfo_from_document (doc);
402- return pkginfo;
403- }
404+ matches = value.compare (sep+1, value.size() - sep, query) == 0;
405+ }
406+ else
407+ {
408+ matches = value == query;
409+ }
410+ if (matches)
411+ {
412+ pkginfo = _pkginfo_from_document (doc);
413+ return pkginfo;
414 }
415 ++it;
416 }
417
418=== modified file 'src/unity-package-search.h'
419--- src/unity-package-search.h 2012-10-09 15:26:49 +0000
420+++ src/unity-package-search.h 2013-04-24 12:06:28 +0000
421@@ -19,6 +19,7 @@
422
423 #include <glib.h>
424 #include <gmenu-tree.h>
425+#include <unity-protocol.h>
426
427 typedef struct _UnityPackageSearcher UnityPackageSearcher;
428
429@@ -44,6 +45,7 @@
430 {
431 gchar *package_name;
432 gchar *application_name;
433+ gchar *description;
434 gchar *desktop_file;
435 gchar *icon;
436 gchar *price;
437@@ -61,6 +63,7 @@
438 UnityPackageSearcher* unity_package_searcher_new ();
439
440 UnityPackageSearcher* unity_package_searcher_new_for_menu (GMenuTree *menu);
441+UnityPackageSearcher* unity_package_searcher_new_for_scopes (UnityProtocolScopeRegistry *scope_registry);
442
443 void unity_package_searcher_free (UnityPackageSearcher *searcher);
444
445
446=== modified file 'src/xapian-utils.vala'
447--- src/xapian-utils.vala 2013-03-22 10:10:13 +0000
448+++ src/xapian-utils.vala 2013-04-24 12:06:28 +0000
449@@ -109,9 +109,9 @@
450 if (Utils.is_search_empty (search_string))
451 {
452 if (options == null || !options.filtering)
453- return "type:Application";
454+ return "(type:Application OR type:Scope)";
455 else
456- return "type:Application AND " + extract_type_query (options);
457+ return "(type:Application OR type:Scope) AND " + extract_type_query (options);
458 }
459 else
460 {
461@@ -127,9 +127,9 @@
462 s = s.delimit ("-", ' ');
463
464 if (options == null || !options.filtering)
465- return "type:Application AND " + s;
466+ return "(type:Application OR type:Scope) AND " + s;
467 else
468- return "type:Application AND %s AND %s".printf (extract_type_query (options), s);
469+ return "(type:Application OR type:Scope) AND %s AND %s".printf (extract_type_query (options), s);
470 }
471 }
472 }
473
474=== modified file 'tests/unit/Makefile.am'
475--- tests/unit/Makefile.am 2013-03-01 15:41:08 +0000
476+++ tests/unit/Makefile.am 2013-04-24 12:06:28 +0000
477@@ -30,6 +30,8 @@
478 $(test_libs) \
479 $(UNITY_PACKAGE_SEARCH_LIBS)
480
481+LDFLAGS += -rpath $(PROTOCOLPRIVATELIBDIR)
482+
483 AM_CPPFLAGS = \
484 $(LENS_DAEMON_CFLAGS) \
485 -I$(srcdir) \
486
487=== modified file 'tests/unit/test-xapian-utils.vala'
488--- tests/unit/test-xapian-utils.vala 2012-10-08 08:41:45 +0000
489+++ tests/unit/test-xapian-utils.vala 2013-04-24 12:06:28 +0000
490@@ -43,7 +43,7 @@
491 internal static void test_empty_search_query ()
492 {
493 var query = XapianUtils.prepare_pkg_search_string ("", null);
494- assert (query == "type:Application");
495+ assert (query == "(type:Application OR type:Scope)");
496 }
497
498 internal static void test_empty_search_with_single_cat_filter ()
499@@ -54,7 +54,7 @@
500 filter.add_option ("internet", "Internet", null);
501
502 var query = XapianUtils.prepare_pkg_search_string ("", filter);
503- assert (query == "type:Application AND (category:AudioVideo)");
504+ assert (query == "(type:Application OR type:Scope) AND (category:AudioVideo)");
505 }
506
507 internal static void test_empty_search_with_multi_cat_filter ()
508@@ -65,16 +65,16 @@
509 filter.add_option ("internet", "Internet", null);
510 filter.add_option ("game", "Game", null).active = true;
511 var query = XapianUtils.prepare_pkg_search_string ("", filter);
512- assert (query == "type:Application AND (category:Game OR category:AudioVideo)");
513+ assert (query == "(type:Application OR type:Scope) AND (category:Game OR category:AudioVideo)");
514 }
515
516 internal static void test_search_query_no_filters ()
517 {
518 var query = XapianUtils.prepare_pkg_search_string (" foo ", null);
519- assert (query == "type:Application AND foo");
520+ assert (query == "(type:Application OR type:Scope) AND foo");
521
522 query = XapianUtils.prepare_pkg_search_string ("foo", null);
523- assert (query == "type:Application AND foo");
524+ assert (query == "(type:Application OR type:Scope) AND foo");
525 }
526
527 internal static void test_search_query_with_single_cat_filter ()
528@@ -84,7 +84,7 @@
529 filter.add_option ("media", "Media", null);
530 filter.add_option ("internet", "Internet", null).active = true;
531 var query = XapianUtils.prepare_pkg_search_string ("foo", filter);
532- assert (query == "type:Application AND (category:Network) AND foo");
533+ assert (query == "(type:Application OR type:Scope) AND (category:Network) AND foo");
534 }
535
536 internal static void test_search_query_with_multi_cat_filter ()
537@@ -95,7 +95,7 @@
538 filter.add_option ("internet", "Internet", null).active = true;
539 filter.add_option ("game", "Game", null).active = true;
540 var query = XapianUtils.prepare_pkg_search_string ("foo", filter);
541- assert (query == "type:Application AND (category:Game OR category:Network) AND foo");
542+ assert (query == "(type:Application OR type:Scope) AND (category:Game OR category:Network) AND foo");
543 }
544
545 internal static void test_zg_empty_search_query ()
546
547=== modified file 'vapi/unity-package-search.deps'
548--- vapi/unity-package-search.deps 2012-10-18 12:36:37 +0000
549+++ vapi/unity-package-search.deps 2013-04-24 12:06:28 +0000
550@@ -1,2 +1,3 @@
551 glib-2.0
552 libgnome-menu-3.0
553+unity-protocol
554
555=== modified file 'vapi/unity-package-search.vapi'
556--- vapi/unity-package-search.vapi 2012-10-08 15:11:07 +0000
557+++ vapi/unity-package-search.vapi 2013-04-24 12:06:28 +0000
558@@ -27,6 +27,8 @@
559 public Searcher ();
560 [CCode (cname = "unity_package_searcher_new_for_menu")]
561 public Searcher.for_menu(GMenu.Tree menu);
562+ [CCode (cname = "unity_package_searcher_new_for_scopes")]
563+ public Searcher.for_scopes(Unity.Protocol.ScopeRegistry scope_registry);
564 public SearchResult search (string search_string, uint max_hits, Unity.Package.SearchType search_type, Unity.Package.Sort sort);
565 public SearchResult get_random_apps (string? filter_query, uint n_apps);
566 public SearchResult get_apps (string? filter_query, uint n_apps, AppFilterCallback cb);
567@@ -49,6 +51,7 @@
568 public PackageInfo ();
569 public string package_name;
570 public string application_name;
571+ public string description;
572 public string desktop_file;
573 public string icon;
574 public string price;

Subscribers

People subscribed via source and target branches

to all changes: