Merge lp:~kamstrup/libunity/faves-enumerator into lp:libunity
- faves-enumerator
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Michal Hruby |
Approved revision: | 99 |
Merged at revision: | 96 |
Proposed branch: | lp:~kamstrup/libunity/faves-enumerator |
Merge into: | lp:libunity |
Diff against target: |
472 lines (+338/-9) 9 files modified
src/unity-appinfo-manager.vala (+7/-1) src/unity-launcher.vala (+115/-2) test/Makefile.am (+1/-0) test/data/applications/asdasdasd.desktop (+11/-0) test/data/applications/testapp1.desktop (+11/-0) test/vala/Makefile.integration_tests (+10/-0) test/vala/test-appinfo-manager.vala (+6/-6) test/vala/test-launcher-integration.vala (+176/-0) test/vala/test-launcher.vala (+1/-0) |
To merge this branch: | bzr merge lp:~kamstrup/libunity/faves-enumerator |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michal Hruby (community) | Approve | ||
Review via email: mp+84470@code.launchpad.net |
Commit message
Description of the change
Add Unity.LauncherF
Note that this is a read-only API intentionally. The Unity policy is that the
user alone is in control of the launcher. You can listen for changes, and the
ordering is guaranteed to match that of Unity.
Mikkel Kamstrup Erlandsen (kamstrup) wrote : | # |
> 1) libunity is inconsistent in method names to get singleton instance
> (get_instance vs get_default), I'd rather see us using get_default which is
> more common in gobject world.
I thought quite a lot about this when writing the API. The idea was that get_instance() had the semantics of a "pure" singleton, which you can only ever have precisely one of; while get_default() implies that you can have different instances, but normally just one.
But thinking about it again today I don't think API consumers is gonna appreciate this pedantry ;-) I'll rename it to get_default().
In the same spirit I think we should rename Unity.AppInfoMa
> 2) it'd be nice to add `public bool contains (string id)`, to support 'in'
> operator.
Also thought about that one. If we could overload it with a version that takes an AppInfo then maybe, but this is too much of a Valaism to my liking. The lib is meant to have a sensible C and Python API as well. If we can fix it with some clever #defines or -custom.vala overrides then I am OK with it, but as a part of the ABI I don't like it...
Michal Hruby (mhr3) wrote : | # |
> I thought quite a lot about this when writing the API. The idea was that
> get_instance() had the semantics of a "pure" singleton, which you can only
> ever have precisely one of; while get_default() implies that you can have
> different instances, but normally just one.
You can't really have "pure" singleton with gobject (g_object_new (...)), that's why everyone uses get_default.
> In the same spirit I think we should rename
> Unity.AppInfoMa
> API break..?
>
I was thinking about that as well, but yea don't like the API break there, maybe we can add get_default and mark get_instance deprecated for now?
> > 2) it'd be nice to add `public bool contains (string id)`, to support 'in'
> > operator.
>
> Also thought about that one. If we could overload it with a version that takes
> an AppInfo then maybe, but this is too much of a Valaism to my liking. The lib
> is meant to have a sensible C and Python API as well. If we can fix it with
> some clever #defines or -custom.vala overrides then I am OK with it, but as a
> part of the ABI I don't like it...
Right, it'd be best to have that only in the vapi, unfortunately valac doesn't do -custom.vala when you're generating vapi from vala sources. The only thing we could do would be some sed :( Let's forget about that then...
Mikkel Kamstrup Erlandsen (kamstrup) wrote : | # |
> > I thought quite a lot about this when writing the API. The idea was that
> > get_instance() had the semantics of a "pure" singleton, which you can only
> > ever have precisely one of; while get_default() implies that you can have
> > different instances, but normally just one.
>
> You can't really have "pure" singleton with gobject (g_object_new (...)),
> that's why everyone uses get_default.
Sure you can, just override GObject-
> > In the same spirit I think we should rename
> > Unity.AppInfoMa
> an
> > API break..?
> >
>
> I was thinking about that as well, but yea don't like the API break there,
> maybe we can add get_default and mark get_instance deprecated for now?
ok
> > > 2) it'd be nice to add `public bool contains (string id)`, to support 'in'
> > > operator.
> >
> > Also thought about that one. If we could overload it with a version that
> takes
> > an AppInfo then maybe, but this is too much of a Valaism to my liking. The
> lib
> > is meant to have a sensible C and Python API as well. If we can fix it with
> > some clever #defines or -custom.vala overrides then I am OK with it, but as
> a
> > part of the ABI I don't like it...
>
> Right, it'd be best to have that only in the vapi, unfortunately valac doesn't
> do -custom.vala when you're generating vapi from vala sources. The only thing
> we could do would be some sed :( Let's forget about that then...
We can look at it down the road if we find time for it
- 98. By Mikkel Kamstrup Erlandsen
-
Rename method LauncherFavorit
es.get_ instance( ) to get_default() - 99. By Mikkel Kamstrup Erlandsen
-
Deprecate AppInfoManager.
get_instance( ) and rename it to get_default(). This make sure that all singletons in libunity are accessed similarly
Mikkel Kamstrup Erlandsen (kamstrup) wrote : | # |
Pushed r99. Please re-review
Michal Hruby (mhr3) wrote : | # |
> > You can't really have "pure" singleton with gobject (g_object_new (...)),
> > that's why everyone uses get_default.
>
> Sure you can, just override GObject-
> on the solution :-)
>
Hmm, interesting, in that case people are just too lazy to do it I guess :)
The changes look fine, thanks.
Preview Diff
1 | === modified file 'src/unity-appinfo-manager.vala' |
2 | --- src/unity-appinfo-manager.vala 2011-12-01 12:42:22 +0000 |
3 | +++ src/unity-appinfo-manager.vala 2011-12-06 12:05:26 +0000 |
4 | @@ -86,10 +86,16 @@ |
5 | } |
6 | } |
7 | |
8 | + [Deprecated (replacement = "AppInfoManager.get_default")] |
9 | + public static AppInfoManager get_instance () |
10 | + { |
11 | + return AppInfoManager.get_default (); |
12 | + } |
13 | + |
14 | /** |
15 | * Get a ref to the singleton AppInfoManager |
16 | */ |
17 | - public static AppInfoManager get_instance () |
18 | + public static AppInfoManager get_default () |
19 | { |
20 | if (AppInfoManager.singleton == null) |
21 | AppInfoManager.singleton = new AppInfoManager(); |
22 | |
23 | === modified file 'src/unity-launcher.vala' |
24 | --- src/unity-launcher.vala 2011-08-02 07:49:39 +0000 |
25 | +++ src/unity-launcher.vala 2011-12-06 12:05:26 +0000 |
26 | @@ -343,6 +343,119 @@ |
27 | props.insert ("quicklist", l._object_path); |
28 | |
29 | return props; |
30 | - } |
31 | - |
32 | + } |
33 | + |
34 | + public class LauncherFavorites : Object |
35 | + { |
36 | + public signal void changed (); |
37 | + |
38 | + private static LauncherFavorites? singleton = null; |
39 | + private Settings settings; |
40 | + |
41 | + /* We keep both a map and a list in order to have the correct sorting */ |
42 | + private HashTable<string,AppInfo?> fav_cache; |
43 | + private string[] fav_list; |
44 | + |
45 | + private LauncherFavorites () |
46 | + { |
47 | + settings = new Settings ("com.canonical.Unity.Launcher"); |
48 | + fav_cache = new HashTable<string,AppInfo?> (str_hash, str_equal); |
49 | + reset_fav_cache (); |
50 | + |
51 | + settings.changed["favorites"].connect (reset_fav_cache); |
52 | + } |
53 | + |
54 | + private void reset_fav_cache () |
55 | + { |
56 | + fav_cache.remove_all (); |
57 | + fav_list = settings.get_strv ("favorites"); |
58 | + foreach (string id in fav_list) |
59 | + { |
60 | + fav_cache.insert (id, null); |
61 | + } |
62 | + |
63 | + changed (); |
64 | + } |
65 | + |
66 | + /** |
67 | + * Get the default singleton Unity.LauncherFavorites instance, creating it |
68 | + * dynamically if necessary. |
69 | + * |
70 | + * @return: (transfer none): The singleton Unity.LauncherFavorites. |
71 | + * If calling from C do not free this instance. |
72 | + * |
73 | + */ |
74 | + public static unowned LauncherFavorites get_default () |
75 | + { |
76 | + if (singleton == null) |
77 | + singleton = new LauncherFavorites (); |
78 | + |
79 | + return singleton; |
80 | + } |
81 | + |
82 | + public bool has_app_info (AppInfo appinfo) { |
83 | + if (appinfo.get_id () == null) |
84 | + { |
85 | + critical ("Can not look up favorite for AppInfo with NULL id"); |
86 | + return false; |
87 | + } |
88 | + |
89 | + return has_app_id (appinfo.get_id ()); |
90 | + } |
91 | + |
92 | + public bool has_app_id (string app_id) |
93 | + { |
94 | + return fav_cache.lookup_extended (app_id, null, null); |
95 | + } |
96 | + |
97 | + public AppInfo? lookup (string app_id) |
98 | + { |
99 | + AppInfo? appinfo; |
100 | + bool has_id = fav_cache.lookup_extended (app_id, null, out appinfo); |
101 | + |
102 | + /* If we don't have the appinfo cached, pull it out of the |
103 | + * AppInfoManager and cache it */ |
104 | + if (has_id) |
105 | + { |
106 | + if (appinfo != null) |
107 | + return appinfo; |
108 | + |
109 | + var appman = AppInfoManager.get_default (); |
110 | + appinfo = appman.lookup (app_id); |
111 | + fav_cache.insert (app_id, appinfo); |
112 | + |
113 | + // FIXME: We really should return a dummy AppInfo for faves |
114 | + // where we can't find the .desktop file... |
115 | + if (appinfo == null) |
116 | + { |
117 | + critical ("Can't find AppInfo for favorite '%s'", app_id); |
118 | + return null; |
119 | + } |
120 | + |
121 | + return appinfo; |
122 | + } |
123 | + return null; |
124 | + } |
125 | + |
126 | + public string[] enumerate_ids () |
127 | + { |
128 | + return fav_list; |
129 | + } |
130 | + |
131 | + public AppInfo[] enumerate_app_infos () |
132 | + { |
133 | + int i = 0; |
134 | + var infos = new AppInfo[fav_cache.size ()]; |
135 | + |
136 | + foreach (string id in fav_list) |
137 | + { |
138 | + var appinfo = lookup (id); |
139 | + infos[i] = appinfo; |
140 | + i++; |
141 | + } |
142 | + |
143 | + return infos; |
144 | + } |
145 | + } |
146 | + |
147 | } /* namespace */ |
148 | |
149 | === modified file 'test/Makefile.am' |
150 | --- test/Makefile.am 2011-12-02 14:37:36 +0000 |
151 | +++ test/Makefile.am 2011-12-06 12:05:26 +0000 |
152 | @@ -2,5 +2,6 @@ |
153 | |
154 | EXTRA_DIST = \ |
155 | data/applications/ubuntu-about.desktop \ |
156 | + data/applications/asdasdasd.desktop \ |
157 | data/scope0.scope \ |
158 | data/test_desktop_file.desktop |
159 | |
160 | === added file 'test/data/applications/asdasdasd.desktop' |
161 | --- test/data/applications/asdasdasd.desktop 1970-01-01 00:00:00 +0000 |
162 | +++ test/data/applications/asdasdasd.desktop 2011-12-06 12:05:26 +0000 |
163 | @@ -0,0 +1,11 @@ |
164 | +[Desktop Entry] |
165 | +Encoding=UTF-8 |
166 | +Name=libunity bogus app |
167 | +Comment=For testing non-exisiting apps |
168 | +Exec=xterm |
169 | +Icon=distributor-logo |
170 | +Terminal=false |
171 | +Type=Application |
172 | +Categories=GNOME;Application;Core; |
173 | +StartupNotify=true |
174 | + |
175 | |
176 | === added file 'test/data/applications/testapp1.desktop' |
177 | --- test/data/applications/testapp1.desktop 1970-01-01 00:00:00 +0000 |
178 | +++ test/data/applications/testapp1.desktop 2011-12-06 12:05:26 +0000 |
179 | @@ -0,0 +1,11 @@ |
180 | +[Desktop Entry] |
181 | +Encoding=UTF-8 |
182 | +Name=libunity test app 1 |
183 | +Comment=Test App 1 for testing non-exisiting apps |
184 | +Exec=xterm |
185 | +Icon=distributor-logo |
186 | +Terminal=false |
187 | +Type=Application |
188 | +Categories=GNOME;Application;Core; |
189 | +StartupNotify=true |
190 | + |
191 | |
192 | === modified file 'test/vala/Makefile.integration_tests' |
193 | --- test/vala/Makefile.integration_tests 2011-12-01 15:43:28 +0000 |
194 | +++ test/vala/Makefile.integration_tests 2011-12-06 12:05:26 +0000 |
195 | @@ -1,4 +1,5 @@ |
196 | check_PROGRAMS += \ |
197 | + test-launcher-integration \ |
198 | test-sound-menu \ |
199 | test-mpris-backend-client \ |
200 | test-mpris-backend-server \ |
201 | @@ -11,6 +12,7 @@ |
202 | if ENABLE_INTEGRATION_TESTS |
203 | TEST_PROGS += \ |
204 | test-lens-scope-interactions \ |
205 | + test-launcher-integration \ |
206 | test-sound-menu \ |
207 | test-mpris-backend \ |
208 | test-mpris-backend-prop-updates |
209 | @@ -27,6 +29,14 @@ |
210 | @chmod +x $@ |
211 | |
212 | ######################################### |
213 | +## test-launcher-integration |
214 | +######################################### |
215 | +test_launcher_integration_SOURCES = \ |
216 | + test-launcher-integration.vala |
217 | + |
218 | +test_launcher_integration_LDADD = $(test_libs) |
219 | + |
220 | +######################################### |
221 | ## test-sound-menu |
222 | ######################################### |
223 | test_sound_menu_SOURCES = \ |
224 | |
225 | === modified file 'test/vala/test-appinfo-manager.vala' |
226 | --- test/vala/test-appinfo-manager.vala 2011-09-27 09:48:39 +0000 |
227 | +++ test/vala/test-appinfo-manager.vala 2011-12-06 12:05:26 +0000 |
228 | @@ -43,14 +43,14 @@ |
229 | /* Test that we can even get a valid ref to the manager */ |
230 | internal static void test_allocation() |
231 | { |
232 | - var manager = AppInfoManager.get_instance(); |
233 | + var manager = AppInfoManager.get_default(); |
234 | assert (manager is AppInfoManager); |
235 | } |
236 | |
237 | /* Test that we can clear an empty manager */ |
238 | internal static void test_clear_empty() |
239 | { |
240 | - var manager = AppInfoManager.get_instance(); |
241 | + var manager = AppInfoManager.get_default(); |
242 | manager.clear (); |
243 | manager.clear (); |
244 | } |
245 | @@ -58,7 +58,7 @@ |
246 | /* Test that we can clear an empty manager */ |
247 | internal static void test_sync_lookup_missing() |
248 | { |
249 | - var manager = AppInfoManager.get_instance(); |
250 | + var manager = AppInfoManager.get_default(); |
251 | assert (manager.lookup ("_foobar.desktop") == null); |
252 | assert (manager.get_categories ("_foobar.desktop") == null); |
253 | assert (manager.get_keywords ("_foobar.desktop") == null); |
254 | @@ -74,7 +74,7 @@ |
255 | |
256 | internal static async void do_test_async_lookup_missing (MainLoop mainloop) |
257 | { |
258 | - var manager = AppInfoManager.get_instance(); |
259 | + var manager = AppInfoManager.get_default(); |
260 | |
261 | try { |
262 | AppInfo? appinfo = yield manager.lookup_async ("_foobar.desktop"); |
263 | @@ -92,7 +92,7 @@ |
264 | /* Test that we can lookup something which is indeed there */ |
265 | internal static void test_sync_lookup_ok() |
266 | { |
267 | - var manager = AppInfoManager.get_instance(); |
268 | + var manager = AppInfoManager.get_default(); |
269 | |
270 | var info = manager.lookup ("ubuntu-about.desktop"); |
271 | assert (info != null); |
272 | @@ -128,7 +128,7 @@ |
273 | |
274 | internal static async void do_test_async_lookup_ok (MainLoop mainloop) |
275 | { |
276 | - var manager = AppInfoManager.get_instance(); |
277 | + var manager = AppInfoManager.get_default(); |
278 | |
279 | try{ |
280 | var info = yield manager.lookup_async ("ubuntu-about.desktop"); |
281 | |
282 | === added file 'test/vala/test-launcher-integration.vala' |
283 | --- test/vala/test-launcher-integration.vala 1970-01-01 00:00:00 +0000 |
284 | +++ test/vala/test-launcher-integration.vala 2011-12-06 12:05:26 +0000 |
285 | @@ -0,0 +1,176 @@ |
286 | +/* |
287 | + * Copyright (C) 2011 Canonical Ltd |
288 | + * |
289 | + * This program is free software: you can redistribute it and/or modify |
290 | + * it under the terms of the GNU General Public License version 3 as |
291 | + * published by the Free Software Foundation. |
292 | + * |
293 | + * This program is distributed in the hope that it will be useful, |
294 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
295 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
296 | + * GNU General Public License for more details. |
297 | + * |
298 | + * You should have received a copy of the GNU General Public License |
299 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
300 | + * |
301 | + * Authored by Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com> |
302 | + * |
303 | + */ |
304 | + |
305 | +/* |
306 | + * Despite the relative simplicity of this API we still need to relegate it |
307 | + * to the integration tests suite because it depends on the GSettings schema |
308 | + * from Unity. |
309 | + */ |
310 | + |
311 | +public class Main |
312 | +{ |
313 | + public static int main (string[] args) |
314 | + { |
315 | + /* Prepend test search path for XDG_DATA_DIRS so we can find |
316 | + * our sample .desktop files */ |
317 | + var datadirs = Environment.get_variable ("XDG_DATA_DIRS"); |
318 | + if (datadirs != null) |
319 | + datadirs = Config.TESTDIR + "/data:" + datadirs; |
320 | + else |
321 | + datadirs = Config.TESTDIR + "/data"; |
322 | + Environment.set_variable ("XDG_DATA_DIRS", datadirs, true); |
323 | + |
324 | + /* Make sure we don't hose the user env with our tests... */ |
325 | + Environment.set_variable ("GSETTINGS_BACKEND", "memory", true); |
326 | + |
327 | + Test.init (ref args); |
328 | + |
329 | + Test.add_data_func ("/Integration/Launcher/Favorites/UnknownApps", |
330 | + test_has_unknown_apps); |
331 | + |
332 | + Test.add_data_func ("/Integration/Launcher/Favorites/HasSampleApps", |
333 | + test_has_sample_apps); |
334 | + |
335 | + Test.add_data_func ("/Integration/Launcher/Favorites/Lookup", |
336 | + test_lookup); |
337 | + |
338 | + Test.add_data_func ("/Integration/Launcher/Favorites/EnumerateIds", |
339 | + test_enumerate_ids); |
340 | + |
341 | + Test.add_data_func ("/Integration/Launcher/Favorites/EnumerateAppInfos", |
342 | + test_enumerate_app_infos); |
343 | + |
344 | + Test.add_data_func ("/Integration/Launcher/Favorites/Changes", |
345 | + test_changes); |
346 | + |
347 | + Test.run (); |
348 | + |
349 | + return 0; |
350 | + } |
351 | + |
352 | + internal static void set_up () { |
353 | + assert ("memory" == Environment.get_variable ("GSETTINGS_BACKEND")); |
354 | + var settings = new Settings ("com.canonical.Unity.Launcher"); |
355 | + |
356 | + string[] faves = { "rhythmbox.desktop", "testapp1.desktop", "ubuntu-about.desktop" }; |
357 | + settings.set_strv ("favorites", faves); |
358 | + } |
359 | + |
360 | + internal static void test_has_unknown_apps () |
361 | + { |
362 | + set_up (); |
363 | + |
364 | + var faves = Unity.LauncherFavorites.get_default (); |
365 | + assert (!faves.has_app_id ("hulabaloola")); |
366 | + |
367 | + var appinfo = new DesktopAppInfo ("asdasdasd.desktop"); |
368 | + assert (appinfo != null); |
369 | + assert (!faves.has_app_info (appinfo)); |
370 | + } |
371 | + |
372 | + internal static void test_has_sample_apps () |
373 | + { |
374 | + set_up (); |
375 | + |
376 | + var faves = Unity.LauncherFavorites.get_default (); |
377 | + assert (faves.has_app_id ("rhythmbox.desktop")); |
378 | + assert (faves.has_app_id ("testapp1.desktop")); |
379 | + assert (faves.has_app_id ("ubuntu-about.desktop")); |
380 | + |
381 | + var appinfo = new DesktopAppInfo ("rhythmbox.desktop"); |
382 | + assert (faves.has_app_info (appinfo)); |
383 | + appinfo = new DesktopAppInfo ("testapp1.desktop"); |
384 | + assert (faves.has_app_info (appinfo)); |
385 | + appinfo = new DesktopAppInfo ("ubuntu-about.desktop"); |
386 | + assert (faves.has_app_info (appinfo)); |
387 | + } |
388 | + |
389 | + internal static void test_lookup () |
390 | + { |
391 | + set_up (); |
392 | + |
393 | + var faves = Unity.LauncherFavorites.get_default (); |
394 | + var appinfo = faves.lookup ("rhythmbox.desktop"); |
395 | + assert (appinfo.get_name () == "Rhythmbox"); |
396 | + |
397 | + appinfo = faves.lookup ("testapp1.desktop"); |
398 | + assert (appinfo.get_name () == "libunity test app 1"); |
399 | + |
400 | + appinfo = faves.lookup ("ubuntu-about.desktop"); |
401 | + assert (appinfo.get_name () == "About Ubuntu"); |
402 | + |
403 | + appinfo = faves.lookup ("pakupachupikamachu.desktop"); |
404 | + assert (appinfo == null); |
405 | + } |
406 | + |
407 | + internal static void test_enumerate_ids () |
408 | + { |
409 | + set_up (); |
410 | + |
411 | + var faves = Unity.LauncherFavorites.get_default (); |
412 | + var ids = faves.enumerate_ids (); |
413 | + |
414 | + assert (ids.length == 3); |
415 | + assert (ids[0] == "rhythmbox.desktop"); |
416 | + assert (ids[1] == "testapp1.desktop"); |
417 | + assert (ids[2] == "ubuntu-about.desktop"); |
418 | + } |
419 | + |
420 | + internal static void test_enumerate_app_infos () |
421 | + { |
422 | + set_up (); |
423 | + |
424 | + var faves = Unity.LauncherFavorites.get_default (); |
425 | + var infos = faves.enumerate_app_infos (); |
426 | + |
427 | + assert (infos.length == 3); |
428 | + assert (infos[0].get_name() == "Rhythmbox"); |
429 | + assert (infos[1].get_name() == "libunity test app 1"); |
430 | + assert (infos[2].get_name() == "About Ubuntu"); |
431 | + } |
432 | + |
433 | + internal static void test_changes () |
434 | + { |
435 | + set_up (); |
436 | + |
437 | + var faves = Unity.LauncherFavorites.get_default (); |
438 | + bool was_changed = false; |
439 | + |
440 | + faves.changed.connect ( () => { |
441 | + was_changed = true; |
442 | + }); |
443 | + |
444 | + /* Change the faves */ |
445 | + var settings = new Settings ("com.canonical.Unity.Launcher"); |
446 | + string[] new_faves = { "rhythmbox.desktop" }; |
447 | + settings.set_strv ("favorites", new_faves); |
448 | + |
449 | + /* Wait for updates */ |
450 | + var ml = new MainLoop (); |
451 | + Idle.add (() => { ml.quit(); return false; }); |
452 | + ml.run (); |
453 | + |
454 | + assert (was_changed == true); |
455 | + assert (faves.enumerate_ids().length == 1); |
456 | + assert (faves.enumerate_ids()[0] == "rhythmbox.desktop"); |
457 | + } |
458 | + |
459 | + |
460 | + |
461 | +} |
462 | |
463 | === modified file 'test/vala/test-launcher.vala' |
464 | --- test/vala/test-launcher.vala 2011-04-01 20:19:52 +0000 |
465 | +++ test/vala/test-launcher.vala 2011-12-06 12:05:26 +0000 |
466 | @@ -84,5 +84,6 @@ |
467 | |
468 | // FIXME: We're not testing the quicklist here, that's a bit tricky |
469 | } |
470 | + |
471 | } |
472 | } |
Looks good, just two minor issues:
1) libunity is inconsistent in method names to get singleton instance (get_instance vs get_default), I'd rather see us using get_default which is more common in gobject world.
2) it'd be nice to add `public bool contains (string id)`, to support 'in' operator.