[Xfce4-commits] <garcon:jannis/basic-monitoring> Monitor merged files/dirs and reload menus when one of them changes.

Jannis Pohlmann noreply at xfce.org
Sun Sep 5 16:58:01 CEST 2010


Updating branch refs/heads/jannis/basic-monitoring
         to ccf88785ae826293eb0a1868985dda89f542eac5 (commit)
       from 7b9ad615f0fb2c0945edd08a848afaa96e5e4dd1 (commit)

commit ccf88785ae826293eb0a1868985dda89f542eac5
Author: Jannis Pohlmann <jannis at xfce.org>
Date:   Sun Sep 5 16:55:32 2010 +0200

    Monitor merged files/dirs and reload menus when one of them changes.
    
    This requires a modification to GarconMenuMerger as it needs to collect
    and return a list of all files and directories that were merged into the
    menu tree.

 garcon/garcon-menu-merger.c |   73 +++++++++++++++++--------
 garcon/garcon-menu-merger.h |    2 +
 garcon/garcon-menu.c        |  128 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 178 insertions(+), 25 deletions(-)

diff --git a/garcon/garcon-menu-merger.c b/garcon/garcon-menu-merger.c
index b917782..f620d6f 100644
--- a/garcon/garcon-menu-merger.c
+++ b/garcon/garcon-menu-merger.c
@@ -35,16 +35,6 @@
 
 typedef struct _GarconMenuMergerContext GarconMenuMergerContext;
 
-struct _GarconMenuMergerContext
-{
-  GarconMenuNodeType node_type;
-  GarconMenuMerger  *merger;
-  GCancellable      *cancellable;
-  GError           **error;
-  gboolean           success;
-  GList             *file_stack;
-};
-
 
 
 #define GARCON_MENU_MERGER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GARCON_TYPE_MENU_MERGER, GarconMenuMergerPrivate))
@@ -98,6 +88,18 @@ struct _GarconMenuMergerPrivate
   GList                  *file_stack;
 };
 
+struct _GarconMenuMergerContext
+{
+  GarconMenuNodeType node_type;
+  GarconMenuMerger  *merger;
+  GCancellable      *cancellable;
+  GError           **error;
+  gboolean           success;
+  GList             *file_stack;
+  GList            **merge_files;
+  GList            **merge_dirs;
+};
+
 
 
 G_DEFINE_TYPE_WITH_CODE (GarconMenuMerger, garcon_menu_merger, G_TYPE_OBJECT,
@@ -266,6 +268,8 @@ garcon_menu_merger_prepare_merging (GarconMenuMerger        *merger,
 
 gboolean
 garcon_menu_merger_run (GarconMenuMerger *merger,
+                        GList           **merge_files,
+                        GList           **merge_dirs,
                         GCancellable     *cancellable,
                         GError          **error)
 {
@@ -280,6 +284,8 @@ garcon_menu_merger_run (GarconMenuMerger *merger,
   context.error = error;
   context.success = TRUE;
   context.file_stack = NULL;
+  context.merge_files = merge_files;
+  context.merge_dirs = merge_dirs;
 
   file = garcon_menu_tree_provider_get_file (GARCON_MENU_TREE_PROVIDER (merger));
   context.file_stack = g_list_concat (context.file_stack, merger->priv->file_stack);
@@ -315,7 +321,7 @@ garcon_menu_merger_run (GarconMenuMerger *merger,
                    (GNodeTraverseFunc) garcon_menu_merger_resolve_relative_paths,
                    &context);
 
-  garcon_menu_merger_remove_duplicate_paths (merger->priv->menu,GARCON_MENU_NODE_TYPE_DIRECTORY_DIR);
+  garcon_menu_merger_remove_duplicate_paths (merger->priv->menu, GARCON_MENU_NODE_TYPE_DIRECTORY_DIR);
   garcon_menu_merger_remove_duplicate_paths (merger->priv->menu, GARCON_MENU_NODE_TYPE_DIRECTORY);
 
   garcon_menu_merger_resolve_moves (merger->priv->menu);
@@ -439,6 +445,16 @@ garcon_menu_merger_insert_default_dirs (GNode *parent,
 
 
 
+static gint
+compare_files (GFile *file,
+               GFile *other_file)
+{
+  return g_file_equal (file, other_file) ? 0 : 1;
+}
+
+
+
+
 static void
 garcon_menu_merger_insert_default_merge_dirs (GNode *parent,
                                               GNode *defaults_node)
@@ -750,11 +766,21 @@ garcon_menu_merger_resolve_merge_dirs (GNode                   *node,
 
   dir = _garcon_file_new_for_unknown_input (garcon_menu_node_tree_get_string (node), NULL);
 
+  if (dir == NULL)
+    return FALSE;
+
   enumerator = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME,
                                           G_FILE_QUERY_INFO_NONE, NULL, NULL);
 
   if (G_UNLIKELY (enumerator != NULL))
     {
+      /* Add merge dir to the list */
+      if (context->merge_dirs != NULL 
+          && !g_list_find_custom (*context->merge_dirs, dir, (GCompareFunc) compare_files))
+        {
+          *context->merge_dirs = g_list_prepend (*context->merge_dirs, g_object_ref (dir));
+        }
+
       while (TRUE)
         {
           file_info = g_file_enumerator_next_file (enumerator, NULL, NULL);
@@ -813,16 +839,6 @@ garcon_menu_parser_insert_elements (GNode *node,
 
 
 
-static gint
-compare_files (GFile *file,
-               GFile *other_file)
-{
-  return g_file_equal (file, other_file) ? 0 : 1;
-}
-
-
-
-
 static gboolean
 garcon_menu_merger_process_merge_files (GNode                   *node,
                                         GarconMenuMergerContext *context)
@@ -850,7 +866,6 @@ garcon_menu_merger_process_merge_files (GNode                   *node,
     }
 
   parser = garcon_menu_parser_new (file);
-  g_object_unref (file);
 
   if (G_LIKELY (garcon_menu_parser_run (parser, NULL, NULL)))
     {
@@ -860,7 +875,10 @@ garcon_menu_merger_process_merge_files (GNode                   *node,
       merger->priv->file_stack = g_list_copy (context->file_stack);
       g_list_foreach (merger->priv->file_stack, (GFunc) g_object_ref, NULL);
 
-      if (G_LIKELY (garcon_menu_merger_run (merger, NULL, NULL)))
+      if (G_LIKELY (garcon_menu_merger_run (merger, 
+                                            context->merge_files, 
+                                            context->merge_dirs, 
+                                            context->cancellable, NULL)))
         {
           tree = garcon_menu_tree_provider_get_tree (GARCON_MENU_TREE_PROVIDER (merger));
           g_object_unref (merger);
@@ -869,11 +887,20 @@ garcon_menu_merger_process_merge_files (GNode                   *node,
           g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
                            (GNodeTraverseFunc) garcon_menu_parser_insert_elements, tree);
           g_node_destroy (tree);
+
+          /* Add merged file to the list */
+          if (context->merge_files != NULL
+              && !g_list_find_custom (*context->merge_files, file, (GCompareFunc) compare_files))
+            {
+              *context->merge_files = g_list_prepend (*context->merge_files, g_object_ref (file));
+            }
         }
     }
 
   garcon_menu_node_tree_free (node);
 
+  g_object_unref (file);
+
   return FALSE;
 }
 
diff --git a/garcon/garcon-menu-merger.h b/garcon/garcon-menu-merger.h
index 45a63ca..129fc43 100644
--- a/garcon/garcon-menu-merger.h
+++ b/garcon/garcon-menu-merger.h
@@ -45,6 +45,8 @@ GType             garcon_menu_merger_get_type (void) G_GNUC_CONST;
 
 GarconMenuMerger *garcon_menu_merger_new      (GarconMenuTreeProvider *provider) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
 gboolean          garcon_menu_merger_run      (GarconMenuMerger       *merger,
+                                               GList                 **merge_files,
+                                               GList                 **merge_dirs,
                                                GCancellable           *cancellable,
                                                GError                **error);
 
diff --git a/garcon/garcon-menu.c b/garcon/garcon-menu.c
index f01259c..467d4f0 100644
--- a/garcon/garcon-menu.c
+++ b/garcon/garcon-menu.c
@@ -152,11 +152,26 @@ static gboolean             garcon_menu_get_element_equal               (GarconM
 static void                 garcon_menu_start_monitoring                (GarconMenu              *menu);
 static void                 garcon_menu_stop_monitoring                 (GarconMenu              *menu);
 static void                 garcon_menu_monitor_menu_files              (GarconMenu              *menu);
+static void                 garcon_menu_monitor_files                   (GarconMenu              *menu,
+                                                                         GList                   *files,
+                                                                         gpointer                 callback);
 static void                 garcon_menu_file_changed                    (GarconMenu              *menu,
                                                                          GFile                   *file,
                                                                          GFile                   *other_file,
                                                                          GFileMonitorEvent        event_type,
                                                                          GFileMonitor            *monitor);
+static void                 garcon_menu_merge_file_changed              (GarconMenu              *menu,
+                                                                         GFile                   *file,
+                                                                         GFile                   *other_file,
+                                                                         GFileMonitorEvent        event_type,
+                                                                         GFileMonitor            *monitor);
+static void                 garcon_menu_merge_dir_changed               (GarconMenu              *menu,
+                                                                         GFile                   *file,
+                                                                         GFile                   *other_file,
+                                                                         GFileMonitorEvent        event_type,
+                                                                         GFileMonitor            *monitor);
+
+
 
 
 
@@ -168,6 +183,10 @@ struct _GarconMenuPrivate
   /* DOM tree */
   GNode               *tree;
 
+  /* Merged menu files and merge directories */
+  GList               *merge_files;
+  GList               *merge_dirs;
+
   /* File and directory monitors */
   GList               *monitors;
 
@@ -199,6 +218,7 @@ G_DEFINE_TYPE_WITH_CODE (GarconMenu, garcon_menu, G_TYPE_OBJECT,
 
 
 static guint menu_signals[LAST_SIGNAL];
+static GQuark garcon_menu_file_quark;
 
 
 
@@ -253,6 +273,8 @@ garcon_menu_class_init (GarconMenuClass *klass)
                   g_cclosure_marshal_VOID__VOID,
                   G_TYPE_NONE,
                   0);
+
+  garcon_menu_file_quark = g_quark_from_string ("garcon-menu-file-quark");
 }
 
 
@@ -277,6 +299,8 @@ garcon_menu_init (GarconMenu *menu)
   menu->priv = GARCON_MENU_GET_PRIVATE (menu);
   menu->priv->file = NULL;
   menu->priv->tree = NULL;
+  menu->priv->merge_files = NULL;
+  menu->priv->merge_dirs = NULL;
   menu->priv->monitors = NULL;
   menu->priv->directory = NULL;
   menu->priv->submenus = NULL;
@@ -304,6 +328,16 @@ garcon_menu_clear (GarconMenu *menu)
       /* Destroy the menu tree */
       garcon_menu_node_tree_free (menu->priv->tree);
       menu->priv->tree = NULL;
+
+      /* Release the merge files */
+      g_list_foreach (menu->priv->merge_files, (GFunc) g_object_unref, NULL);
+      g_list_free (menu->priv->merge_files);
+      menu->priv->merge_files = NULL;
+
+      /* Release the merge dirs */
+      g_list_foreach (menu->priv->merge_dirs, (GFunc) g_object_unref, NULL);
+      g_list_free (menu->priv->merge_dirs);
+      menu->priv->merge_dirs = NULL;
     }
 
   /* Free submenus */
@@ -651,8 +685,8 @@ garcon_menu_load (GarconMenu   *menu,
       merger = garcon_menu_merger_new (GARCON_MENU_TREE_PROVIDER (parser));
 
       if (garcon_menu_merger_run (merger, 
-                                  /* &menu->priv->merge_files,
-                                  &menu->priv->merge_dirs, */
+                                  &menu->priv->merge_files,
+                                  &menu->priv->merge_dirs,
                                   cancellable, error))
         {
           menu->priv->tree = 
@@ -1682,6 +1716,12 @@ garcon_menu_start_monitoring (GarconMenu *menu)
   if (menu->priv->parent == NULL)
     {
       garcon_menu_monitor_menu_files (menu);
+
+      garcon_menu_monitor_files (menu, menu->priv->merge_files, 
+                                 garcon_menu_merge_file_changed);
+      
+      garcon_menu_monitor_files (menu, menu->priv->merge_dirs,
+                                 garcon_menu_merge_dir_changed);
     }
 
   /* Recurse into submenus */
@@ -1769,6 +1809,60 @@ garcon_menu_monitor_menu_files (GarconMenu *menu)
 
 
 
+static gint
+find_file_monitor (GFileMonitor *monitor,
+                   GFile        *file)
+{
+  GFile *monitored_file;
+
+  monitored_file = g_object_get_qdata (G_OBJECT (monitor), garcon_menu_file_quark);
+
+  if (monitored_file != NULL && g_file_equal (monitored_file, file))
+    return 0;
+  else
+    return -1;
+}
+
+
+
+static void
+garcon_menu_monitor_files (GarconMenu *menu,
+                           GList      *files,
+                           gpointer    callback)
+{
+  GFileMonitor *monitor;
+  GList        *lp;
+
+  g_return_if_fail (GARCON_IS_MENU (menu));
+  g_return_if_fail (menu->priv->parent == NULL);
+
+  /* Monitor all files from the list */
+  for (lp = files; lp != NULL; lp = lp->next)
+    {
+      /* Monitor files only if they are not being monitored already */
+      if (g_list_find_custom (menu->priv->monitors, lp->data, 
+                              (GCompareFunc) find_file_monitor) == NULL)
+        {
+          /* Try to monitor the file */
+          monitor = g_file_monitor (lp->data, G_FILE_MONITOR_NONE, NULL, NULL);
+          if (monitor != NULL)
+            {
+              /* Associate the monitor with the monitored file */
+              g_object_set_qdata_full (G_OBJECT (monitor), garcon_menu_file_quark,
+                                       g_object_ref (lp->data), g_object_unref);
+
+              /* Add the monitor to the list of monitors belonging to the menu */
+              menu->priv->monitors = g_list_prepend (menu->priv->monitors, monitor);
+
+              /* Make sure we are notified when the file changes */
+              g_signal_connect_swapped (monitor, "changed", G_CALLBACK (callback), menu);
+            }
+        }
+    }
+}
+
+
+
 static void
 garcon_menu_file_changed (GarconMenu       *menu,
                           GFile            *file,
@@ -1826,3 +1920,33 @@ garcon_menu_file_changed (GarconMenu       *menu,
   if (!lower_priority && higher_priority)
     g_signal_emit (menu, menu_signals[RELOAD_REQUIRED], 0);
 }
+
+
+
+static void
+garcon_menu_merge_file_changed (GarconMenu       *menu,
+                                GFile            *file,
+                                GFile            *other_file,
+                                GFileMonitorEvent event_type,
+                                GFileMonitor     *monitor)
+{
+  g_return_if_fail (GARCON_IS_MENU (menu));
+  g_return_if_fail (menu->priv->parent == NULL);
+
+  g_signal_emit (menu, menu_signals[RELOAD_REQUIRED], 0);
+}
+
+
+
+static void
+garcon_menu_merge_dir_changed (GarconMenu       *menu,
+                               GFile            *file,
+                               GFile            *other_file,
+                               GFileMonitorEvent event_type,
+                               GFileMonitor     *monitor)
+{
+  g_return_if_fail (GARCON_IS_MENU (menu));
+  g_return_if_fail (menu->priv->parent == NULL);
+
+  g_signal_emit (menu, menu_signals[RELOAD_REQUIRED], 0);
+}



More information about the Xfce4-commits mailing list