Merge lp:~stolowski/unity-lens-applications/fuzzy-public-content into lp:unity-lens-applications

Proposed by Paweł Stołowski
Status: Superseded
Proposed branch: lp:~stolowski/unity-lens-applications/fuzzy-public-content
Merge into: lp:unity-lens-applications
Diff against target: 2478 lines (+1085/-330) (has conflicts)
24 files modified
Makefile.am (+6/-11)
applications.lens.in.in (+0/-12)
applications.scope.in.in (+13/-0)
commands.scope.in.in (+6/-4)
configure.ac (+12/-5)
data/Makefile.am (+2/-2)
data/unity-scope-applications.service.in (+1/-1)
debian/changelog (+55/-0)
debian/control (+1/-1)
po/POTFILES.in (+2/-2)
src/Makefile.am (+2/-1)
src/config.vala.in (+3/-1)
src/daemon.vala (+620/-153)
src/main.vala (+4/-4)
src/runner.vala (+99/-112)
src/schemas.vala (+10/-0)
src/unity-package-search.cc (+127/-7)
src/unity-package-search.h (+7/-2)
src/utils.vala (+93/-0)
src/xapian-utils.vala (+7/-5)
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 (+5/-0)
Text conflict in debian/changelog
Text conflict in src/daemon.vala
To merge this branch: bzr merge lp:~stolowski/unity-lens-applications/fuzzy-public-content
Reviewer Review Type Date Requested Status
Unity Team Pending
Review via email: mp+162976@code.launchpad.net

This proposal has been superseded by a proposal from 2013-05-08.

Commit message

Mark results of libcolumbus fuzzy searches as 'default' content (as opposed to 'personal'). Also mark apps returned by software-center-dbus-provider as 'default', unless they were purchased before.

Description of the change

Mark results of libcolumbus fuzzy searches as 'default' content (as opposed to 'personal'). Also mark apps returned by software-center-dbus-provider as 'default', unless they were purchased before.

To post a comment you must log in.
348. By Paweł Stołowski

Fixed conditional to treat all apps from category other than AVAILABLE as personal content, as this also includes
more categories than just INSTALLED (e.g. RECENT apps).

Unmerged revisions

348. By Paweł Stołowski

Fixed conditional to treat all apps from category other than AVAILABLE as personal content, as this also includes
more categories than just INSTALLED (e.g. RECENT apps).

347. By Paweł Stołowski

Mark results of libcolumbus fuzzy searches as 'default' content (as opposed to 'personal'). Also mark apps returned by software-center-dbus-provider
as 'default', unless they were purchased before.

346. By PS Jenkins bot

Releasing 6.10.0daily13.05.07ubuntu.unity.experimental.certified-0ubuntu1 to ubuntu.

Approved by PS Jenkins bot.

345. By Michal Hruby

Remove an old icon used by the commands scope.

Approved by Pawel Stolowski, PS Jenkins bot.

344. By James Henstridge

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. Fixes: https://bugs.launchpad.net/bugs/1174453, https://bugs.launchpad.net/bugs/1174910.

Approved by PS Jenkins bot, Michal Hruby.

343. By James Henstridge

Various scope search result fixes: show local scopes on empty search, filter out master scopes from results and move disabled local scopes to available category. Fixes: https://bugs.launchpad.net/bugs/1174464.

Approved by Michal Hruby, PS Jenkins bot.

342. By Michal Hruby

Update the scope description.

Approved by Pawel Stolowski, PS Jenkins bot.

341. By James Henstridge

Index local scopes and include them in the search results. Fixes: https://bugs.launchpad.net/bugs/1170713.

Approved by Michal Hruby, PS Jenkins bot.

340. By Andrea Azzarone

Don't show the ratings widget for remote scope. Fixes: https://bugs.launchpad.net/bugs/1170715.

Approved by Michal Hruby, PS Jenkins bot.

339. By PS Jenkins bot

Releasing 6.10.0daily13.04.23ubuntu.unity.experimental.certified-0ubuntu1 to ubuntu.

Approved by PS Jenkins bot.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile.am'
--- Makefile.am 2013-02-15 10:11:07 +0000
+++ Makefile.am 2013-05-08 13:32:23 +0000
@@ -4,18 +4,14 @@
4#4#
5# Install the applications.lens file5# Install the applications.lens file
6#6#
7lens_in_files = applications.lens.in7scope_in_files = applications.scope.in commands.scope.in
8lensdir = $(datadir)/unity/lenses/applications8scopedir = $(datadir)/unity/scopes
9lens_DATA = $(lens_in_files:.lens.in=.lens)9scope_DATA = $(scope_in_files:.scope.in=.scope)
10
11cmdlens_in_files = commands.lens.in
12cmdlensdir = $(datadir)/unity/lenses/commands
13cmdlens_DATA = $(cmdlens_in_files:.lens.in=.lens)
1410
15icondir = $(datadir)/unity/themes11icondir = $(datadir)/unity/themes
16icon_DATA = applications.png12icon_DATA = applications.png
1713
18@INTLTOOL_LENS_RULE@14@INTLTOOL_SCOPE_RULE@
1915
20DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall16DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall
2117
@@ -37,7 +33,7 @@
37EXTRA_DIST = \33EXTRA_DIST = \
38 applications.png \34 applications.png \
39 autogen.sh \35 autogen.sh \
40 $(lens_in_files) \36 $(scope_in_files) \
41 AUTHORS \37 AUTHORS \
42 COPYING \38 COPYING \
43 HACKING \39 HACKING \
@@ -50,8 +46,7 @@
50 $(NULL)46 $(NULL)
5147
52CLEANFILES = \48CLEANFILES = \
53 $(lens_DATA) \49 $(scope_DATA) \
54 $(cmdlens_DATA) \
55 $(NULL)50 $(NULL)
5651
57include $(top_srcdir)/Makefile.am.coverage52include $(top_srcdir)/Makefile.am.coverage
5853
=== removed file 'applications.lens.in.in'
--- applications.lens.in.in 2012-07-04 16:05:38 +0000
+++ applications.lens.in.in 1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
1[Lens]
2DBusName=com.canonical.Unity.Lens.Applications
3DBusPath=/com/canonical/unity/lens/applications
4_Name=Applications
5Icon=@prefix@/share/unity/6/lens-nav-app.svg
6Description=
7_SearchHint=Search Applications
8Shortcut=a
9
10[Desktop Entry]
11X-Ubuntu-Gettext-Domain=unity-lens-applications
12
130
=== added file 'applications.scope.in.in'
--- applications.scope.in.in 1970-01-01 00:00:00 +0000
+++ applications.scope.in.in 2013-05-08 13:32:23 +0000
@@ -0,0 +1,13 @@
1[Scope]
2DBusName=com.canonical.Unity.Scope.Applications
3DBusPath=/com/canonical/unity/scope/applications
4Icon=@prefix@/share/unity/icons/lens-nav-app.svg
5_Name=Applications
6_Description=This is an Ubuntu search plugin that enables information from local applications to be searched and displayed in the Dash underneath the Applications header. If you do not wish to search this content source, you can disable this search plugin.
7Type=applications
8_SearchHint=Search Applications
9Shortcut=a
10
11[Desktop Entry]
12X-Ubuntu-Gettext-Domain=unity-lens-applications
13
014
=== renamed file 'commands.lens.in.in' => 'commands.scope.in.in'
--- commands.lens.in.in 2011-08-08 22:05:14 +0000
+++ commands.scope.in.in 2013-05-08 13:32:23 +0000
@@ -1,8 +1,10 @@
1[Lens]1[Scope]
2DBusName=com.canonical.Unity.Lens.Applications2DBusName=com.canonical.Unity.Scope.Applications
3DBusPath=/com/canonical/unity/lens/commands3DBusPath=/com/canonical/unity/scope/commands
4_Name=Commands4_Name=Commands
5Icon=@prefix@/share/unity/themes/applications.png5_Description=This is an Ubuntu search plugin that enables information from local binaries to be searched and displayed in the Dash. If you do not wish to search this content source, you can disable this search plugin.
6Icon=
7Type=commands
6_SearchHint=Run a command8_SearchHint=Run a command
7Visible=false9Visible=false
810
911
=== modified file 'configure.ac'
--- configure.ac 2013-03-01 15:11:29 +0000
+++ configure.ac 2013-05-08 13:32:23 +0000
@@ -47,10 +47,10 @@
47AC_DEFINE_UNQUOTED(PREFIXDIR, "${PREFIX}",[Prefix directory])47AC_DEFINE_UNQUOTED(PREFIXDIR, "${PREFIX}",[Prefix directory])
4848
49######################################################49######################################################
50# intltool rule for generating translated .lens file50# intltool rule for generating translated .scope file
51######################################################51######################################################
52INTLTOOL_LENS_RULE='%.lens: %.lens.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'52INTLTOOL_SCOPE_RULE='%.scope: %.scope.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
53AC_SUBST(INTLTOOL_LENS_RULE)53AC_SUBST(INTLTOOL_SCOPE_RULE)
5454
55###########################55###########################
56# gcov coverage reporting56# gcov coverage reporting
@@ -77,6 +77,7 @@
77 zeitgeist-1.0 >= 0.3.877 zeitgeist-1.0 >= 0.3.8
78 libcolumbus0 >= 0.4.078 libcolumbus0 >= 0.4.0
79 unity >= 6.7.079 unity >= 6.7.0
80 unity-protocol-private
80 libgnome-menu-3.0 >= 3.6.0)81 libgnome-menu-3.0 >= 3.6.0)
8182
82AC_SUBST(LENS_DAEMON_CFLAGS)83AC_SUBST(LENS_DAEMON_CFLAGS)
@@ -138,6 +139,12 @@
138AS_AC_EXPAND(DATADIR, $datarootdir)139AS_AC_EXPAND(DATADIR, $datarootdir)
139AC_SUBST(DATADIR)140AC_SUBST(DATADIR)
140141
142#####################################################
143# Look for protocol-private lib dir
144#####################################################
145PROTOCOLPRIVATELIBDIR="`$PKG_CONFIG --variable=libdir unity-protocol-private`/libunity"
146AC_SUBST(PROTOCOLPRIVATELIBDIR)
147
141#############################################148#############################################
142# look for dbus service dir149# look for dbus service dir
143#############################################150#############################################
@@ -159,8 +166,8 @@
159#############################################166#############################################
160AC_CONFIG_FILES([167AC_CONFIG_FILES([
161 Makefile168 Makefile
162 applications.lens.in169 applications.scope.in
163 commands.lens.in170 commands.scope.in
164 data/com.canonical.Unity.AppsLens.gschema.xml.in171 data/com.canonical.Unity.AppsLens.gschema.xml.in
165 data/Makefile172 data/Makefile
166 data/X-Unity-All-Applications.directory173 data/X-Unity-All-Applications.directory
167174
=== modified file 'data/Makefile.am'
--- data/Makefile.am 2012-11-08 04:49:06 +0000
+++ data/Makefile.am 2013-05-08 13:32:23 +0000
@@ -2,7 +2,7 @@
2# DBus service files2# DBus service files
3#############################################################3#############################################################
4dbus_servicesdir = $(DBUSSERVICEDIR)4dbus_servicesdir = $(DBUSSERVICEDIR)
5service_in_files = unity-lens-applications.service.in5service_in_files = unity-scope-applications.service.in
6dbus_services_DATA = $(service_in_files:.service.in=.service)6dbus_services_DATA = $(service_in_files:.service.in=.service)
77
8%.service: %.service.in8%.service: %.service.in
@@ -39,6 +39,6 @@
39 $(menu_in_files)39 $(menu_in_files)
4040
41CLEANFILES = \41CLEANFILES = \
42 unity-lens-applications.service \42 unity-scope-applications.service \
43 $(gsettings_SCHEMAS)43 $(gsettings_SCHEMAS)
4444
4545
=== renamed file 'data/unity-lens-applications.service.in' => 'data/unity-scope-applications.service.in'
--- data/unity-lens-applications.service.in 2012-11-08 04:49:06 +0000
+++ data/unity-scope-applications.service.in 2013-05-08 13:32:23 +0000
@@ -1,3 +1,3 @@
1[D-BUS Service]1[D-BUS Service]
2Name=com.canonical.Unity.Lens.Applications2Name=com.canonical.Unity.Scope.Applications
3Exec=@pkglibexecdir@/unity-applications-daemon3Exec=@pkglibexecdir@/unity-applications-daemon
44
=== modified file 'debian/changelog'
--- debian/changelog 2013-05-01 21:58:08 +0000
+++ debian/changelog 2013-05-08 13:32:23 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
1unity-lens-applications (6.10.0daily13.05.01.1ubuntu.unity.next-0ubuntu1) raring; urgency=low2unity-lens-applications (6.10.0daily13.05.01.1ubuntu.unity.next-0ubuntu1) raring; urgency=low
23
3 [ Sebastien Bacher ]4 [ Sebastien Bacher ]
@@ -25,6 +26,48 @@
2526
26 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 17 Apr 2013 04:07:02 +000027 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 17 Apr 2013 04:07:02 +0000
2728
29=======
30unity-lens-applications (6.10.0daily13.05.07ubuntu.unity.experimental.certified-0ubuntu1) raring; urgency=low
31
32 [ James Henstridge ]
33 * Master scopes shouldn't be displayed in App Lens results (LP:
34 #1174464)
35 * Previews for scopes should use a screenshot of web page (LP:
36 #1174453)
37 * It should not be possible to disable the App Scope from within the
38 App Lens preview. (LP: #1174910)
39 * The “Search Plugins” filter in the apps lens displays remote scopes
40 only (LP: #1170713)
41
42 [ Andrea Azzarone ]
43 * Search Plugins previews in the apps lens should not display any
44 ‘review stars’ (LP: #1170715)
45
46 [ Ubuntu daily release ]
47 * Automatic snapshot from revision 345 (ubuntu-unity/experimental-
48 certified)
49
50 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 07 May 2013 10:43:23 +0000
51
52unity-lens-applications (6.10.0daily13.04.23ubuntu.unity.experimental.certified-0ubuntu1) raring; urgency=low
53
54 [ Michal Hruby ]
55 * Application scope not behaving when searching for " " with filters
56 (LP: #1161337)
57
58 [ Mathieu Trudel-Lapierre <mathieu-tl@ubuntu.com>, Jussi Pakkanen ]
59 * search in application lens is innacurate (LP: #1159812)
60
61 [ Mathieu Trudel-Lapierre ]
62 * search in application lens is innacurate (LP: #1159812)
63
64 [ Ubuntu daily release ]
65 * Automatic snapshot from revision 338 (ubuntu-unity/experimental-
66 certified)
67
68 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 23 Apr 2013 07:03:12 +0000
69
70>>>>>>> MERGE-SOURCE
28unity-lens-applications (6.10.0daily13.04.15-0ubuntu1) raring; urgency=low71unity-lens-applications (6.10.0daily13.04.15-0ubuntu1) raring; urgency=low
2972
30 [ Sebastien Bacher ]73 [ Sebastien Bacher ]
@@ -38,6 +81,18 @@
3881
39 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 15 Apr 2013 04:17:07 +000082 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 15 Apr 2013 04:17:07 +0000
4083
84unity-lens-applications (6.10.0daily13.04.10ubuntu.unity.experimental.certified-0ubuntu1) raring; urgency=low
85
86 [ Didier Roche ]
87 * debian/control:
88 - bump build-dep on latest libunity version
89
90 [ Ubuntu daily release ]
91 * Automatic snapshot from revision 335 (ubuntu-unity/experimental-
92 certified)
93
94 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Wed, 10 Apr 2013 07:14:44 +0000
95
41unity-lens-applications (6.10.0daily13.03.06-0ubuntu1) raring; urgency=low96unity-lens-applications (6.10.0daily13.03.06-0ubuntu1) raring; urgency=low
4297
43 [ Jussi Pakkanen ]98 [ Jussi Pakkanen ]
4499
=== modified file 'debian/control'
--- debian/control 2013-04-12 12:21:04 +0000
+++ debian/control 2013-05-08 13:32:23 +0000
@@ -11,7 +11,7 @@
11 libgee-dev,11 libgee-dev,
12 libdee-dev (>= 0.5.16),12 libdee-dev (>= 0.5.16),
13 libzeitgeist-dev (>= 0.3.8),13 libzeitgeist-dev (>= 0.3.8),
14 libunity-dev (>= 6.8.0),14 libunity-dev (>= 6.91),
15 libgnome-menu-3-dev,15 libgnome-menu-3-dev,
16 dh-autoreconf,16 dh-autoreconf,
17 libxapian-dev,17 libxapian-dev,
1818
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2011-08-04 10:07:39 +0000
+++ po/POTFILES.in 2013-05-08 13:32:23 +0000
@@ -4,5 +4,5 @@
4src/utils.vala4src/utils.vala
5src/main.vala5src/main.vala
6data/X-Unity-All-Applications.directory.in6data/X-Unity-All-Applications.directory.in
7[type: gettext/ini]applications.lens.in.in7[type: gettext/ini]applications.scope.in.in
8[type: gettext/ini]commands.lens.in.in8[type: gettext/ini]commands.scope.in.in
99
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2013-02-22 12:05:05 +0000
+++ src/Makefile.am 2013-05-08 13:32:23 +0000
@@ -35,6 +35,7 @@
35 --pkg dee-1.0 \35 --pkg dee-1.0 \
36 --pkg zeitgeist-1.0 \36 --pkg zeitgeist-1.0 \
37 --pkg unity \37 --pkg unity \
38 --pkg unity-protocol \
38 --pkg gee-1.0 \39 --pkg gee-1.0 \
39 --pkg libgnome-menu-3.0 \40 --pkg libgnome-menu-3.0 \
40 --pkg unity-package-search \41 --pkg unity-package-search \
@@ -54,7 +55,7 @@
54 unity-ratings-db.o \55 unity-ratings-db.o \
55 $(NULL)56 $(NULL)
5657
57unity_applications_daemon_LDFLAGS = $(COVERAGE_LDFLAGS)58unity_applications_daemon_LDFLAGS = -rpath $(PROTOCOLPRIVATELIBDIR) $(COVERAGE_LDFLAGS)
5859
59unity_applications_daemon_VALASOURCES = \60unity_applications_daemon_VALASOURCES = \
60 app-watcher.vala \61 app-watcher.vala \
6162
=== modified file 'src/config.vala.in'
--- src/config.vala.in 2010-06-22 07:36:19 +0000
+++ src/config.vala.in 2013-05-08 13:32:23 +0000
@@ -4,6 +4,8 @@
4 4
5 const string DATADIR = "@DATADIR@";5 const string DATADIR = "@DATADIR@";
6 6
7 const string PKGDATADIR = "@DATADIR@/unity";
8
7 const string BINDIR = "@prefix@/bin";9 const string BINDIR = "@prefix@/bin";
8 10
9 const string LOCALEDIR = "@DATADIR@/locale";11 const string LOCALEDIR = "@DATADIR@/locale";
@@ -11,4 +13,4 @@
11 const string PACKAGE = "@PACKAGE@";13 const string PACKAGE = "@PACKAGE@";
12 14
13 const string VERSION = "@VERSION@";15 const string VERSION = "@VERSION@";
14}
15\ No newline at end of file16\ No newline at end of file
17}
1618
=== modified file 'src/daemon.vala'
--- src/daemon.vala 2013-04-22 17:45:49 +0000
+++ src/daemon.vala 2013-05-08 13:32:23 +0000
@@ -42,9 +42,13 @@
4242
43 const string ICON_PATH = Config.DATADIR + "/icons/unity-icon-theme/places/svg/";43 const string ICON_PATH = Config.DATADIR + "/icons/unity-icon-theme/places/svg/";
44 const string GENERIC_APP_ICON = "applications-other";44 const string GENERIC_APP_ICON = "applications-other";
45 const string GENERIC_SCOPE_ICON = ICON_PATH + "service-generic.svg";
46
47 const string LIBUNITY_SCHEMA = "com.canonical.Unity.Lenses";
4548
46 public class Daemon : GLib.Object49 public class Daemon : GLib.Object
47 {50 {
51 private Variant empty_asv;
48 private Zeitgeist.Log log;52 private Zeitgeist.Log log;
49 private Zeitgeist.Index zg_index;53 private Zeitgeist.Index zg_index;
50 private Zeitgeist.Monitor monitor;54 private Zeitgeist.Monitor monitor;
@@ -55,14 +59,14 @@
55 /* The searcher for online material may be null if it fails to load59 /* The searcher for online material may be null if it fails to load
56 * the Xapian index from the Software Center */60 * the Xapian index from the Software Center */
57 private Unity.Package.Searcher? pkgsearcher;61 private Unity.Package.Searcher? pkgsearcher;
62 private Unity.Package.Searcher? scopesearcher;
58 public Unity.Package.Searcher appsearcher;63 public Unity.Package.Searcher appsearcher;
5964
60 /* Read the app ratings dumped by the Software Center */65 /* Read the app ratings dumped by the Software Center */
61 private bool ratings_db_initialized = false;66 private bool ratings_db_initialized = false;
62 private Unity.Ratings.Database? ratings = null;67 private Unity.Ratings.Database? ratings = null;
6368
64 private Unity.Lens lens;69 private Unity.DeprecatedScope scope;
65 private Unity.Scope scope;
6670
67 /* Support aptd dbus interface; created when application install/remove was requested by preview action */71 /* Support aptd dbus interface; created when application install/remove was requested by preview action */
68 private AptdProxy aptdclient;72 private AptdProxy aptdclient;
@@ -107,6 +111,7 @@
107 private Regex mountable_regex;111 private Regex mountable_regex;
108112
109 private Settings gp_settings;113 private Settings gp_settings;
114 private HashTable<unowned string, unowned string> disabled_scope_ids;
110115
111 private const string DISPLAY_RECENT_APPS_KEY = "display-recent-apps";116 private const string DISPLAY_RECENT_APPS_KEY = "display-recent-apps";
112 private const string DISPLAY_AVAILABLE_APPS_KEY = "display-available-apps";117 private const string DISPLAY_AVAILABLE_APPS_KEY = "display-available-apps";
@@ -116,6 +121,9 @@
116 public bool force_small_icons_for_suggestions { get; set; default = true; }121 public bool force_small_icons_for_suggestions { get; set; default = true; }
117122
118 private PurchaseInfoHelper purchase_info = null;123 private PurchaseInfoHelper purchase_info = null;
124 private Dee.Model remote_scopes_model;
125 private Dee.Index scopes_index;
126 private Dee.Analyzer analyzer;
119127
120 construct128 construct
121 {129 {
@@ -123,6 +131,7 @@
123131
124 log = new Zeitgeist.Log();132 log = new Zeitgeist.Log();
125 zg_index = new Zeitgeist.Index();133 zg_index = new Zeitgeist.Index();
134 empty_asv = new Variant.array (new VariantType ("{sv}"), {});
126 monitor = new Zeitgeist.Monitor (new Zeitgeist.TimeRange.from_now (),135 monitor = new Zeitgeist.Monitor (new Zeitgeist.TimeRange.from_now (),
127 zg_templates);136 zg_templates);
128 monitor.events_inserted.connect (mark_dirty);137 monitor.events_inserted.connect (mark_dirty);
@@ -159,14 +168,17 @@
159 image_extensions.add ("jpg");168 image_extensions.add ("jpg");
160169
161 build_app_menu_index ();170 build_app_menu_index ();
171 build_scope_index.begin ();
162172
163 file_icon_cache = new HashTable<string,Icon>(str_hash, str_equal);173 file_icon_cache = new HashTable<string,Icon>(str_hash, str_equal);
164 sc_mangler = new SoftwareCenterUtils.MangledDesktopFileLookup ();174 sc_mangler = new SoftwareCenterUtils.MangledDesktopFileLookup ();
165175
166 scope = new Unity.Scope ("/com/canonical/unity/scope/applications");176 scope = new Unity.DeprecatedScope ("/com/canonical/unity/scope/applications",
167 scope.provides_personal_content = true;177 "applications");
168 //scope.icon = @"$(Config.PREFIX)/share/unity/themes/applications.png";
169178
179 scope.search_hint = _("Search Applications");
180 scope.search_in_global = true;
181 // scope.sources_display_name = _("Sources");
170 // TRANSLATORS: Please make sure this string is short enough to fit182 // TRANSLATORS: Please make sure this string is short enough to fit
171 // into the filter button183 // into the filter button
172 local_apps_option = scope.sources.add_option ("local", _("Local Apps"));184 local_apps_option = scope.sources.add_option ("local", _("Local Apps"));
@@ -177,6 +189,10 @@
177 usc_apps_option = scope.sources.add_option ("usc", _("Software Center"));189 usc_apps_option = scope.sources.add_option ("usc", _("Software Center"));
178 }190 }
179191
192 populate_categories ();
193 populate_filters();
194 //scope.icon = @"$(Config.PREFIX)/share/unity/themes/applications.png";
195
180 scope.generate_search_key.connect ((lens_search) =>196 scope.generate_search_key.connect ((lens_search) =>
181 {197 {
182 return lens_search.search_string.strip ();198 return lens_search.search_string.strip ();
@@ -184,16 +200,10 @@
184 /* Listen for changes to the lens scope search */200 /* Listen for changes to the lens scope search */
185 scope.search_changed.connect ((lens_search, search_type, cancellable) =>201 scope.search_changed.connect ((lens_search, search_type, cancellable) =>
186 {202 {
187 dispatch_search (lens_search, search_type, cancellable);203 dispatch_search.begin (lens_search, search_type, cancellable);
188 });204 });
189205
190 /* Re-do the search if the filters changed */206 /* Re-do the search if the sources change */
191 scope.filters_changed.connect (() =>
192 {
193 scope.queue_search_changed (SearchType.DEFAULT);
194 });
195
196 /* And also if the sources change */
197 scope.active_sources_changed.connect (() =>207 scope.active_sources_changed.connect (() =>
198 {208 {
199 scope.queue_search_changed (SearchType.DEFAULT);209 scope.queue_search_changed (SearchType.DEFAULT);
@@ -225,15 +235,35 @@
225 aptdclient = new AptdProxy ();235 aptdclient = new AptdProxy ();
226 launcherservice = new LauncherProxy ();236 launcherservice = new LauncherProxy ();
227237
228 lens = new Unity.Lens ("/com/canonical/unity/lens/applications", "applications");238 scope.export ();
229 lens.search_hint = _("Search Applications");239
230 lens.visible = true;240 remote_scopes_model = new Dee.SharedModel ("com.canonical.Unity.SmartScopes.RemoteScopesModel");
231 lens.search_in_global = true;241 remote_scopes_model.set_schema ("s", "s", "s", "s", "s", "as");
232 lens.sources_display_name = _("Sources");242
233 populate_categories ();243 scopes_index = Utils.prepare_index (remote_scopes_model,
234 populate_filters();244 RemoteScopesColumn.NAME,
235 lens.add_local_scope (scope);245 (model, iter) =>
236 lens.export ();246 {
247 unowned string name = model.get_string (iter, RemoteScopesColumn.NAME);
248 return "%s\n%s".printf (_("scope"), name);
249 }, out analyzer);
250
251 disabled_scope_ids = new HashTable<unowned string, unowned string> (str_hash, str_equal);
252 update_disabled_scopes_hash ();
253
254 var pref_man = PreferencesManager.get_default ();
255 pref_man.notify["disabled-scopes"].connect (update_disabled_scopes_hash);
256 }
257
258 private void update_disabled_scopes_hash ()
259 {
260 disabled_scope_ids.remove_all ();
261 var pref_man = PreferencesManager.get_default ();
262 foreach (unowned string scope_id in pref_man.disabled_scopes)
263 {
264 // using HashTable as a set (optimized in glib when done like this)
265 disabled_scope_ids[scope_id] = scope_id;
266 }
237 }267 }
238268
239 private void init_ratings_db ()269 private void init_ratings_db ()
@@ -251,9 +281,9 @@
251 ratings_db_initialized = true;281 ratings_db_initialized = true;
252 }282 }
253283
254 private async void dispatch_search (LensSearch lens_search,284 private async void dispatch_search (DeprecatedScopeSearch search,
255 SearchType search_type,285 SearchType search_type,
256 Cancellable cancellable)286 GLib.Cancellable cancellable)
257 {287 {
258 if (popularities_dirty)288 if (popularities_dirty)
259 {289 {
@@ -265,43 +295,45 @@
265 }295 }
266296
267 if (search_type == SearchType.DEFAULT)297 if (search_type == SearchType.DEFAULT)
268 yield update_scope_search (lens_search, cancellable);298 yield update_scope_search (search, cancellable);
269 else299 else
270 yield update_global_search (lens_search, cancellable);300 yield update_global_search (search, cancellable);
301
302 search.finished ();
271 }303 }
272304
273 private void populate_categories ()305 private void populate_categories ()
274 {306 {
275 GLib.List<Unity.Category> categories = new GLib.List<Unity.Category> ();307 Unity.CategorySet categories = new Unity.CategorySet ();
276 File icon_dir = File.new_for_path (ICON_PATH);308 File icon_dir = File.new_for_path (ICON_PATH);
277309
278 var cat = new Unity.Category (_("Applications"),310 var cat = new Unity.Category ("apps", _("Applications"),
279 new FileIcon (icon_dir.get_child ("group-apps.svg")));311 new FileIcon (icon_dir.get_child ("group-apps.svg")));
280 categories.append (cat);312 categories.add (cat);
281313
282 cat = new Unity.Category (_("Recently Used"),314 cat = new Unity.Category ("recently-used", _("Recently Used"),
283 new FileIcon (icon_dir.get_child ("group-recent.svg")));315 new FileIcon (icon_dir.get_child ("group-recent.svg")));
284 categories.append (cat);316 categories.add (cat);
285317
286 cat = new Unity.Category (_("Recent Apps"),318 cat = new Unity.Category ("recent", _("Recent Apps"),
287 new FileIcon (icon_dir.get_child ("group-apps.svg")));319 new FileIcon (icon_dir.get_child ("group-apps.svg")));
288 categories.append (cat);320 categories.add (cat);
289321
290 cat = new Unity.Category (_("Installed"),322 cat = new Unity.Category ("installed", _("Installed"),
291 new FileIcon (icon_dir.get_child ("group-installed.svg")));323 new FileIcon (icon_dir.get_child ("group-installed.svg")));
292 categories.append (cat);324 categories.add (cat);
293325
294 cat = new Unity.Category (_("More suggestions"),326 cat = new Unity.Category ("more", _("More suggestions"),
295 new FileIcon (icon_dir.get_child ("group-treat-yourself.svg")),327 new FileIcon (icon_dir.get_child ("group-treat-yourself.svg")),
296 Unity.CategoryRenderer.FLOW);328 Unity.CategoryRenderer.FLOW);
297 categories.append (cat);329 categories.add (cat);
298330
299 lens.categories = categories;331 scope.categories = categories;
300 }332 }
301333
302 private void populate_filters()334 private void populate_filters()
303 {335 {
304 GLib.List<Unity.Filter> filters = new GLib.List<Unity.Filter> ();336 Unity.FilterSet filters = new Unity.FilterSet ();
305337
306 /* Type filter */338 /* Type filter */
307 {339 {
@@ -320,25 +352,28 @@
320 filter.add_option ("accessibility", _("Accessibility"));352 filter.add_option ("accessibility", _("Accessibility"));
321 filter.add_option ("developer", _("Developer"));353 filter.add_option ("developer", _("Developer"));
322 filter.add_option ("science-and-engineering", _("Science & Engineering"));354 filter.add_option ("science-and-engineering", _("Science & Engineering"));
355 filter.add_option ("scopes", _("Search plugins"));
323 filter.add_option ("system", _("System"));356 filter.add_option ("system", _("System"));
324357
325 filters.append (filter);358 filters.add (filter);
326 }359 }
327360
328 lens.filters = filters;361 scope.filters = filters;
329 }362 }
330363
331 private bool local_apps_active ()364 private bool local_apps_active (DeprecatedScopeSearch search)
332 {365 {
333 if (scope.sources.filtering && local_apps_option != null)366 var filter = search.get_filter (scope.sources.id) as Unity.OptionsFilter;
334 return local_apps_option.active;367 if (filter.filtering && local_apps_option != null)
368 return filter.get_option (local_apps_option.id).active;
335 return true;369 return true;
336 }370 }
337371
338 private bool usc_apps_active ()372 private bool usc_apps_active (DeprecatedScopeSearch search)
339 {373 {
340 if (scope.sources.filtering && usc_apps_option != null)374 var filter = search.get_filter (scope.sources.id) as Unity.OptionsFilter;
341 return usc_apps_option.active;375 if (filter.filtering && usc_apps_option != null)
376 return filter.get_option (usc_apps_option.id).active;
342 return true;377 return true;
343 }378 }
344379
@@ -401,6 +436,15 @@
401 return false;436 return false;
402 }437 }
403438
439 private async void build_scope_index ()
440 {
441 var scope_registry = yield Unity.Protocol.ScopeRegistry.find_scopes (
442 Config.PKGDATADIR + "/scopes");
443
444 debug ("Indexing scopes");
445 scopesearcher = new Unity.Package.Searcher.for_scopes (scope_registry);
446 }
447
404 private void populate_zg_templates ()448 private void populate_zg_templates ()
405 {449 {
406 /* Create a template that activation of applications */450 /* Create a template that activation of applications */
@@ -430,7 +474,7 @@
430 zg_templates,474 zg_templates,
431 StorageState.ANY,475 StorageState.ANY,
432 256,476 256,
433 ResultType.MOST_POPULAR_SUBJECTS,477 Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,
434 null);478 null);
435479
436 // most popular apps must have high value, so unknown apps (where480 // most popular apps must have high value, so unknown apps (where
@@ -461,21 +505,22 @@
461 return app == null;505 return app == null;
462 }506 }
463507
464 private async void update_scope_search (Unity.LensSearch search,508 private async void update_scope_search (DeprecatedScopeSearch search,
465 Cancellable cancellable)509 GLib.Cancellable cancellable)
466 {510 {
467 var model = search.results_model;511 var model = search.results_model;
468 /* We'll clear the model once we finish waiting for the dbus-call512 /* We'll clear the model once we finish waiting for the dbus-call
469 * to finish, to prevent flicker. */513 * to finish, to prevent flicker. */
470514
471 debug ("Searching for: %s", search.search_string);515 var search_string = search.search_string.strip ();
472516 debug ("Searching for: %s", search_string);
473 var filter = scope.get_filter ("type") as OptionsFilter;517
474518 var type_filter = search.get_filter ("type") as OptionsFilter;
475 string pkg_search_string = XapianUtils.prepare_pkg_search_string (search.search_string, filter);519
476520 string pkg_search_string = XapianUtils.prepare_pkg_search_string (search_string, type_filter);
477 bool has_filter = (filter != null && filter.filtering);521
478 bool has_search = !Utils.is_search_empty (search.search_string);522 bool has_filter = (type_filter != null && type_filter.filtering);
523 bool has_search = !Utils.is_search_empty (search_string);
479524
480 Timer timer = new Timer ();525 Timer timer = new Timer ();
481526
@@ -494,7 +539,7 @@
494 has_search ?539 has_search ?
495 Unity.Package.Sort.BY_RELEVANCY :540 Unity.Package.Sort.BY_RELEVANCY :
496 Unity.Package.Sort.BY_NAME);541 Unity.Package.Sort.BY_NAME);
497 if (local_apps_active ())542 if (local_apps_active (search))
498 {543 {
499 if (has_search) resort_pkg_search_results (appresults);544 if (has_search) resort_pkg_search_results (appresults);
500 add_pkg_search_result (appresults, installed_uris, available_uris,545 add_pkg_search_result (appresults, installed_uris, available_uris,
@@ -505,7 +550,7 @@
505 debug ("Entry search listed %i Installed apps in %fms for query: %s",550 debug ("Entry search listed %i Installed apps in %fms for query: %s",
506 appresults.num_hits, timer.elapsed ()*1000, pkg_search_string);551 appresults.num_hits, timer.elapsed ()*1000, pkg_search_string);
507552
508 if (local_apps_active () && display_recent_apps)553 if (local_apps_active (search) && display_recent_apps)
509 {554 {
510 try555 try
511 {556 {
@@ -513,7 +558,7 @@
513 /* Ignore the search string, we want to keep displaying the same apps558 /* Ignore the search string, we want to keep displaying the same apps
514 * in the recent category and just filter out those that don't match559 * in the recent category and just filter out those that don't match
515 * the search query */560 * the search query */
516 var zg_search_string = XapianUtils.prepare_zg_search_string ("", filter);561 var zg_search_string = XapianUtils.prepare_zg_search_string ("", type_filter);
517562
518 var results = yield zg_index.search (zg_search_string,563 var results = yield zg_index.search (zg_search_string,
519 new Zeitgeist.TimeRange.anytime(),564 new Zeitgeist.TimeRange.anytime(),
@@ -535,16 +580,23 @@
535 // no need to bother580 // no need to bother
536 return;581 return;
537 } catch (GLib.Error e) {582 } catch (GLib.Error e) {
538 warning ("Error performing search '%s': %s", search.search_string, e.message);583 warning ("Error performing search '%s': %s", search_string, e.message);
539 }584 }
540 }585 }
541586
542 transaction.commit ();587 transaction.commit ();
543588
589 // add scopes (if filter is active)
590 if (!has_filter || type_filter.get_option ("scopes").active)
591 {
592 add_local_scopes_results (search_string, model, installed_uris);
593 add_remote_scopes_results (search_string, model);
594 }
595
544 purchase_info = new PurchaseInfoHelper ();596 purchase_info = new PurchaseInfoHelper ();
545597
546 /* If we don't have a search we display 6 random apps */598 /* If we don't have a search we display 6 random apps */
547 if (usc_apps_active () && display_available_apps && pkgsearcher != null)599 if (usc_apps_active (search) && display_available_apps && pkgsearcher != null)
548 {600 {
549 if (has_search)601 if (has_search)
550 {602 {
@@ -561,7 +613,7 @@
561 else if (has_filter) /* Empty search string + active filters should get lots of results from selected categories */613 else if (has_filter) /* Empty search string + active filters should get lots of results from selected categories */
562 {614 {
563 timer.start ();615 timer.start ();
564 string? filter_query = XapianUtils.prepare_pkg_search_string (search.search_string, filter);616 string? filter_query = XapianUtils.prepare_pkg_search_string (search_string, type_filter);
565617
566 var pkgresults = pkgsearcher.get_apps (filter_query, MAX_APP_FOR_DOWNLOAD_FOR_EMPTY_QUERY, filter_cb);618 var pkgresults = pkgsearcher.get_apps (filter_query, MAX_APP_FOR_DOWNLOAD_FOR_EMPTY_QUERY, filter_cb);
567 purchase_info.from_pkgresults (pkgresults);619 purchase_info.from_pkgresults (pkgresults);
@@ -610,19 +662,18 @@
610 search.set_reply_hint ("no-results-hint",662 search.set_reply_hint ("no-results-hint",
611 _("Sorry, there are no applications that match your search."));663 _("Sorry, there are no applications that match your search."));
612 }664 }
613
614 search.finished ();
615 }665 }
616666
617 private async void update_global_search (Unity.LensSearch search,667 private async void update_global_search (DeprecatedScopeSearch search,
618 Cancellable cancellable)668 GLib.Cancellable cancellable)
619 {669 {
620 /*670 /*
621 * In global search, with a non-empty search string, we collate all671 * In global search, with a non-empty search string, we collate all
622 * hits under one Applications category672 * hits under one Applications category
623 */673 */
674 var search_string = search.search_string.strip ();
624675
625 if (Utils.is_search_empty (search.search_string))676 if (Utils.is_search_empty (search_string))
626 {677 {
627 yield update_global_without_search (search, cancellable);678 yield update_global_without_search (search, cancellable);
628 return;679 return;
@@ -632,11 +683,11 @@
632683
633 model.clear ();684 model.clear ();
634685
635 var search_string = XapianUtils.prepare_pkg_search_string (search.search_string, null);686 var pkg_search_string = XapianUtils.prepare_pkg_search_string (search_string, null);
636 Set<string> installed_uris = new HashSet<string> ();687 Set<string> installed_uris = new HashSet<string> ();
637 Set<string> available_uris = new HashSet<string> ();688 Set<string> available_uris = new HashSet<string> ();
638 var timer = new Timer ();689 var timer = new Timer ();
639 var appresults = appsearcher.search (search_string, 0,690 var appresults = appsearcher.search (pkg_search_string, 0,
640 Unity.Package.SearchType.PREFIX,691 Unity.Package.SearchType.PREFIX,
641 Unity.Package.Sort.BY_RELEVANCY);692 Unity.Package.Sort.BY_RELEVANCY);
642 resort_pkg_search_results (appresults);693 resort_pkg_search_results (appresults);
@@ -645,17 +696,11 @@
645696
646 timer.stop ();697 timer.stop ();
647 debug ("Global search listed %i Installed apps in %fms for query: %s",698 debug ("Global search listed %i Installed apps in %fms for query: %s",
648 appresults.num_hits, timer.elapsed ()*1000, search_string);699 appresults.num_hits, timer.elapsed ()*1000, pkg_search_string);
649
650 /* Allow new searches once we enter an idle again.
651 * We don't do it directly from here as that could mean we start
652 * changing the model even before we had flushed out current changes
653 */
654 search.finished ();
655 }700 }
656701
657 private async void update_global_without_search (Unity.LensSearch search,702 private async void update_global_without_search (DeprecatedScopeSearch search,
658 Cancellable cancellable)703 GLib.Cancellable cancellable)
659 {704 {
660 /*705 /*
661 * In global search, with an empty search string, we show just Recent Apps706 * In global search, with an empty search string, we show just Recent Apps
@@ -665,12 +710,12 @@
665710
666 Timer timer = new Timer ();711 Timer timer = new Timer ();
667712
668 if (local_apps_active () && display_recent_apps)713 if (local_apps_active (search) && display_recent_apps)
669 {714 {
670 try715 try
671 {716 {
672 var zg_search_string = XapianUtils.prepare_zg_search_string (search.search_string,717 var zg_search_string = XapianUtils.prepare_zg_search_string ("",
673 null);718 null);
674719
675 var time_range = new Zeitgeist.TimeRange.anytime ();720 var time_range = new Zeitgeist.TimeRange.anytime ();
676 var results = yield log.find_events (time_range,721 var results = yield log.find_events (time_range,
@@ -697,8 +742,6 @@
697 search.search_string, e.message);742 search.search_string, e.message);
698 }743 }
699 }744 }
700
701 search.finished ();
702 }745 }
703746
704 public Icon find_pkg_icon (string? desktop_file, string icon_name)747 public Icon find_pkg_icon (string? desktop_file, string icon_name)
@@ -871,10 +914,12 @@
871914
872 model.append (uri, icon_obj,915 model.append (uri, icon_obj,
873 category,916 category,
917 pinfo != null && pinfo.paid ? Unity.ResultType.PERSONAL : Unity.ResultType.DEFAULT,
874 "application/x-desktop",918 "application/x-desktop",
875 app.application_name,919 app.application_name,
876 "", //comment920 "", //comment
877 "file://" + app.desktop_file);921 "file://" + app.desktop_file,
922 empty_asv);
878 duplicates_lookup.add (uri);923 duplicates_lookup.add (uri);
879 i++;924 i++;
880 if (i == max_results)925 if (i == max_results)
@@ -968,11 +1013,16 @@
968 icon_str = icon.to_string ();1013 icon_str = icon.to_string ();
969 }1014 }
9701015
1016 var result_type = (category == Category.INSTALLED && !results.fuzzy_search) ?
1017 Unity.ResultType.PERSONAL : Unity.ResultType.DEFAULT;
971 model.append (uri, icon_str,1018 model.append (uri, icon_str,
972 category,"application/x-desktop",1019 category,
1020 result_type,
1021 "application/x-desktop",
973 display_name != null ? display_name : "",1022 display_name != null ? display_name : "",
974 comment != null ? comment : "",1023 comment != null ? comment : "",
975 full_path != null ? "file://" + full_path : "");1024 full_path != null ? "file://" + full_path : "",
1025 empty_asv);
9761026
977 /* Stop if we added the number of items requested */1027 /* Stop if we added the number of items requested */
978 n_added++;1028 n_added++;
@@ -981,6 +1031,124 @@
981 }1031 }
982 }1032 }
9831033
1034 private static Icon? get_default_scope_icon ()
1035 {
1036 try
1037 {
1038 return Icon.new_for_string (GENERIC_SCOPE_ICON);
1039 }
1040 catch (Error err)
1041 {
1042 warning ("%s", err.message);
1043 }
1044 return null;
1045 }
1046
1047 private void add_local_scopes_results (string search_string,
1048 Dee.Model model,
1049 Set<string> installed_uris)
1050 {
1051 // If the local scopes Xapian index hasn't been built, return.
1052 if (scopesearcher == null)
1053 return;
1054
1055 bool has_search = !Utils.is_search_empty (search_string);
1056 var pkg_search_string = XapianUtils.prepare_pkg_search_string (
1057 search_string, null);
1058
1059 var results = scopesearcher.search (pkg_search_string, 0,
1060 Unity.Package.SearchType.PREFIX,
1061 has_search ?
1062 Unity.Package.Sort.BY_RELEVANCY :
1063 Unity.Package.Sort.BY_NAME);
1064
1065 foreach (unowned Unity.Package.PackageInfo info in results.results)
1066 {
1067 /* De-dupe by "application://foo.scope", since that is what is
1068 * used for software-center results. */
1069 string dedup_key = @"application://$(info.desktop_file)";
1070 if (dedup_key in installed_uris)
1071 continue;
1072 installed_uris.add(dedup_key);
1073
1074 /* Don't include master scopes in the search results. This is
1075 * performed after deduping so the master scopes don't just
1076 * move to hte "available" category. */
1077 if (info.is_master_scope)
1078 continue;
1079
1080 var uri = @"scope://$(info.desktop_file)";
1081 var name = info.application_name;
1082 var icon_hint = info.icon;
1083 var category = info.desktop_file in disabled_scope_ids ?
1084 Category.AVAILABLE : Category.INSTALLED;
1085
1086 try
1087 {
1088 Icon base_icon = icon_hint == null || icon_hint == "" ?
1089 get_default_scope_icon () : Icon.new_for_string (icon_hint);
1090 var anno_icon = new AnnotatedIcon (base_icon);
1091 anno_icon.size_hint = IconSizeHint.SMALL;
1092 icon_hint = anno_icon.to_string ();
1093 }
1094 catch (Error err)
1095 {
1096 icon_hint = "";
1097 }
1098
1099 model.append (uri,
1100 icon_hint,
1101 category,
1102 ResultType.DEFAULT,
1103 "application/x-unity-scope",
1104 name != "" ? name : uri,
1105 "",
1106 "", // dnd_uri ?!
1107 empty_asv);
1108 }
1109 }
1110
1111 private void add_remote_scopes_results (string search_string,
1112 Dee.Model model)
1113 {
1114 var results = Utils.search_index (scopes_index, analyzer, search_string);
1115 foreach (var iter in results)
1116 {
1117 unowned string scope_id =
1118 remote_scopes_model.get_string (iter, RemoteScopesColumn.SCOPE_ID);
1119 var uri = @"scope://$(scope_id)";
1120 var name =
1121 remote_scopes_model.get_string (iter, RemoteScopesColumn.NAME);
1122 var icon_hint =
1123 remote_scopes_model.get_string (iter, RemoteScopesColumn.ICON_HINT);
1124
1125 try
1126 {
1127 Icon base_icon = icon_hint == null || icon_hint == "" ?
1128 get_default_scope_icon () : Icon.new_for_string (icon_hint);
1129 var anno_icon = new AnnotatedIcon (base_icon);
1130 anno_icon.size_hint = IconSizeHint.SMALL;
1131 icon_hint = anno_icon.to_string ();
1132 }
1133 catch (Error err)
1134 {
1135 icon_hint = "";
1136 }
1137
1138 var category = scope_id in disabled_scope_ids ?
1139 Category.AVAILABLE : Category.INSTALLED;
1140
1141 model.append (uri,
1142 icon_hint,
1143 category,
1144 ResultType.DEFAULT,
1145 "application/x-unity-scope",
1146 name != "" ? name : uri,
1147 "",
1148 "", // dnd_uri ?!
1149 empty_asv);
1150 }
1151 }
984 private async void call_install_packages (string package_name, out string tid) throws IOError1152 private async void call_install_packages (string package_name, out string tid) throws IOError
985 {1153 {
986 tid = yield aptdclient.install_packages ({package_name});1154 tid = yield aptdclient.install_packages ({package_name});
@@ -1141,74 +1309,308 @@
11411309
1142 public Unity.Preview preview (string uri)1310 public Unity.Preview preview (string uri)
1143 {1311 {
1312 Unity.Preview? preview = null;
1313 bool installed = uri.has_prefix ("application://");
1314 bool is_scope = uri.has_prefix ("scope://");
1315
1316 if (installed || uri.has_prefix ("unity-install://"))
1317 {
1318 preview = make_app_preview (uri, installed);
1319 }
1320 else if (is_scope)
1321 {
1322 preview = make_scope_preview (uri);
1323 }
1324 return preview;
1325 }
1326
1327 private SoftwareCenterData.AppDetailsData get_app_details (string appname, string pkgname) throws Error
1328 {
1329 if (sc_data_provider == null)
1330 {
1331 sc_data_provider = new SoftwareCenterDataCache (TOP_RATED_ITEMS_CACHE_LIFETIME);
1332 sc_data_provider.connect_to ();
1333 }
1334
1335 debug ("Requesting pkg info: %s, %s\n", pkgname, appname);
1336 return sc_data_provider.get_app_details (appname, pkgname);
1337 }
1338
1339 private Unity.Preview make_app_preview (string uri, bool installed)
1340 {
1144 Unity.ApplicationPreview? preview = null;1341 Unity.ApplicationPreview? preview = null;
11451342 string desktopfile = null;
1146 string pkgname = "";1343 string pkgname = "";
1147 string appname = "";1344 string appname = "";
1148 bool installed = uri.has_prefix ("application://");1345
11491346 if (installed)
1150 if (installed || uri.has_prefix ("unity-install://"))1347 {
1151 {1348 desktopfile = uri.substring (14); //remove "application://" prefix
1152 string desktopfile = null;1349
1153 if (installed)1350 // de-mangle desktop file names back to what S-C expects
1154 {1351 if (sc_mangler.contains (desktopfile))
1155 desktopfile = uri.substring (14); //remove "application://" prefix1352 {
11561353 desktopfile = sc_mangler.get (desktopfile);
1157 // de-mangle desktop file names back to what S-C expects1354 }
1158 if (sc_mangler.contains (desktopfile))1355
1159 {1356 Unity.Package.PackageInfo pkginfo = pkgsearcher.get_by_desktop_file (desktopfile);
1160 desktopfile = sc_mangler.get (desktopfile);1357 if (pkginfo != null)
1161 }1358 {
11621359 appname = pkginfo.application_name;
1163 Unity.Package.PackageInfo pkginfo = pkgsearcher.get_by_desktop_file (desktopfile);1360 pkgname = pkginfo.package_name;
1164 if (pkginfo != null)1361 }
1165 {1362 }
1166 appname = pkginfo.application_name;1363 else // unity-install
1167 pkgname = pkginfo.package_name;1364 {
1168 }1365 string app = uri.substring (16); //remove "unity-install://" prefix
1169 }1366 string[] parts = app.split ("/");
1170 else // unity-install1367 if (parts.length > 1)
1171 {1368 {
1172 string app = uri.substring (16); //remove "unity-install://" prefix1369 pkgname = parts[0];
1173 string[] parts = app.split ("/");1370 appname = parts[1];
1174 if (parts.length > 1)1371 }
1175 {1372 }
1176 pkgname = parts[0];1373
1177 appname = parts[1];1374 if (pkgname != "")
1178 }1375 {
1179 }1376 try {
11801377 var details = get_app_details (appname, pkgname);
1181 if (pkgname != "")1378
1182 {1379 Icon? icon = null;
1380 if (installed)
1381 icon = new GLib.ThemedIcon (details.icon);
1382 else
1383 {
1384 icon = find_pkg_icon (null, details.icon);
1385 if (icon.to_string () == GENERIC_APP_ICON && details.icon_url != null && details.icon_url != "")
1386 {
1387 icon = new GLib.FileIcon (File.new_for_uri (details.icon_url));
1388 }
1389 }
1390
1391 Icon? screenshot = null;
1392
1393 if (details.screenshot != null)
1394 {
1395 File scr_file = File.new_for_uri (details.screenshot);
1396 screenshot = new FileIcon (scr_file);
1397 }
1398
1399 string subtitle = "";
1400 if (details.version != "")
1401 subtitle = _("Version %s").printf (details.version);
1402 if (details.size > 0)
1403 {
1404 if (subtitle != "")
1405 subtitle += ", ";
1406 subtitle += ("Size %s").printf (GLib.format_size (details.size));
1407 }
1408 preview = new Unity.ApplicationPreview (details.name, subtitle, details.description, icon, screenshot);
1409 preview.license = details.license;
1410
1411 init_ratings_db ();
1412 if (ratings != null)
1413 {
1414 Unity.Ratings.Result result;
1415 ratings.query (pkgname, out result);
1416 preview.set_rating (result.average_rating / 5.0f, result.total_rating);
1417 }
1418
1419 if (details.hardware_requirements != "")
1420 preview.add_info (new InfoHint ("hardware-requirements", _("Hardware requirements"), null, details.hardware_requirements));
1421
1422 if (uri.has_prefix ("unity-install://")) // application needs to be purchased/installed
1423 {
1424 // uninstalled and not purchased before
1425 if (details.pkg_state == SoftwareCenterData.PackageState.NEEDS_PURCHASE)
1426 {
1427 var buy_action = new Unity.PreviewAction ("buy", _("Buy"), null);
1428 if (details.price != null && details.price != "")
1429 {
1430 buy_action.extra_text = details.price;
1431 }
1432
1433 buy_action.activated.connect (start_software_center);
1434 preview.add_action (buy_action);
1435 }
1436 else // uninstalled, purchased before
1437 {
1438
1439 Unity.PreviewAction install_action = null;
1440 if (details.raw_price == null || details.raw_price == "")
1441 {
1442 install_action = new Unity.PreviewAction ("install", _("Free Download"), null);
1443 install_action.activated.connect (app_preview_install);
1444 }
1445 else
1446 {
1447 install_action = new Unity.PreviewAction ("install", _("Install"), null);
1448 install_action.activated.connect (start_software_center);
1449 }
1450 preview.add_action (install_action);
1451 }
1452
1453 if (details.website != null && details.website != "")
1454 {
1455 preview_developer_website = details.website;
1456 var website_action = new Unity.PreviewAction ("website", _("Developer Site"), null);
1457 website_action.activated.connect (app_preview_website);
1458 preview.add_action (website_action);
1459 }
1460 }
1461 else // application is already installed
1462 {
1463 preview.add_info (new InfoHint ("date-installed", _("Installed on"), null, details.installation_date));
1464 var launch_action = new Unity.PreviewAction ("launch", _("Launch"), null);
1465 preview.add_action (launch_action);
1466 if (!details.is_desktop_dependency)
1467 {
1468 var uninstall_action = new Unity.PreviewAction ("uninstall", _("Uninstall"), null);
1469 uninstall_action.activated.connect (app_preview_uninstall);
1470 preview.add_action (uninstall_action);
1471 }
1472 }
1473
1474 preview_installable_desktop_file = details.desktop_file;
1475 preview_installable_icon_file = details.icon;
1476 }
1477 catch (Error e)
1478 {
1479 warning ("Failed to get package details for '%s': %s", uri, e.message);
1480 preview = null;
1481 }
1482 }
1483
1484 // xapian db doesn't know this .desktop file or S-C dbus data provider fails,
1485 // fallback to DesktopAppInfo (based on installed .desktop file) if available
1486 if (preview == null && desktopfile != null)
1487 {
1488 var app_info = new DesktopAppInfo (desktopfile);
1489 if (app_info != null)
1490 {
1491 preview = new Unity.ApplicationPreview (app_info.get_display_name (), "", app_info.get_description () ?? "", app_info.get_icon (), null);
1492 var launch_action = new Unity.PreviewAction ("launch", _("Launch"), null);
1493 preview.add_action (launch_action);
1494 }
1495 }
1496
1497 if (preview == null)
1498 {
1499 warning ("No pksearcher nor desktop app info for '%s'", uri);
1500 }
1501 return preview;
1502 }
1503
1504 private Unity.Preview make_scope_preview(string uri)
1505 {
1506 Unity.ApplicationPreview? preview = null;
1507 var scope_id = uri.substring (8);
1508 bool scope_disabled = scope_id in disabled_scope_ids;
1509
1510 // figure out if the scope is remote
1511 bool is_remote_scope = false;
1512 var info = scopesearcher.get_by_desktop_file (scope_id);
1513
1514 Dee.ModelIter found_iter = null;
1515 if (info == null)
1516 {
1517 var iter = remote_scopes_model.get_first_iter ();
1518 var end_iter = remote_scopes_model.get_last_iter ();
1519 while (iter != end_iter)
1520 {
1521 if (remote_scopes_model.get_string (iter, 0) == scope_id)
1522 {
1523 is_remote_scope = true;
1524 found_iter = iter;
1525 break;
1526 }
1527 iter = remote_scopes_model.next (iter);
1528 }
1529 }
1530
1531 if (is_remote_scope)
1532 {
1533 var name = remote_scopes_model.get_string (found_iter, 1);
1534 if (name == null || name == "")
1535 name = remote_scopes_model.get_string (found_iter, 0);
1536 var description = remote_scopes_model.get_string (found_iter, 2);
1537 if (description != null)
1538 description = Markup.escape_text(description);
1539 Icon? icon = null;
1540 Icon? screenshot = null;
1541 var icon_hint = remote_scopes_model.get_string (found_iter, 3);
1542 var screenshot_url = remote_scopes_model.get_string (found_iter, 4);
1543 try
1544 {
1545 if (icon_hint != "") icon = Icon.new_for_string (icon_hint);
1546 if (screenshot_url != "") screenshot = Icon.new_for_string (screenshot_url);
1547 }
1548 catch (Error err)
1549 {
1550 warning ("%s", err.message);
1551 }
1552
1553 if (icon == null) icon = get_default_scope_icon ();
1554
1555 preview = new Unity.ApplicationPreview (name,
1556 "",
1557 description,
1558 icon,
1559 screenshot);
1560 }
1561 else if (info != null)
1562 {
1563 var name = info.application_name;
1564 if (name == null || name == "")
1565 name = info.desktop_file;
1566 var subtitle = "";
1567 var description = info.description;
1568 if (description != null)
1569 description = Markup.escape_text(description);
1570 Icon? icon = null;
1571 Icon? screenshot = null;
1572 try
1573 {
1574 if (info.icon != null && info.icon != "")
1575 icon = Icon.new_for_string (info.icon);
1576 }
1577 catch (Error err)
1578 {
1579 warning ("%s", err.message);
1580 }
1581 if (icon == null)
1582 icon = get_default_scope_icon ();
1583
1584 // de-mangle desktop file names back to what S-C expects
1585 string mangled_id;
1586 if (sc_mangler.contains (scope_id))
1587 {
1588 mangled_id = sc_mangler.get (scope_id);
1589 }
1590 else
1591 {
1592 mangled_id = scope_id;
1593 }
1594
1595 Unity.Package.PackageInfo pkginfo = pkgsearcher.get_by_desktop_file (mangled_id);
1596 if (pkginfo != null)
1597 {
1598 SoftwareCenterData.AppDetailsData? details;
1183 try {1599 try {
1184 if (sc_data_provider == null)1600 details = get_app_details(pkginfo.application_name,
1185 {1601 pkginfo.package_name);
1186 sc_data_provider = new SoftwareCenterDataCache (TOP_RATED_ITEMS_CACHE_LIFETIME);1602 } catch (Error e) {
1187 sc_data_provider.connect_to ();1603 details = null;
1188 }1604 }
11891605 if (details != null) {
1190 debug ("Requesting pkg info: %s, %s\n", pkgname, appname);1606 if (details.version != "")
1191 var details = sc_data_provider.get_app_details (appname, pkgname);1607 subtitle = _("Version %s").printf (details.version);
1192
1193 Icon? icon = null;
1194 if (installed)
1195 icon = new GLib.ThemedIcon (details.icon);
1196 else
1197 {
1198 icon = find_pkg_icon (null, details.icon);
1199 if (icon.to_string () == GENERIC_APP_ICON && details.icon_url != null && details.icon_url != "")
1200 {
1201 icon = new GLib.FileIcon (File.new_for_uri (details.icon_url));
1202 }
1203 }
1204
1205 Icon? screenshot = null;
1206
1207 if (details.screenshot != null)1608 if (details.screenshot != null)
1208 {1609 {
1209 File scr_file = File.new_for_uri (details.screenshot);1610 File scr_file = File.new_for_uri (details.screenshot);
1210 screenshot = new FileIcon (scr_file);1611 screenshot = new FileIcon (scr_file);
1211 }1612 }
1613<<<<<<< TREE
12121614
1213 string subtitle = "";1615 string subtitle = "";
1214 if (details.version != "")1616 if (details.version != "")
@@ -1312,10 +1714,72 @@
1312 {1714 {
1313 warning ("No pksearcher nor desktop app info for '%s'", uri);1715 warning ("No pksearcher nor desktop app info for '%s'", uri);
1314 }1716 }
1717=======
1718 }
1719 }
1720
1721 preview = new Unity.ApplicationPreview (name,
1722 subtitle,
1723 description,
1724 icon,
1725 screenshot);
1726 }
1727 if (preview != null && scope_id != "home.scope" &&
1728 scope_id != "applications.scope")
1729 {
1730 PreviewAction action;
1731 preview.set_rating(-1.0f, 0);
1732 if (scope_disabled)
1733 {
1734 action = new Unity.PreviewAction ("enable-scope", _("Enable"), null);
1735 action.activated.connect (() =>
1736 {
1737 enable_scope (scope_id);
1738 return new ActivationResponse.with_preview (this.preview (uri));
1739 });
1740 }
1741 else
1742 {
1743 action = new Unity.PreviewAction ("disable-scope", _("Disable"), null);
1744 action.activated.connect (() =>
1745 {
1746 disable_scope (scope_id);
1747 return new ActivationResponse.with_preview (this.preview (uri));
1748 });
1749 }
1750 preview.add_action (action);
1751>>>>>>> MERGE-SOURCE
1315 }1752 }
1316 return preview;1753 return preview;
1317 }1754 }
13181755
1756 private void disable_scope (string scope_id)
1757 {
1758 if (scope_id in disabled_scope_ids) return;
1759
1760 var pref_man = PreferencesManager.get_default ();
1761 var disabled_scopes = pref_man.disabled_scopes;
1762 disabled_scopes += scope_id;
1763
1764 var settings = new Settings (LIBUNITY_SCHEMA);
1765 settings.set_strv ("disabled-scopes", disabled_scopes);
1766 }
1767
1768 private void enable_scope (string scope_id)
1769 {
1770 if (!(scope_id in disabled_scope_ids)) return;
1771
1772 var pref_man = PreferencesManager.get_default ();
1773 string[] disabled_scopes = {};
1774 foreach (unowned string disabled_scope_id in pref_man.disabled_scopes)
1775 {
1776 if (disabled_scope_id != scope_id)
1777 disabled_scopes += disabled_scope_id;
1778 }
1779
1780 var settings = new Settings (LIBUNITY_SCHEMA);
1781 settings.set_strv ("disabled-scopes", disabled_scopes);
1782 }
1319 /**1783 /**
1320 * Override of the default activation handler. The apps lens daemon1784 * Override of the default activation handler. The apps lens daemon
1321 * can handle activation of installable apps using the Software Center1785 * can handle activation of installable apps using the Software Center
@@ -1324,7 +1788,7 @@
1324 {1788 {
1325 string[] args;1789 string[] args;
1326 string exec_or_dir = null;1790 string exec_or_dir = null;
1327 if (uri.has_prefix ("unity-install://"))1791 if (uri.has_prefix ("unity-install://") || uri.has_prefix ("scope://"))
1328 {1792 {
1329 var prv = preview (uri);1793 var prv = preview (uri);
1330 if (prv != null)1794 if (prv != null)
@@ -1334,7 +1798,7 @@
1334 else1798 else
1335 {1799 {
1336 warning ("Failed to generate preview for %s", uri);1800 warning ("Failed to generate preview for %s", uri);
1337 return new Unity.ActivationResponse(Unity.HandledType.NOT_HANDLED);1801 return new Unity.ActivationResponse (Unity.HandledType.NOT_HANDLED);
1338 }1802 }
1339 }1803 }
1340 else if (uri.has_prefix ("unity-runner://"))1804 else if (uri.has_prefix ("unity-runner://"))
@@ -1462,9 +1926,12 @@
1462 string full_path = appmanager.get_path (desktop_id);1926 string full_path = appmanager.get_path (desktop_id);
1463 string full_uri = full_path != null ? "file://" + full_path : app_uri;1927 string full_uri = full_path != null ? "file://" + full_path : app_uri;
14641928
1465 results.append (app_uri, app.get_icon().to_string(), category_id,1929 results.append (app_uri, app.get_icon().to_string(),
1930 category_id, Unity.ResultType.DEFAULT,
1466 "application/x-desktop", app.get_display_name (),1931 "application/x-desktop", app.get_display_name (),
1467 sanitize_binary_name (app.get_executable ()), full_uri);1932 sanitize_binary_name (app.get_executable ()),
1933 full_uri,
1934 empty_asv);
1468 }1935 }
1469 }1936 }
14701937
14711938
=== modified file 'src/main.vala'
--- src/main.vala 2011-10-06 12:25:59 +0000
+++ src/main.vala 2013-05-08 13:32:23 +0000
@@ -22,6 +22,7 @@
2222
23namespace Unity.ApplicationsLens {23namespace Unity.ApplicationsLens {
2424
25 const string DBUS_NAME = "com.canonical.Unity.Scope.Applications";
25 static Application? app = null;26 static Application? app = null;
26 static Daemon? daemon = null;27 static Daemon? daemon = null;
2728
@@ -71,7 +72,7 @@
71 * making it race against GDBus' worker thread to export our72 * making it race against GDBus' worker thread to export our
72 * objects on the bus before/after owning our name and receiving73 * objects on the bus before/after owning our name and receiving
73 * method calls on our objects (which may not yet be up!)*/74 * method calls on our objects (which may not yet be up!)*/
74 if (dbus_name_has_owner ("com.canonical.Unity.Lens.Applications"))75 if (dbus_name_has_owner (DBUS_NAME))
75 {76 {
76 print ("Another instance of the Unity Applications Daemon " +77 print ("Another instance of the Unity Applications Daemon " +
77 "already appears to be running.\nBailing out.\n");78 "already appears to be running.\nBailing out.\n");
@@ -83,8 +84,7 @@
83 daemon = new Daemon ();84 daemon = new Daemon ();
84 85
85 /* Use GApplication directly for single instance app functionality */86 /* Use GApplication directly for single instance app functionality */
86 app = new Application ("com.canonical.Unity.Lens.Applications",87 app = new Application (DBUS_NAME, ApplicationFlags.IS_SERVICE);
87 ApplicationFlags.IS_SERVICE);
88 try {88 try {
89 app.register ();89 app.register ();
90 } catch (Error e) {90 } catch (Error e) {
@@ -93,7 +93,7 @@
93 print ("Failed to start applications daemon: %s\n", e.message);93 print ("Failed to start applications daemon: %s\n", e.message);
94 return 1;94 return 1;
95 }95 }
96 96
97 if (app.get_is_remote ())97 if (app.get_is_remote ())
98 {98 {
99 print ("Another instance of the Unity Applications Daemon " +99 print ("Another instance of the Unity Applications Daemon " +
100100
=== modified file 'src/runner.vala'
--- src/runner.vala 2012-11-05 19:18:41 +0000
+++ src/runner.vala 2013-05-08 13:32:23 +0000
@@ -27,7 +27,7 @@
27 public string name;27 public string name;
28 public string exec;28 public string exec;
29 public Icon icon;29 public Icon icon;
30 30
31 public AboutEntry (string name, string exec, Icon icon)31 public AboutEntry (string name, string exec, Icon icon)
32 {32 {
33 this.name = name;33 this.name = name;
@@ -37,30 +37,33 @@
37 }37 }
3838
39 public class Runner: GLib.Object39 public class Runner: GLib.Object
40 { 40 {
41 41
42 private Unity.ApplicationsLens.Daemon daemon; 42 private Unity.ApplicationsLens.Daemon daemon;
43 private const string BUS_NAME_PREFIX = "com.canonical.Unity.ApplicationsLens.Runner";43 private const string BUS_NAME_PREFIX = "com.canonical.Unity.ApplicationsLens.Runner";
44 44
45 /* for now, load the same keys as gnome-panel */45 /* for now, load the same keys as gnome-panel */
46 private const string HISTORY_KEY = "history";46 private const string HISTORY_KEY = "history";
47 private const int MAX_HISTORY = 10;47 private const int MAX_HISTORY = 10;
48 48
49 public Unity.Lens lens;49 public Unity.DeprecatedScope scope;
50 public Unity.Scope scope;
5150
52 private Gee.HashMap<string,AboutEntry> about_entries;51 private Gee.HashMap<string,AboutEntry> about_entries;
53 private Gee.List<string> history;52 private Gee.List<string> history;
54 private ExecSearcher exec_searcher = new ExecSearcher ();53 private ExecSearcher exec_searcher = new ExecSearcher ();
5554
56 private Settings gp_settings;55 private Settings gp_settings;
57 56
58 public Runner (Unity.ApplicationsLens.Daemon daemon)57 public Runner (Unity.ApplicationsLens.Daemon daemon)
59 {58 {
60 /* First create scope */59 /* First create scope */
61 scope = new Unity.Scope ("/com/canonical/unity/scope/commands");60 scope = new Unity.DeprecatedScope ("/com/canonical/unity/scope/commands",
61 "commands");
62 scope.search_in_global = false;62 scope.search_in_global = false;
63 63 scope.search_hint = _("Run a command");
64 scope.visible = false;
65 populate_categories ();
66
64 /* Listen for changes to the lens scope search */67 /* Listen for changes to the lens scope search */
65 scope.search_changed.connect ((lens_search, search_type, cancellable) =>68 scope.search_changed.connect ((lens_search, search_type, cancellable) =>
66 {69 {
@@ -73,56 +76,53 @@
73 return lens_search.search_string.strip ();76 return lens_search.search_string.strip ();
74 });77 });
7578
76 // Listen for when the lens is hidden/shown by the Unity Shell
77 scope.notify["active"].connect(() =>
78 {
79 if (scope.active)
80 {
81 scope.queue_search_changed (SearchType.DEFAULT);
82 }
83 });
84
85 scope.activate_uri.connect (daemon.activate);79 scope.activate_uri.connect (daemon.activate);
8680
87 /* Now create Lens */
88 lens = new Unity.Lens ("/com/canonical/unity/lens/commands", "commands");
89 lens.search_hint = _("Run a command");
90 lens.visible = false;
91 lens.search_in_global = false;
92 populate_categories ();
93 //populate_filters();
94 lens.add_local_scope (scope);
95 lens.export ();
96
97 /* create the private about entries */81 /* create the private about entries */
98 about_entries = new Gee.HashMap<string,AboutEntry> ();82 about_entries = new Gee.HashMap<string,AboutEntry> ();
99 load_about_entries ();83 load_about_entries ();
100 84
101 this.gp_settings = new Settings ("com.canonical.Unity.Runner");85 this.gp_settings = new Settings ("com.canonical.Unity.Runner");
102 history = new Gee.ArrayList<string> ();86 history = new Gee.ArrayList<string> ();
103 load_history ();87 load_history ();
104 88
105 this.daemon = daemon;89 this.daemon = daemon;
106 90
91 scope.export ();
107 }92 }
10893
109 private void populate_categories ()94 private void populate_categories ()
110 {95 {
111 var categories = new GLib.List<Unity.Category> ();96 var categories = new Unity.CategorySet ();
112 var icon_dir = File.new_for_path (ICON_PATH);97 var icon_dir = File.new_for_path (ICON_PATH);
113 var cat = new Unity.Category (_("Results"),98 var cat = new Unity.Category ("results", _("Results"),
114 new FileIcon (icon_dir.get_child ("group-installed.svg")));99 new FileIcon (icon_dir.get_child ("group-installed.svg")));
115 categories.append (cat);100 categories.add (cat);
116101
117 cat = new Unity.Category (_("History"),102 cat = new Unity.Category ("history", _("History"),
118 new FileIcon (icon_dir.get_child ("group-available.svg")));103 new FileIcon (icon_dir.get_child ("group-available.svg")));
119104
120 categories.append (cat);105 categories.add (cat);
121106
122 lens.categories = categories;107 scope.categories = categories;
123 }108 }
124109
125 private async void update_search (LensSearch search)110 private void add_result (Dee.Model model, string uri, string icon_hint,
111 uint category_id, string mimetype, string title)
112 {
113 Variant row_data[9];
114 model.append_row (
115 model.build_named_row_static (row_data, "uri", uri,
116 "icon_hint", icon_hint,
117 "category", category_id,
118 "result_type", ResultType.DEFAULT,
119 "mimetype", mimetype,
120 "title", title,
121 "comment", "",
122 "dnd_uri", uri));
123 }
124
125 private async void update_search (DeprecatedScopeSearch search)
126 {126 {
127 var model = search.results_model;127 var model = search.results_model;
128 var executables_match = new Gee.ArrayList<string> ();128 var executables_match = new Gee.ArrayList<string> ();
@@ -132,19 +132,17 @@
132 var search_string = search.search_string;132 var search_string = search.search_string;
133 bool has_search = !Utils.is_search_empty (search.search_string);133 bool has_search = !Utils.is_search_empty (search.search_string);
134134
135 string uri; 135 string uri;
136 Icon icon;136 Icon icon;
137 string mimetype;137 string mimetype;
138 string display_name;138 string display_name;
139 var category_id = RunnerCategory.HISTORY;139 var category_id = RunnerCategory.HISTORY;
140140
141 foreach (var command in this.history)141 foreach (var command in this.history)
142 { 142 {
143 display_name = get_icon_uri_and_mimetype (command, out icon, out uri, out mimetype); 143 display_name = get_icon_uri_and_mimetype (command, out icon, out uri, out mimetype);
144 model.append (uri, icon.to_string (),144 add_result (model, uri, icon.to_string (), category_id, mimetype,
145 category_id, mimetype,145 display_name);
146 display_name,
147 null);
148 }146 }
149147
150 if (!has_search)148 if (!has_search)
@@ -154,34 +152,30 @@
154 }152 }
155153
156 Timer timer = new Timer ();154 Timer timer = new Timer ();
157 155
158 /* no easter egg in unity */156 /* no easter egg in unity */
159 if (search_string == "free the fish")157 if (search_string == "free the fish")
160 {158 {
161 uri = "no-easter-egg";159 uri = "about:blank";
162 string commenteaster = _("There is no easter egg in Unity");160 string commenteaster = _("There is no easter egg in Unity");
163 icon = new ThemedIcon ("gnome-panel-fish");161 icon = new ThemedIcon ("gnome-panel-fish");
164 model.append (uri, icon.to_string (),162 add_result (model, uri, icon.to_string (), 0, "text/plain",
165 0, "no-mime",163 commenteaster);
166 commenteaster,
167 null);
168 search.finished ();164 search.finished ();
169 return;165 return;
170 }166 }
171 else if (search_string == "gegls from outer space")167 else if (search_string == "gegls from outer space")
172 {168 {
173 uri = "really-no-easter-egg";169 uri = "about:blank";
174 string commentnoeaster = _("Still no easter egg in Unity");170 string commentnoeaster = _("Still no easter egg in Unity");
175 icon = new ThemedIcon ("gnome-panel-fish");171 icon = new ThemedIcon ("gnome-panel-fish");
176 model.append (uri, icon.to_string (),172 add_result (model, uri, icon.to_string (), 0, "text/plain",
177 0, "no-mime",173 commentnoeaster);
178 commentnoeaster,
179 null);
180 search.finished ();174 search.finished ();
181 return;175 return;
182 176
183 }177 }
184 178
185 /* manual seek with directory and executables result */179 /* manual seek with directory and executables result */
186 if (search_string.has_prefix ("/") || search_string.has_prefix ("~"))180 if (search_string.has_prefix ("/") || search_string.has_prefix ("~"))
187 {181 {
@@ -189,7 +183,7 @@
189 var search_dirname = Path.get_dirname (search_string);183 var search_dirname = Path.get_dirname (search_string);
190 var directory = File.new_for_path (search_dirname);184 var directory = File.new_for_path (search_dirname);
191 var search_dirname_in_path = false;185 var search_dirname_in_path = false;
192 186
193 /* strip path_directory if in executable in path */187 /* strip path_directory if in executable in path */
194 foreach (var path_directory in Environment.get_variable ("PATH").split(":"))188 foreach (var path_directory in Environment.get_variable ("PATH").split(":"))
195 {189 {
@@ -208,7 +202,7 @@
208 var subelem_info = iterator.next_file ();202 var subelem_info = iterator.next_file ();
209 if (subelem_info == null)203 if (subelem_info == null)
210 break;204 break;
211 205
212 var complete_path = Path.build_filename (search_dirname, subelem_info.get_name ());206 var complete_path = Path.build_filename (search_dirname, subelem_info.get_name ());
213 if (complete_path.has_prefix (search_string))207 if (complete_path.has_prefix (search_string))
214 {208 {
@@ -241,10 +235,10 @@
241 executables_match.add (matching_exec);235 executables_match.add (matching_exec);
242 }236 }
243 }237 }
244 238
245 executables_match.sort ();239 executables_match.sort ();
246 dirs_match.sort ();240 dirs_match.sort ();
247 241
248 category_id = RunnerCategory.RESULTS;242 category_id = RunnerCategory.RESULTS;
249243
250 // populate results244 // populate results
@@ -252,45 +246,38 @@
252 if ((executables_match.size == 0) && (dirs_match.size == 0))246 if ((executables_match.size == 0) && (dirs_match.size == 0))
253 {247 {
254 display_name = get_icon_uri_and_mimetype (search_string, out icon, out uri, out mimetype);248 display_name = get_icon_uri_and_mimetype (search_string, out icon, out uri, out mimetype);
255 model.append (uri.strip (), icon.to_string (),249 add_result (model, uri.strip (), icon.to_string (),
256 category_id, mimetype,250 category_id, mimetype, display_name);
257 display_name,
258 null);
259 }251 }
260 252
261 // 2. add possible directories (we don't store them)253 // 2. add possible directories (we don't store them)
262 mimetype = "inode/directory";254 mimetype = "inode/directory";
263 icon = ContentType.get_icon (mimetype);255 icon = ContentType.get_icon (mimetype);
264 foreach (var dir in dirs_match)256 foreach (var dir in dirs_match)
265 {257 {
266 uri = @"unity-runner://$(dir)";258 uri = @"unity-runner://$(dir)";
267 model.append (uri, icon.to_string (),259 add_result (model, uri, icon.to_string (),
268 category_id, mimetype,260 category_id, mimetype, dir);
269 dir,
270 null);
271 }261 }
272 262
273 // 3. add available exec263 // 3. add available exec
274 foreach (var final_exec in executables_match)264 foreach (var final_exec in executables_match)
275 {265 {
276 // TODO: try to match to a desktop file for the icon266 // TODO: try to match to a desktop file for the icon
277 uri = @"unity-runner://$(final_exec)";267 uri = @"unity-runner://$(final_exec)";
278 display_name = get_icon_uri_and_mimetype (final_exec, out icon, out uri, out mimetype); 268 display_name = get_icon_uri_and_mimetype (final_exec, out icon, out uri, out mimetype);
279 269 add_result (model, uri, icon.to_string (),
280 model.append (uri, icon.to_string (),270 category_id, mimetype, display_name);
281 category_id, mimetype,
282 display_name,
283 null);
284 }271 }
285 272
286 timer.stop ();273 timer.stop ();
287 debug ("Entry search listed %i dir matches and %i exec matches in %fms for search: %s",274 debug ("Entry search listed %i dir matches and %i exec matches in %fms for search: %s",
288 dirs_match.size, executables_match.size, timer.elapsed ()*1000, search_string);275 dirs_match.size, executables_match.size, timer.elapsed ()*1000, search_string);
289 276
290277
291 search.finished ();278 search.finished ();
292 }279 }
293 280
294 private class ExecSearcher: Object281 private class ExecSearcher: Object
295 {282 {
296 public ExecSearcher ()283 public ExecSearcher ()
@@ -378,13 +365,13 @@
378 return matching;365 return matching;
379 }366 }
380 }367 }
381 368
382 private string get_icon_uri_and_mimetype (string exec_string, out Icon? icon, out string? uri, out string? mimetype)369 private string get_icon_uri_and_mimetype (string exec_string, out Icon? icon, out string? uri, out string? mimetype)
383 {370 {
384 371
385 AboutEntry? entry = null;372 AboutEntry? entry = null;
386 373
387 mimetype = "application/x-unity-run"; 374 mimetype = "application/x-unity-run";
388 entry = about_entries[exec_string];375 entry = about_entries[exec_string];
389 if (entry != null)376 if (entry != null)
390 {377 {
@@ -395,7 +382,7 @@
395382
396 uri = @"unity-runner://$(exec_string)";383 uri = @"unity-runner://$(exec_string)";
397384
398 385
399 // if it's a folder, show… a folder icone! + right exec386 // if it's a folder, show… a folder icone! + right exec
400 if (FileUtils.test (exec_string, FileTest.IS_DIR))387 if (FileUtils.test (exec_string, FileTest.IS_DIR))
401 {388 {
@@ -404,7 +391,7 @@
404 return exec_string;391 return exec_string;
405 }392 }
406393
407 var s = exec_string.delimit ("-", '_').split (" ", 0)[0]; 394 var s = exec_string.delimit ("-", '_').split (" ", 0)[0];
408 var appresults = this.daemon.appsearcher.search (@"type:Application AND exec:$s", 0,395 var appresults = this.daemon.appsearcher.search (@"type:Application AND exec:$s", 0,
409 Unity.Package.SearchType.EXACT,396 Unity.Package.SearchType.EXACT,
410 Unity.Package.Sort.BY_NAME);397 Unity.Package.Sort.BY_NAME);
@@ -413,19 +400,19 @@
413400
414 if (pkginfo.desktop_file == null)401 if (pkginfo.desktop_file == null)
415 continue;402 continue;
416 403
417 // pick the first one404 // pick the first one
418 icon = this.daemon.find_pkg_icon (pkginfo.desktop_file, pkginfo.icon);405 icon = this.daemon.find_pkg_icon (pkginfo.desktop_file, pkginfo.icon);
419 return exec_string;406 return exec_string;
420 407
421 }408 }
422 409
423 // if no result, default icon410 // if no result, default icon
424 icon = new ThemedIcon ("gtk-execute");411 icon = new ThemedIcon ("gtk-execute");
425 return exec_string;412 return exec_string;
426 413
427 }414 }
428 415
429416
430 public void add_history (string last_command)417 public void add_history (string last_command)
431 {418 {
@@ -434,14 +421,14 @@
434 var new_history = new Gee.ArrayList<string> ();421 var new_history = new Gee.ArrayList<string> ();
435 var history_store = new string [this.history.size + 1];422 var history_store = new string [this.history.size + 1];
436 int i = 1;423 int i = 1;
437 424
438 new_history.add (last_command);425 new_history.add (last_command);
439 history_store[0] = last_command;426 history_store[0] = last_command;
440 for (var j = 0; (j < this.history.size) && (i < MAX_HISTORY); j++)427 for (var j = 0; (j < this.history.size) && (i < MAX_HISTORY); j++)
441 {428 {
442 if (this.history[j] == last_command)429 if (this.history[j] == last_command)
443 continue;430 continue;
444 431
445 new_history.add(history[j]);432 new_history.add(history[j]);
446 history_store[i] = history[j];433 history_store[i] = history[j];
447 i++;434 i++;
@@ -450,11 +437,11 @@
450437
451 // store in gsettings438 // store in gsettings
452 this.gp_settings.set_strv (HISTORY_KEY, history_store);439 this.gp_settings.set_strv (HISTORY_KEY, history_store);
453 440
454 // force a search to refresh history order (TODO: be more clever in the future)441 // force a search to refresh history order (TODO: be more clever in the future)
455 scope.queue_search_changed (SearchType.DEFAULT);442 scope.queue_search_changed (SearchType.DEFAULT);
456 }443 }
457 444
458 private void load_history ()445 private void load_history ()
459 {446 {
460 int i = 0;447 int i = 0;
@@ -467,39 +454,39 @@
467 i++;454 i++;
468 }455 }
469 }456 }
470 457
471 private void load_about_entries ()458 private void load_about_entries ()
472 { 459 {
473 AboutEntry entry;460 AboutEntry entry;
474 string name;461 string name;
475 string exec;462 string exec;
476 Icon icon;463 Icon icon;
477 464
478 // first about:config465 // first about:config
479 name = "about:config";466 name = "about:config";
480 exec = "ccsm -p unityshell";467 exec = "ccsm -p unityshell";
481 try {468 try {
482 icon = Icon.new_for_string (@"$(Config.PREFIX)/share/ccsm/icons/hicolor/64x64/apps/plugin-unityshell.png"); 469 icon = Icon.new_for_string (@"$(Config.PREFIX)/share/ccsm/icons/hicolor/64x64/apps/plugin-unityshell.png");
483 }470 }
484 catch (Error err) {471 catch (Error err) {
485 warning ("Can't find unityshell icon: %s", err.message);472 warning ("Can't find unityshell icon: %s", err.message);
486 icon = new ThemedIcon ("gtk-execute");473 icon = new ThemedIcon ("gtk-execute");
487 } 474 }
488 entry = new AboutEntry (name, exec, icon);475 entry = new AboutEntry (name, exec, icon);
489 476
490 about_entries[name] = entry;477 about_entries[name] = entry;
491 about_entries[exec] = entry;478 about_entries[exec] = entry;
492 479
493 // second about:robots480 // second about:robots
494 name = "Robots have a plan.";481 name = "Robots have a plan.";
495 exec = "firefox about:robots";482 exec = "firefox about:robots";
496 entry = new AboutEntry (name, exec, icon = new ThemedIcon ("battery"));483 entry = new AboutEntry (name, exec, icon = new ThemedIcon ("battery"));
497 484
498 about_entries["about:robots"] = entry;485 about_entries["about:robots"] = entry;
499 about_entries[exec] = entry;486 about_entries[exec] = entry;
500 487
501 }488 }
502 489
503 }490 }
504 491
505}492}
506493
=== modified file 'src/schemas.vala'
--- src/schemas.vala 2012-09-13 11:15:00 +0000
+++ src/schemas.vala 2013-05-08 13:32:23 +0000
@@ -37,6 +37,16 @@
37 INSTALLED,37 INSTALLED,
38 AVAILABLE,38 AVAILABLE,
39 }39 }
40
41 public enum RemoteScopesColumn
42 {
43 SCOPE_ID,
44 NAME,
45 DESCRIPTION,
46 ICON_HINT,
47 SCREENSHOT_URL,
48 KEYWORDS
49 }
40 50
41 public enum RunnerCategory51 public enum RunnerCategory
42 {52 {
4353
=== modified file 'src/unity-package-search.cc'
--- src/unity-package-search.cc 2013-04-15 16:32:36 +0000
+++ src/unity-package-search.cc 2013-05-08 13:32:23 +0000
@@ -59,6 +59,10 @@
59#define XAPIAN_VALUE_EXENAME 29459#define XAPIAN_VALUE_EXENAME 294
60#define XAPIAN_VALUE_CURRENCY 20160#define XAPIAN_VALUE_CURRENCY 201
6161
62/* this isn't a Software Center slot, but we use it to mark master
63 * scopes in the scope index. */
64#define XAPIAN_VALUE_MASTERSCOPE 1000
65
62#include "unity-package-search.h"66#include "unity-package-search.h"
63#include "columbus.hh"67#include "columbus.hh"
6468
@@ -184,6 +188,10 @@
184 query_parser->add_prefix ("pkgname", "AP");188 query_parser->add_prefix ("pkgname", "AP");
185 query_parser->add_prefix ("exec", "XX");189 query_parser->add_prefix ("exec", "XX");
186 query_parser->add_prefix ("keyword", "KW");190 query_parser->add_prefix ("keyword", "KW");
191 query_parser->add_prefix ("pkg_wildcard", "XP");
192 query_parser->add_prefix ("pkg_wildcard", "XPM");
193 query_parser->add_prefix ("pkg_wildcard", "AP");
194 query_parser->add_prefix ("pkg_wildcard", "APM");
187 query_parser->set_default_op (Xapian::Query::OP_AND);195 query_parser->set_default_op (Xapian::Query::OP_AND);
188 query_parser->set_database (db);196 query_parser->set_database (db);
189 searcher->query_parser = query_parser;197 searcher->query_parser = query_parser;
@@ -235,6 +243,9 @@
235 if (g_app_info_get_display_name (app_info))243 if (g_app_info_get_display_name (app_info))
236 doc.add_value (XAPIAN_VALUE_APPNAME, g_app_info_get_display_name (app_info));244 doc.add_value (XAPIAN_VALUE_APPNAME, g_app_info_get_display_name (app_info));
237245
246 if (g_app_info_get_description (app_info))
247 doc.add_value (XAPIAN_VALUE_DESCRIPTION, g_app_info_get_description (app_info));
248
238 if (g_app_info_get_icon (app_info))249 if (g_app_info_get_icon (app_info))
239 {250 {
240 gchar *icon_str = g_icon_to_string (g_app_info_get_icon (app_info));251 gchar *icon_str = g_icon_to_string (g_app_info_get_icon (app_info));
@@ -379,6 +390,97 @@
379 return searcher;390 return searcher;
380}391}
381392
393/* Recursively traverse the set of scopes */
394static void
395index_scope (Xapian::WritableDatabase *db,
396 Xapian::TermGenerator *indexer,
397 UnityProtocolScopeRegistryScopeMetadata *info)
398{
399 Xapian::Document doc;
400 char *dum1;
401
402 if (info->name != NULL)
403 doc.add_value (XAPIAN_VALUE_APPNAME, info->name);
404 if (info->description != NULL)
405 doc.add_value (XAPIAN_VALUE_DESCRIPTION, info->description);
406 if (info->icon != NULL)
407 doc.add_value (XAPIAN_VALUE_ICON, info->icon);
408 if (info->id != NULL)
409 doc.add_value (XAPIAN_VALUE_DESKTOP_FILE, info->id);
410 if (info->is_master)
411 doc.add_value (XAPIAN_VALUE_MASTERSCOPE, "true");
412
413 indexer->set_document (doc);
414 if (info->name != NULL)
415 {
416 dum1 = unity_applications_lens_utils_preprocess_string (info->name);
417 indexer->index_text (dum1, 5);
418 g_free (dum1);
419 }
420 if (info->description != NULL)
421 {
422 dum1 = unity_applications_lens_utils_preprocess_string (info->description);
423 indexer->index_text (dum1, 5);
424 g_free (dum1);
425 }
426 for (GSList *l = info->keywords; l != NULL; l = l->next)
427 {
428 dum1 = unity_applications_lens_utils_preprocess_string ((char *)l->data);
429 indexer->index_text (dum1, 0);
430 indexer->index_text (dum1, 0, "KW");
431 g_free (dum1);
432 }
433
434 /* Always assume Type=Scope for scopes... */
435 doc.add_term ("ATscope");
436
437 /* Index application name */
438 dum1 = g_strconcat ("AA", info->name, NULL);
439 doc.add_term (dum1);
440 g_free (dum1);
441
442 db->add_document (doc);
443}
444
445UnityPackageSearcher*
446unity_package_searcher_new_for_scopes (UnityProtocolScopeRegistry *scope_registry)
447{
448 UnityPackageSearcher *searcher;
449 Xapian::WritableDatabase *db;
450
451 searcher = new UnityPackageSearcher;
452 db = new Xapian::WritableDatabase ();
453 searcher->db = db;
454 searcher->db->add_database (Xapian::InMemory::open ());
455
456 init_searcher (searcher);
457
458 /* Index the menu recursively */
459 searcher->db_merged = false;
460 Xapian::TermGenerator *indexer = new Xapian::TermGenerator ();
461
462 GSList *scopes = unity_protocol_scope_registry_get_scopes (scope_registry);
463 for (GSList *l = scopes; l != NULL; l = l->next)
464 {
465 UnityProtocolScopeRegistryScopeRegistryNode *node = (UnityProtocolScopeRegistryScopeRegistryNode *)l->data;
466 index_scope (db, indexer, node->scope_info);
467
468 // Also index any sub-scopes
469 for (GSList *sl = node->sub_scopes; sl != NULL; sl = sl->next)
470 {
471 UnityProtocolScopeRegistryScopeMetadata *info = (UnityProtocolScopeRegistryScopeMetadata *)sl->data;
472 index_scope (db, indexer, info);
473 }
474 }
475 delete indexer;
476 db->flush ();
477
478 searcher->matcher = new Columbus::Matcher();
479 buildMatcher(searcher);
480
481 return searcher;
482}
483
382/* Create a new searcher that searches into the Xapian index484/* Create a new searcher that searches into the Xapian index
383 * provided by the Software Center */485 * provided by the Software Center */
384UnityPackageSearcher*486UnityPackageSearcher*
@@ -448,6 +550,9 @@
448 string appname = doc.get_value (XAPIAN_VALUE_APPNAME);550 string appname = doc.get_value (XAPIAN_VALUE_APPNAME);
449 pkginfo->application_name = g_strdup (appname.c_str ());551 pkginfo->application_name = g_strdup (appname.c_str ());
450552
553 string description = doc.get_value (XAPIAN_VALUE_DESCRIPTION);
554 pkginfo->description = g_strdup (description.c_str ());
555
451 string desktop_file = doc.get_value (XAPIAN_VALUE_DESKTOP_FILE);556 string desktop_file = doc.get_value (XAPIAN_VALUE_DESKTOP_FILE);
452 pkginfo->desktop_file = g_strdup (desktop_file.c_str ());557 pkginfo->desktop_file = g_strdup (desktop_file.c_str ());
453558
@@ -465,6 +570,9 @@
465 const string purchase_date = doc.get_value (XAPIAN_VALUE_PURCHASED_DATE);570 const string purchase_date = doc.get_value (XAPIAN_VALUE_PURCHASED_DATE);
466 pkginfo->needs_purchase = purchase_date.empty ();571 pkginfo->needs_purchase = purchase_date.empty ();
467572
573 string is_master = doc.get_value (XAPIAN_VALUE_MASTERSCOPE);
574 pkginfo->is_master_scope = (is_master == "true");
575
468 return pkginfo;576 return pkginfo;
469}577}
470578
@@ -572,6 +680,7 @@
572 // Retrieve the results, note that we build the result->results680 // Retrieve the results, note that we build the result->results
573 // list in reverse order and then reverse it before we return it681 // list in reverse order and then reverse it before we return it
574 result->num_hits = matches.get_matches_estimated ();682 result->num_hits = matches.get_matches_estimated ();
683 result->fuzzy_search = false;
575684
576 for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i)685 for (Xapian::MSetIterator i = matches.begin(); i != matches.end(); ++i)
577 {686 {
@@ -623,6 +732,7 @@
623 }732 }
624733
625 result->results = g_slist_reverse (result->results);734 result->results = g_slist_reverse (result->results);
735 result->fuzzy_search = true;
626 return result;736 return result;
627}737}
628738
@@ -637,11 +747,12 @@
637 g_return_val_if_fail (searcher != NULL, NULL);747 g_return_val_if_fail (searcher != NULL, NULL);
638 g_return_val_if_fail (search_string != NULL, NULL);748 g_return_val_if_fail (search_string != NULL, NULL);
639749
640 bool has_category = strstr(search_string, "category:") != NULL;750 bool is_filtered = strstr(search_string, "category:") != NULL
751 || strstr(search_string, "pkg_wildcard:") != NULL;
641 const char *col_query_str = strstr(search_string, "AND");752 const char *col_query_str = strstr(search_string, "AND");
642 xap_result = xapian_search(searcher, search_string, max_hits, search_type, sort);753 xap_result = xapian_search(searcher, search_string, max_hits, search_type, sort);
643 // If Xapian does not find anything, try fuzzy matching.754 // If Xapian does not find anything, try fuzzy matching.
644 if(g_slist_length(xap_result->results) == 0 && (!has_category && col_query_str)) {755 if (g_slist_length(xap_result->results) == 0 && (!is_filtered && col_query_str)) {
645 g_slice_free(UnityPackageSearchResult, xap_result);756 g_slice_free(UnityPackageSearchResult, xap_result);
646 col_query_str += 3;757 col_query_str += 3;
647 UnityPackageSearchResult *res = libcolumbus_search(searcher, col_query_str);758 UnityPackageSearchResult *res = libcolumbus_search(searcher, col_query_str);
@@ -710,6 +821,7 @@
710 g_hash_table_unref (unique);821 g_hash_table_unref (unique);
711822
712 result->num_hits = num_matches;823 result->num_hits = num_matches;
824 result->fuzzy_search = false;
713 return result;825 return result;
714}826}
715827
@@ -726,6 +838,7 @@
726838
727 result = g_slice_new0 (UnityPackageSearchResult);839 result = g_slice_new0 (UnityPackageSearchResult);
728 result->num_hits = n_apps;840 result->num_hits = n_apps;
841 result->fuzzy_search = false;
729 lastdocid = searcher->db->get_lastdocid ();842 lastdocid = searcher->db->get_lastdocid ();
730843
731 /* Since we really just pick random apps we may end up with dupes */844 /* Since we really just pick random apps we may end up with dupes */
@@ -867,6 +980,7 @@
867 }980 }
868981
869 result->num_hits = num_matches;982 result->num_hits = num_matches;
983 result->fuzzy_search = false;
870 return result;984 return result;
871}985}
872986
@@ -887,14 +1001,20 @@
887 Xapian::Document doc = searcher->db->get_document (*it);1001 Xapian::Document doc = searcher->db->get_document (*it);
888 string value = doc.get_value (XAPIAN_VALUE_DESKTOP_FILE);1002 string value = doc.get_value (XAPIAN_VALUE_DESKTOP_FILE);
8891003
1004 bool matches = false;
890 size_t sep = value.find (':');1005 size_t sep = value.find (':');
891 if (sep != string::npos)1006 if (sep != string::npos)
892 {1007 {
893 if (value.compare (sep+1, value.size() - sep, query) == 0)1008 matches = value.compare (sep+1, value.size() - sep, query) == 0;
894 {1009 }
895 pkginfo = _pkginfo_from_document (doc);1010 else
896 return pkginfo;1011 {
897 }1012 matches = value == query;
1013 }
1014 if (matches)
1015 {
1016 pkginfo = _pkginfo_from_document (doc);
1017 return pkginfo;
898 }1018 }
899 ++it;1019 ++it;
900 }1020 }
9011021
=== modified file 'src/unity-package-search.h'
--- src/unity-package-search.h 2012-10-09 15:26:49 +0000
+++ src/unity-package-search.h 2013-05-08 13:32:23 +0000
@@ -19,6 +19,7 @@
1919
20#include <glib.h>20#include <glib.h>
21#include <gmenu-tree.h>21#include <gmenu-tree.h>
22#include <unity-protocol.h>
2223
23typedef struct _UnityPackageSearcher UnityPackageSearcher;24typedef struct _UnityPackageSearcher UnityPackageSearcher;
2425
@@ -36,19 +37,22 @@
3637
37typedef struct38typedef struct
38{39{
39 GSList *results;40 GSList *results;
40 gint num_hits;41 gint num_hits;
42 gboolean fuzzy_search;
41} UnityPackageSearchResult;43} UnityPackageSearchResult;
4244
43typedef struct45typedef struct
44{46{
45 gchar *package_name;47 gchar *package_name;
46 gchar *application_name;48 gchar *application_name;
49 gchar *description;
47 gchar *desktop_file;50 gchar *desktop_file;
48 gchar *icon;51 gchar *icon;
49 gchar *price;52 gchar *price;
50 gboolean needs_purchase;53 gboolean needs_purchase;
51 gint relevancy;54 gint relevancy;
55 gboolean is_master_scope;
52} UnityPackageInfo;56} UnityPackageInfo;
5357
54typedef gboolean (*AppFilterCallback)(UnityPackageInfo *, void *);58typedef gboolean (*AppFilterCallback)(UnityPackageInfo *, void *);
@@ -61,6 +65,7 @@
61UnityPackageSearcher* unity_package_searcher_new ();65UnityPackageSearcher* unity_package_searcher_new ();
6266
63UnityPackageSearcher* unity_package_searcher_new_for_menu (GMenuTree *menu);67UnityPackageSearcher* unity_package_searcher_new_for_menu (GMenuTree *menu);
68UnityPackageSearcher* unity_package_searcher_new_for_scopes (UnityProtocolScopeRegistry *scope_registry);
6469
65void unity_package_searcher_free (UnityPackageSearcher *searcher);70void unity_package_searcher_free (UnityPackageSearcher *searcher);
6671
6772
=== modified file 'src/utils.vala'
--- src/utils.vala 2012-10-05 16:17:11 +0000
+++ src/utils.vala 2013-05-08 13:32:23 +0000
@@ -138,6 +138,99 @@
138 }138 }
139 }139 }
140140
141 public Dee.Index prepare_index (Dee.Model model,
142 uint sort_column,
143 owned Dee.ModelReaderFunc reader_func,
144 out Dee.Analyzer out_analyzer)
145 {
146 // reuse the icu_filter
147 if (icu_filter == null)
148 {
149 icu_filter = new Dee.ICUTermFilter.ascii_folder ();
150 }
151
152 var sort_filter = Dee.Filter.new_collator (sort_column);
153 var filter_model = new Dee.FilterModel (model, sort_filter);
154
155 var analyzer = new Dee.TextAnalyzer ();
156 analyzer.add_term_filter ((terms_in, terms_out) =>
157 {
158 for (uint i = 0; i < terms_in.num_terms (); i++)
159 {
160 unowned string term = terms_in.get_term (i);
161 var folded = icu_filter.apply (term);
162 terms_out.add_term (term);
163 if (folded != term) terms_out.add_term (folded);
164 }
165 });
166 out_analyzer = analyzer;
167
168 var reader = Dee.ModelReader.new (reader_func);
169 return new Dee.TreeIndex (filter_model, analyzer, reader);
170 }
171
172 public SList<Dee.ModelIter> search_index (Dee.Index index,
173 Dee.Analyzer analyzer,
174 string query)
175 {
176 if (is_search_empty (query))
177 {
178 var model = index.get_model ();
179 var iter = model.get_first_iter ();
180 var end_iter = model.get_last_iter ();
181
182 var result = new SList<Dee.ModelIter> ();
183 while (iter != end_iter)
184 {
185 result.prepend (iter);
186 iter = model.next (iter);
187 }
188 result.reverse ();
189 return result;
190 }
191
192 var term_list = Object.new (typeof (Dee.TermList)) as Dee.TermList;
193 analyzer.tokenize (query, term_list);
194 var matches = new Sequence<Dee.ModelIter> ();
195
196 uint num_terms = term_list.num_terms ();
197 for (uint i = 0; i < num_terms; i++)
198 {
199 var rs = index.lookup (term_list.get_term (i),
200 i < num_terms - 1 ? Dee.TermMatchFlag.EXACT : Dee.TermMatchFlag.PREFIX);
201
202 bool first_pass = i == 0;
203 CompareDataFunc<Dee.ModelIter> cmp_func = (a, b) =>
204 {
205 return a == b ? 0 : ((void*) a > (void*) b ? 1 : -1);
206 };
207 // intersect the results (cause we want to AND the terms)
208 var remaining = new Sequence<Dee.ModelIter> ();
209 foreach (var item in rs)
210 {
211 if (first_pass)
212 matches.insert_sorted (item, cmp_func);
213 else if (matches.lookup (item, cmp_func) != null)
214 remaining.insert_sorted (item, cmp_func);
215 }
216 if (!first_pass) matches = (owned) remaining;
217 // final result set empty already?
218 if (matches.get_begin_iter () == matches.get_end_iter ()) break;
219 }
220
221 var result = new SList<Dee.ModelIter> ();
222 var iter = matches.get_begin_iter ();
223 var end_iter = matches.get_end_iter ();
224 while (iter != end_iter)
225 {
226 result.prepend (iter.get ());
227 iter = iter.next ();
228 }
229
230 result.reverse ();
231 return result;
232 }
233
141 /* Substitute tilde character in @s by the home directory.234 /* Substitute tilde character in @s by the home directory.
142 * Expansion of ~username also works if 'username' is found. */235 * Expansion of ~username also works if 'username' is found. */
143 public string subst_tilde (string s)236 public string subst_tilde (string s)
144237
=== modified file 'src/xapian-utils.vala'
--- src/xapian-utils.vala 2012-10-08 13:30:44 +0000
+++ src/xapian-utils.vala 2013-05-08 13:32:23 +0000
@@ -31,6 +31,7 @@
31 "accessibility",31 "accessibility",
32 "developer",32 "developer",
33 "science-and-engineering",33 "science-and-engineering",
34 "scopes",
34 "system"35 "system"
35 };36 };
3637
@@ -58,6 +59,7 @@
58 type_queries.insert ("accessibility", "(category:Accessibility AND NOT category:Settings)");59 type_queries.insert ("accessibility", "(category:Accessibility AND NOT category:Settings)");
59 type_queries.insert ("developer", "category:Development"); // FIXME emacs.desktop should be added60 type_queries.insert ("developer", "category:Development"); // FIXME emacs.desktop should be added
60 type_queries.insert ("science-and-engineering", "(category:Science OR category:Engineering)");61 type_queries.insert ("science-and-engineering", "(category:Science OR category:Engineering)");
62 type_queries.insert ("scopes", "(pkg_wildcard:unity_scope_* OR pkg_wildcard:unity_lens_*)");
61 type_queries.insert ("system", "(category:System OR category:Security)");63 type_queries.insert ("system", "(category:System OR category:Security)");
62 }64 }
63 }65 }
@@ -107,9 +109,9 @@
107 if (Utils.is_search_empty (search_string))109 if (Utils.is_search_empty (search_string))
108 {110 {
109 if (options == null || !options.filtering)111 if (options == null || !options.filtering)
110 return "type:Application";112 return "(type:Application OR type:Scope)";
111 else113 else
112 return "type:Application AND " + extract_type_query (options);114 return "(type:Application OR type:Scope) AND " + extract_type_query (options);
113 }115 }
114 else116 else
115 {117 {
@@ -125,9 +127,9 @@
125 s = s.delimit ("-", ' ');127 s = s.delimit ("-", ' ');
126 128
127 if (options == null || !options.filtering)129 if (options == null || !options.filtering)
128 return "type:Application AND " + s;130 return "(type:Application OR type:Scope) AND " + s;
129 else131 else
130 return "type:Application AND %s AND %s".printf (extract_type_query (options), s);132 return "(type:Application OR type:Scope) AND %s AND %s".printf (extract_type_query (options), s);
131 }133 }
132 }134 }
133}
134\ No newline at end of file135\ No newline at end of file
136}
135137
=== modified file 'tests/unit/Makefile.am'
--- tests/unit/Makefile.am 2013-03-01 15:41:08 +0000
+++ tests/unit/Makefile.am 2013-05-08 13:32:23 +0000
@@ -30,6 +30,8 @@
30 $(test_libs) \30 $(test_libs) \
31 $(UNITY_PACKAGE_SEARCH_LIBS)31 $(UNITY_PACKAGE_SEARCH_LIBS)
3232
33LDFLAGS += -rpath $(PROTOCOLPRIVATELIBDIR)
34
33AM_CPPFLAGS = \35AM_CPPFLAGS = \
34 $(LENS_DAEMON_CFLAGS) \36 $(LENS_DAEMON_CFLAGS) \
35 -I$(srcdir) \37 -I$(srcdir) \
3638
=== modified file 'tests/unit/test-xapian-utils.vala'
--- tests/unit/test-xapian-utils.vala 2012-10-08 08:41:45 +0000
+++ tests/unit/test-xapian-utils.vala 2013-05-08 13:32:23 +0000
@@ -43,7 +43,7 @@
43 internal static void test_empty_search_query ()43 internal static void test_empty_search_query ()
44 {44 {
45 var query = XapianUtils.prepare_pkg_search_string ("", null);45 var query = XapianUtils.prepare_pkg_search_string ("", null);
46 assert (query == "type:Application");46 assert (query == "(type:Application OR type:Scope)");
47 }47 }
4848
49 internal static void test_empty_search_with_single_cat_filter ()49 internal static void test_empty_search_with_single_cat_filter ()
@@ -54,7 +54,7 @@
54 filter.add_option ("internet", "Internet", null);54 filter.add_option ("internet", "Internet", null);
5555
56 var query = XapianUtils.prepare_pkg_search_string ("", filter);56 var query = XapianUtils.prepare_pkg_search_string ("", filter);
57 assert (query == "type:Application AND (category:AudioVideo)");57 assert (query == "(type:Application OR type:Scope) AND (category:AudioVideo)");
58 }58 }
5959
60 internal static void test_empty_search_with_multi_cat_filter ()60 internal static void test_empty_search_with_multi_cat_filter ()
@@ -65,16 +65,16 @@
65 filter.add_option ("internet", "Internet", null);65 filter.add_option ("internet", "Internet", null);
66 filter.add_option ("game", "Game", null).active = true;66 filter.add_option ("game", "Game", null).active = true;
67 var query = XapianUtils.prepare_pkg_search_string ("", filter);67 var query = XapianUtils.prepare_pkg_search_string ("", filter);
68 assert (query == "type:Application AND (category:Game OR category:AudioVideo)");68 assert (query == "(type:Application OR type:Scope) AND (category:Game OR category:AudioVideo)");
69 }69 }
7070
71 internal static void test_search_query_no_filters ()71 internal static void test_search_query_no_filters ()
72 {72 {
73 var query = XapianUtils.prepare_pkg_search_string (" foo ", null);73 var query = XapianUtils.prepare_pkg_search_string (" foo ", null);
74 assert (query == "type:Application AND foo");74 assert (query == "(type:Application OR type:Scope) AND foo");
7575
76 query = XapianUtils.prepare_pkg_search_string ("foo", null);76 query = XapianUtils.prepare_pkg_search_string ("foo", null);
77 assert (query == "type:Application AND foo");77 assert (query == "(type:Application OR type:Scope) AND foo");
78 }78 }
7979
80 internal static void test_search_query_with_single_cat_filter ()80 internal static void test_search_query_with_single_cat_filter ()
@@ -84,7 +84,7 @@
84 filter.add_option ("media", "Media", null);84 filter.add_option ("media", "Media", null);
85 filter.add_option ("internet", "Internet", null).active = true;85 filter.add_option ("internet", "Internet", null).active = true;
86 var query = XapianUtils.prepare_pkg_search_string ("foo", filter);86 var query = XapianUtils.prepare_pkg_search_string ("foo", filter);
87 assert (query == "type:Application AND (category:Network) AND foo");87 assert (query == "(type:Application OR type:Scope) AND (category:Network) AND foo");
88 }88 }
8989
90 internal static void test_search_query_with_multi_cat_filter ()90 internal static void test_search_query_with_multi_cat_filter ()
@@ -95,7 +95,7 @@
95 filter.add_option ("internet", "Internet", null).active = true;95 filter.add_option ("internet", "Internet", null).active = true;
96 filter.add_option ("game", "Game", null).active = true;96 filter.add_option ("game", "Game", null).active = true;
97 var query = XapianUtils.prepare_pkg_search_string ("foo", filter);97 var query = XapianUtils.prepare_pkg_search_string ("foo", filter);
98 assert (query == "type:Application AND (category:Game OR category:Network) AND foo");98 assert (query == "(type:Application OR type:Scope) AND (category:Game OR category:Network) AND foo");
99 }99 }
100100
101 internal static void test_zg_empty_search_query ()101 internal static void test_zg_empty_search_query ()
102102
=== modified file 'vapi/unity-package-search.deps'
--- vapi/unity-package-search.deps 2012-10-18 12:36:37 +0000
+++ vapi/unity-package-search.deps 2013-05-08 13:32:23 +0000
@@ -1,2 +1,3 @@
1glib-2.01glib-2.0
2libgnome-menu-3.02libgnome-menu-3.0
3unity-protocol
34
=== modified file 'vapi/unity-package-search.vapi'
--- vapi/unity-package-search.vapi 2012-10-08 15:11:07 +0000
+++ vapi/unity-package-search.vapi 2013-05-08 13:32:23 +0000
@@ -27,6 +27,8 @@
27 public Searcher ();27 public Searcher ();
28 [CCode (cname = "unity_package_searcher_new_for_menu")]28 [CCode (cname = "unity_package_searcher_new_for_menu")]
29 public Searcher.for_menu(GMenu.Tree menu);29 public Searcher.for_menu(GMenu.Tree menu);
30 [CCode (cname = "unity_package_searcher_new_for_scopes")]
31 public Searcher.for_scopes(Unity.Protocol.ScopeRegistry scope_registry);
30 public SearchResult search (string search_string, uint max_hits, Unity.Package.SearchType search_type, Unity.Package.Sort sort);32 public SearchResult search (string search_string, uint max_hits, Unity.Package.SearchType search_type, Unity.Package.Sort sort);
31 public SearchResult get_random_apps (string? filter_query, uint n_apps);33 public SearchResult get_random_apps (string? filter_query, uint n_apps);
32 public SearchResult get_apps (string? filter_query, uint n_apps, AppFilterCallback cb);34 public SearchResult get_apps (string? filter_query, uint n_apps, AppFilterCallback cb);
@@ -41,6 +43,7 @@
41 public SearchResult ();43 public SearchResult ();
42 public GLib.SList<PackageInfo> results;44 public GLib.SList<PackageInfo> results;
43 public int num_hits;45 public int num_hits;
46 public bool fuzzy_search;
44 }47 }
45 48
46 [Compact]49 [Compact]
@@ -49,11 +52,13 @@
49 public PackageInfo ();52 public PackageInfo ();
50 public string package_name;53 public string package_name;
51 public string application_name;54 public string application_name;
55 public string description;
52 public string desktop_file;56 public string desktop_file;
53 public string icon;57 public string icon;
54 public string price;58 public string price;
55 public bool needs_purchase;59 public bool needs_purchase;
56 public int relevancy;60 public int relevancy;
61 public bool is_master_scope;
57 }62 }
58 }63 }
59}64}

Subscribers

People subscribed via source and target branches