Merge lp:~mhr3/dockmanager/metadata-update into lp:dockmanager
- metadata-update
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 32 |
Proposed branch: | lp:~mhr3/dockmanager/metadata-update |
Merge into: | lp:dockmanager |
Diff against target: |
497 lines (+260/-74) 16 files modified
configure.ac (+4/-5) daemon/dockmanager-daemon.vala (+188/-15) metadata/banshee_control.py.info (+5/-4) metadata/deluge_badge.py.info (+5/-4) metadata/emesene_control.py.info (+5/-4) metadata/gajim_badge.py.info (+5/-4) metadata/gtg_menus.py.info (+5/-4) metadata/liferea_badge.py.info (+5/-4) metadata/open_terminal_here.py.info (+5/-4) metadata/pidgin_control.py.info (+5/-4) metadata/rhythmbox_control.py.info (+5/-4) metadata/tomboy_menus.py.info (+5/-4) metadata/transmission_badge.py.info (+5/-4) metadata/tsclient_menus.py.info (+5/-4) metadata/zeitgeist_journal.py.info (+4/-3) metadata/zeitgeist_menus.py.info (+4/-3) |
To merge this branch: | bzr merge lp:~mhr3/dockmanager/metadata-update |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Robert Dyer (community) | Needs Fixing | ||
Review via email: mp+26745@code.launchpad.net |
Commit message
Description of the change
Michal Hruby (mhr3) wrote : | # |
It includes changes to the daemon which read this format, so it's related.
It's standard key-file format used everywhere (and parser for it available in glib), section name is required in keyfiles, therefore if it's not there, it's invalid. As for supporting more sections and/or keys it's easily possible when needed.
Robert Dyer (psybers) wrote : | # |
Ok but the name of the section, is that a standard? Or are we going to just grab the first section in the file? What if there are more sections?
Michal Hruby (mhr3) wrote : | # |
The APIs reading keyfiles usually need both group name and key name, so you shouldn't just grab the first one, anyway maybe we should use something more specific than "DEFAULT" (for example .desktop files use "DesktopEntry"), perhaps "DockmanagerHel
Rico Tzschichholz (ricotz) wrote : | # |
The new metadata-file format is fine. "DockmanagerHelper" sounds good.
- 32. By Michal Hruby
-
Use DockmanagerHelper
Michal Hruby (mhr3) wrote : | # |
Branch updated, please merge when Docky is ready to handle it.
Preview Diff
1 | === modified file 'configure.ac' |
2 | --- configure.ac 2010-06-02 11:27:12 +0000 |
3 | +++ configure.ac 2010-06-05 13:05:33 +0000 |
4 | @@ -13,18 +13,17 @@ |
5 | |
6 | dnl Bzr Revno, if release set BZR_REVNO to the release version number |
7 | if test -d $top_srcdir/.bzr ; then |
8 | - BZR_REVNO=`bzr version-info --custom \ |
9 | - --template="{revno}"` |
10 | + BZR_REVNO=`bzr revno` |
11 | else |
12 | BZR_REVNO=0.1 |
13 | fi |
14 | AC_SUBST(BZR_REVNO) |
15 | |
16 | -if test -d $top_srcdir/.bzr ; then |
17 | +if test -e $top_srcdir/.version_info ; then |
18 | + VERSION_INFO=`cat .version_info` |
19 | +elif test -d $top_srcdir/.bzr ; then |
20 | VERSION_INFO=`bzr version-info --custom \ |
21 | --template="bzr {branch_nick} r{revno}"` |
22 | -elif test -e $top_srcdir/.version_info ; then |
23 | - VERSION_INFO=`cat .version_info` |
24 | else |
25 | VERSION_INFO="Release" |
26 | fi |
27 | |
28 | === modified file 'daemon/dockmanager-daemon.vala' |
29 | --- daemon/dockmanager-daemon.vala 2010-06-02 09:39:27 +0000 |
30 | +++ daemon/dockmanager-daemon.vala 2010-06-05 13:05:33 +0000 |
31 | @@ -24,12 +24,35 @@ |
32 | |
33 | namespace DockManager |
34 | { |
35 | + const string GROUP_NAME = "DockmanagerHelper"; |
36 | + |
37 | + public struct HelperInfo |
38 | + { |
39 | + string path; |
40 | + string? name; |
41 | + string? description; |
42 | + string? icon_name; |
43 | + string? app_name; |
44 | + bool app_available; |
45 | + } |
46 | + |
47 | + private struct HelperProcessInfo |
48 | + { |
49 | + int pid; |
50 | + uint timer_id; |
51 | + } |
52 | + |
53 | [DBus (name = "org.dockmanager.Daemon")] |
54 | public interface DaemonInterface: GLib.Object |
55 | { |
56 | + public abstract HelperInfo[] get_all_helpers () throws DBus.Error; |
57 | + public abstract void run_helper (string path) throws DBus.Error; |
58 | + public abstract void stop_helper (string path) throws DBus.Error; |
59 | + public abstract void restart_all () throws DBus.Error; |
60 | public abstract void show_preferences () throws DBus.Error; |
61 | public abstract void embed_preferences (int64 xid) throws DBus.Error; |
62 | - public abstract void restart_all () throws DBus.Error; |
63 | + |
64 | + public signal void helper_stopped (string path); |
65 | } |
66 | |
67 | const string DBUS_UNIQUE_NAME = "org.dockmanager.Daemon"; |
68 | @@ -50,11 +73,14 @@ |
69 | } |
70 | } |
71 | |
72 | - private HashTable<string, int> helpers; |
73 | + private HashTable<string, HelperProcessInfo?> helper_process_info; |
74 | + private List<HelperInfo?> all_scripts; |
75 | |
76 | public HelperDaemon () |
77 | { |
78 | - helpers = new HashTable<string, int> (str_hash, str_equal); |
79 | + helper_process_info = |
80 | + new HashTable<string, HelperProcessInfo?> (str_hash, str_equal); |
81 | + all_scripts = new List<HelperInfo?> (); |
82 | } |
83 | |
84 | public override void constructed () |
85 | @@ -92,6 +118,7 @@ |
86 | { |
87 | connection.register_object ("/org/dockmanager/Daemon", this); |
88 | |
89 | + this.init (); |
90 | this.run_helpers (); |
91 | |
92 | Gtk.main (); |
93 | @@ -107,47 +134,172 @@ |
94 | } |
95 | } |
96 | |
97 | + private void init () |
98 | + { |
99 | + string[] prefixes = |
100 | + { |
101 | + Build.PKGDATADIR, |
102 | + Environment.get_user_data_dir () + "/dockmanager" |
103 | + }; |
104 | + |
105 | + foreach (unowned string prefix in prefixes) |
106 | + { |
107 | + string path = prefix + "/scripts"; |
108 | + string metadata_dir = prefix + "/metadata/"; |
109 | + var scripts_dir = DesktopAgnostic.VFS.file_new_for_path (path); |
110 | + if (!scripts_dir.exists ()) continue; |
111 | + |
112 | + foreach (var f in scripts_dir.enumerate_children ()) |
113 | + { |
114 | + var hi = HelperInfo (); |
115 | + hi.path = f.path; |
116 | + hi.app_available = true; // probably... we'll set it later |
117 | + all_scripts.append (hi); |
118 | + } |
119 | + |
120 | + foreach (unowned HelperInfo? hi in all_scripts) |
121 | + { |
122 | + string metadata = metadata_dir + Path.get_basename (hi.path) + ".info"; |
123 | + var metadata_file = DesktopAgnostic.VFS.file_new_for_path (metadata); |
124 | + if (!metadata_file.exists ()) continue; |
125 | + |
126 | + string contents; |
127 | + size_t length; |
128 | + metadata_file.load_contents (out contents, out length); |
129 | + |
130 | + var keyfile = new KeyFile (); |
131 | + try |
132 | + { |
133 | + keyfile.load_from_data (contents, length, KeyFileFlags.NONE); |
134 | + } |
135 | + catch (KeyFileError err) |
136 | + { |
137 | + warning ("Cannot load %s: %s", metadata, err.message); |
138 | + continue; |
139 | + } |
140 | + |
141 | + try |
142 | + { |
143 | + hi.name = keyfile.get_string (GROUP_NAME, "Name"); |
144 | + hi.description = keyfile.get_string (GROUP_NAME, "Description"); |
145 | + } |
146 | + catch (KeyFileError err) |
147 | + { |
148 | + warning ("Required key missing in %s", metadata); |
149 | + continue; |
150 | + } |
151 | + try |
152 | + { |
153 | + hi.icon_name = keyfile.get_string (GROUP_NAME, "Icon"); |
154 | + } |
155 | + catch (KeyFileError err) { } |
156 | + try |
157 | + { |
158 | + int status; |
159 | + hi.app_name = keyfile.get_string (GROUP_NAME, "AppName"); |
160 | + Process.spawn_command_line_sync ("which " + hi.app_name, null, null, |
161 | + out status); |
162 | + hi.app_available = status == 0; |
163 | + } |
164 | + catch (GLib.Error err) |
165 | + { |
166 | + warning ("%s", err.message); |
167 | + } |
168 | + } |
169 | + } |
170 | + } |
171 | + |
172 | public void run_helpers () |
173 | { |
174 | foreach (Value v in _helper_list) |
175 | { |
176 | unowned string helper = v.get_string (); |
177 | - int pid = run_helper (helper); |
178 | - helpers.insert (helper, pid); |
179 | + run_helper (helper); |
180 | } |
181 | |
182 | - helpers.@foreach ((k, v) => |
183 | + helper_process_info.@foreach ((k, v) => |
184 | { |
185 | unowned string key = (string) k; |
186 | - int val = (int)(long) v; |
187 | - debug ("%s: %d", key, val); |
188 | + unowned HelperProcessInfo? val = (HelperProcessInfo?) v; |
189 | + debug ("%s: %d", key, val.pid); |
190 | }); |
191 | } |
192 | |
193 | - public int run_helper (string uri) |
194 | + private int get_helper_pid (string path) |
195 | + { |
196 | + unowned HelperProcessInfo? hpi = helper_process_info.lookup (path); |
197 | + return hpi != null ? hpi.pid : 0; |
198 | + } |
199 | + |
200 | + public void run_helper (string path) throws DBus.Error |
201 | { |
202 | Pid child_pid = 0; |
203 | string[] argv; |
204 | |
205 | + if (get_helper_pid (path) != 0) |
206 | + { |
207 | + debug ("%s is already running", path); |
208 | + return; |
209 | + } |
210 | + |
211 | try |
212 | { |
213 | - Shell.parse_argv (uri, out argv); |
214 | + Shell.parse_argv (path, out argv); |
215 | var flags = SpawnFlags.DO_NOT_REAP_CHILD | SpawnFlags.SEARCH_PATH; |
216 | Process.spawn_async (null, argv, null, flags, null, out child_pid); |
217 | - ChildWatch.add (child_pid, this.child_died); |
218 | + ChildWatch.add_full (Priority.DEFAULT, child_pid, (pid, status) => |
219 | + { |
220 | + debug ("[%d] \"%s\" exitted", pid, Path.get_basename (path)); |
221 | + unowned HelperProcessInfo? hpi = helper_process_info.lookup (path); |
222 | + if (hpi != null) |
223 | + { |
224 | + if (hpi.timer_id != 0) |
225 | + { |
226 | + Source.remove (hpi.timer_id); |
227 | + } |
228 | + hpi.pid = 0; |
229 | + hpi.timer_id = 0; |
230 | + } |
231 | + Process.close_pid (pid); |
232 | + helper_stopped (path); |
233 | + }); |
234 | } |
235 | catch (GLib.Error err) |
236 | { |
237 | warning ("%s", err.message); |
238 | - return 0; |
239 | + throw new DBus.Error.SPAWN_FAILED (err.message); |
240 | } |
241 | |
242 | - return (int)child_pid; |
243 | + unowned HelperProcessInfo? hpi = helper_process_info.lookup (path); |
244 | + if (hpi != null) |
245 | + { |
246 | + hpi.pid = (int) child_pid; |
247 | + } |
248 | + else |
249 | + { |
250 | + var pi = HelperProcessInfo (); |
251 | + pi.pid = (int) child_pid; |
252 | + helper_process_info.insert (path, pi); |
253 | + } |
254 | } |
255 | |
256 | - private void child_died (Pid pid, int status) |
257 | + public void stop_helper (string path) throws DBus.Error |
258 | { |
259 | - debug ("[%d] died, status: %d", pid, status); |
260 | + int pid = get_helper_pid (path); |
261 | + if (pid == 0) return; |
262 | + |
263 | + unowned HelperProcessInfo? hpi = helper_process_info.lookup (path); |
264 | + Posix.kill ((Posix.pid_t)pid, Posix.SIGTERM); |
265 | + |
266 | + hpi.timer_id = Timeout.add (2000, () => |
267 | + { |
268 | + if (hpi.pid != 0) |
269 | + { |
270 | + Posix.kill ((Posix.pid_t)hpi.pid, Posix.SIGKILL); |
271 | + } |
272 | + hpi.timer_id = 0; |
273 | + return false; |
274 | + }); |
275 | } |
276 | |
277 | public void show_preferences () |
278 | @@ -158,6 +310,27 @@ |
279 | { |
280 | } |
281 | |
282 | + public HelperInfo[] get_all_helpers () |
283 | + { |
284 | + int i = 0; |
285 | + |
286 | + HelperInfo[] helpers = new HelperInfo [all_scripts.length ()]; |
287 | + foreach (unowned HelperInfo hi in all_scripts) |
288 | + { |
289 | + // our custom copy, dbus doesn't like NULLs |
290 | + helpers[i].path = hi.path; |
291 | + helpers[i].name = hi.name != null ? hi.name : ""; |
292 | + helpers[i].description = hi.description != null ? hi.description : ""; |
293 | + helpers[i].icon_name = hi.icon_name != null ? hi.icon_name : ""; |
294 | + helpers[i].app_name = hi.app_name != null ? hi.app_name : ""; |
295 | + helpers[i].app_available = hi.app_available; |
296 | + |
297 | + i++; |
298 | + } |
299 | + |
300 | + return helpers; |
301 | + } |
302 | + |
303 | public void restart_all () |
304 | { |
305 | } |
306 | |
307 | === modified file 'metadata/banshee_control.py.info' |
308 | --- metadata/banshee_control.py.info 2010-06-02 02:54:39 +0000 |
309 | +++ metadata/banshee_control.py.info 2010-06-05 13:05:33 +0000 |
310 | @@ -1,4 +1,5 @@ |
311 | -NAME="Banshee Controls" |
312 | -DESCRIPTION="Control Banshee media playback" |
313 | -ICON="banshee" |
314 | -APPURI="/usr/bin/banshee" |
315 | +[DockmanagerHelper] |
316 | +Name=Banshee Controls |
317 | +Description=Control Banshee media playback |
318 | +Icon=banshee |
319 | +AppName=banshee |
320 | |
321 | === modified file 'metadata/deluge_badge.py.info' |
322 | --- metadata/deluge_badge.py.info 2010-06-02 02:54:39 +0000 |
323 | +++ metadata/deluge_badge.py.info 2010-06-05 13:05:33 +0000 |
324 | @@ -1,4 +1,5 @@ |
325 | -NAME="Deluge" |
326 | -DESCRIPTION="Show transfer rates" |
327 | -ICON="deluge" |
328 | -APPURI="/usr/bin/deluge" |
329 | +[DockmanagerHelper] |
330 | +Name=Deluge |
331 | +Description=Show transfer rates |
332 | +Icon=deluge |
333 | +AppName=deluge |
334 | |
335 | === modified file 'metadata/emesene_control.py.info' |
336 | --- metadata/emesene_control.py.info 2010-06-02 02:54:39 +0000 |
337 | +++ metadata/emesene_control.py.info 2010-06-05 13:05:33 +0000 |
338 | @@ -1,4 +1,5 @@ |
339 | -NAME="Emesene Controls" |
340 | -DESCRIPTION="See your message count status on Emesene" |
341 | -ICON="emesene" |
342 | -APPURI="/usr/bin/emesene" |
343 | +[DockmanagerHelper] |
344 | +Name=Emesene Controls |
345 | +Description=See your message count status on Emesene |
346 | +Icon=emesene |
347 | +AppName=emesene |
348 | |
349 | === modified file 'metadata/gajim_badge.py.info' |
350 | --- metadata/gajim_badge.py.info 2010-06-02 02:54:39 +0000 |
351 | +++ metadata/gajim_badge.py.info 2010-06-05 13:05:33 +0000 |
352 | @@ -1,4 +1,5 @@ |
353 | -NAME="Gajim" |
354 | -DESCRIPTION="Shows new messages count" |
355 | -ICON="gajim" |
356 | -APPURI="/usr/bin/gajim" |
357 | +[DockmanagerHelper] |
358 | +Name=Gajim |
359 | +Description=Shows new messages count |
360 | +Icon=gajim |
361 | +AppName=gajim |
362 | |
363 | === modified file 'metadata/gtg_menus.py.info' |
364 | --- metadata/gtg_menus.py.info 2010-06-02 02:54:39 +0000 |
365 | +++ metadata/gtg_menus.py.info 2010-06-05 13:05:33 +0000 |
366 | @@ -1,4 +1,5 @@ |
367 | -NAME="Getting Things GNOME!" |
368 | -DESCRIPTION="Access your tasks" |
369 | -ICON="gtg" |
370 | -APPURI="/usr/bin/gtg" |
371 | +[DockmanagerHelper] |
372 | +Name=Getting Things GNOME! |
373 | +Description=Access your tasks |
374 | +Icon=gtg |
375 | +AppName=gtg |
376 | |
377 | === modified file 'metadata/liferea_badge.py.info' |
378 | --- metadata/liferea_badge.py.info 2010-06-02 02:54:39 +0000 |
379 | +++ metadata/liferea_badge.py.info 2010-06-05 13:05:33 +0000 |
380 | @@ -1,4 +1,5 @@ |
381 | -NAME="Liferea" |
382 | -DESCRIPTION="Shows unread messages count" |
383 | -ICON="liferea" |
384 | -APPURI="/usr/bin/liferea" |
385 | +[DockmanagerHelper] |
386 | +Name=Liferea |
387 | +Description=Shows unread messages count |
388 | +Icon=liferea |
389 | +AppName=liferea |
390 | |
391 | === modified file 'metadata/open_terminal_here.py.info' |
392 | --- metadata/open_terminal_here.py.info 2010-06-02 02:54:39 +0000 |
393 | +++ metadata/open_terminal_here.py.info 2010-06-05 13:05:33 +0000 |
394 | @@ -1,4 +1,5 @@ |
395 | -NAME="Open Terminal Here" |
396 | -DESCRIPTION="Opens a terminal at the selected location" |
397 | -ICON="gnome-terminal" |
398 | -APPURI="/usr/bin/gnome-terminal" |
399 | +[DockmanagerHelper] |
400 | +Name=Open Terminal Here |
401 | +Description=Opens a terminal at the selected location |
402 | +Icon=gnome-terminal |
403 | +AppName=gnome-terminal |
404 | |
405 | === modified file 'metadata/pidgin_control.py.info' |
406 | --- metadata/pidgin_control.py.info 2010-06-02 02:54:39 +0000 |
407 | +++ metadata/pidgin_control.py.info 2010-06-05 13:05:33 +0000 |
408 | @@ -1,4 +1,5 @@ |
409 | -NAME="Pidgin Controls" |
410 | -DESCRIPTION="Control your availability and connectivity status on Pidgin" |
411 | -ICON="pidgin" |
412 | -APPURI="/usr/bin/pidgin" |
413 | +[DockmanagerHelper] |
414 | +Name=Pidgin Controls |
415 | +Description=Control your availability and connectivity status on Pidgin |
416 | +Icon=pidgin |
417 | +AppName=pidgin |
418 | |
419 | === modified file 'metadata/rhythmbox_control.py.info' |
420 | --- metadata/rhythmbox_control.py.info 2010-06-02 02:54:39 +0000 |
421 | +++ metadata/rhythmbox_control.py.info 2010-06-05 13:05:33 +0000 |
422 | @@ -1,4 +1,5 @@ |
423 | -NAME="Rhythmbox Controls" |
424 | -DESCRIPTION="Control Rhythmbox media playback" |
425 | -ICON="rhythmbox" |
426 | -APPURI="/usr/bin/rhythmbox" |
427 | +[DockmanagerHelper] |
428 | +Name=Rhythmbox Controls |
429 | +Description=Control Rhythmbox media playback |
430 | +Icon=rhythmbox |
431 | +AppName=rhythmbox |
432 | |
433 | === modified file 'metadata/tomboy_menus.py.info' |
434 | --- metadata/tomboy_menus.py.info 2010-06-02 02:54:39 +0000 |
435 | +++ metadata/tomboy_menus.py.info 2010-06-05 13:05:33 +0000 |
436 | @@ -1,4 +1,5 @@ |
437 | -NAME="Tomboy Notes" |
438 | -DESCRIPTION="Access your Tomboy notes" |
439 | -ICON="tomboy" |
440 | -APPURI="/usr/bin/tomboy" |
441 | +[DockmanagerHelper] |
442 | +Name=Tomboy Notes |
443 | +Description=Access your Tomboy notes |
444 | +Icon=tomboy |
445 | +AppName=tomboy |
446 | |
447 | === modified file 'metadata/transmission_badge.py.info' |
448 | --- metadata/transmission_badge.py.info 2010-06-02 02:54:39 +0000 |
449 | +++ metadata/transmission_badge.py.info 2010-06-05 13:05:33 +0000 |
450 | @@ -1,4 +1,5 @@ |
451 | -NAME="Transmission" |
452 | -DESCRIPTION="Show transfer rates" |
453 | -ICON="transmission" |
454 | -APPURI="/usr/bin/transmission" |
455 | +[DockmanagerHelper] |
456 | +Name=Transmission |
457 | +Description=Show transfer rates |
458 | +Icon=transmission |
459 | +AppName=transmission |
460 | |
461 | === modified file 'metadata/tsclient_menus.py.info' |
462 | --- metadata/tsclient_menus.py.info 2010-06-02 02:54:39 +0000 |
463 | +++ metadata/tsclient_menus.py.info 2010-06-05 13:05:33 +0000 |
464 | @@ -1,4 +1,5 @@ |
465 | -NAME="Terminal Server Client" |
466 | -DESCRIPTION="Jump directly to Terminal Server Client bookmarks" |
467 | -ICON="tsclient" |
468 | -APPURI="/usr/bin/tsclient" |
469 | +[DockmanagerHelper] |
470 | +Name=Terminal Server Client |
471 | +Description=Jump directly to Terminal Server Client bookmarks |
472 | +Icon=tsclient |
473 | +AppName=tsclient |
474 | |
475 | === modified file 'metadata/zeitgeist_journal.py.info' |
476 | --- metadata/zeitgeist_journal.py.info 2010-06-02 10:08:48 +0000 |
477 | +++ metadata/zeitgeist_journal.py.info 2010-06-05 13:05:33 +0000 |
478 | @@ -1,3 +1,4 @@ |
479 | -NAME="Zeitgeist Journal" |
480 | -DESCRIPTION="Provides a journal of all activity for the selected application supplied by Zeitgeist" |
481 | -APPURI="/usr/bin/zeitgeist-daemon" |
482 | +[DockmanagerHelper] |
483 | +Name=Zeitgeist Journal |
484 | +Description=Provides a journal of all activity for the selected application supplied by Zeitgeist |
485 | +AppName=zeitgeist-daemon |
486 | |
487 | === modified file 'metadata/zeitgeist_menus.py.info' |
488 | --- metadata/zeitgeist_menus.py.info 2010-06-02 10:08:48 +0000 |
489 | +++ metadata/zeitgeist_menus.py.info 2010-06-05 13:05:33 +0000 |
490 | @@ -1,3 +1,4 @@ |
491 | -NAME="Zeitgeist Integration" |
492 | -DESCRIPTION="Interfaces with Zeitgeist to supply a list of most used items for an application" |
493 | -APPURI="/usr/bin/zeitgeist-daemon" |
494 | +[DockmanagerHelper] |
495 | +Name=Zeitgeist Integration |
496 | +Description=Interfaces with Zeitgeist to supply a list of most used items for an application |
497 | +AppName=zeitgeist-daemon |
First of all, your diff includes way more than what you wanted. You should fix that up.
Second, what is the point to the metadata changes? What is the format used? Is it just a true INI file format? Must we verify the section is named 'DEFAULT'? What if it isnt, do we still use it? Will we allow other sections, if so what are those?