[gnome-menus/wip/gobject-review: 22/38] Remove GMenuTreeItem from public API



commit 16ba775de7fd59ec7868597bb336c2235e9958ff
Author: Colin Walters <walters verbum org>
Date:   Wed Apr 20 17:42:39 2011 -0400

    Remove GMenuTreeItem from public API
    
    gmenu_tree_directory_get_contents() wasn't actually bindable because
    there's no way to express to introspection the inheritance hierarchy
    (and to do the runtime type checking necessary via
    gmenu_tree_item_get_item_type()).
    
    Therefore, drop it, and instead add explicit functions where each type
    is needed.  So for gmenu_tree_directory_get_contents(), we instead
    add an explicit typesafe iterator object.
    
    The only other instance was gmenu_tree_alias.
    
    Note that gmenu_tree_item_ref() and gmenu_tree_item_unref() remain;
    they're C only, and already just took "gpointer".

 libmenu/gmenu-tree.c  |  244 +++++++++++++++++++++++++++++++++++++++++++-----
 libmenu/gmenu-tree.h  |   32 ++++---
 util/test-menu-spec.c |   44 +++++----
 3 files changed, 263 insertions(+), 57 deletions(-)
---
diff --git a/libmenu/gmenu-tree.c b/libmenu/gmenu-tree.c
index 12306bd..8498d2a 100644
--- a/libmenu/gmenu-tree.c
+++ b/libmenu/gmenu-tree.c
@@ -29,6 +29,15 @@
 #include "menu-util.h"
 #include "canonicalize.h"
 
+/* private */
+typedef struct GMenuTreeItem GMenuTreeItem;
+#define GMENU_TREE_ITEM(i)      ((GMenuTreeItem *)(i))
+#define GMENU_TREE_DIRECTORY(i) ((GMenuTreeDirectory *)(i))
+#define GMENU_TREE_ENTRY(i)     ((GMenuTreeEntry *)(i))
+#define GMENU_TREE_SEPARATOR(i) ((GMenuTreeSeparator *)(i))
+#define GMENU_TREE_HEADER(i)    ((GMenuTreeHeader *)(i))
+#define GMENU_TREE_ALIAS(i)     ((GMenuTreeAlias *)(i))
+
 enum {
   PROP_0,
 
@@ -76,6 +85,17 @@ struct GMenuTreeItem
   gint refcount;
 };
 
+struct GMenuTreeIter
+{
+  gint refcount;
+
+  gint tree_serial;
+
+  GMenuTreeItem *item;
+  GSList *contents;
+  GSList *contents_iter;
+};
+
 struct GMenuTreeDirectory
 {
   GMenuTreeItem item;
@@ -660,7 +680,7 @@ find_path (GMenuTreeDirectory *directory,
     {
       GMenuTreeItem *item = tmp->data;
 
-      if (gmenu_tree_item_get_item_type (item) != GMENU_TREE_ITEM_DIRECTORY)
+      if (item->type != GMENU_TREE_ITEM_DIRECTORY)
         {
           tmp = tmp->next;
           continue;
@@ -713,14 +733,6 @@ gmenu_tree_invoke_monitors (GMenuTree *tree)
   g_signal_emit (tree, gmenu_tree_signals[CHANGED], 0);
 }
 
-GMenuTreeItemType
-gmenu_tree_item_get_item_type (GMenuTreeItem *item)
-{
-  g_return_val_if_fail (item != NULL, 0);
-
-  return item->type;
-}
-
 /**
  * gmenu_tree_directory_get_parent:
  * @entry: a #GMenuTreeDirectory
@@ -760,26 +772,158 @@ gmenu_tree_item_set_parent (GMenuTreeItem      *item,
   item->parent = parent;
 }
 
-GSList *
-gmenu_tree_directory_get_contents (GMenuTreeDirectory *directory)
+/**
+ * gmenu_tree_iter_ref: (skip)
+ * @iter: iter
+ *
+ * Increment the reference count of @iter
+ */
+GMenuTreeIter *
+gmenu_tree_iter_ref     (GMenuTreeIter *iter)
 {
-  GSList *retval;
-  GSList *tmp;
+  g_atomic_int_inc (&iter->refcount);
+  return iter;
+}
+
+/**
+ * gmenu_tree_iter_unref: (skip)
+ * @iter: iter
+ *
+ * Decrement the reference count of @iter
+ */
+void
+gmenu_tree_iter_unref   (GMenuTreeIter *iter)
+{
+  if (!g_atomic_int_dec_and_test (&iter->refcount))
+    return;
+
+  g_slist_foreach (iter->contents, (GFunc)gmenu_tree_item_unref, NULL);
+  g_slist_free (iter->contents);
+
+  g_slice_free (GMenuTreeIter, iter);
+}
+
+/**
+ * gmenu_tree_directory_iter:
+ * @directory: directory
+ *
+ * Returns: (transfer full): A new iterator over the directory contents
+ */
+GMenuTreeIter *
+gmenu_tree_directory_iter (GMenuTreeDirectory *directory)
+{
+  GMenuTreeIter *iter;
 
   g_return_val_if_fail (directory != NULL, NULL);
 
-  retval = NULL;
+  iter = g_slice_new0 (GMenuTreeIter);
+  iter->refcount = 1;
 
-  tmp = directory->contents;
-  while (tmp != NULL)
-    {
-      retval = g_slist_prepend (retval,
-                                gmenu_tree_item_ref (tmp->data));
+  iter->contents = g_slist_copy (directory->contents);
+  iter->contents_iter = iter->contents;
+  g_slist_foreach (iter->contents, (GFunc) gmenu_tree_item_ref, NULL);
 
-      tmp = tmp->next;
+  return iter;
+}
+
+/**
+ * gmenu_tree_iter_next:
+ * @iter: iter
+ *
+ * Change the iterator to the next item, and return its type.  If
+ * there are no more items, %GMENU_TREE_ITEM_INVALID is returned.
+ *
+ * Returns: The type of the next item that can be retrived from the iterator
+ */
+GMenuTreeItemType
+gmenu_tree_iter_next (GMenuTreeIter   *iter)
+{
+  g_return_val_if_fail (iter != NULL, GMENU_TREE_ITEM_INVALID);
+
+  if (iter->contents_iter)
+    {
+      iter->item = iter->contents_iter->data;
+      iter->contents_iter = iter->contents_iter->next;
+      return iter->item->type;
     }
+  else
+    return GMENU_TREE_ITEM_INVALID;
+}
+
+/**
+ * gmenu_tree_iter_get_directory:
+ * @iter: iter
+ *
+ * This method may only be called if gmenu_tree_iter_get_next_type()
+ * returned GMENU_TREE_ITEM_DIRECTORY.
+ *
+ * Returns: (transfer full): A directory
+ */
+GMenuTreeDirectory *
+gmenu_tree_iter_get_directory (GMenuTreeIter   *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == GMENU_TREE_ITEM_DIRECTORY, NULL);
+ 
+  return (GMenuTreeDirectory*)gmenu_tree_item_ref (iter->item);
+}
+
+/**
+ * gmenu_tree_iter_get_entry:
+ * @iter: iter
+ *
+ * This method may only be called if gmenu_tree_iter_get_next_type()
+ * returned GMENU_TREE_ITEM_ENTRY.
+ *
+ * Returns: (transfer full): An entry
+ */
+GMenuTreeEntry *
+gmenu_tree_iter_get_entry (GMenuTreeIter   *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == GMENU_TREE_ITEM_ENTRY, NULL);
+ 
+  return (GMenuTreeEntry*)gmenu_tree_item_ref (iter->item);
+}
+
+/**
+ * gmenu_tree_iter_get_header:
+ * @iter: iter
+ *
+ * This method may only be called if gmenu_tree_iter_get_next_type()
+ * returned GMENU_TREE_ITEM_HEADER.
+ *
+ * Returns: (transfer full): A header
+ */
+GMenuTreeHeader *
+gmenu_tree_iter_get_header (GMenuTreeIter   *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == GMENU_TREE_ITEM_HEADER, NULL);
+ 
+  return (GMenuTreeHeader*)gmenu_tree_item_ref (iter->item);
+}
 
-  return g_slist_reverse (retval);
+/**
+ * gmenu_tree_iter_get_alias:
+ * @iter: iter
+ *
+ * This method may only be called if gmenu_tree_iter_get_next_type()
+ * returned GMENU_TREE_ITEM_ALIAS.
+ *
+ * Returns: (transfer full): An alias
+ */
+GMenuTreeAlias *
+gmenu_tree_iter_get_alias (GMenuTreeIter   *iter)
+{
+  g_return_val_if_fail (iter != NULL, NULL);
+  g_return_val_if_fail (iter->item != NULL, NULL);
+  g_return_val_if_fail (iter->item->type == GMENU_TREE_ITEM_ALIAS, NULL);
+ 
+  return (GMenuTreeAlias*)gmenu_tree_item_ref (iter->item);
 }
 
 const char *
@@ -924,6 +1068,16 @@ gmenu_tree_header_get_directory (GMenuTreeHeader *header)
   return gmenu_tree_item_ref (header->directory);
 }
 
+GMenuTreeItemType
+gmenu_tree_alias_get_item_type (GMenuTreeAlias *alias)
+{
+  g_return_val_if_fail (alias != NULL, GMENU_TREE_ITEM_INVALID);
+
+  g_assert (alias->aliased_item != NULL);
+  return alias->aliased_item->type;
+}
+
+
 GMenuTreeDirectory *
 gmenu_tree_alias_get_directory (GMenuTreeAlias *alias)
 {
@@ -932,12 +1086,34 @@ gmenu_tree_alias_get_directory (GMenuTreeAlias *alias)
   return gmenu_tree_item_ref (alias->directory);
 }
 
-GMenuTreeItem *
-gmenu_tree_alias_get_item (GMenuTreeAlias *alias)
+/**
+ * gmenu_tree_alias_get_aliased_directory:
+ * @alias: alias
+ *
+ * Returns: (transfer full): The aliased directory entry
+ */
+GMenuTreeDirectory *
+gmenu_tree_alias_get_aliased_directory (GMenuTreeAlias *alias)
 {
   g_return_val_if_fail (alias != NULL, NULL);
+  g_return_val_if_fail (((GMenuTreeItem*)alias->aliased_item)->type == GMENU_TREE_ITEM_DIRECTORY, NULL);
 
-  return gmenu_tree_item_ref (alias->aliased_item);
+  return (GMenuTreeDirectory*)gmenu_tree_item_ref (alias->aliased_item);
+}
+/**
+
+ * gmenu_tree_alias_get_aliased_entry:
+ * @alias: alias
+ *
+ * Returns: (transfer full): The aliased entry
+ */
+GMenuTreeEntry *
+gmenu_tree_alias_get_aliased_entry (GMenuTreeAlias *alias)
+{
+  g_return_val_if_fail (alias != NULL, NULL);
+  g_return_val_if_fail (((GMenuTreeItem*)alias->aliased_item)->type == GMENU_TREE_ITEM_ENTRY, NULL);
+
+  return (GMenuTreeEntry*)gmenu_tree_item_ref (alias->aliased_item);
 }
 
 static GMenuTreeDirectory *
@@ -1107,7 +1283,10 @@ gmenu_tree_alias_new (GMenuTreeDirectory *parent,
   if (item->type != GMENU_TREE_ITEM_ALIAS)
     retval->aliased_item = gmenu_tree_item_ref (item);
   else
-    retval->aliased_item = gmenu_tree_item_ref (gmenu_tree_alias_get_item (GMENU_TREE_ALIAS (item)));
+    {
+      GMenuTreeAlias *alias = GMENU_TREE_ALIAS (item);
+      retval->aliased_item = gmenu_tree_item_ref (alias->aliased_item);
+    }
 
   gmenu_tree_item_set_parent (GMENU_TREE_ITEM (retval->directory), NULL);
   gmenu_tree_item_set_parent (retval->aliased_item, NULL);
@@ -3881,7 +4060,7 @@ merge_subdirs_and_entries (GMenuTree          *tree,
       GMenuTreeItem     *item = tmp->data;
       GMenuTreeItemType  type;
 
-      type = gmenu_tree_item_get_item_type (item);
+      type = item->type;
 
       if (type == GMENU_TREE_ITEM_ALIAS)
         {
@@ -4188,6 +4367,19 @@ gmenu_tree_force_rebuild (GMenuTree *tree)
 }
 
 GType
+gmenu_tree_iter_get_type (void)
+{
+  static GType gtype = G_TYPE_INVALID;
+  if (gtype == G_TYPE_INVALID)
+    {
+      gtype = g_boxed_type_register_static ("GMenuTreeIter",
+          (GBoxedCopyFunc)gmenu_tree_iter_ref,
+          (GBoxedFreeFunc)gmenu_tree_iter_unref);
+    }
+  return gtype;
+}
+
+GType
 gmenu_tree_directory_get_type (void)
 {
   static GType gtype = G_TYPE_INVALID;
diff --git a/libmenu/gmenu-tree.h b/libmenu/gmenu-tree.h
index 061cc6d..14716b8 100644
--- a/libmenu/gmenu-tree.h
+++ b/libmenu/gmenu-tree.h
@@ -45,7 +45,7 @@ struct _GMenuTreeClass
 
 GType            gmenu_tree_get_type          (void) G_GNUC_CONST;
 
-typedef struct GMenuTreeItem      GMenuTreeItem;
+typedef struct GMenuTreeIter      GMenuTreeIter;
 typedef struct GMenuTreeDirectory GMenuTreeDirectory;
 typedef struct GMenuTreeEntry     GMenuTreeEntry;
 typedef struct GMenuTreeSeparator GMenuTreeSeparator;
@@ -62,12 +62,7 @@ typedef enum
   GMENU_TREE_ITEM_ALIAS
 } GMenuTreeItemType;
 
-#define GMENU_TREE_ITEM(i)      ((GMenuTreeItem *)(i))
-#define GMENU_TREE_DIRECTORY(i) ((GMenuTreeDirectory *)(i))
-#define GMENU_TREE_ENTRY(i)     ((GMenuTreeEntry *)(i))
-#define GMENU_TREE_SEPARATOR(i) ((GMenuTreeSeparator *)(i))
-#define GMENU_TREE_HEADER(i)    ((GMenuTreeHeader *)(i))
-#define GMENU_TREE_ALIAS(i)     ((GMenuTreeAlias *)(i))
+GType gmenu_tree_iter_get_type (void);
 
 /* Explicitly skip item, it's a "hidden" base class */
 GType gmenu_tree_directory_get_type (void);
@@ -101,10 +96,8 @@ GMenuTreeDirectory *gmenu_tree_get_directory_from_path (GMenuTree  *tree,
 
 gpointer gmenu_tree_item_ref   (gpointer item);
 void     gmenu_tree_item_unref (gpointer item);
-GMenuTreeItemType   gmenu_tree_item_get_item_type   (GMenuTreeItem *item);
 
 GMenuTreeDirectory *gmenu_tree_directory_get_parent    (GMenuTreeDirectory *directory);
-GSList     *gmenu_tree_directory_get_contents          (GMenuTreeDirectory *directory);
 const char *gmenu_tree_directory_get_name              (GMenuTreeDirectory *directory);
 const char *gmenu_tree_directory_get_comment           (GMenuTreeDirectory *directory);
 const char *gmenu_tree_directory_get_icon              (GMenuTreeDirectory *directory);
@@ -113,12 +106,23 @@ const char *gmenu_tree_directory_get_menu_id           (GMenuTreeDirectory *dire
 
 gboolean gmenu_tree_directory_get_is_nodisplay (GMenuTreeDirectory *directory);
 
+GMenuTreeIter *gmenu_tree_directory_iter               (GMenuTreeDirectory *directory);
+
+GMenuTreeIter *gmenu_tree_iter_ref     (GMenuTreeIter *iter);
+void           gmenu_tree_iter_unref   (GMenuTreeIter *iter);
+
+GMenuTreeItemType   gmenu_tree_iter_next                 (GMenuTreeIter   *iter); 
+GMenuTreeDirectory *gmenu_tree_iter_get_directory        (GMenuTreeIter   *iter); 
+GMenuTreeEntry     *gmenu_tree_iter_get_entry            (GMenuTreeIter   *iter); 
+GMenuTreeHeader    *gmenu_tree_iter_get_header           (GMenuTreeIter   *iter); 
+GMenuTreeAlias     *gmenu_tree_iter_get_alias            (GMenuTreeIter   *iter); 
+
 char *gmenu_tree_directory_make_path (GMenuTreeDirectory *directory,
 				      GMenuTreeEntry     *entry);
 
 
-GDesktopAppInfo *gmenu_tree_entry_get_app_info       (GMenuTreeEntry *entry);
-GMenuTreeDirectory *gmenu_tree_entry_get_parent      (GMenuTreeEntry *entry);
+GDesktopAppInfo    *gmenu_tree_entry_get_app_info       (GMenuTreeEntry *entry);
+GMenuTreeDirectory *gmenu_tree_entry_get_parent         (GMenuTreeEntry *entry);
 
 const char *gmenu_tree_entry_get_desktop_file_path (GMenuTreeEntry *entry);
 const char *gmenu_tree_entry_get_desktop_file_id   (GMenuTreeEntry *entry);
@@ -128,8 +132,10 @@ gboolean gmenu_tree_entry_get_is_nodisplay (GMenuTreeEntry *entry);
 
 GMenuTreeDirectory *gmenu_tree_header_get_directory (GMenuTreeHeader *header);
 
-GMenuTreeDirectory *gmenu_tree_alias_get_directory (GMenuTreeAlias *alias);
-GMenuTreeItem      *gmenu_tree_alias_get_item      (GMenuTreeAlias *alias);
+GMenuTreeDirectory *gmenu_tree_alias_get_directory         (GMenuTreeAlias *alias);
+GMenuTreeItemType   gmenu_tree_alias_get_item_type         (GMenuTreeAlias *alias);
+GMenuTreeDirectory *gmenu_tree_alias_get_aliased_directory (GMenuTreeAlias *alias);
+GMenuTreeEntry     *gmenu_tree_alias_get_aliased_entry     (GMenuTreeAlias *alias);
 
 G_END_DECLS
 
diff --git a/util/test-menu-spec.c b/util/test-menu-spec.c
index cb0d032..3320033 100644
--- a/util/test-menu-spec.c
+++ b/util/test-menu-spec.c
@@ -106,8 +106,7 @@ print_entry (GMenuTreeEntry *entry,
 static void
 print_directory (GMenuTreeDirectory *directory)
 {
-  GSList     *items;
-  GSList     *tmp;
+  GMenuTreeIter *iter;
   const char *path;
   char       *freeme;
 
@@ -117,34 +116,42 @@ print_directory (GMenuTreeDirectory *directory)
   else
     path = freeme + 1;
 
-  items = gmenu_tree_directory_get_contents (directory);
+  iter = gmenu_tree_directory_iter (directory);
 
-  tmp = items;
-  while (tmp != NULL)
+  while (TRUE)
     {
-      GMenuTreeItem *item = tmp->data;
+      gpointer item;
 
-      switch (gmenu_tree_item_get_item_type (item))
+      switch (gmenu_tree_iter_next (iter))
 	{
+	case GMENU_TREE_ITEM_INVALID:
+	  goto done;
+
 	case GMENU_TREE_ITEM_ENTRY:
-	  print_entry (GMENU_TREE_ENTRY (item), path);
+	  item = gmenu_tree_iter_get_entry (iter);
+	  print_entry ((GMenuTreeEntry*)item, path);
 	  break;
 
 	case GMENU_TREE_ITEM_DIRECTORY:
-	  print_directory (GMENU_TREE_DIRECTORY (item));
+	  item = gmenu_tree_iter_get_directory (iter);
+	  print_directory ((GMenuTreeDirectory*)item);
 	  break;
 
 	case GMENU_TREE_ITEM_HEADER:
 	case GMENU_TREE_ITEM_SEPARATOR:
+	  item = NULL;
 	  break;
 
 	case GMENU_TREE_ITEM_ALIAS:
 	  {
-	    GMenuTreeItem *aliased_item;
-
-	    aliased_item = gmenu_tree_alias_get_item (GMENU_TREE_ALIAS (item));
-	    if (gmenu_tree_item_get_item_type (aliased_item) == GMENU_TREE_ITEM_ENTRY)
-	      print_entry (GMENU_TREE_ENTRY (aliased_item), path);
+	    item = gmenu_tree_iter_get_alias (iter);
+
+	    if (gmenu_tree_alias_get_item_type (item) == GMENU_TREE_ITEM_ENTRY)
+	      {
+		GMenuTreeEntry *entry = gmenu_tree_alias_get_aliased_entry (item);
+		print_entry (entry, path);
+		gmenu_tree_item_unref (entry);
+	      }
 	  }
 	  break;
 
@@ -153,12 +160,13 @@ print_directory (GMenuTreeDirectory *directory)
 	  break;
 	}
 
-      gmenu_tree_item_unref (tmp->data);
-
-      tmp = tmp->next;
+      gmenu_tree_item_unref (item);
+      continue;
+    done:
+      break;
     }
 
-  g_slist_free (items);
+  gmenu_tree_iter_unref (iter);
 
   g_free (freeme);
 }



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