[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