Updating branch refs/heads/master to ccf88785ae826293eb0a1868985dda89f542eac5 (commit) from 7b9ad615f0fb2c0945edd08a848afaa96e5e4dd1 (commit)
commit ccf88785ae826293eb0a1868985dda89f542eac5 Author: Jannis Pohlmann <jan...@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); +} _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits