]>
Commit | Line | Data |
---|---|---|
a0f3b157 | 1 | --- desktop-file-utils-0.6/src/menu-process.c.directory-change-notify 2004-05-03 23:46:00.074881280 -0400 |
2 | +++ desktop-file-utils-0.6/src/menu-process.c 2004-05-03 23:47:09.124384160 -0400 | |
3 | @@ -41,8 +41,16 @@ | |
4 | const char *name, | |
5 | gboolean create_if_not_found); | |
6 | ||
7 | +static DesktopEntryTreeDirAddCallback dir_add_callback = NULL; | |
8 | +void desktop_entry_tree_dir_add_notify (void *element, void *user_data); | |
9 | ||
10 | ||
11 | +void | |
12 | +desktop_entry_tree_diradd_callback_set (DesktopEntryTreeDirAddCallback proc) | |
13 | +{ | |
14 | + dir_add_callback = proc; | |
15 | +} | |
16 | + | |
17 | static MenuNode* | |
18 | find_menu_child (MenuNode *node) | |
19 | { | |
20 | @@ -1005,6 +1013,7 @@ | |
21 | MenuNode *orig_node; | |
22 | MenuNode *resolved_node; | |
23 | TreeNode *root; | |
24 | + GSList *monitored_dirs; | |
25 | }; | |
26 | ||
27 | static void build_tree (DesktopEntryTree *tree); | |
28 | @@ -1015,6 +1024,21 @@ | |
29 | static char* localized_path_for_entry (TreeNode *parent, | |
30 | Entry *entry); | |
31 | static char* localized_path_for_node (TreeNode *node); | |
32 | +static TreeNode* tree_node_from_menu_node (TreeNode *parent, | |
33 | + MenuNode *menu_node, | |
34 | + GHashTable *allocated, | |
35 | + const DesktopEntryTree *tree); | |
36 | +static void remove_empty_submenus (TreeNode * node); | |
37 | +static void process_only_unallocated (TreeNode *node, | |
38 | + GHashTable *allocated); | |
39 | + | |
40 | +const char *desktop_entry_tree_get_menu_file_name (DesktopEntryTree *tree) | |
41 | +{ | |
42 | + g_return_val_if_fail (tree != NULL, NULL); | |
43 | + | |
44 | + return tree->menu_file; | |
45 | +} | |
46 | + | |
47 | ||
48 | DesktopEntryTree* | |
49 | desktop_entry_tree_load (const char *filename, | |
50 | @@ -1083,6 +1107,7 @@ | |
51 | tree->orig_node = orig_node; | |
52 | tree->resolved_node = resolved_node; | |
53 | tree->root = NULL; | |
54 | + tree->monitored_dirs = NULL; | |
55 | ||
56 | return tree; | |
57 | } | |
58 | @@ -1096,6 +1121,14 @@ | |
59 | tree->refcount += 1; | |
60 | } | |
61 | ||
62 | +static void | |
63 | +monitored_dir_list_clear (void *element, | |
64 | + void *user_data) | |
65 | +{ | |
66 | + GSList *list = element; | |
67 | + g_free (list->data); | |
68 | +} | |
69 | + | |
70 | void | |
71 | desktop_entry_tree_unref (DesktopEntryTree *tree) | |
72 | { | |
73 | @@ -1111,10 +1144,15 @@ | |
74 | menu_node_unref (tree->orig_node); | |
75 | menu_node_unref (tree->resolved_node); | |
76 | if (tree->root) | |
77 | + { | |
78 | tree_node_free (tree->root); | |
79 | + tree->root = NULL; | |
80 | + } | |
81 | + g_slist_foreach (tree->monitored_dirs, monitored_dir_list_clear, NULL); | |
82 | + g_slist_free (tree->monitored_dirs); | |
83 | entry_cache_unref (tree->entry_cache); | |
84 | menu_cache_unref (tree->menu_cache); | |
85 | -#if 1 | |
86 | +#if 0 | |
87 | /* debugging, to make memory stuff fail */ | |
88 | memset (tree, 0xff, sizeof (*tree)); | |
89 | tree->refcount = -5; | |
90 | @@ -1125,12 +1163,42 @@ | |
91 | ||
92 | void | |
93 | desktop_entry_tree_invalidate (DesktopEntryTree *tree, | |
94 | - const char *dirname) | |
95 | + const char *menu_file, | |
96 | + const char *entry_path) | |
97 | { | |
98 | - menu_cache_invalidate (tree->menu_cache, dirname); | |
99 | + GHashTable *allocated; | |
100 | + TreeNode *new_node; | |
101 | + char *dirname; | |
102 | + | |
103 | + /* menu_file: the actual .menu file to reload */ | |
104 | + /* entry_dir: actual FS directory of .desktop files to reload */ | |
105 | + menu_cache_invalidate (tree->menu_cache, menu_file); | |
106 | + dirname = g_path_get_dirname (entry_path); | |
107 | entry_cache_invalidate (tree->entry_cache, dirname); | |
108 | + g_free (dirname); | |
109 | + | |
110 | + /* FIXME For the actual DesktopEntryTree itself, there aren't really | |
111 | + * invalidation functions yet (FIXME). Therefore, we blow away the root | |
112 | + * and rebuild it every time. | |
113 | + */ | |
114 | + allocated = g_hash_table_new (NULL, NULL); | |
115 | + | |
116 | + new_node = tree_node_from_menu_node (NULL, | |
117 | + find_menu_child (tree->resolved_node), | |
118 | + allocated, | |
119 | + tree); | |
120 | + if (new_node) | |
121 | + { | |
122 | + tree_node_free (tree->root); | |
123 | + tree->root = new_node; | |
124 | + process_only_unallocated (tree->root, allocated); | |
125 | + remove_empty_submenus (tree->root); | |
126 | + } | |
127 | + | |
128 | + g_hash_table_destroy (allocated); | |
129 | } | |
130 | ||
131 | + | |
132 | static TreeNode* | |
133 | find_subdir (TreeNode *parent, | |
134 | const char *subdir) | |
135 | @@ -1634,7 +1702,11 @@ | |
136 | { | |
137 | GSList *tmp; | |
138 | ||
139 | + if (!node) | |
140 | + return; | |
141 | + | |
142 | g_free (node->name); | |
143 | + node->name = NULL; | |
144 | ||
145 | tmp = node->subdirs; | |
146 | while (tmp != NULL) | |
147 | @@ -1812,10 +1884,39 @@ | |
148 | } | |
149 | #endif | |
150 | ||
151 | +/* Called from an entry_directory_list_foreach()... */ | |
152 | +void | |
153 | +desktop_entry_tree_dir_add_notify (void *element, void *user_data) | |
154 | +{ | |
155 | + EntryDirectory *dir = element; | |
156 | + DesktopEntryTree *tree = user_data; | |
157 | + GSList *tmp; | |
158 | + const char *path; | |
159 | + | |
160 | + g_return_if_fail (dir != NULL); | |
161 | + path = entry_directory_get_absolute_path (dir); | |
162 | + | |
163 | + /* Ensure we haven't already set a callback for this directory with | |
164 | + * this tree. | |
165 | + */ | |
166 | + tmp = tree->monitored_dirs; | |
167 | + while (tmp != NULL) | |
168 | + { | |
169 | + if (strcmp (tmp->data, path) == 0) | |
170 | + return; | |
171 | + tmp = tmp->next; | |
172 | + } | |
173 | + | |
174 | + tree->monitored_dirs = g_slist_append (tree->monitored_dirs, g_strdup (path)); | |
175 | + if (dir_add_callback) | |
176 | + (*dir_add_callback) (tree, path); | |
177 | +} | |
178 | + | |
179 | static TreeNode* | |
180 | tree_node_from_menu_node (TreeNode *parent, | |
181 | MenuNode *menu_node, | |
182 | - GHashTable *allocated) | |
183 | + GHashTable *allocated, | |
184 | + const DesktopEntryTree *tree) | |
185 | { | |
186 | MenuNode *child; | |
187 | EntryDirectoryList *app_dirs; | |
188 | @@ -1854,7 +1955,8 @@ | |
189 | ||
190 | child_tree = tree_node_from_menu_node (tree_node, | |
191 | child, | |
192 | - allocated); | |
193 | + allocated, | |
194 | + tree); | |
195 | if (child_tree) | |
196 | tree_node->subdirs = g_slist_prepend (tree_node->subdirs, | |
197 | child_tree); | |
198 | @@ -2012,7 +2114,12 @@ | |
199 | if (tree_node_free_if_broken (tree_node)) | |
200 | return NULL; | |
201 | else | |
202 | + { | |
203 | + /* Monitor directories containing .desktop & .directory files for changes */ | |
204 | + entry_directory_list_foreach (app_dirs, desktop_entry_tree_dir_add_notify, tree); | |
205 | + entry_directory_list_foreach (dir_dirs, desktop_entry_tree_dir_add_notify, tree); | |
206 | return tree_node; | |
207 | + } | |
208 | } | |
209 | ||
210 | static void | |
211 | @@ -2102,7 +2209,8 @@ | |
212 | ||
213 | tree->root = tree_node_from_menu_node (NULL, | |
214 | find_menu_child (tree->resolved_node), | |
215 | - allocated); | |
216 | + allocated, | |
217 | + tree); | |
218 | if (tree->root) | |
219 | process_only_unallocated (tree->root, allocated); | |
220 | ||
221 | --- desktop-file-utils-0.6/src/menu-process.h.directory-change-notify 2004-03-21 23:46:20.000000000 -0500 | |
222 | +++ desktop-file-utils-0.6/src/menu-process.h 2004-05-03 23:46:00.403831272 -0400 | |
223 | @@ -67,7 +67,8 @@ | |
224 | ||
225 | /* after calling this, the tree is out-of-date vs. what's on disk */ | |
226 | void desktop_entry_tree_invalidate (DesktopEntryTree *tree, | |
227 | - const char *dirname); | |
228 | + const char *menu_file, | |
229 | + const char *entry_path); | |
230 | ||
231 | /* These don't return references; the DesktopEntryTree is just immutable. */ | |
232 | gboolean desktop_entry_tree_get_node (DesktopEntryTree *tree, | |
233 | @@ -134,6 +135,11 @@ | |
234 | const char *menu_path_basename, | |
235 | const char *override_fs_dirname_dest, | |
236 | GError **error); | |
237 | +const char *desktop_entry_tree_get_menu_file_name (DesktopEntryTree *tree); | |
238 | + | |
239 | +/* Callback for each .desktop directory added */ | |
240 | +typedef void (*DesktopEntryTreeDirAddCallback)(DesktopEntryTree * tree, const char *path); | |
241 | +void desktop_entry_tree_diradd_callback_set (DesktopEntryTreeDirAddCallback proc); | |
242 | ||
243 | ||
244 | /* Diff */ | |
245 | --- desktop-file-utils-0.6/src/menu-tree-cache.c.directory-change-notify 2004-05-03 23:45:59.753930072 -0400 | |
246 | +++ desktop-file-utils-0.6/src/menu-tree-cache.c 2004-05-03 23:46:00.407830664 -0400 | |
247 | @@ -491,7 +491,7 @@ | |
248 | /* tell the tree that it needs to reload the .desktop file | |
249 | * cache | |
250 | */ | |
251 | - desktop_entry_tree_invalidate (tree, override_dir); | |
252 | + desktop_entry_tree_invalidate (tree, override_dir, override_dir); | |
253 | ||
254 | /* Now include the .desktop file in the .menu file */ | |
255 | if (!desktop_entry_tree_include (tree, | |
256 | @@ -583,7 +583,7 @@ | |
257 | /* tell the tree that it needs to reload the .desktop file | |
258 | * cache | |
259 | */ | |
260 | - desktop_entry_tree_invalidate (tree, override_dir); | |
261 | + desktop_entry_tree_invalidate (tree, override_dir, override_dir); | |
262 | ||
263 | /* Now include the .desktop file in the .menu file */ | |
264 | if (!desktop_entry_tree_exclude (tree, | |
265 | --- desktop-file-utils-0.6/src/menu-entries.c.directory-change-notify 2004-03-21 23:46:20.000000000 -0500 | |
266 | +++ desktop-file-utils-0.6/src/menu-entries.c 2004-05-03 23:46:00.413829752 -0400 | |
267 | @@ -247,32 +247,29 @@ | |
268 | const char *path) | |
269 | { | |
270 | CachedDir* dir; | |
271 | - char *dirname; | |
272 | char *basename; | |
273 | + char *dirname; | |
274 | char *canonical; | |
275 | Entry *retval; | |
276 | ||
277 | retval = NULL; | |
278 | - dirname = g_path_get_basename (path); | |
279 | - | |
280 | - canonical = g_canonicalize_file_name (dirname, FALSE); | |
281 | + canonical = g_canonicalize_file_name (path, FALSE); | |
282 | if (canonical == NULL) | |
283 | { | |
284 | menu_verbose ("Error %d getting entry \"%s\": %s\n", errno, path, | |
285 | g_strerror (errno)); | |
286 | - g_free (dirname); | |
287 | return NULL; | |
288 | } | |
289 | ||
290 | - basename = g_path_get_dirname (path); | |
291 | - | |
292 | + dirname = g_path_get_dirname (path); | |
293 | dir = cached_dir_load (cache, dirname, 0, NULL); | |
294 | - | |
295 | if (dir != NULL) | |
296 | - retval = cached_dir_find_entry (dir, basename); | |
297 | - | |
298 | + { | |
299 | + basename = g_path_get_basename (path); | |
300 | + retval = cached_dir_find_entry (dir, basename); | |
301 | + g_free (basename); | |
302 | + } | |
303 | g_free (dirname); | |
304 | - g_free (basename); | |
305 | ||
306 | if (retval) | |
307 | entry_ref (retval); | |
308 | @@ -344,6 +341,12 @@ | |
309 | } | |
310 | } | |
311 | ||
312 | +const char* | |
313 | +entry_directory_get_absolute_path (EntryDirectory *dir) | |
314 | +{ | |
315 | + return dir->absolute_path; | |
316 | +} | |
317 | + | |
318 | static Entry* | |
319 | entry_from_cached_entry (EntryDirectory *ed, | |
320 | Entry *src, | |
321 | @@ -681,6 +684,12 @@ | |
322 | } | |
323 | ||
324 | void | |
325 | +entry_directory_list_foreach (EntryDirectoryList *list, EntryDirectoryListForeachProc proc, DesktopEntryTree *tree) | |
326 | +{ | |
327 | + g_slist_foreach (list->dirs, proc, tree); | |
328 | +} | |
329 | + | |
330 | +void | |
331 | entry_directory_list_prepend (EntryDirectoryList *list, | |
332 | EntryDirectory *dir) | |
333 | { | |
334 | @@ -1501,6 +1510,7 @@ | |
335 | while (tmp != NULL) | |
336 | { | |
337 | g_string_append (str, tmp->data); | |
338 | + g_string_append (str, "/"); | |
339 | ||
340 | tmp = tmp->next; | |
341 | } | |
342 | @@ -2173,6 +2183,10 @@ | |
343 | static EntryCache* | |
344 | cached_dir_get_cache (CachedDir *dir) | |
345 | { | |
346 | + if (!dir->have_read_entries) | |
347 | + { | |
348 | + cached_dir_scan_recursive (dir, NULL); | |
349 | + } | |
350 | return dir->cache; | |
351 | } | |
352 | ||
353 | --- desktop-file-utils-0.6/src/menu-entries.h.directory-change-notify 2004-03-21 23:46:20.000000000 -0500 | |
354 | +++ desktop-file-utils-0.6/src/menu-entries.h 2004-05-03 23:46:00.416829296 -0400 | |
355 | @@ -24,6 +24,7 @@ | |
356 | ||
357 | #include <glib.h> | |
358 | #include "menu-layout.h" | |
359 | +#include "menu-process.h" | |
360 | ||
361 | /* This API is about actually loading directories full of .desktop | |
362 | * files and the .desktop/.directory files themselves. It also has | |
363 | @@ -84,12 +85,19 @@ | |
364 | void entry_directory_get_by_category (EntryDirectory *dir, | |
365 | const char *category, | |
366 | EntrySet *add_to_set); | |
367 | +const char* entry_directory_get_absolute_path (EntryDirectory *dir); | |
368 | + | |
369 | +typedef void (*EntryDirectoryListForeachProc)(void *element, void *user_data); | |
370 | ||
371 | EntryDirectoryList* entry_directory_list_new (void); | |
372 | ||
373 | void entry_directory_list_ref (EntryDirectoryList *list); | |
374 | void entry_directory_list_unref (EntryDirectoryList *list); | |
375 | void entry_directory_list_clear (EntryDirectoryList *list); | |
376 | +void entry_directory_list_foreach (EntryDirectoryList *list, | |
377 | + EntryDirectoryListForeachProc proc, | |
378 | + DesktopEntryTree *tree); | |
379 | + | |
380 | /* prepended dirs are searched first */ | |
381 | void entry_directory_list_prepend (EntryDirectoryList *list, | |
382 | EntryDirectory *dir); | |
383 | --- desktop-file-utils-0.6/src/menu-method.c.directory-change-notify 2004-05-03 23:45:59.440977648 -0400 | |
384 | +++ desktop-file-utils-0.6/src/menu-method.c 2004-05-03 23:46:00.423828232 -0400 | |
385 | @@ -29,9 +29,11 @@ | |
386 | #include <sys/stat.h> | |
387 | #include <fcntl.h> | |
388 | #include <errno.h> | |
389 | +#include <stdio.h> | |
390 | ||
391 | #include <config.h> | |
392 | ||
393 | +#include <libgnomevfs/gnome-vfs-ops.h> | |
394 | #include <libgnomevfs/gnome-vfs-method.h> | |
395 | #include <libgnomevfs/gnome-vfs-module-shared.h> | |
396 | #include <libgnomevfs/gnome-vfs-module.h> | |
397 | @@ -46,6 +48,8 @@ | |
398 | ||
399 | #include "menu-tree-cache.h" | |
400 | #include "menu-util.h" | |
401 | +#include "menu-entries.h" | |
402 | +#include "menu-process.h" | |
403 | ||
404 | /* FIXME - we have a gettext domain problem while not included in libgnomevfs */ | |
405 | #define _(x) x | |
406 | @@ -151,6 +155,14 @@ | |
407 | static void monitor_handle_ref (MonitorHandle *handle); | |
408 | static void monitor_handle_unref (MonitorHandle *handle); | |
409 | ||
410 | + | |
411 | +static void directory_add_callback (DesktopEntryTree * tree, const char * path); | |
412 | +void directory_monitor_callback (GnomeVFSMonitorHandle *handle, | |
413 | + const gchar *monitor_uri, | |
414 | + const gchar *info_uri, | |
415 | + GnomeVFSMonitorEventType event_type, | |
416 | + gpointer user_data); | |
417 | + | |
418 | struct { | |
419 | const char *scheme; | |
420 | const char *menu_file; | |
421 | @@ -737,6 +749,7 @@ | |
422 | GnomeVFSMethod * | |
423 | vfs_module_init (const char *method_name, const char *args) | |
424 | { | |
425 | + desktop_entry_tree_diradd_callback_set (directory_add_callback); | |
426 | return &vtable; | |
427 | } | |
428 | ||
429 | @@ -1988,3 +2001,33 @@ | |
430 | g_free (handle); | |
431 | } | |
432 | } | |
433 | + | |
434 | +static void | |
435 | +directory_add_callback (DesktopEntryTree * tree, const char * path) | |
436 | +{ | |
437 | + GnomeVFSMonitorHandle* handle; | |
438 | + | |
439 | + gnome_vfs_monitor_add (&handle, path, | |
440 | + GNOME_VFS_MONITOR_DIRECTORY, | |
441 | + directory_monitor_callback, tree); | |
442 | +} | |
443 | + | |
444 | + | |
445 | +void directory_monitor_callback (GnomeVFSMonitorHandle *handle, | |
446 | + const gchar *monitor_uri, | |
447 | + const gchar *info_uri, | |
448 | + GnomeVFSMonitorEventType event_type, | |
449 | + gpointer user_data) | |
450 | +{ | |
451 | + MenuMethod * method; | |
452 | + DesktopEntryTree * tree = user_data; | |
453 | + | |
454 | + method = method_checkout (); | |
455 | + | |
456 | + if (tree) | |
457 | + desktop_entry_tree_invalidate( tree, | |
458 | + desktop_entry_tree_get_menu_file_name (tree), | |
459 | + gnome_vfs_get_local_path_from_uri (info_uri)); | |
460 | + | |
461 | + method_return (method); | |
462 | +} |