[gnome-menus] Add explicit gmenu_tree_load_sync()



commit 8ecb1aa5d762d25f787002dd001e92e404efabe9
Author: Colin Walters <walters verbum org>
Date:   Sun Apr 17 09:31:34 2011 -0400

    Add explicit gmenu_tree_load_sync()
    
    Rather than having _get_root_directory() be lazy, require users
    to explicitly load via this function (or in the future, an
    async variant).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=647968

 libmenu/gmenu-tree.c  |   74 ++++++++++++++++++++++++++++++++++++++++--------
 libmenu/gmenu-tree.h  |    3 ++
 util/test-menu-spec.c |   16 ++++++++++
 3 files changed, 80 insertions(+), 13 deletions(-)
---
diff --git a/libmenu/gmenu-tree.c b/libmenu/gmenu-tree.c
index fa70eb0..c738796 100644
--- a/libmenu/gmenu-tree.c
+++ b/libmenu/gmenu-tree.c
@@ -59,7 +59,10 @@ struct _GMenuTree
   MenuLayoutNode *layout;
   GMenuTreeDirectory *root;
 
+  GError *load_error;
+
   guint canonical : 1;
+  guint loaded    : 1;
 };
 
 G_DEFINE_TYPE (GMenuTree, gmenu_tree, G_TYPE_OBJECT)
@@ -138,7 +141,7 @@ struct GMenuTreeAlias
 
 static void      gmenu_tree_load_layout          (GMenuTree       *tree);
 static void      gmenu_tree_force_reload         (GMenuTree       *tree);
-static void      gmenu_tree_build_from_layout    (GMenuTree       *tree);
+static gboolean  gmenu_tree_build_from_layout    (GMenuTree       *tree, GError **error);
 static void      gmenu_tree_force_rebuild        (GMenuTree       *tree);
 static void      gmenu_tree_resolve_files        (GMenuTree       *tree,
 						  GHashTable      *loaded_menu_files,
@@ -489,6 +492,8 @@ gmenu_tree_finalize (GObject *object)
     g_free (tree->canonical_path);
   tree->canonical_path = NULL;
 
+  g_clear_error (&(tree->load_error));
+
   G_OBJECT_CLASS (gmenu_tree_parent_class)->finalize (object);
 }
 
@@ -572,18 +577,50 @@ gmenu_tree_get_menu_file (GMenuTree *tree)
   return ugly_result_cache;
 }
 
-GMenuTreeDirectory *
-gmenu_tree_get_root_directory (GMenuTree *tree)
+/**
+ * gmenu_tree_load_sync:
+ * @tree: a #GMenuTree
+ * @error: a #GError
+ *
+ * Synchronously load the menu contents.  This function
+ * performs a significant amount of blocking I/O if the
+ * tree has not been loaded yet.
+ * 
+ * Returns: %TRUE on success, %FALSE on error
+ */
+gboolean
+gmenu_tree_load_sync (GMenuTree   *tree,
+		      GError     **error)
 {
-  g_return_val_if_fail (tree != NULL, NULL);
-
-  if (!tree->root)
+  if (!tree->loaded)
     {
-      gmenu_tree_build_from_layout (tree);
+      g_clear_error (&tree->load_error);
+      gmenu_tree_build_from_layout (tree, &tree->load_error);
+      tree->loaded = TRUE;
+    }
 
-      if (!tree->root)
-        return NULL;
+  if (tree->load_error)
+    {
+      g_propagate_error (error, tree->load_error);
+      return FALSE;
     }
+  return TRUE;
+}
+
+/**
+ * gmenu_tree_get_root_directory:
+ * @tree: a #GMenuTree
+ *
+ * Get the root directory; you must have loaded the tree first (at
+ * least once) via gmenu_tree_load_sync() or a variant thereof.
+ * 
+ * Returns: (transfer full): Root of the tree
+ */
+GMenuTreeDirectory *
+gmenu_tree_get_root_directory (GMenuTree *tree)
+{
+  g_return_val_if_fail (tree != NULL, NULL);
+  g_return_val_if_fail (tree->loaded, NULL);
 
   return gmenu_tree_item_ref (tree->root);
 }
@@ -4085,17 +4122,24 @@ handle_entries_changed (MenuLayoutNode *layout,
     }
 }
 
-static void
-gmenu_tree_build_from_layout (GMenuTree *tree)
+static gboolean
+gmenu_tree_build_from_layout (GMenuTree *tree,
+			      GError   **error)
 {
   DesktopEntrySet *allocated;
 
   if (tree->root)
-    return;
+    return TRUE;
 
   gmenu_tree_load_layout (tree);
   if (!tree->layout)
-    return;
+    {
+      g_set_error (error,
+		   G_IO_ERROR,
+		   G_IO_ERROR_FAILED,
+		   "Failed to load layout");
+      return FALSE;
+    }
 
   menu_verbose ("Building menu tree from layout\n");
 
@@ -4125,6 +4169,8 @@ gmenu_tree_build_from_layout (GMenuTree *tree)
     }
 
   desktop_entry_set_unref (allocated);
+  
+  return TRUE;
 }
 
 static void
@@ -4135,6 +4181,8 @@ gmenu_tree_force_rebuild (GMenuTree *tree)
       gmenu_tree_directory_set_tree (tree->root, NULL);
       gmenu_tree_item_unref (tree->root);
       tree->root = NULL;
+      g_clear_error (&tree->load_error);
+      tree->loaded = FALSE;
 
       g_assert (tree->layout != NULL);
 
diff --git a/libmenu/gmenu-tree.h b/libmenu/gmenu-tree.h
index 4cbf61a..19e4784 100644
--- a/libmenu/gmenu-tree.h
+++ b/libmenu/gmenu-tree.h
@@ -91,6 +91,9 @@ GType gmenu_tree_flags_get_type (void);
 GMenuTree *gmenu_tree_new (const char     *menu_file,
 			   GMenuTreeFlags  flags);
 
+gboolean   gmenu_tree_load_sync (GMenuTree   *tree,
+				 GError     **error);
+
 const char         *gmenu_tree_get_menu_file           (GMenuTree  *tree);
 GMenuTreeDirectory *gmenu_tree_get_root_directory      (GMenuTree  *tree);
 GMenuTreeDirectory *gmenu_tree_get_directory_from_path (GMenuTree  *tree,
diff --git a/util/test-menu-spec.c b/util/test-menu-spec.c
index d21f78d..9748a13 100644
--- a/util/test-menu-spec.c
+++ b/util/test-menu-spec.c
@@ -22,6 +22,7 @@
 #include "gmenu-tree.h"
 
 #include <string.h>
+#include <stdlib.h>
 
 /* This is only a test program, so we don't need translations. Still keep the
  * infrastructure in place in case we suddenly decide we want to localize this
@@ -166,9 +167,17 @@ static void
 handle_tree_changed (GMenuTree *tree)
 {
   GMenuTreeDirectory *root;
+  GError *error = NULL;
 
   g_print (_("\n\n\n==== Menu changed, reloading ====\n\n\n"));
 
+  if (!gmenu_tree_load_sync (tree, &error))
+    {
+      g_printerr ("Failed to load tree: %s\n", error->message);
+      g_clear_error (&error);
+      return;
+    }
+
   root = gmenu_tree_get_root_directory (tree);
   if (root == NULL)
     {
@@ -187,6 +196,7 @@ main (int argc, char **argv)
   GMenuTree          *tree;
   GMenuTreeDirectory *root;
   GMenuTreeFlags      flags;
+  GError             *error = NULL;
 
   g_type_init ();
 
@@ -211,6 +221,12 @@ main (int argc, char **argv)
   tree = gmenu_tree_new (menu_file ? menu_file : "applications.menu", flags);
   g_assert (tree != NULL);
 
+  if (!gmenu_tree_load_sync (tree, &error))
+    {
+      g_printerr ("Failed to load tree: %s\n", error->message);
+      exit (1);
+    }
+
   root = gmenu_tree_get_root_directory (tree);
   if (root != NULL)
     {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]