]> git.pld-linux.org Git - packages/desktop-file-utils.git/blob - desktop-file-utils-directory_change_notify.patch
- make new desktop files and changes instantly visible
[packages/desktop-file-utils.git] / desktop-file-utils-directory_change_notify.patch
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 +}
This page took 0.117819 seconds and 3 git commands to generate.