Merge lp:~njpatel/unity-lens-applications/unity-lens-applications into lp:unity-lens-applications

Proposed by Neil J. Patel
Status: Merged
Approved by: Alex Launi
Approved revision: 218
Merged at revision: 213
Proposed branch: lp:~njpatel/unity-lens-applications/unity-lens-applications
Merge into: lp:unity-lens-applications
Diff against target: 1684 lines (+361/-562)
14 files modified
.bzrignore (+11/-0)
Makefile.am (+11/-7)
applications.lens.in.in (+4/-19)
commands.lens.in.in (+10/-0)
configure.ac (+12/-11)
data/Makefile.am (+3/-3)
data/unity-lens-applications.service.in (+1/-1)
po/POTFILES.in (+2/-1)
src/Makefile.am (+2/-2)
src/daemon.vala (+192/-352)
src/main.vala (+3/-3)
src/runner.vala (+97/-119)
src/schemas.vala (+3/-34)
src/utils.vala (+10/-10)
To merge this branch: bzr merge lp:~njpatel/unity-lens-applications/unity-lens-applications
Reviewer Review Type Date Requested Status
Alex Launi (community) Approve
Review via email: mp+70408@code.launchpad.net

Description of the change

This ports the application place to the new infrastructure. The only way to test it is over d-feet and it requires lp:~njpatel/libunity/lenses-extras to compile.

This also s/place/lens, which means we need new packaging and we need to ask LP guys to rename this project.

To post a comment you must log in.
218. By Neil J. Patel

update version

Revision history for this message
Alex Launi (alexlauni) wrote :

Looks pretty much like a port from the new api to the old. Looks good to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2010-01-27 13:08:27 +0000
+++ .bzrignore 2011-08-04 08:16:52 +0000
@@ -60,3 +60,14 @@
60ABOUT-NLS60ABOUT-NLS
61config.rpath61config.rpath
62po/unity-place-applications.pot62po/unity-place-applications.pot
63applications.place
64applications.place.in
65data/X-Unity-All-Applications.directory
66data/unity-place-applications.menu
67po/da.gmo
68src/config.c
69src/config.vala
70src/daemon.c
71src/schemas.c
72src/unity-applications-daemon
73src/unity_applications_daemon.vala.stamp
6374
=== modified file 'Makefile.am'
--- Makefile.am 2011-02-11 12:35:12 +0000
+++ Makefile.am 2011-08-04 08:16:52 +0000
@@ -1,16 +1,20 @@
1SUBDIRS = src data po1SUBDIRS = src data po
22
3#3#
4# Install the applications.place file4# Install the applications.lens file
5#5#
6place_in_files = applications.place.in6lens_in_files = applications.lens.in
7placedir = $(datadir)/unity/places7lensdir = $(datadir)/unity/lenses/applications
8place_DATA = $(place_in_files:.place.in=.place)8lens_DATA = $(lens_in_files:.lens.in=.lens)
9
10cmdlens_in_files = commands.lens.in
11cmdlensdir = $(datadir)/unity/lenses/commands
12cmdlens_DATA = $(cmdlens_in_files:.lens.in=.lens)
913
10icondir = $(datadir)/unity/themes14icondir = $(datadir)/unity/themes
11icon_DATA = applications.png15icon_DATA = applications.png
1216
13@INTLTOOL_PLACE_RULE@17@INTLTOOL_LENS_RULE@
1418
15DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall19DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall
1620
@@ -32,7 +36,7 @@
32EXTRA_DIST = \36EXTRA_DIST = \
33 applications.png \37 applications.png \
34 autogen.sh \38 autogen.sh \
35 $(place_in_files) \39 $(lens_in_files) \
36 AUTHORS \40 AUTHORS \
37 COPYING \41 COPYING \
38 HACKING \42 HACKING \
@@ -42,5 +46,5 @@
42 vapi/unity-package-search.deps46 vapi/unity-package-search.deps
4347
44CLEANFILES = \48CLEANFILES = \
45 $(place_DATA)49 $(lens_DATA)
4650
4751
=== renamed file 'applications.place.in.in' => 'applications.lens.in.in'
--- applications.place.in.in 2011-04-01 14:54:26 +0000
+++ applications.lens.in.in 2011-08-04 08:16:52 +0000
@@ -1,27 +1,12 @@
1[Place]1[Lens]
2DBusName=com.canonical.Unity.ApplicationsPlace2DBusName=com.canonical.Unity.Lens.Applications
3DBusObjectPath=/com/canonical/unity/applicationsplace3DBusObjectPath=/com/canonical/unity/lens/applications
4
5[Entry:Files]
6DBusObjectPath=/com/canonical/unity/applicationsplace/applications
7Icon=@prefix@/share/unity/themes/applications.png4Icon=@prefix@/share/unity/themes/applications.png
8_Name=Applications5_Name=Applications
9Description=6Description=
10_SearchHint=Search Applications7_SearchHint=Search Applications
11Shortcut=a8Shortcut=a
129
13[Entry:Runner]
14DBusObjectPath=/com/canonical/unity/applicationsplace/runner
15_Name=Commands
16_SearchHint=Run a command
17ShowGlobal=false
18ShowEntry=false
19
20[Activation]
21URIPattern=unity-(install|runner)://.+
22MimetypePattern=application/x-unity-available-application
23Priority=0
24
25[Desktop Entry]10[Desktop Entry]
26X-Ubuntu-Gettext-Domain=unity-place-applications11X-Ubuntu-Gettext-Domain=unity-lens-applications
2712
2813
=== added file 'commands.lens.in.in'
--- commands.lens.in.in 1970-01-01 00:00:00 +0000
+++ commands.lens.in.in 2011-08-04 08:16:52 +0000
@@ -0,0 +1,10 @@
1[Lens]
2DBusName=com.canonical.Unity.Lens.Applications
3DBusObjectPath=/com/canonical/unity/lens/commands
4Icon=@prefix@/share/unity/themes/applications.png
5_Name=Commands
6_SearchHint=Run a command
7Visible=false
8
9[Desktop Entry]
10X-Ubuntu-Gettext-Domain=unity-lens-applications
011
=== modified file 'configure.ac'
--- configure.ac 2011-04-07 10:51:45 +0000
+++ configure.ac 2011-08-04 08:16:52 +0000
@@ -1,4 +1,4 @@
1AC_INIT(unity-place-applications, 0.2.47, https://launchpad.net/unity-place-applications)1AC_INIT(unity-lens-applications, 0.3.0, https://launchpad.net/unity-lens-applications)
2AC_COPYRIGHT([Copyright 2010 Canonical])2AC_COPYRIGHT([Copyright 2010 Canonical])
33
4AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)4AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
@@ -46,16 +46,16 @@
46AC_DEFINE_UNQUOTED(PREFIXDIR, "${PREFIX}",[Prefix directory])46AC_DEFINE_UNQUOTED(PREFIXDIR, "${PREFIX}",[Prefix directory])
4747
48######################################################48######################################################
49# intltool rule for generating translated .place file49# intltool rule for generating translated .lens file
50######################################################50######################################################
51INTLTOOL_PLACE_RULE='%.place: %.place.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 $< [$]@'51INTLTOOL_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 $< [$]@'
52AC_SUBST(INTLTOOL_PLACE_RULE)52AC_SUBST(INTLTOOL_LENS_RULE)
5353
54#############################################54#############################################
55# Check for module and library dependancies55# Check for module and library dependancies
56#############################################56#############################################
57GLIB_REQUIRED=2.2757GLIB_REQUIRED=2.27
58PKG_CHECK_MODULES(PLACE_DAEMON,58PKG_CHECK_MODULES(LENS_DAEMON,
59 glib-2.0 >= $GLIB_REQUIRED59 glib-2.0 >= $GLIB_REQUIRED
60 gobject-2.0 >= $GLIB_REQUIRED60 gobject-2.0 >= $GLIB_REQUIRED
61 gio-2.0 >= $GLIB_REQUIRED61 gio-2.0 >= $GLIB_REQUIRED
@@ -64,11 +64,11 @@
64 gee-1.064 gee-1.0
65 dee-1.0 >= 0.5.1665 dee-1.0 >= 0.5.16
66 zeitgeist-1.0 >= 0.3.866 zeitgeist-1.0 >= 0.3.8
67 unity >= 3.6.367 unity >= 4.0
68 libgnome-menu)68 libgnome-menu)
6969
70AC_SUBST(PLACE_DAEMON_CFLAGS)70AC_SUBST(LENS_DAEMON_CFLAGS)
71AC_SUBST(PLACE_DAEMON_LIBS)71AC_SUBST(LENS_DAEMON_LIBS)
7272
73#############################################73#############################################
74# local install for distcheck and stand-alone running74# local install for distcheck and stand-alone running
@@ -106,10 +106,11 @@
106#############################################106#############################################
107AC_CONFIG_FILES([107AC_CONFIG_FILES([
108 Makefile108 Makefile
109 applications.place.in109 applications.lens.in
110 commands.lens.in
110 data/Makefile111 data/Makefile
111 data/X-Unity-All-Applications.directory112 data/X-Unity-All-Applications.directory
112 data/unity-place-applications.menu113 data/unity-lens-applications.menu
113 src/Makefile114 src/Makefile
114 src/config.vala115 src/config.vala
115 po/Makefile.in116 po/Makefile.in
@@ -119,7 +120,7 @@
119dnl Output the results120dnl Output the results
120AC_MSG_NOTICE([121AC_MSG_NOTICE([
121122
122 Unity Applications Place Daemon $VERSION123 Unity Applications Lens Daemon $VERSION
123 ------------------------------------124 ------------------------------------
124125
125 Prefix : ${prefix}126 Prefix : ${prefix}
126127
=== modified file 'data/Makefile.am'
--- data/Makefile.am 2011-03-10 10:56:46 +0000
+++ data/Makefile.am 2011-08-04 08:16:52 +0000
@@ -1,5 +1,5 @@
1dbus_servicesdir = $(DBUSSERVICEDIR)1dbus_servicesdir = $(DBUSSERVICEDIR)
2service_in_files = unity-place-applications.service.in2service_in_files = unity-lens-applications.service.in
3dbus_services_DATA = $(service_in_files:.service.in=.service)3dbus_services_DATA = $(service_in_files:.service.in=.service)
44
5%.service: %.service.in5%.service: %.service.in
@@ -14,7 +14,7 @@
1414
15menudir = $(sysconfdir)/xdg/menus15menudir = $(sysconfdir)/xdg/menus
16menu_in_files = \16menu_in_files = \
17 unity-place-applications.menu.in17 unity-lens-applications.menu.in
18menu_DATA = $(menu_in_files:.menu.in=.menu)18menu_DATA = $(menu_in_files:.menu.in=.menu)
19 19
2020
@@ -24,4 +24,4 @@
24 $(menu_in_files)24 $(menu_in_files)
2525
26CLEANFILES = \26CLEANFILES = \
27 unity-place-applications.service27 unity-lens-applications.service
2828
=== renamed file 'data/unity-place-applications.menu.in' => 'data/unity-lens-applications.menu.in'
=== renamed file 'data/unity-place-applications.service.in' => 'data/unity-lens-applications.service.in'
--- data/unity-place-applications.service.in 2010-06-24 18:02:29 +0000
+++ data/unity-lens-applications.service.in 2011-08-04 08:16:52 +0000
@@ -1,3 +1,3 @@
1[D-BUS Service]1[D-BUS Service]
2Name=com.canonical.Unity.ApplicationsPlace2Name=com.canonical.Unity.Lens.Applications
3Exec=@libexecdir@/unity-applications-daemon3Exec=@libexecdir@/unity-applications-daemon
44
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2011-03-10 13:25:55 +0000
+++ po/POTFILES.in 2011-08-04 08:16:52 +0000
@@ -4,4 +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.place.in.in7[type: gettext/ini]applications.lens.in.in
8[type: gettext/ini]commands.lens.in.in
89
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2011-03-30 01:29:07 +0000
+++ src/Makefile.am 2011-08-04 08:16:52 +0000
@@ -14,7 +14,7 @@
14 -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \14 -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \
15 -DG_LOG_DOMAIN=\"unity-applications-daemon\" \15 -DG_LOG_DOMAIN=\"unity-applications-daemon\" \
16 -DGMENU_I_KNOW_THIS_IS_UNSTABLE \16 -DGMENU_I_KNOW_THIS_IS_UNSTABLE \
17 $(PLACE_DAEMON_CFLAGS) \17 $(LENS_DAEMON_CFLAGS) \
18 $(MAINTAINER_CFLAGS) \18 $(MAINTAINER_CFLAGS) \
19 -I$(srcdir) \19 -I$(srcdir) \
20 -g20 -g
@@ -40,7 +40,7 @@
40unity_package_search_libs = -lxapian -lstdc++40unity_package_search_libs = -lxapian -lstdc++
4141
42unity_applications_daemon_LDADD = \42unity_applications_daemon_LDADD = \
43 $(PLACE_DAEMON_LIBS) \43 $(LENS_DAEMON_LIBS) \
44 $(unity_package_search_libs) \44 $(unity_package_search_libs) \
45 unity-package-search.o \45 unity-package-search.o \
46 $(NULL)46 $(NULL)
4747
=== modified file 'src/daemon.vala'
--- src/daemon.vala 2011-05-04 13:20:43 +0000
+++ src/daemon.vala 2011-08-04 08:16:52 +0000
@@ -14,6 +14,7 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *15 *
16 * Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>16 * Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
17 * Neil Jagdish Patel <neil.patel@canonical.com>
17 *18 *
18 */19 */
19using Dee;20using Dee;
@@ -23,11 +24,11 @@
23using Gee;24using Gee;
24using GMenu;25using GMenu;
2526
26namespace Unity.ApplicationsPlace {27namespace Unity.ApplicationsLens {
2728
28 const string ICON_PATH = Config.DATADIR + "/icons/unity-icon-theme/places/svg/";29 const string ICON_PATH = Config.DATADIR + "/icons/unity-icon-theme/lenss/svg/";
2930
30 public class Daemon : GLib.Object, Unity.Activation31 public class Daemon : GLib.Object
31 {32 {
32 private Zeitgeist.Log log;33 private Zeitgeist.Log log;
33 private Zeitgeist.Index zg_index;34 private Zeitgeist.Index zg_index;
@@ -37,67 +38,36 @@
37 private Unity.Package.Searcher? pkgsearcher;38 private Unity.Package.Searcher? pkgsearcher;
38 public Unity.Package.Searcher appsearcher;39 public Unity.Package.Searcher appsearcher;
3940
40 private Unity.PlaceController control;41 private Unity.Lens lens;
41 private Unity.PlaceEntryInfo applications;42 private Unity.Scope scope;
42 43
43 private Unity.ApplicationsPlace.Runner runner;44 private Unity.ApplicationsLens.Runner runner;
4445
45 /* For each section we have a set filtering query we use to restrict46 /* For each section we have a set filtering query we use to restrict
46 * Xapian queries to that section */47 * Xapian queries to that type */
47 private Gee.List<string> section_queries;48 private HashTable<string, string> type_queries;
4849
49 private Gee.List<string> image_extensions;50 private Gee.List<string> image_extensions;
50 private HashTable<string,Icon> file_icon_cache;51 private HashTable<string,Icon> file_icon_cache;
51 52
52 /* We remember the previous search so we can figure out if we should do53 /* We remember the previous search so we can figure out if we should do
53 * incremental filtering of the result models */54 * incremental filtering of the result models */
54 private PlaceSearch? previous_search;55 private Unity.LensSearch? previous_search;
55 private PlaceSearch? previous_global_search;56 private Unity.LensSearch? previous_global_search;
56 57
57 /* To make sure we don't fire of unnecessary queries if the active section
58 * is in fact not changed */
59 private uint previous_active_section;
60
61 private PtrArray zg_templates;58 private PtrArray zg_templates;
62 59
63 /* Gnome menu structure - also used to check whether apps are installed */60 /* Gnome menu structure - also used to check whether apps are installed */
64 private uint app_menu_changed_reindex_timeout = 0;61 private uint app_menu_changed_reindex_timeout = 0;
65 private GMenu.Tree app_menu = null;62 private GMenu.Tree app_menu = null;
6663
67 private bool all_models_synced;
68
69 private Regex? uri_regex;64 private Regex? uri_regex;
7065
71 construct66 construct
72 {67 {
73 var sections_model = new Dee.SharedModel("com.canonical.Unity.ApplicationsPlace.SectionsModel");68 populate_type_queries ();
74 sections_model.set_schema ("s", "s");
75
76 var groups_model = new Dee.SharedModel("com.canonical.Unity.ApplicationsPlace.GroupsModel");
77 groups_model.set_schema ("s", "s", "s");
78
79 var global_groups_model = new Dee.SharedModel("com.canonical.Unity.ApplicationsPlace.GlobalGroupsModel");
80 global_groups_model.set_schema ("s", "s", "s");
81
82 var results_model = new Dee.SharedModel("com.canonical.Unity.ApplicationsPlace.ResultsModel");
83 results_model.set_schema ("s", "s", "u", "s", "s", "s");
84
85 var global_results_model = new Dee.SharedModel("com.canonical.Unity.ApplicationsPlace.GlobalResultsModel");
86 global_results_model.set_schema ("s", "s", "u", "s", "s", "s");
87
88 section_queries = new Gee.ArrayList<string> ();
89 populate_section_queries();
90 populate_zg_templates ();69 populate_zg_templates ();
9170
92 applications = new PlaceEntryInfo ("/com/canonical/unity/applicationsplace/applications");
93 applications.sections_model = sections_model;
94 applications.entry_renderer_info.groups_model = groups_model;
95 applications.entry_renderer_info.results_model = results_model;
96 applications.global_renderer_info.groups_model = global_groups_model;
97 applications.global_renderer_info.results_model = global_results_model;
98
99 applications.icon = @"$(Config.PREFIX)/share/unity/themes/applications.png";
100
101 log = new Zeitgeist.Log();71 log = new Zeitgeist.Log();
102 zg_index = new Zeitgeist.Index();72 zg_index = new Zeitgeist.Index();
103 73
@@ -119,68 +89,60 @@
119 89
120 previous_search = null;90 previous_search = null;
121 previous_global_search = null;91 previous_global_search = null;
122 previous_active_section = Section.LAST_SECTION; /* Must be an invalid section! */92
123
124 build_app_menu_index ();93 build_app_menu_index ();
125 94
126 file_icon_cache = new HashTable<string,Icon>(str_hash, str_equal);95 file_icon_cache = new HashTable<string,Icon>(str_hash, str_equal);
96
97 scope = new Unity.Scope ("/com/canonical/unity/scope/applications");
98 //scope.icon = @"$(Config.PREFIX)/share/unity/themes/applications.png";
127 99
128 /* Listen for section changes */100 /* Listen for changes to the lens scope search */
129 applications.notify["active-section"].connect (101 scope.notify["active-search"].connect (
130 (obj, pspec) => {102 (obj, pspec) => {
131 if (!all_models_synced)103 var search = scope.active_search;
132 return;104
133
134 if (previous_active_section == applications.active_section)
135 return;
136
137 var search = applications.active_search;
138 var section = (Section) applications.active_section;
139 update_entry_search.begin (search, section);
140
141 previous_search = search;
142 previous_active_section = applications.active_section;
143 }
144 );
145
146 /* Listen for changes to the place entry search */
147 applications.notify["active-search"].connect (
148 (obj, pspec) => {
149 if (!all_models_synced)
150 return;
151
152 var search = applications.active_search;
153 Section section = (Section) applications.active_section;
154
155 if (!Utils.search_has_really_changed (previous_search, search))105 if (!Utils.search_has_really_changed (previous_search, search))
156 return;106 return;
107
108 update_scope_search.begin (search);
109 previous_search = search;
110 }
111 );
112
113 /* Re-do the search if the filters changed */
114 scope.filters_changed.connect (
115 () => {
116 var search = scope.active_search;
117 if (search.search_string == null)
118 return;
119
120 update_scope_search.begin (search);
121 previous_search = search;
157 122
158 update_entry_search.begin (search, section);
159 previous_search = search;
160 }123 }
161 );124 );
162125
163 /* Listen for changes to the global search aka Dash search */126 /* Listen for changes to the global search aka Dash search */
164 applications.notify["active-global-search"].connect (127 scope.notify["active-global-search"].connect (
165 (obj, pspec) => {128 (obj, pspec) => {
166 if (!all_models_synced)129 var search = scope.active_global_search;
167 return;
168130
169 var search = applications.active_global_search;
170
171 if (!Utils.search_has_really_changed (previous_global_search, search))131 if (!Utils.search_has_really_changed (previous_global_search, search))
172 return;132 return;
173 133
174 update_global_search.begin(search);134 update_global_search.begin (search);
175 previous_global_search = search;135 previous_global_search = search;
176 }136 }
177 );137 );
178138
139 scope.activate_uri.connect (activate);
140
179 /* Listen for changes in the installed applications */141 /* Listen for changes in the installed applications */
180 AppInfoManager.get_instance().changed.connect (on_appinfo_changed);142 AppInfoManager.get_instance().changed.connect (on_appinfo_changed);
181 143
182 /* Now start the RunEntry */144 /* Now start the RunEntry */
183 runner = new Unity.ApplicationsPlace.Runner (this);145 runner = new Unity.ApplicationsLens.Runner (this);
184 146
185 try {147 try {
186 uri_regex = new Regex ("^[a-z]+:.+$");148 uri_regex = new Regex ("^[a-z]+:.+$");
@@ -189,131 +151,89 @@
189 critical ("Failed to compile URI regex. URL launching will be disabled");151 critical ("Failed to compile URI regex. URL launching will be disabled");
190 }152 }
191 153
192154 lens = new Unity.Lens ("/com/canonical/unity/lens/applications", "applications");
193 /* The last thing we do is export the controller. Once that is up,155 lens.search_hint = _("Search Applications");
194 * clients will expect the SharedModels to work */156 lens.visible = true;
195 control = new Unity.PlaceController ("/com/canonical/unity/applicationsplace");157 lens.search_in_global = true;
196 control.add_entry (applications);158 populate_categories ();
197 control.add_entry (runner.place_entry);159 populate_filters();
198 control.activation = this;160 lens.add_local_scope (scope);
199 try {161 lens.export ();
200 control.export ();162 }
201 } catch (IOError error) {163
202 critical ("Failed to export DBus service for '%s': %s",164 /* Pre-populates the type queries so it's easier/faster to build our search */
203 control.dbus_path, error.message);165 private void populate_type_queries ()
204 }166 {
205167 type_queries = new HashTable<string, string> (null, null);
206 /* We should not start manipulating any of our models before they are168 type_queries.insert ("all", "NOT category:XYZ");
207 * all synchronized. When they are we set all_models_synced = true */169
208 sections_model.notify["synchronized"].connect (check_models_synced);170 type_queries.insert ("accessories", "(category:Utility AND NOT category:Accessibility)");
209 groups_model.notify["synchronized"].connect (check_models_synced);171 type_queries.insert ("education", "(category:Education AND NOT category:Science)");
210 global_groups_model.notify["synchronized"].connect (check_models_synced);172 type_queries.insert ("game", "category:Game");
211 results_model.notify["synchronized"].connect (check_models_synced);173 type_queries.insert ("graphics", "category:Graphics");
212 global_results_model.notify["synchronized"].connect (check_models_synced);174 type_queries.insert ("internet", "category:Network");
213 all_models_synced = false;175 type_queries.insert ("fonts", "category:Fonts"); // FIXME: wtf?
214 }176 type_queries.insert ("office", "category:Office");
215177 type_queries.insert ("media", "category:AudioVideo");
216 /* The check_models_synced() method acts like a latch - once all models178 type_queries.insert ("customization", "category:Settings");
217 * have reported themselves to be synchronized we set179 type_queries.insert ("accessibility", "(category:Accessibility AND NOT category:Settings)");
218 * all_models_synced = true and tell the searches to re-check their state180 type_queries.insert ("developer", "category:Development"); // FIXME emacs.desktop should be added
219 * as they should refuse to run when all_models_synced == false */181 type_queries.insert ("science-and-engineering", "(category:Science OR category:Engineering)");
220 private void check_models_synced (Object obj, ParamSpec pspec)182 type_queries.insert ("system", "(category:System OR category:Security)");
221 {183 }
222 if ((applications.sections_model as Dee.SharedModel).synchronized &&184
223 (applications.entry_renderer_info.groups_model as Dee.SharedModel).synchronized &&185 private void populate_categories ()
224 (applications.entry_renderer_info.results_model as Dee.SharedModel).synchronized &&186 {
225 (applications.global_renderer_info.groups_model as Dee.SharedModel).synchronized &&187 Unity.Category[] categories = {};
226 (applications.global_renderer_info.results_model as Dee.SharedModel).synchronized) {188
227 if (all_models_synced == false)189 var cat = new Unity.Category (_("Most Frequently Used"),
228 {190 ICON_PATH + "category-mostused.svg");
229 all_models_synced = true;191 categories += cat;
230 192
231 populate_sections ();193 cat = new Unity.Category (_("Installed"),
232 populate_groups (applications.entry_renderer_info.groups_model);194 ICON_PATH + "category-installed.svg");
233 populate_groups (applications.global_renderer_info.groups_model);195 categories += cat;
234 196
235 /* Emitting notify here will make us recheck if the search results197 cat = new Unity.Category (_("Apps Available for Download"),
236 * need update. In the negative case this is a noop */198 ICON_PATH + "category-available.svg");
237 applications.notify_property ("active-search");199 categories += cat;
238 applications.notify_property ("active-global-search");200
239 }201 lens.categories = categories;
240 }202 }
241 }203
242204 private void populate_filters()
243 private void populate_sections ()205 {
244 {206 Unity.Filter[] filters = {};
245 var sections = applications.sections_model;207
246208 /* Type filter */
247 if (sections.get_n_rows() != 0)209 {
248 {210 var filter = new RadioOptionFilter ("type", _("Type"));
249 debug ("Sections model already populated. We probably cloned it off Unity. Rebuilding.");211 filter.add_option ("accessories", _("Accessories"));
250 sections.clear ();212 filter.add_option ("education", _("Education"));
251 }213 filter.add_option ("games", _("Games"));
252214 filter.add_option ("graphics", _("Graphics"));
253 sections.append (_("All Applications"), "");215 filter.add_option ("internet", _("Internet"));
254 sections.append (_("Accessories"), "");216 filter.add_option ("fonts", _("Fonts"));
255 sections.append (_("Universal Access"), "");217 filter.add_option ("office", _("Office"));
256 sections.append (_("Developer Tools"), "");218 filter.add_option ("media", _("Media"));
257 sections.append (_("Education"), "");219 filter.add_option ("customization", _("Customization"));
258 sections.append (_("Science & Engineering"), "");220 filter.add_option ("accessibility", _("Accessibility"));
259 sections.append (_("Games"), "");221 filter.add_option ("developer", _("Developer"));
260 sections.append (_("Graphics"), "");222 filter.add_option ("science-and-engineering", _("Science & Engineering"));
261 sections.append (_("Internet"), "");223 filter.add_option ("system", _("System"));
262 sections.append (_("Multimedia"), "");224
263 sections.append (_("Office"), "");225 filters += filter;
264 sections.append (_("Themes & Tweaks"), "");226 }
265 sections.append (_("System"), "");227
266 }228 /* Rating filter */
267229 {
268 private void populate_groups (Dee.Model groups)230 var filter = new RatingsFilter("rating", _("Rating"));
269 {231 filters += filter;
270 if (groups.get_n_rows() != 0)232 }
271 {233
272 debug ("The groups model already populated. We probably cloned it off Unity. Rebuilding.");234 lens.filters = filters;
273 groups.clear ();235 }
274 }236
275
276 groups.append ("UnityShowcaseRenderer",
277 _("Most Frequently Used"),
278 ICON_PATH + "group-mostused.svg");
279 groups.append ("UnityDefaultRenderer",
280 _("Installed"),
281 ICON_PATH + "group-installed.svg");
282 groups.append ("UnityDefaultRenderer",
283 _("Apps Available for Download"),
284 ICON_PATH + "group-available.svg");
285 groups.append ("UnityEmptySearchRenderer",
286 "No search results", // No i18n, should never be rendered
287 "");
288 groups.append ("UnityEmptySectionRenderer",
289 "Empty section", // No i18n, should never be rendered
290 "");
291
292 /* Always expand the Installed group */
293 applications.entry_renderer_info.set_hint ("ExpandedGroups",
294 @"$((uint)Group.INSTALLED)");
295 }
296
297 private void populate_section_queries ()
298 {
299 /* XDG category names. Not for translation. */
300 /* We need the hack for ALL_APPLICATIONS below because Xapian doesn't
301 * like '' or '*' queries */
302 section_queries.add ("NOT category:XYZ"); //ALL_APPLICATIONS
303 section_queries.add ("(category:Utility AND NOT category:Accessibility)"); //ACCESSORIES
304 section_queries.add ("(category:Accessibility AND NOT category:Settings)"); //UNIVERSAL_ACCESS
305 section_queries.add ("category:Development"); //DEVELOPER_TOOLS FIXME emacs.desktop should be added
306 section_queries.add ("(category:Education AND NOT category:Science)"); // EDUCATION
307 section_queries.add ("(category:Science OR category:Engineering)"); // SCIENCE
308 section_queries.add ("category:Game"); // GAMES
309 section_queries.add ("category:Graphics"); // GRAPHICS
310 section_queries.add ("category:Network"); // INTERNET
311 section_queries.add ("category:AudioVideo"); // MULTIMEDIA
312 section_queries.add ("category:Office"); // OFFICE
313 section_queries.add ("category:Settings"); // THEMES
314 section_queries.add ("(category:System OR category:Security)"); // SYSTEM
315 }
316
317 /* Load xdg menu info and build a Xapian index over it.237 /* Load xdg menu info and build a Xapian index over it.
318 * Do throttled re-index if the menu changes */238 * Do throttled re-index if the menu changes */
319 private bool build_app_menu_index ()239 private bool build_app_menu_index ()
@@ -323,10 +243,10 @@
323 debug ("Building initial application menu");243 debug ("Building initial application menu");
324 244
325 /* We need INCLUDE_NODISPLAY to employ proper de-duping between245 /* We need INCLUDE_NODISPLAY to employ proper de-duping between
326 * the Installed and Availabale groups. If a NoDisplay app is installed,246 * the Installed and Availabale categorys. If a NoDisplay app is installed,
327 * eg. Evince, it wont otherwise be in the menu index, only in the247 * eg. Evince, it wont otherwise be in the menu index, only in the
328 * S-C index - thus show up in the Available group */248 * S-C index - thus show up in the Available category */
329 app_menu = GMenu.Tree.lookup ("unity-place-applications.menu",249 app_menu = GMenu.Tree.lookup ("unity-lens-applications.menu",
330 GMenu.TreeFlags.INCLUDE_NODISPLAY);250 GMenu.TreeFlags.INCLUDE_NODISPLAY);
331 251
332 app_menu.add_monitor ((menu) => {252 app_menu.add_monitor ((menu) => {
@@ -350,7 +270,7 @@
350270
351 /* Called when our app_menu structure changes - probably because something271 /* Called when our app_menu structure changes - probably because something
352 * has been installed or removed. We rebuild the index and update the272 * has been installed or removed. We rebuild the index and update the
353 * result models for global and entry. We need to update both because273 * result models for global and scope. We need to update both because
354 * we can't know exactly what Unity may be showing */274 * we can't know exactly what Unity may be showing */
355 private bool build_app_menu_index_and_result_models ()275 private bool build_app_menu_index_and_result_models ()
356 {276 {
@@ -359,8 +279,8 @@
359 debug ("Updating result models");279 debug ("Updating result models");
360 previous_search = null;280 previous_search = null;
361 previous_global_search = null;281 previous_global_search = null;
362 applications.notify_property ("active-search");282 scope.notify_property ("active-search");
363 applications.notify_property ("active-global-search");283 scope.notify_property ("active-global-search");
364 284
365 return false;285 return false;
366 }286 }
@@ -377,12 +297,13 @@
377 zg_templates.add ((ev as GLib.Object).ref());297 zg_templates.add ((ev as GLib.Object).ref());
378 }298 }
379299
380 private string prepare_zg_search_string (PlaceSearch? search, Section section)300 private string prepare_zg_search_string (Unity.LensSearch? search,
301 string type_id="all")
381 {302 {
382 303
383 string s;304 string s;
384 if (search != null)305 if (search != null)
385 s = search.get_search_string ();306 s = search.search_string;
386 else307 else
387 s = "";308 s = "";
388309
@@ -394,26 +315,30 @@
394 if (s != "")315 if (s != "")
395 s = @"app:($s)";316 s = @"app:($s)";
396 else317 else
397 return section_queries.get(section);318 return type_queries.lookup(type_id);
398 319
399 if (section == Section.ALL_APPLICATIONS)320 if (type_id == "all")
400 return s;321 return s;
401 else322 else
402 return s + @" AND $(section_queries.get(section))";323 return s + @" AND $(type_queries.lookup(type_id))";
403 }324 }
404325
405 private async void update_entry_search (PlaceSearch? search,326 private async void update_scope_search (Unity.LensSearch? search)
406 Section section)
407 {327 {
408 /* Prevent concurrent searches and concurrent updates of our models,328 /* Prevent concurrent searches and concurrent updates of our models,
409 * by preventing any notify signals from propagating to us.329 * by preventing any notify signals from propagating to us.
410 * Important: Remeber to thaw the notifys again! */330 * Important: Remeber to thaw the notifys again! */
411 applications.freeze_notify ();331 scope.freeze_notify ();
412332
413 var model = applications.entry_renderer_info.results_model;333 var model = scope.results_model;
414 model.clear ();334 model.clear ();
415 335
416 string pkg_search_string = prepare_pkg_search_string (search, section);336 var filter = scope.get_filter ("type") as RadioOptionFilter;
337 Unity.FilterOption? option = filter.get_active_option ();
338 string type_id = option == null ? "all" : option.id;
339
340 string pkg_search_string = prepare_pkg_search_string (search, type_id);
341
417 bool has_search = !Utils.search_is_invalid (search);342 bool has_search = !Utils.search_is_invalid (search);
418 343
419 Timer timer = new Timer ();344 Timer timer = new Timer ();
@@ -425,7 +350,7 @@
425 Unity.Package.Sort.BY_RELEVANCY :350 Unity.Package.Sort.BY_RELEVANCY :
426 Unity.Package.Sort.BY_NAME);351 Unity.Package.Sort.BY_NAME);
427 add_pkg_search_result (appresults, installed_uris, available_uris, model,352 add_pkg_search_result (appresults, installed_uris, available_uris, model,
428 Group.INSTALLED);353 Category.INSTALLED);
429 354
430 timer.stop ();355 timer.stop ();
431 debug ("Entry search listed %i Installed apps in %fms for query: %s",356 debug ("Entry search listed %i Installed apps in %fms for query: %s",
@@ -437,7 +362,7 @@
437 * So we can update the UI quicker */362 * So we can update the UI quicker */
438 (model as Dee.SharedModel).flush_revision_queue ();363 (model as Dee.SharedModel).flush_revision_queue ();
439 364
440 var zg_search_string = prepare_zg_search_string (search, section); 365 var zg_search_string = prepare_zg_search_string (search, type_id);
441366
442 try {367 try {
443 timer.start ();368 timer.start ();
@@ -449,7 +374,7 @@
449 Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,374 Zeitgeist.ResultType.MOST_POPULAR_SUBJECTS,
450 null);375 null);
451376
452 append_events_with_group (results, model, Group.MOST_USED, section);377 append_events_with_category (results, model, Category.MOST_USED);
453 378
454 timer.stop ();379 timer.stop ();
455 debug ("Entry search found %u/%u Most Used apps in %fms for query '%s'",380 debug ("Entry search found %u/%u Most Used apps in %fms for query '%s'",
@@ -458,7 +383,7 @@
458383
459 } catch (GLib.Error e) {384 } catch (GLib.Error e) {
460 warning ("Error performing search '%s': %s",385 warning ("Error performing search '%s': %s",
461 search.get_search_string (), e.message);386 search.search_string, e.message);
462 }387 }
463 388
464 /* We force a flush of the shared model's revision queue here because389 /* We force a flush of the shared model's revision queue here because
@@ -475,7 +400,7 @@
475 Unity.Package.SearchType.PREFIX,400 Unity.Package.SearchType.PREFIX,
476 Unity.Package.Sort.BY_RELEVANCY);401 Unity.Package.Sort.BY_RELEVANCY);
477 add_pkg_search_result (pkgresults, installed_uris, available_uris,402 add_pkg_search_result (pkgresults, installed_uris, available_uris,
478 model, Group.AVAILABLE);403 model, Category.AVAILABLE);
479 timer.stop ();404 timer.stop ();
480 debug ("Entry search listed %i Available apps in %fms for query: %s",405 debug ("Entry search listed %i Available apps in %fms for query: %s",
481 pkgresults.num_hits, timer.elapsed ()*1000, pkg_search_string);406 pkgresults.num_hits, timer.elapsed ()*1000, pkg_search_string);
@@ -483,27 +408,21 @@
483 else if (pkgsearcher != null)408 else if (pkgsearcher != null)
484 {409 {
485 timer.start ();410 timer.start ();
486 string? category = (section == Section.ALL_APPLICATIONS ?411 string? category = null;
487 null : section_queries.get(section));
488 var random_pkgresults = pkgsearcher.get_random_apps (category, 12);412 var random_pkgresults = pkgsearcher.get_random_apps (category, 12);
489 add_pkg_search_result (random_pkgresults, installed_uris, available_uris,413 add_pkg_search_result (random_pkgresults, installed_uris, available_uris,
490 model, Group.AVAILABLE, 6);414 model, Category.AVAILABLE, 6);
491 timer.stop ();415 timer.stop ();
492 debug ("Entry search listed %i random Available apps in %fms",416 debug ("Entry search listed %i random Available apps in %fms",
493 random_pkgresults.num_hits, timer.elapsed ()*1000);417 random_pkgresults.num_hits, timer.elapsed ()*1000);
494 }418 }
495 419
496 if (has_search)
497 check_empty_search (search, model);
498 else
499 check_empty_section (section, model);
500
501 /* Allow new searches once we enter an idle again.420 /* Allow new searches once we enter an idle again.
502 * We don't do it directly from here as that could mean we start421 * We don't do it directly from here as that could mean we start
503 * changing the model even before we had flushed out current changes422 * changing the model even before we had flushed out current changes
504 */423 */
505 Idle.add (() => {424 Idle.add (() => {
506 applications.thaw_notify ();425 scope.thaw_notify ();
507 return false;426 return false;
508 });427 });
509 428
@@ -511,9 +430,9 @@
511 search.finished ();430 search.finished ();
512 }431 }
513 432
514 private async void update_global_search (PlaceSearch? search)433 private async void update_global_search (Unity.LensSearch? search)
515 {434 {
516 var model = applications.global_renderer_info.results_model;435 var model = scope.global_results_model;
517 436
518 model.clear ();437 model.clear ();
519 438
@@ -525,10 +444,9 @@
525 /* Prevent concurrent searches and concurrent updates of our models,444 /* Prevent concurrent searches and concurrent updates of our models,
526 * by preventing any notify signals from propagating to us.445 * by preventing any notify signals from propagating to us.
527 * Important: Remember to thaw the notifys again! */446 * Important: Remember to thaw the notifys again! */
528 applications.freeze_notify (); 447 scope.freeze_notify ();
529 448
530 var search_string = prepare_pkg_search_string (search,449 var search_string = prepare_pkg_search_string (search, "all");
531 Section.ALL_APPLICATIONS);
532 Set<string> installed_uris = new HashSet<string> ();450 Set<string> installed_uris = new HashSet<string> ();
533 Set<string> available_uris = new HashSet<string> ();451 Set<string> available_uris = new HashSet<string> ();
534 var timer = new Timer ();452 var timer = new Timer ();
@@ -536,14 +454,14 @@
536 Unity.Package.SearchType.PREFIX,454 Unity.Package.SearchType.PREFIX,
537 Unity.Package.Sort.BY_RELEVANCY); 455 Unity.Package.Sort.BY_RELEVANCY);
538 add_pkg_search_result (appresults, installed_uris, available_uris, model,456 add_pkg_search_result (appresults, installed_uris, available_uris, model,
539 Group.INSTALLED);457 Category.INSTALLED);
540 458
541 timer.stop ();459 timer.stop ();
542 debug ("Global search listed %i Installed apps in %fms for query: %s",460 debug ("Global search listed %i Installed apps in %fms for query: %s",
543 appresults.num_hits, timer.elapsed ()*1000, search_string);461 appresults.num_hits, timer.elapsed ()*1000, search_string);
544462
545 // Dowloadable Apps search disabled from global search463 // Dowloadable Apps search disabled from global search
546 // See https://bugs.launchpad.net/unity-place-applications/+bug/733669464 // See https://bugs.launchpad.net/unity-lens-applications/+bug/733669
547 /*465 /*
548 if (pkgsearcher != null)466 if (pkgsearcher != null)
549 { 467 {
@@ -558,7 +476,7 @@
558 Unity.Package.SearchType.PREFIX,476 Unity.Package.SearchType.PREFIX,
559 Unity.Package.Sort.BY_RELEVANCY);477 Unity.Package.Sort.BY_RELEVANCY);
560 add_pkg_search_result (pkgresults, installed_uris, available_uris,478 add_pkg_search_result (pkgresults, installed_uris, available_uris,
561 model, Group.AVAILABLE);479 model, Category.AVAILABLE);
562 timer.stop ();480 timer.stop ();
563 debug ("Global search listed %i Available apps in %fms for query: %s",481 debug ("Global search listed %i Available apps in %fms for query: %s",
564 pkgresults.num_hits, timer.elapsed ()*1000, search_string);482 pkgresults.num_hits, timer.elapsed ()*1000, search_string);
@@ -570,7 +488,7 @@
570 * changing the model even before we had flushed out current changes488 * changing the model even before we had flushed out current changes
571 */489 */
572 Idle.add (() => {490 Idle.add (() => {
573 applications.thaw_notify ();491 scope.thaw_notify ();
574 return false;492 return false;
575 });493 });
576 494
@@ -578,18 +496,18 @@
578 search.finished ();496 search.finished ();
579 }497 }
580 498
581 private string prepare_pkg_search_string (PlaceSearch? search, Section section)499 private string prepare_pkg_search_string (Unity.LensSearch? search, string type_id="all")
582 { 500 {
583 if (Utils.search_is_invalid (search))501 if (Utils.search_is_invalid (search))
584 {502 {
585 if (section == Section.ALL_APPLICATIONS)503 if (type_id == "all")
586 return "type:Application";504 return "type:Application";
587 else505 else
588 return @"type:Application AND $(section_queries.get(section))";506 return @"type:Application AND $(type_queries.lookup(type_id))";
589 }507 }
590 else508 else
591 {509 {
592 var s = search.get_search_string ();510 var s = search.search_string;
593511
594 s = s.strip ();512 s = s.strip ();
595 513
@@ -600,10 +518,10 @@
600 * match 'd-feet' etc. */518 * match 'd-feet' etc. */
601 s = s.delimit ("-", ' ');519 s = s.delimit ("-", ' ');
602520
603 if (section == Section.ALL_APPLICATIONS)521 if (type_id == "all")
604 return @"type:Application AND $s";522 return @"type:Application AND $s";
605 else523 else
606 return @"type:Application AND $(section_queries.get(section)) AND $s";524 return @"type:Application AND $(type_queries.lookup(type_id)) AND $s";
607 }525 }
608 }526 }
609 527
@@ -668,14 +586,14 @@
668 private void on_appinfo_changed (string id, AppInfo? appinfo)586 private void on_appinfo_changed (string id, AppInfo? appinfo)
669 {587 {
670 debug ("Application changed: %s", id);588 debug ("Application changed: %s", id);
671 //update_entry_results_model.begin ();589 //update_scope_results_model.begin ();
672 }590 }
673 591
674 private void add_pkg_search_result (Unity.Package.SearchResult results,592 private void add_pkg_search_result (Unity.Package.SearchResult results,
675 Set<string> installed_uris,593 Set<string> installed_uris,
676 Set<string> available_uris,594 Set<string> available_uris,
677 Dee.Model model,595 Dee.Model model,
678 Group group,596 Category category,
679 uint max_add=0)597 uint max_add=0)
680 {598 {
681 var appmanager = AppInfoManager.get_instance();599 var appmanager = AppInfoManager.get_instance();
@@ -699,20 +617,20 @@
699 /* Extract basic metadata and register de-dupe keys */617 /* Extract basic metadata and register de-dupe keys */
700 string display_name;618 string display_name;
701 string comment;619 string comment;
702 switch (group)620 switch (category)
703 {621 {
704 case Group.INSTALLED:622 case Category.INSTALLED:
705 installed_uris.add (uri);623 installed_uris.add (uri);
706 display_name = app.get_display_name ();624 display_name = app.get_display_name ();
707 comment = app.get_description ();625 comment = app.get_description ();
708 break;626 break;
709 case Group.AVAILABLE:627 case Category.AVAILABLE:
710 available_uris.add (uri);628 available_uris.add (uri);
711 display_name = pkginfo.application_name;629 display_name = pkginfo.application_name;
712 comment = "";630 comment = "";
713 break;631 break;
714 default:632 default:
715 warning (@"Illegal group for package search $(group)");633 warning (@"Illegal category for package search $(category)");
716 continue;634 continue;
717 } 635 }
718 636
@@ -722,7 +640,7 @@
722 if (app != null && !app.should_show ())640 if (app != null && !app.should_show ())
723 continue;641 continue;
724 642
725 if (group == Group.AVAILABLE)643 if (category == Category.AVAILABLE)
726 {644 {
727 /* If we have an available item, which is not a dupe, but is645 /* If we have an available item, which is not a dupe, but is
728 * installed anyway, we weed it out here, because it's probably646 * installed anyway, we weed it out here, because it's probably
@@ -731,7 +649,7 @@
731 if (app != null)649 if (app != null)
732 continue; 650 continue;
733 651
734 /* Apps that are not installed, ie. in the Available group652 /* Apps that are not installed, ie. in the Available category
735 * use the 'unity-install://pkgname/Full App Name' URI scheme,653 * use the 'unity-install://pkgname/Full App Name' URI scheme,
736 * but only use that after we've de-duped the results.654 * but only use that after we've de-duped the results.
737 * But only change the URI *after* we've de-duped the results! */655 * But only change the URI *after* we've de-duped the results! */
@@ -742,7 +660,7 @@
742 Icon icon = find_pkg_icon (pkginfo);660 Icon icon = find_pkg_icon (pkginfo);
743 661
744 model.append (uri, icon.to_string (),662 model.append (uri, icon.to_string (),
745 group,"application/x-desktop",663 category,"application/x-desktop",
746 display_name != null ? display_name : "",664 display_name != null ? display_name : "",
747 comment != null ? comment : "");665 comment != null ? comment : "");
748 666
@@ -754,10 +672,10 @@
754 }672 }
755673
756 /**674 /**
757 * Override of the default activation handler. The apps place daemon675 * Override of the default activation handler. The apps lens daemon
758 * can handle activation of installable apps using the Software Center676 * can handle activation of installable apps using the Software Center
759 */677 */
760 public async uint32 activate (string uri)678 public Unity.ActivationResponse activate (string uri)
761 {679 {
762 string[] args;680 string[] args;
763 string exec_or_dir = null;681 string exec_or_dir = null;
@@ -778,9 +696,10 @@
778 AppInfo.launch_default_for_uri (orig, null);696 AppInfo.launch_default_for_uri (orig, null);
779 } catch (GLib.Error error) {697 } catch (GLib.Error error) {
780 warning ("Failed to launch URI %s", orig);698 warning ("Failed to launch URI %s", orig);
781 return ActivationStatus.NOT_ACTIVATED;699 return new Unity.ActivationResponse(Unity.HandledType.NOT_HANDLED);
782 }700 }
783 return ActivationStatus.ACTIVATED_HIDE_DASH;701 return new Unity.ActivationResponse(Unity.HandledType.HIDE_DASH);
702
784 } else {703 } else {
785 exec_or_dir = Utils.subst_tilde (orig);704 exec_or_dir = Utils.subst_tilde (orig);
786 args = exec_or_dir.split (" ", 0);705 args = exec_or_dir.split (" ", 0);
@@ -792,7 +711,7 @@
792 else711 else
793 {712 {
794 debug ("Declined activation of URI '%s': Expected URI scheme unity-install:// or unity-runner://", uri);713 debug ("Declined activation of URI '%s': Expected URI scheme unity-install:// or unity-runner://", uri);
795 return ActivationStatus.NOT_ACTIVATED;714 return new Unity.ActivationResponse(Unity.HandledType.NOT_HANDLED);
796 }715 }
797716
798 if ((exec_or_dir != null) && FileUtils.test (exec_or_dir, FileTest.IS_DIR))717 if ((exec_or_dir != null) && FileUtils.test (exec_or_dir, FileTest.IS_DIR))
@@ -802,7 +721,7 @@
802 } catch (GLib.Error err) {721 } catch (GLib.Error err) {
803 warning ("Failed to open current folder '%s' in file manager: %s",722 warning ("Failed to open current folder '%s' in file manager: %s",
804 exec_or_dir, err.message);723 exec_or_dir, err.message);
805 return ActivationStatus.NOT_ACTIVATED;724 return new Unity.ActivationResponse(Unity.HandledType.NOT_HANDLED);
806 }725 }
807 }726 }
808 else727 else
@@ -813,20 +732,19 @@
813 } catch (SpawnError e) {732 } catch (SpawnError e) {
814 warning ("Failed to spawn software-center or direct URI activation '%s': %s",733 warning ("Failed to spawn software-center or direct URI activation '%s': %s",
815 uri, e.message);734 uri, e.message);
816 return ActivationStatus.NOT_ACTIVATED;735 return new Unity.ActivationResponse(Unity.HandledType.NOT_HANDLED);
817 }736 }
818 }737 }
819738
820 return ActivationStatus.ACTIVATED_HIDE_DASH;739 return new Unity.ActivationResponse(Unity.HandledType.HIDE_DASH);
821 740
822 }741 }
823742
824 /* Appends the subject URIs from a set of Zeitgeist.Events to our Dee.Model743 /* Appends the subject URIs from a set of Zeitgeist.Events to our Dee.Model
825 * assuming that these events are already sorted */744 * assuming that these events are already sorted */
826 public void append_events_with_group (Zeitgeist.ResultSet events,745 public void append_events_with_category (Zeitgeist.ResultSet events,
827 Dee.Model results,746 Dee.Model results,
828 uint group_id,747 uint category_id)
829 int section_filter = -1)
830 {748 {
831 foreach (var ev in events)749 foreach (var ev in events)
832 {750 {
@@ -848,90 +766,12 @@
848 if (!app.should_show ())766 if (!app.should_show ())
849 continue; 767 continue;
850 768
851 results.append (app_uri, app.get_icon().to_string(), group_id,769 results.append (app_uri, app.get_icon().to_string(), category_id,
852 "application/x-desktop", app.get_display_name (),770 "application/x-desktop", app.get_display_name (),
853 app.get_description ());771 app.get_description ());
854 }772 }
855 }773 }
856 774
857 public void check_empty_search (PlaceSearch? search,
858 Dee.Model results_model)
859 {
860 if (results_model.get_n_rows () > 0)
861 return;
862
863 if (Utils.search_is_invalid (search))
864 return;
865
866 results_model.append ("", "", Group.EMPTY_SEARCH, "",
867 _("Your search did not match any applications"),
868 "");
869
870 // FIXME: Use prefered browser
871 // FIXME: URL escape search string
872 results_model.append (@"http://google.com/#q=$(search.get_search_string())",
873 "", Group.EMPTY_SEARCH, "",
874 _("Search the web"), "");
875 }
876
877 public void check_empty_section (Section section,
878 Dee.Model results_model)
879 {
880 if (results_model.get_n_rows () > 0)
881 return;
882
883 string msg;
884
885 switch (section)
886 {
887 case Section.ALL_APPLICATIONS:
888 msg = _("There are no applications installed on this computer");
889 break;
890 case Section.ACCESSORIES:
891 msg = _("There are no accessories installed on this computer");
892 break;
893 case Section.UNIVERSAL_ACCESS:
894 msg = _("There are no universal access applications installed on this computer");
895 break;
896 case Section.DEVELOPER_TOOLS:
897 msg = _("There are no developer tools installed on this computer");
898 break;
899 case Section.EDUCATION:
900 msg = _("There are no educational applications installed on this computer");
901 break;
902 case Section.SCIENCE:
903 msg = _("There are no scientific or engineering applications installed on this computer");
904 break;
905 case Section.GAMES:
906 msg = _("There are no games installed on this computer");
907 break;
908 case Section.GRAPHICS:
909 msg = _("There are no graphics applications installed on this computer");
910 break;
911 case Section.INTERNET:
912 msg = _("There are no internet applications installed on this computer");
913 break;
914 case Section.MULTIMEDIA:
915 msg = _("There are no multimedia applications installed on this computer");
916 break;
917 case Section.OFFICE:
918 msg = _("There are no office applications installed on this computer");
919 break;
920 case Section.THEMES:
921 msg = _("There are no theming or tweaking applications installed on this computer");
922 break;
923 case Section.SYSTEM:
924 msg = _("There are no system applications installed on this computer");
925 break;
926 default:
927 msg = _("There are no applications installed on this computer");
928 warning ("Unknown section: %u", section);
929 break;
930 }
931
932 results_model.append ("", "", Group.EMPTY_SECTION, "", msg, "");
933 }
934
935 } /* END: class Daemon */775 } /* END: class Daemon */
936776
937} /* namespace */777} /* namespace */
938778
=== modified file 'src/main.vala'
--- src/main.vala 2011-01-31 10:37:41 +0000
+++ src/main.vala 2011-08-04 08:16:52 +0000
@@ -20,7 +20,7 @@
20using GLib;20using GLib;
21using Config;21using Config;
2222
23namespace Unity.ApplicationsPlace {23namespace Unity.ApplicationsLens {
2424
25 static Application? app = null;25 static Application? app = null;
26 static Daemon? daemon = null;26 static Daemon? daemon = null;
@@ -66,7 +66,7 @@
66 * making it race against GDBus' worker thread to export our66 * making it race against GDBus' worker thread to export our
67 * objects on the bus before/after owning our name and receiving67 * objects on the bus before/after owning our name and receiving
68 * method calls on our objects (which may not yet be up!)*/68 * method calls on our objects (which may not yet be up!)*/
69 if (dbus_name_has_owner ("com.canonical.Unity.ApplicationsPlace"))69 if (dbus_name_has_owner ("com.canonical.Unity.Lens.Applications"))
70 {70 {
71 print ("Another instance of the Unity Applications Daemon " +71 print ("Another instance of the Unity Applications Daemon " +
72 "already appears to be running.\nBailing out.\n");72 "already appears to be running.\nBailing out.\n");
@@ -78,7 +78,7 @@
78 daemon = new Daemon ();78 daemon = new Daemon ();
79 79
80 /* Use GApplication directly for single instance app functionality */80 /* Use GApplication directly for single instance app functionality */
81 app = new Application ("com.canonical.Unity.ApplicationsPlace",81 app = new Application ("com.canonical.Unity.Lens.Applications",
82 ApplicationFlags.IS_SERVICE);82 ApplicationFlags.IS_SERVICE);
83 try {83 try {
84 app.register ();84 app.register ();
8585
=== modified file 'src/runner.vala'
--- src/runner.vala 2011-07-20 06:43:25 +0000
+++ src/runner.vala 2011-08-04 08:16:52 +0000
@@ -21,7 +21,7 @@
21using Gee;21using Gee;
2222
2323
24namespace Unity.ApplicationsPlace {24namespace Unity.ApplicationsLens {
2525
26 private class AboutEntry {26 private class AboutEntry {
27 public string name;27 public string name;
@@ -39,20 +39,21 @@
39 public class Runner: GLib.Object39 public class Runner: GLib.Object
40 { 40 {
41 41
42 private Unity.ApplicationsPlace.Daemon daemon; 42 private Unity.ApplicationsLens.Daemon daemon;
43 private const string BUS_NAME_PREFIX = "com.canonical.Unity.ApplicationsPlace.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.PlaceEntryInfo place_entry;49 public Unity.Lens lens;
50 public Unity.Scope scope;
5051
51 private bool all_models_synced;52 private bool all_models_synced;
5253
53 /* We remember the previous search so we can figure out if we should do54 /* We remember the previous search so we can figure out if we should do
54 * incremental filtering of the result models */55 * incremental filtering of the result models */
55 private PlaceSearch? previous_search; 56 private LensSearch? previous_search;
56 57
57 private Gee.HashMap<string,AboutEntry> about_entries;58 private Gee.HashMap<string,AboutEntry> about_entries;
58 private Gee.List<string> executables;59 private Gee.List<string> executables;
@@ -60,22 +61,61 @@
6061
61 private Settings gp_settings;62 private Settings gp_settings;
62 63
63 public Runner (Unity.ApplicationsPlace.Daemon daemon)64 public Runner (Unity.ApplicationsLens.Daemon daemon)
64 {65 {
65 var sections_model = new Dee.SharedModel(BUS_NAME_PREFIX + "SectionsModel");66 /* First create scope */
66 sections_model.set_schema ("s", "s");67 scope = new Unity.Scope ("/com/canonical/unity/scope/commands");
6768 scope.search_in_global = false;
68 var groups_model = new Dee.SharedModel(BUS_NAME_PREFIX + "GroupsModel");69
69 groups_model.set_schema ("s", "s", "s");70 /* Listen for changes to the lens scope search */
7071 scope.notify["active-search"].connect (
71 var results_model = new Dee.SharedModel(BUS_NAME_PREFIX + "ResultsModel");72 (obj, pspec) => {
72 results_model.set_schema ("s", "s", "u", "s", "s", "s");73 var search = scope.active_search;
73 74
74 place_entry = new PlaceEntryInfo ("/com/canonical/unity/applicationsplace/runner");75 if (!Utils.search_has_really_changed (previous_search, search))
75 place_entry.sections_model = sections_model;76 return;
76 place_entry.entry_renderer_info.groups_model = groups_model;77
77 place_entry.entry_renderer_info.results_model = results_model;78 update_search.begin(search);
7879 previous_search = search;
80 }
81 );
82
83 /* Re-do the search if the filters changed */
84 scope.filters_changed.connect (
85 () => {
86 var search = scope.active_search;
87 if (search.search_string == null)
88 return;
89
90 update_search.begin(search);
91 previous_search = search;
92
93 }
94 );
95
96 // Listen for when the lens is hidden/shown by the Unity Shell
97 scope.notify["active"].connect(
98 (obj, pspec) => {
99 if (scope.active)
100 {
101 var search = scope.active_search;
102 update_search.begin(search);
103 previous_search = search;
104 }
105 }
106 );
107
108 scope.activate_uri.connect (daemon.activate);
109
110 /* Now create Lens */
111 lens = new Unity.Lens ("/com/canonical/unity/lens/commands", "commands");
112 lens.search_hint = _("Run a command");
113 lens.visible = false;
114 lens.search_in_global = false;
115 populate_categories ();
116 //populate_filters();
117 lens.add_local_scope (scope);
118 lens.export ();
79 previous_search = null;119 previous_search = null;
80 120
81 /* create the private about entries */121 /* create the private about entries */
@@ -89,78 +129,59 @@
89 history = new Gee.ArrayList<string> ();129 history = new Gee.ArrayList<string> ();
90 load_history ();130 load_history ();
91 131
92 /* Listen for changes to the place entry search */
93 place_entry.notify["active-search"].connect (
94 (obj, pspec) => {
95 if (!all_models_synced)
96 return;
97
98 var search = place_entry.active_search;
99
100 if (!Utils.search_has_really_changed (previous_search, search))
101 return;
102
103 update_search.begin(search);
104 previous_search = search;
105 }
106 );
107
108 // Listen for when the place is hidden/shown by the Unity Shell
109 place_entry.notify["active"].connect(
110 (obj, pspec) => {
111 if (place_entry.active)
112 {
113 var search = place_entry.active_search;
114 update_search.begin(search);
115 previous_search = search;
116 }
117 }
118 );
119
120 /* We should not start manipulating any of our models before they are
121 * all synchronized. When they are we set all_models_synced = true */
122 sections_model.notify["synchronized"].connect (check_models_synced);
123 groups_model.notify["synchronized"].connect (check_models_synced);
124 results_model.notify["synchronized"].connect (check_models_synced);
125 all_models_synced = false;
126
127 this.daemon = daemon;132 this.daemon = daemon;
128 133
129 }134 }
130135
131 private async void update_search (PlaceSearch? search)136 private void populate_categories ()
132 {137 {
133 var model = place_entry.entry_renderer_info.results_model;138 Unity.Category[] categories = {};
139
140 var cat = new Unity.Category (_("Results"),
141 ICON_PATH + "category-installed.svg");
142 categories += cat;
143
144 cat = new Unity.Category (_("History"),
145 ICON_PATH + "category-available.svg");
146
147 categories += cat;
148
149 lens.categories = categories;
150 }
151
152 private async void update_search (LensSearch? search)
153 {
154 var model = scope.results_model;
134 var executables_match = new Gee.ArrayList<string> ();155 var executables_match = new Gee.ArrayList<string> ();
135 var dirs_match = new Gee.ArrayList<string> ();156 var dirs_match = new Gee.ArrayList<string> ();
136 model.clear ();157 model.clear ();
137158
138 var search_string = search.get_search_string ();159 var search_string = search.search_string;
139 bool has_search = !Utils.search_is_invalid (search);160 bool has_search = !Utils.search_is_invalid (search);
140161
141 string uri; 162 string uri;
142 Icon icon;163 Icon icon;
143 string mimetype;164 string mimetype;
144 string display_name;165 string display_name;
145 var group_id = RunnerGroup.HISTORY;166 var category_id = RunnerCategory.HISTORY;
146167
147 foreach (var command in this.history)168 foreach (var command in this.history)
148 { 169 {
149 display_name = get_icon_uri_and_mimetype (command, out icon, out uri, out mimetype); 170 display_name = get_icon_uri_and_mimetype (command, out icon, out uri, out mimetype);
150 model.append (uri, icon.to_string (),171 model.append (uri, icon.to_string (),
151 group_id, mimetype,172 category_id, mimetype,
152 display_name,173 display_name,
153 null);174 null);
154 }175 }
155 176
156 /* Prevent concurrent searches and concurrent updates of our models,177 /* Prevent concurrent searches and concurrent updates of our models,
157 * by preventing any notify signals from propagating to us.178 * by preventing any notify signals from propagating to us.
158 * Important: Remember to thaw the notifys with release_entrylock()! */179 * Important: Remember to thaw the notifys with release_scopelock()! */
159 place_entry.freeze_notify ();180 scope.freeze_notify ();
160181
161 if (!has_search)182 if (!has_search)
162 {183 {
163 release_entrylock ();184 release_scopelock ();
164 search.finished ();185 search.finished ();
165 return;186 return;
166 }187 }
@@ -177,7 +198,7 @@
177 0, "no-mime",198 0, "no-mime",
178 commenteaster,199 commenteaster,
179 null);200 null);
180 release_entrylock ();201 release_scopelock ();
181 search.finished ();202 search.finished ();
182 return;203 return;
183 }204 }
@@ -190,7 +211,7 @@
190 0, "no-mime",211 0, "no-mime",
191 commentnoeaster,212 commentnoeaster,
192 null);213 null);
193 release_entrylock ();214 release_scopelock ();
194 search.finished ();215 search.finished ();
195 return;216 return;
196 217
@@ -261,13 +282,13 @@
261 executables_match.sort ();282 executables_match.sort ();
262 dirs_match.sort ();283 dirs_match.sort ();
263 284
264 group_id = RunnerGroup.RESULTS;285 category_id = RunnerCategory.RESULTS;
265286
266 // populate results287 // populate results
267 // 1. enable launching the exact search string288 // 1. enable launching the exact search string
268 display_name = get_icon_uri_and_mimetype (search_string, out icon, out uri, out mimetype);289 display_name = get_icon_uri_and_mimetype (search_string, out icon, out uri, out mimetype);
269 model.append (uri.strip (), icon.to_string (),290 model.append (uri.strip (), icon.to_string (),
270 group_id, mimetype,291 category_id, mimetype,
271 display_name,292 display_name,
272 null);293 null);
273 294
@@ -278,7 +299,7 @@
278 {299 {
279 uri = @"unity-runner://$(dir)";300 uri = @"unity-runner://$(dir)";
280 model.append (uri, icon.to_string (),301 model.append (uri, icon.to_string (),
281 group_id, mimetype,302 category_id, mimetype,
282 dir,303 dir,
283 null); 304 null);
284 }305 }
@@ -291,7 +312,7 @@
291 display_name = get_icon_uri_and_mimetype (final_exec, out icon, out uri, out mimetype); 312 display_name = get_icon_uri_and_mimetype (final_exec, out icon, out uri, out mimetype);
292 313
293 model.append (uri, icon.to_string (),314 model.append (uri, icon.to_string (),
294 group_id, mimetype,315 category_id, mimetype,
295 display_name,316 display_name,
296 null);317 null);
297 }318 }
@@ -301,18 +322,18 @@
301 dirs_match.size, executables_match.size, timer.elapsed ()*1000, search_string);322 dirs_match.size, executables_match.size, timer.elapsed ()*1000, search_string);
302 323
303324
304 release_entrylock ();325 release_scopelock ();
305 search.finished ();326 search.finished ();
306 }327 }
307 328
308 private void release_entrylock ()329 private void release_scopelock ()
309 {330 {
310 /* Allow new searches once we enter an idle again.331 /* Allow new searches once we enter an idle again.
311 * We don't do it directly from here as that could mean we start332 * We don't do it directly from here as that could mean we start
312 * changing the model even before we had flushed out current changes333 * changing the model even before we had flushed out current changes
313 */334 */
314 Idle.add (() => {335 Idle.add (() => {
315 place_entry.thaw_notify ();336 scope.thaw_notify ();
316 return false;337 return false;
317 }); 338 });
318 }339 }
@@ -395,51 +416,8 @@
395 return exec_string;416 return exec_string;
396 417
397 }418 }
398419
399 420
400 /* The check_models_synced() method acts like a latch - once all models
401 * have reported themselves to be synchronized we set
402 * all_models_synced = true and tell the searches to re-check their state
403 * as they should refuse to run when all_models_synced == false */
404 private void check_models_synced (Object obj, ParamSpec pspec)
405 {
406 if ((place_entry.sections_model as Dee.SharedModel).synchronized &&
407 (place_entry.entry_renderer_info.groups_model as Dee.SharedModel).synchronized &&
408 (place_entry.entry_renderer_info.results_model as Dee.SharedModel).synchronized) {
409 if (all_models_synced == false)
410 {
411 all_models_synced = true;
412
413 populate_groups (place_entry.entry_renderer_info.groups_model);
414
415 /* Emitting notify here will make us recheck if the search results
416 * need update. In the negative case this is a noop */
417 place_entry.notify_property ("active-search");
418 }
419 }
420 }
421
422 private void populate_groups (Dee.Model groups)
423 {
424 if (groups.get_n_rows() != 0)
425 {
426 debug ("The groups model already populated. We probably cloned it off Unity. Rebuilding.");
427 groups.clear ();
428 }
429
430 // TODO: needs asset
431 groups.append ("UnityDefaultRenderer",
432 _("Results"),
433 ICON_PATH + "group-installed.svg");
434 groups.append ("UnityDefaultRenderer",
435 _("History"),
436 ICON_PATH + "group-available.svg");
437
438 /* expand the history */
439 place_entry.entry_renderer_info.set_hint ("ExpandedGroups",
440 @"$((uint)RunnerGroup.HISTORY)");
441 }
442
443 public void add_history (string last_command)421 public void add_history (string last_command)
444 {422 {
445423
@@ -472,7 +450,7 @@
472 }450 }
473 451
474 // force a search to refresh history order (TODO: be more clever in the future)452 // force a search to refresh history order (TODO: be more clever in the future)
475 update_search.begin(place_entry.active_search);453 update_search.begin(scope.active_search);
476 }454 }
477 455
478 private void load_history ()456 private void load_history ()
479457
=== modified file 'src/schemas.vala'
--- src/schemas.vala 2011-03-10 10:56:46 +0000
+++ src/schemas.vala 2011-08-04 08:16:52 +0000
@@ -17,7 +17,7 @@
17 *17 *
18 */18 */
1919
20namespace Unity.ApplicationsPlace {20namespace Unity.ApplicationsLens {
2121
22 public enum ResultsColumn22 public enum ResultsColumn
23 {23 {
@@ -29,38 +29,7 @@
29 COMMENT29 COMMENT
30 }30 }
31 31
32 public enum SectionsColumn32 public enum Category
33 {
34 DISPLAY_NAME = 0,
35 ICON_HINT
36 }
37
38 public enum Section
39 {
40 ALL_APPLICATIONS = 0,
41 ACCESSORIES,
42 UNIVERSAL_ACCESS,
43 DEVELOPER_TOOLS,
44 EDUCATION,
45 SCIENCE,
46 GAMES,
47 GRAPHICS,
48 INTERNET,
49 MULTIMEDIA,
50 OFFICE,
51 THEMES,
52 SYSTEM,
53 LAST_SECTION
54 }
55
56 public enum GroupsColumn
57 {
58 RENDERER = 0,
59 DISPLAY_NAME,
60 ICON_HINT
61 }
62
63 public enum Group
64 {33 {
65 MOST_USED,34 MOST_USED,
66 INSTALLED,35 INSTALLED,
@@ -69,7 +38,7 @@
69 EMPTY_SECTION38 EMPTY_SECTION
70 }39 }
71 40
72 public enum RunnerGroup41 public enum RunnerCategory
73 {42 {
74 RESULTS,43 RESULTS,
75 HISTORY44 HISTORY
7645
=== modified file 'src/utils.vala'
--- src/utils.vala 2011-03-31 01:30:09 +0000
+++ src/utils.vala 2011-08-04 08:16:52 +0000
@@ -20,7 +20,7 @@
20using Unity;20using Unity;
21using Gee;21using Gee;
22 22
23namespace Unity.ApplicationsPlace.Utils23namespace Unity.ApplicationsLens.Utils
24{ 24{
25 25
26 public AppInfo? get_app_info_for_actor (string actor)26 public AppInfo? get_app_info_for_actor (string actor)
@@ -71,22 +71,22 @@
71 return actor;71 return actor;
72 }72 }
73 73
74 public bool search_is_invalid (PlaceSearch? search)74 public bool search_is_invalid (Unity.LensSearch? search)
75 {75 {
76 /* This boolean expression is unfolded as we seem to get76 /* This boolean expression is unfolded as we seem to get
77 * some null dereference if we join them in a big || expression */77 * some null dereference if we join them in a big || expression */
78 if (search == null)78 if (search == null)
79 return true;79 return true;
80 else if (search.get_search_string () == null)80 else if (search.search_string == null)
81 return true;81 return true;
82 82
83 return search.get_search_string () == "";83 return search.search_string == "";
84 }84 }
85 85
86 /* Sloppy and null-safe equality checking. null == "" and strings86 /* Sloppy and null-safe equality checking. null == "" and strings
87 * are stripped of whitespace before comparison */87 * are stripped of whitespace before comparison */
88 private bool search_has_really_changed (PlaceSearch? old_search,88 private bool search_has_really_changed (Unity.LensSearch? old_search,
89 PlaceSearch? new_search)89 Unity.LensSearch? new_search)
90 {90 {
91 if (old_search == null && new_search == null)91 if (old_search == null && new_search == null)
92 return false;92 return false;
@@ -95,7 +95,7 @@
95 95
96 if (old_search == null)96 if (old_search == null)
97 {97 {
98 s1 = new_search.get_search_string ();98 s1 = new_search.search_string;
99 if (s1 == null || s1.strip() == "")99 if (s1 == null || s1.strip() == "")
100 return false;100 return false;
101 else101 else
@@ -103,7 +103,7 @@
103 }103 }
104 else if (new_search == null)104 else if (new_search == null)
105 {105 {
106 s2 = old_search.get_search_string ();106 s2 = old_search.search_string;
107 if (s2 == null || s2.strip() == "")107 if (s2 == null || s2.strip() == "")
108 return false;108 return false;
109 else109 else
@@ -111,8 +111,8 @@
111 }111 }
112 else112 else
113 {113 {
114 s1 = new_search.get_search_string ();114 s1 = new_search.search_string;
115 s2 = old_search.get_search_string ();115 s2 = old_search.search_string;
116 if (s1 == null)116 if (s1 == null)
117 {117 {
118 if (s2 == null || s2.strip() == "")118 if (s2 == null || s2.strip() == "")

Subscribers

People subscribed via source and target branches