Author: kelnos
Date: 2007-03-19 02:29:49 +0000 (Mon, 19 Mar 2007)
New Revision: 25200

Added:
   xfdesktop/trunk/modules/menu/frapmenu/frap-menu-layout.c
   xfdesktop/trunk/modules/menu/frapmenu/frap-menu-layout.h
   xfdesktop/trunk/modules/menu/frapmenu/frap-menu-separator.c
   xfdesktop/trunk/modules/menu/frapmenu/frap-menu-separator.h
   xfdesktop/trunk/modules/menu/frapmenu/tdb/README
Modified:
   xfdesktop/trunk/modules/menu/desktop-menu.c
   xfdesktop/trunk/modules/menu/frapmenu/Makefile.am
   xfdesktop/trunk/modules/menu/frapmenu/frap-menu-item.c
   xfdesktop/trunk/modules/menu/frapmenu/frap-menu.c
   xfdesktop/trunk/modules/menu/frapmenu/frap-menu.h
   xfdesktop/trunk/modules/menu/frapmenu/libfrapmenu.h
   xfdesktop/trunk/modules/menu/frapmenu/tdb/Makefile.am
   xfdesktop/trunk/modules/menu/frapmenu/tdb/spinlock.c
   xfdesktop/trunk/modules/menu/frapmenu/tdb/spinlock.h
   xfdesktop/trunk/modules/menu/frapmenu/tdb/tdb.c
   xfdesktop/trunk/modules/menu/frapmenu/tdb/tdb.h
   xfdesktop/trunk/modules/menu/frapmenu/tdb/tdbtool.c
   xfdesktop/trunk/modules/menu/menu-data/xfce-applications.menu
Log:
update my local copy of frapmenu - layout works now! (mostly)


Modified: xfdesktop/trunk/modules/menu/desktop-menu.c
===================================================================
--- xfdesktop/trunk/modules/menu/desktop-menu.c 2007-03-18 21:50:03 UTC (rev 
25199)
+++ xfdesktop/trunk/modules/menu/desktop-menu.c 2007-03-19 02:29:49 UTC (rev 
25200)
@@ -99,11 +99,54 @@
                        FrapMenu *frap_menu,
                        GtkWidget *menu)
 {
-    GSList *menus, *items, *l;
+    GSList *layout_items, *l;
     GtkWidget *submenu, *mi;
     FrapMenu *frap_submenu;
     FrapMenuItem *frap_item;
     
+    layout_items = frap_menu_get_layout_items(frap_menu);
+    for(l = layout_items; l; l = l->next) {
+        if(FRAP_IS_MENU(l->data)) {
+            frap_submenu = l->data;
+            
+            submenu = gtk_menu_new();
+            gtk_widget_show(submenu);
+            
+            mi = 
gtk_menu_item_new_with_label(frap_menu_get_name(frap_submenu));
+            gtk_widget_show(mi);
+            gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
+            gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi), submenu);
+            
+            desktop_menu_add_items(desktop_menu, frap_submenu, submenu);
+            
+            /* we have to check emptiness down here instead of at the top of 
the
+             * loop because there may be further submenus that are empty */
+            if(!gtk_container_get_children(GTK_CONTAINER(submenu)))
+                gtk_widget_destroy(mi);
+        } else if(FRAP_IS_MENU_SEPARATOR(l->data)) {
+            mi = gtk_separator_menu_item_new();
+            gtk_widget_show(mi);
+            gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
+        } else if(FRAP_IS_MENU_ITEM(l->data)) {
+            frap_item = l->data;
+            
+            if(frap_menu_item_get_no_display(frap_item)
+               || !frap_menu_item_show_in_environment(frap_item))
+            {
+                continue;
+            }
+            
+            mi = 
xfce_app_menu_item_new_full(frap_menu_item_get_name(frap_item),
+                                             
frap_menu_item_get_command(frap_item),
+                                             
frap_menu_item_get_icon_name(frap_item),
+                                             
frap_menu_item_requires_terminal(frap_item),
+                                             
frap_menu_item_supports_startup_notification(frap_item));
+            gtk_widget_show(mi);
+            gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
+        }
+    }
+    
+#if 0
     /* note: |menus| is owned by the FrapMenu, |items| is owned by us */
     
     menus = frap_menu_get_menus(frap_menu);
@@ -144,7 +187,8 @@
         gtk_widget_show(mi);
         gtk_menu_shell_append(GTK_MENU_SHELL(menu), mi);
     }
-    g_slist_free(items);                                    
+    g_slist_free(items);
+#endif
 }
 
 static gboolean

Modified: xfdesktop/trunk/modules/menu/frapmenu/Makefile.am
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/Makefile.am   2007-03-18 21:50:03 UTC 
(rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/Makefile.am   2007-03-19 02:29:49 UTC 
(rev 25200)
@@ -1,4 +1,4 @@
-# $Id: Makefile.am 24857 2007-02-05 17:23:53Z jannis $ 
+# $Id: Makefile.am 25185 2007-03-18 02:23:12Z jannis $ 
 
 INCLUDES =                                                             \
        -DG_LOG_DOMAIN=\"FrapMenu\"                                     \
@@ -13,6 +13,8 @@
 
 libfrapmenu_la_SOURCES =                                               \
        frap-menu.c                                                     \
+       frap-menu-separator.c                                           \
+       frap-menu-layout.c                                              \
        frap-menu-directory.c                                           \
        frap-menu-rules.c                                               \
        frap-menu-standard-rules.c                                      \
@@ -31,6 +33,8 @@
 noinst_HEADERS =                                                       \
        libfrapmenu.h                                                   \
        frap-menu.h                                                     \
+       frap-menu-separator.h                                           \
+       frap-menu-layout.h                                              \
        frap-menu-directory.h                                           \
        frap-menu-rules.h                                               \
        frap-menu-standard-rules.h                                      \
@@ -59,7 +63,4 @@
        $(LIBXFCE4UTIL_LIBS)                                            \
        $(top_builddir)/modules/menu/frapmenu/tdb/libtdb.la
 
-EXTRA_DIST =                                                           \
-       README
-
 # vi:set ts=8 sw=8 noet ai nocindent syntax=automake:

Modified: xfdesktop/trunk/modules/menu/frapmenu/frap-menu-item.c
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/frap-menu-item.c      2007-03-18 
21:50:03 UTC (rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/frap-menu-item.c      2007-03-19 
02:29:49 UTC (rev 25200)
@@ -1,4 +1,4 @@
-/* $Id: frap-menu-item.c 24974 2007-02-14 10:49:23Z jannis $ */
+/* $Id: frap-menu-item.c 25197 2007-03-18 17:54:52Z jannis $ */
 /* vi:set expandtab sw=2 sts=2: */
 /*-
  * Copyright (c) 2006-2007 Jannis Pohlmann <[EMAIL PROTECTED]>
@@ -421,13 +421,14 @@
   gboolean      startup_notify;
   gboolean      show;
 
-  g_return_val_if_fail (g_path_is_absolute (filename), NULL);
-  g_return_val_if_fail (g_file_test (filename, G_FILE_TEST_EXISTS), NULL);
+  /* Return NULL if the filename is not an absolute path or if the file does 
not exists */
+  if (G_UNLIKELY (!g_path_is_absolute (filename) || !g_file_test (filename, 
G_FILE_TEST_EXISTS)))
+    return NULL;
 
   /* Try to open the .desktop file */
   rc = xfce_rc_simple_open (filename, TRUE);
   if (G_UNLIKELY (rc == NULL))
-    return;
+    return NULL;
 
   /* Use the Desktop Entry section of the desktop file */
   xfce_rc_set_group (rc, "Desktop Entry");

Added: xfdesktop/trunk/modules/menu/frapmenu/frap-menu-layout.c
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/frap-menu-layout.c                    
        (rev 0)
+++ xfdesktop/trunk/modules/menu/frapmenu/frap-menu-layout.c    2007-03-19 
02:29:49 UTC (rev 25200)
@@ -0,0 +1,400 @@
+/* $Id: frap-menu-layout.c 25194 2007-03-18 15:16:39Z jannis $ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2007 Jannis Pohlmann <[EMAIL PROTECTED]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <frap-menu-layout.h>
+
+
+
+#define FRAP_MENU_LAYOUT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), 
FRAP_TYPE_MENU_LAYOUT, FrapMenuLayoutPrivate))
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+};
+
+
+
+struct _FrapMenuLayoutNode
+{
+  FrapMenuLayoutNodeType   type;
+  union
+  {
+    gchar                  *filename;
+    gchar                  *menuname;
+    FrapMenuLayoutMergeType merge_type;
+  } data;
+};
+
+
+
+static void frap_menu_layout_class_init   (FrapMenuLayoutClass *klass);
+static void frap_menu_layout_init         (FrapMenuLayout      *layout);
+static void frap_menu_layout_finalize     (GObject             *object);
+static void frap_menu_layout_get_property (GObject             *object,
+                                           guint                prop_id,
+                                           GValue              *value,
+                                           GParamSpec          *pspec);
+static void frap_menu_layout_set_property (GObject             *object,
+                                           guint                prop_id,
+                                           const GValue        *value,
+                                           GParamSpec          *pspec);
+static void frap_menu_layout_free_node    (FrapMenuLayoutNode  *node);
+
+
+
+struct _FrapMenuLayoutClass
+{
+  GObjectClass __parent__;
+};
+
+struct _FrapMenuLayoutPrivate
+{
+  GSList *nodes;
+};
+
+struct _FrapMenuLayout
+{
+  GObject __parent__;
+
+  /* < private > */
+  FrapMenuLayoutPrivate *priv;
+};
+
+
+
+static GObjectClass *frap_menu_layout_parent_class = NULL;
+
+
+
+GType
+frap_menu_layout_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (FrapMenuLayoutClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) frap_menu_layout_class_init,
+        NULL,
+        NULL,
+        sizeof (FrapMenuLayout),
+        0,
+        (GInstanceInitFunc) frap_menu_layout_init,
+        NULL,
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, "FrapMenuLayout", &info, 
0);
+    }
+
+  return type;
+}
+
+
+
+static void
+frap_menu_layout_class_init (FrapMenuLayoutClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (FrapMenuLayoutPrivate));
+
+  /* Determine parent type class */
+  frap_menu_layout_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = frap_menu_layout_finalize;
+  gobject_class->get_property = frap_menu_layout_get_property;
+  gobject_class->set_property = frap_menu_layout_set_property;
+}
+
+
+
+static void
+frap_menu_layout_init (FrapMenuLayout *layout)
+{
+  layout->priv = FRAP_MENU_LAYOUT_GET_PRIVATE (layout);
+  layout->priv->nodes = NULL;
+}
+
+
+
+static void
+frap_menu_layout_finalize (GObject *object)
+{
+  FrapMenuLayout *layout = FRAP_MENU_LAYOUT (object);
+
+  /* Free nodes */
+  g_slist_foreach (layout->priv->nodes, (GFunc) frap_menu_layout_free_node, 
NULL);
+  g_slist_free (layout->priv->nodes);
+
+  (*G_OBJECT_CLASS (frap_menu_layout_parent_class)->finalize) (object);
+}
+
+
+
+static void
+frap_menu_layout_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  FrapMenuLayout *layout = FRAP_MENU_LAYOUT (layout);
+
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+frap_menu_layout_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  FrapMenuLayout *layout = FRAP_MENU_LAYOUT (layout);
+
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+FrapMenuLayout*
+frap_menu_layout_new (void)
+{
+  return g_object_new (FRAP_TYPE_MENU_LAYOUT, NULL);
+}
+
+
+
+static void
+frap_menu_layout_free_node (FrapMenuLayoutNode *node)
+{
+  if (node->type == FRAP_MENU_LAYOUT_NODE_FILENAME)
+    g_free (node->data.filename);
+  else if (node->type == FRAP_MENU_LAYOUT_NODE_MENUNAME)
+    g_free (node->data.menuname);
+
+  g_free (node);
+}
+
+
+
+void
+frap_menu_layout_add_filename (FrapMenuLayout *layout,
+                               const gchar    *filename)
+{
+  g_return_if_fail (FRAP_IS_MENU_LAYOUT (layout));
+  g_return_if_fail (filename != NULL);
+
+  /* Build filename node */
+  FrapMenuLayoutNode *node = g_new0 (FrapMenuLayoutNode, 1);
+  node->type = FRAP_MENU_LAYOUT_NODE_FILENAME;
+  node->data.filename = g_strdup (filename);
+
+  g_debug ("frap_menu_layout_add_filename ('%s')", filename);
+
+  /* Append node to the list */
+  layout->priv->nodes = g_slist_append (layout->priv->nodes, node);
+}
+
+
+
+void
+frap_menu_layout_add_menuname (FrapMenuLayout *layout,
+                               const gchar    *menuname)
+{
+  g_return_if_fail (FRAP_IS_MENU_LAYOUT (layout));
+  g_return_if_fail (menuname != NULL);
+
+  /* Build menuname node */
+  FrapMenuLayoutNode *node = g_new0 (FrapMenuLayoutNode, 1);
+  node->type = FRAP_MENU_LAYOUT_NODE_MENUNAME;
+  node->data.menuname = g_strdup (menuname);
+
+  g_debug ("frap_menu_layout_add_menuname ('%s')", menuname);
+
+  /* Append node to the list */
+  layout->priv->nodes = g_slist_append (layout->priv->nodes, node);
+}
+
+
+
+void
+frap_menu_layout_add_separator (FrapMenuLayout *layout)
+{
+  g_return_if_fail (FRAP_IS_MENU_LAYOUT (layout));
+
+  /* Build separator node */
+  FrapMenuLayoutNode *node = g_new0 (FrapMenuLayoutNode, 1);
+  node->type = FRAP_MENU_LAYOUT_NODE_SEPARATOR;
+
+  g_debug ("frap_menu_layout_add_separator ()");
+
+  /* Append node to the list */
+  layout->priv->nodes = g_slist_append (layout->priv->nodes, node);
+}
+
+
+
+void
+frap_menu_layout_add_merge (FrapMenuLayout         *layout,
+                            FrapMenuLayoutMergeType type)
+{
+  g_return_if_fail (FRAP_IS_MENU_LAYOUT (layout));
+
+  /* Build merge node */
+  FrapMenuLayoutNode *node = g_new0 (FrapMenuLayoutNode, 1);
+  node->type = FRAP_MENU_LAYOUT_NODE_MERGE;
+  node->data.merge_type = type;
+
+  g_debug ("frap_menu_layout_add_merge (%d)", type);
+
+  /* Append node to the list */
+  layout->priv->nodes = g_slist_append (layout->priv->nodes, node);
+}
+
+
+
+GSList*
+frap_menu_layout_get_nodes (FrapMenuLayout *layout)
+{
+  g_return_val_if_fail (FRAP_IS_MENU_LAYOUT (layout), NULL);
+  return layout->priv->nodes;
+}
+
+
+
+gboolean 
+frap_menu_layout_get_filename_used (FrapMenuLayout *layout,
+                                    const gchar    *filename)
+{
+  FrapMenuLayoutNode *node;
+  GSList             *iter;
+  gboolean            found = FALSE;
+
+  g_return_val_if_fail (FRAP_IS_MENU_LAYOUT (layout), FALSE);
+  g_return_val_if_fail (filename != NULL, FALSE);
+
+  for (iter = layout->priv->nodes; iter != NULL; iter = g_slist_next (iter))
+    {
+      node = (FrapMenuLayoutNode *)iter->data;
+
+      if (G_UNLIKELY (node == NULL))
+        continue;
+
+      if (G_UNLIKELY (node->type == FRAP_MENU_LAYOUT_NODE_FILENAME && 
g_utf8_collate (node->data.filename, filename) == 0))
+        {
+          found = TRUE;
+          break;
+        }
+    }
+
+  return found;
+}
+
+
+
+gboolean 
+frap_menu_layout_get_menuname_used (FrapMenuLayout *layout,
+                                    const gchar    *menuname)
+{
+  FrapMenuLayoutNode *node;
+  GSList             *iter;
+  gboolean            found = FALSE;
+
+  g_return_val_if_fail (FRAP_IS_MENU_LAYOUT (layout), FALSE);
+  g_return_val_if_fail (menuname != NULL, FALSE);
+
+  for (iter = layout->priv->nodes; iter != NULL; iter = g_slist_next (iter))
+    {
+      node = (FrapMenuLayoutNode *)iter->data;
+
+      if (G_UNLIKELY (node == NULL))
+        continue;
+
+      if (G_UNLIKELY (node->type == FRAP_MENU_LAYOUT_NODE_MENUNAME && 
g_utf8_collate (node->data.menuname, menuname) == 0))
+        {
+          found = TRUE;
+          break;
+        }
+    }
+
+  return found;
+}
+
+
+
+FrapMenuLayoutNodeType
+frap_menu_layout_node_get_type (FrapMenuLayoutNode *node)
+{
+  g_return_val_if_fail (node != NULL, FRAP_MENU_LAYOUT_NODE_INVALID);
+  return node->type;
+}
+
+
+
+const gchar*
+frap_menu_layout_node_get_filename (FrapMenuLayoutNode *node)
+{
+  g_return_val_if_fail (node != NULL && node->type == 
FRAP_MENU_LAYOUT_NODE_FILENAME, NULL);
+  return node->data.filename;
+}
+
+
+
+
+const gchar*
+frap_menu_layout_node_get_menuname (FrapMenuLayoutNode *node)
+{
+  g_return_val_if_fail (node != NULL && node->type == 
FRAP_MENU_LAYOUT_NODE_MENUNAME, NULL);
+  return node->data.menuname;
+}
+
+
+
+
+FrapMenuLayoutMergeType
+frap_menu_layout_node_get_merge_type (FrapMenuLayoutNode *node)
+{
+  g_return_val_if_fail (node != NULL && node->type == 
FRAP_MENU_LAYOUT_NODE_MERGE, FRAP_MENU_LAYOUT_MERGE_ALL);
+  return node->data.merge_type;
+}

Added: xfdesktop/trunk/modules/menu/frapmenu/frap-menu-layout.h
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/frap-menu-layout.h                    
        (rev 0)
+++ xfdesktop/trunk/modules/menu/frapmenu/frap-menu-layout.h    2007-03-19 
02:29:49 UTC (rev 25200)
@@ -0,0 +1,90 @@
+/* $Id: frap-menu-layout.h 25194 2007-03-18 15:16:39Z jannis $ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2007 Jannis Pohlmann <[EMAIL PROTECTED]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined(LIBFRAPMENU_INSIDE_LIBFRAPMENU_H) && 
!defined(LIBFRAPMENU_COMPILATION)
+#error "Only <libfrapmenu/libfrapmenu.h> can be included directly. This file 
may disappear or change contents."
+#endif
+
+#ifndef __FRAP_MENU_LAYOUT_H__
+#define __FRAP_MENU_LAYOUT_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS;
+
+typedef enum
+{
+  FRAP_MENU_LAYOUT_MERGE_MENUS,
+  FRAP_MENU_LAYOUT_MERGE_FILES,
+  FRAP_MENU_LAYOUT_MERGE_ALL,
+} FrapMenuLayoutMergeType;
+
+typedef enum
+{
+  FRAP_MENU_LAYOUT_NODE_INVALID,
+  FRAP_MENU_LAYOUT_NODE_FILENAME,
+  FRAP_MENU_LAYOUT_NODE_MENUNAME,
+  FRAP_MENU_LAYOUT_NODE_SEPARATOR,
+  FRAP_MENU_LAYOUT_NODE_MERGE,
+} FrapMenuLayoutNodeType;
+
+typedef struct _FrapMenuLayoutNode    FrapMenuLayoutNode;
+
+typedef struct _FrapMenuLayoutPrivate FrapMenuLayoutPrivate;
+typedef struct _FrapMenuLayoutClass   FrapMenuLayoutClass;
+typedef struct _FrapMenuLayout        FrapMenuLayout;
+
+#define FRAP_TYPE_MENU_LAYOUT            (frap_menu_layout_get_type())
+#define FRAP_MENU_LAYOUT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
FRAP_TYPE_MENU_LAYOUT, FrapMenuLayout))
+#define FRAP_MENU_LAYOUT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), 
FRAP_TYPE_MENU_LAYOUT, FrapMenuLayoutClass))
+#define FRAP_IS_MENU_LAYOUT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
FRAP_TYPE_MENU_LAYOUT))
+#define FRAP_IS_MENU_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
FRAP_TYPE_MENU_LAYOUT))
+#define FRAP_MENU_LAYOUT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), 
FRAP_TYPE_MENU_LAYOUT, FrapMenuLayoutClass))
+
+GType                   frap_menu_layout_get_type          (void) G_GNUC_CONST;
+
+FrapMenuLayout         *frap_menu_layout_new               (void) 
G_GNUC_MALLOC;
+void                    frap_menu_layout_add_filename      (FrapMenuLayout     
     *layout,
+                                                            const gchar        
     *filename);
+void                    frap_menu_layout_add_menuname      (FrapMenuLayout     
     *layout,
+                                                            const gchar        
     *menuname);
+void                    frap_menu_layout_add_separator     (FrapMenuLayout     
     *layout);
+void                    frap_menu_layout_add_merge         (FrapMenuLayout     
     *layout,
+                                                            
FrapMenuLayoutMergeType  type);
+GSList                 *frap_menu_layout_get_nodes         (FrapMenuLayout     
     *layout);
+gboolean                frap_menu_layout_get_filename_used (FrapMenuLayout     
     *layout,
+                                                            const gchar        
     *filename);
+gboolean                frap_menu_layout_get_menuname_used (FrapMenuLayout     
     *layout,
+                                                            const gchar        
     *menuname);
+
+FrapMenuLayoutNodeType  frap_menu_layout_node_get_type     (FrapMenuLayoutNode 
      *node);
+const gchar            *frap_menu_layout_node_get_filename (FrapMenuLayoutNode 
      *node);
+const gchar            *frap_menu_layout_node_get_menuname (FrapMenuLayoutNode 
      *node);
+FrapMenuLayoutMergeType frap_menu_layout_get_merge_type    (FrapMenuLayoutNode 
      *node);
+
+G_END_DECLS;
+
+#endif /* !__FRAP_MENU_LAYOUT_H__ */
+

Added: xfdesktop/trunk/modules/menu/frapmenu/frap-menu-separator.c
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/frap-menu-separator.c                 
        (rev 0)
+++ xfdesktop/trunk/modules/menu/frapmenu/frap-menu-separator.c 2007-03-19 
02:29:49 UTC (rev 25200)
@@ -0,0 +1,136 @@
+/* $Id: frap-menu-separator.c 25185 2007-03-18 02:23:12Z jannis $ */
+/* vim:set et ai sw=2 sts=2: */
+/*-
+ * Copyright (c) 2007 Jannis Pohlmann <[EMAIL PROTECTED]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <frap-menu-separator.h>
+
+
+
+static void               frap_menu_separator_class_init 
(FrapMenuSeparatorClass *klass);
+static void               frap_menu_separator_init       (FrapMenuSeparator    
  *separator);
+static void               frap_menu_separator_finalize   (GObject              
  *object);
+
+
+
+static FrapMenuSeparator *_frap_menu_separator = NULL;
+
+
+
+void
+_frap_menu_separator_init (void)
+{
+  if (G_LIKELY (_frap_menu_separator == NULL))
+    _frap_menu_separator = g_object_new (FRAP_TYPE_MENU_SEPARATOR, NULL);
+}
+
+
+
+void
+_frap_menu_separator_shutdown (void)
+{
+  if (G_LIKELY (_frap_menu_separator != NULL))
+    g_object_unref (G_OBJECT (_frap_menu_separator));
+}
+
+
+
+struct _FrapMenuSeparatorClass
+{
+  GObjectClass __parent__;
+};
+
+struct _FrapMenuSeparator
+{
+  GObject __parent__;
+};
+
+
+
+static GObjectClass *frap_menu_separator_parent_class = NULL;
+
+
+
+GType
+frap_menu_separator_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (FrapMenuSeparatorClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) frap_menu_separator_class_init,
+        NULL,
+        NULL,
+        sizeof (FrapMenuSeparator),
+        0,
+        (GInstanceInitFunc) frap_menu_separator_init,
+        NULL,
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, "FrapMenuSeparator", 
&info, 0);
+    }
+
+  return type;
+}
+
+
+
+static void
+frap_menu_separator_class_init (FrapMenuSeparatorClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  /* Determine parent type class */
+  frap_menu_separator_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = frap_menu_separator_finalize;
+}
+
+
+
+static void
+frap_menu_separator_init (FrapMenuSeparator *separator)
+{
+}
+
+
+
+static void
+frap_menu_separator_finalize (GObject *object)
+{
+  (*G_OBJECT_CLASS (frap_menu_separator_parent_class)->finalize) (object);
+}
+
+
+
+FrapMenuSeparator*
+frap_menu_separator_get_default (void)
+{
+  return _frap_menu_separator;
+}

Added: xfdesktop/trunk/modules/menu/frapmenu/frap-menu-separator.h
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/frap-menu-separator.h                 
        (rev 0)
+++ xfdesktop/trunk/modules/menu/frapmenu/frap-menu-separator.h 2007-03-19 
02:29:49 UTC (rev 25200)
@@ -0,0 +1,59 @@
+/* $Id: frap-menu-separator.h 25185 2007-03-18 02:23:12Z jannis $ */
+/* vi:set et ai sw=2 sts=2: */
+/*-
+ * Copyright (c) 2007 Jannis Pohlmann <[EMAIL PROTECTED]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if !defined(LIBFRAPMENU_INSIDE_LIBFRAPMENU_H) && 
!defined(LIBFRAPMENU_COMPILATION)
+#error "Only <libfrapmenu/libfrapmenu.h> can be included directly. This file 
may disappear or change contents."
+#endif
+
+#ifndef __FRAP_MENU_SEPARATOR_H__
+#define __FRAP_MENU_SEPARATOR_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _FrapMenuSeparatorClass FrapMenuSeparatorClass;
+typedef struct _FrapMenuSeparator      FrapMenuSeparator;
+
+#define FRAP_TYPE_MENU_SEPARATOR            (frap_menu_separator_get_type())
+#define FRAP_MENU_SEPARATOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST 
((obj), FRAP_TYPE_MENU_SEPARATOR, FrapMenuSeparator))
+#define FRAP_MENU_SEPARATOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), 
FRAP_TYPE_MENU_SEPARATOR, FrapMenuSeparatorClass))
+#define FRAP_IS_MENU_SEPARATOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE 
((obj), FRAP_TYPE_MENU_SEPARATOR))
+#define FRAP_IS_MENU_SEPARATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
FRAP_TYPE_MENU_SEPARATOR))
+#define FRAP_MENU_SEPARATOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), 
FRAP_TYPE_MENU_SEPARATOR, FrapMenuSeparatorClass))
+
+
+GType              frap_menu_separator_get_type    (void) G_GNUC_CONST;
+
+FrapMenuSeparator *frap_menu_separator_get_default (void);
+
+#if defined(LIBFRAPMENU_COMPILATION)
+void               _frap_menu_separator_init       (void) G_GNUC_INTERNAL;
+void               _frap_menu_separator_shutdown   (void) G_GNUC_INTERNAL;
+#endif
+
+G_END_DECLS;
+
+#endif /* !__FRAP_MENU_SEPARATOR_H__ */

Modified: xfdesktop/trunk/modules/menu/frapmenu/frap-menu.c
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/frap-menu.c   2007-03-18 21:50:03 UTC 
(rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/frap-menu.c   2007-03-19 02:29:49 UTC 
(rev 25200)
@@ -1,4 +1,4 @@
-/* $Id: frap-menu.c 24974 2007-02-14 10:49:23Z jannis $ */
+/* $Id: frap-menu.c 25195 2007-03-18 16:38:41Z jannis $ */
 /* vi:set expandtab sw=2 sts=2 et: */
 /*-
  * Copyright (c) 2006-2007 Jannis Pohlmann <[EMAIL PROTECTED]>
@@ -40,6 +40,8 @@
 #include <frap-menu-item-pool.h>
 #include <frap-menu-item-cache.h>
 #include <frap-menu-move.h>
+#include <frap-menu-layout.h>
+#include <frap-menu-separator.h>
 #include <frap-menu.h>
 
 
@@ -95,6 +97,9 @@
 
       /* Initialize the directory module */
       _frap_menu_directory_init ();
+
+      /* Creates the menu separator */
+      _frap_menu_separator_init ();
     }
 }
 
@@ -113,6 +118,9 @@
       /* Unset desktop environment */
       frap_menu_set_environment (NULL);
 
+      /* Destroys the menu separator */
+      _frap_menu_separator_shutdown ();
+
       /* Shutdown the directory module */
       _frap_menu_directory_shutdown ();
 
@@ -136,6 +144,7 @@
   FRAP_MENU_PARSE_STATE_RULE,
   FRAP_MENU_PARSE_STATE_END,
   FRAP_MENU_PARSE_STATE_MOVE,
+  FRAP_MENU_PARSE_STATE_LAYOUT,
 
 } FrapMenuParseState;
 
@@ -152,6 +161,7 @@
   FRAP_MENU_PARSE_NODE_TYPE_CATEGORY,
   FRAP_MENU_PARSE_NODE_TYPE_OLD,
   FRAP_MENU_PARSE_NODE_TYPE_NEW,
+  FRAP_MENU_PARSE_NODE_TYPE_MENUNAME,
 
 } FrapMenuParseNodeType;
 
@@ -295,6 +305,8 @@
                                                                             
FrapMenuPair          *data);
 static void               frap_menu_resolve_deleted                        
(FrapMenu              *menu);
 static void               frap_menu_resolve_moves                          
(FrapMenu              *menu);
+static gint               frap_menu_compare_items                          
(gconstpointer         *a,
+                                                                            
gconstpointer         *b);
 
 
 
@@ -342,6 +354,9 @@
   /* Shared menu item cache */
   FrapMenuItemCache *cache;
 
+  /* Menu layout */
+  FrapMenuLayout    *layout;
+
   /* Parse information (used for resolving) */
   FrapMenuParseInfo *parse_info;
 };
@@ -495,6 +510,7 @@
   menu->priv->rules = NULL;
   menu->priv->moves = NULL;
   menu->priv->pool = frap_menu_item_pool_new ();
+  menu->priv->layout = frap_menu_layout_new ();
 
   /* Take reference on the menu item cache */
   menu->priv->cache = frap_menu_item_cache_get_default ();
@@ -548,6 +564,9 @@
   /* Free item pool */
   g_object_unref (G_OBJECT (menu->priv->pool));
 
+  /* Free menu layout */
+  g_object_unref (G_OBJECT (menu->priv->layout));
+
   /* Release item cache reference */
   g_object_unref (G_OBJECT (menu->priv->cache));
 
@@ -711,7 +730,7 @@
 {
   FrapMenu *menu;
 
-  g_return_val_if_fail (g_path_is_absolute (filename), NULL);
+  g_return_val_if_fail (filename != NULL && g_path_is_absolute (filename), 
NULL);
 
   /* Create new menu */
   menu = g_object_new (FRAP_TYPE_MENU, "filename", filename, NULL);
@@ -1216,6 +1235,11 @@
           /* Set parse state */
           menu_context->state = FRAP_MENU_PARSE_STATE_MOVE;
         }
+      else if (g_utf8_collate (element_name, "Layout") == 0)
+        {
+          /* Set parse state */
+          menu_context->state = FRAP_MENU_PARSE_STATE_LAYOUT;
+        }
       
       break;
 
@@ -1289,6 +1313,60 @@
         menu_context->node_type = FRAP_MENU_PARSE_NODE_TYPE_NEW;
 
       break;
+
+    case FRAP_MENU_PARSE_STATE_LAYOUT:
+      /* Fetch current menu from stack */
+      current_menu = g_list_first (menu_context->menu_stack)->data;
+
+      if (g_utf8_collate (element_name, "Filename") == 0)
+        {
+          /* Set node type */
+          menu_context->node_type = FRAP_MENU_PARSE_NODE_TYPE_FILENAME;
+        }
+      else if (g_utf8_collate (element_name, "Menuname") == 0)
+        {
+          /* TODO Parse attributes */
+          
+          /* Set node type */
+          menu_context->node_type = FRAP_MENU_PARSE_NODE_TYPE_MENUNAME;
+        }
+      else if (g_utf8_collate (element_name, "Separator") == 0)
+        {
+          /* Add separator to the menu layout */
+          frap_menu_layout_add_separator (current_menu->priv->layout);
+        }
+      else if (g_utf8_collate (element_name, "Merge") == 0)
+        {
+          FrapMenuLayoutMergeType type = FRAP_MENU_LAYOUT_MERGE_ALL;
+
+          gboolean type_found = FALSE;
+          gint     i;
+
+          /* Find 'type' attribute */
+          for (i = 0; i < g_strv_length (attribute_names); ++i) 
+            {
+              if (g_utf8_collate (attribute_names[i], "type") == 0)
+                {
+                  /* Determine merge type */
+                  if (g_utf8_collate (attribute_values[i], "menus") == 0)
+                    type = FRAP_MENU_LAYOUT_MERGE_MENUS;
+                  else if (g_utf8_collate (attribute_values[i], "files") == 0)
+                    type = FRAP_MENU_LAYOUT_MERGE_FILES;
+                  else if (g_utf8_collate (attribute_values[i], "all") == 0)
+                    type = FRAP_MENU_LAYOUT_MERGE_ALL;
+                  else 
+                    g_warning ("Unsupported layout merge type <Merge 
type='%s'/> detected. Using type 'all'.", attribute_values[i]);
+
+                  type_found = TRUE;
+                }
+            }
+
+          if (G_UNLIKELY (!type_found))
+            g_warning ("Type attribute missing for <Merge> element. Using type 
'all'.");
+
+          /* Add merge to the menu layout */
+          frap_menu_layout_add_merge (current_menu->priv->layout, type);
+        }
     }
 }
 
@@ -1370,6 +1448,16 @@
       else if (g_utf8_collate (element_name, "New") == 0)
         menu_context->move = NULL;
       break;
+
+    case FRAP_MENU_PARSE_STATE_LAYOUT:
+      if (g_utf8_collate (element_name, "Layout") == 0)
+        {
+          if (g_list_length (menu_context->menu_stack) > 1)
+            menu_context->state = FRAP_MENU_PARSE_STATE_MENU;
+          else
+            menu_context->state = FRAP_MENU_PARSE_STATE_ROOT;
+        }
+      break;
     }
 }
 
@@ -1416,8 +1504,13 @@
       break;
 
     case FRAP_MENU_PARSE_NODE_TYPE_FILENAME:
-      if (G_LIKELY (current_rule != NULL))
-        frap_menu_rules_add_filename (current_rule, content);
+      if (menu_context->state == FRAP_MENU_PARSE_STATE_RULE) 
+        {
+          if (G_LIKELY (current_rule != NULL))
+            frap_menu_rules_add_filename (current_rule, content);
+        }
+      else if (menu_context->state == FRAP_MENU_PARSE_STATE_LAYOUT)
+        frap_menu_layout_add_filename (current_menu->priv->layout, content);
       break;
 
     case FRAP_MENU_PARSE_NODE_TYPE_CATEGORY:
@@ -1435,6 +1528,10 @@
       else
         g_warning ("Ignoring <New>%s</New>", content);
       break;
+
+    case FRAP_MENU_PARSE_NODE_TYPE_MENUNAME:
+      frap_menu_layout_add_menuname (current_menu->priv->layout, content);
+      break;
     }
 
   /* Free string */
@@ -1790,7 +1887,7 @@
 frap_menu_get_menus (FrapMenu *menu)
 {
   g_return_val_if_fail (FRAP_IS_MENU (menu), NULL);
-  return menu->priv->submenus;
+  return g_slist_copy (menu->priv->submenus);
 }
 
 
@@ -2473,6 +2570,53 @@
 static void
 frap_menu_resolve_moves (FrapMenu *menu)
 {
+  FrapMenuMove *move;
+  FrapMenu     *source;
+  FrapMenu     *destination;
+  GSList       *iter;
+
+  g_return_if_fail (FRAP_IS_MENU (menu));
+
+  /* Recurse into the submenus which need to perform move actions first */
+  for (iter = menu->priv->submenus; iter != NULL; iter = g_slist_next (iter))
+    {
+      source = FRAP_MENU (iter->data);
+
+      /* Resolve moves of the child menu */
+      frap_menu_resolve_moves (source);
+    }
+
+  /* Iterate over move instructions */
+  for (iter = menu->priv->moves; iter != NULL; iter = g_slist_next (iter))
+    {
+      move = FRAP_MENU_MOVE (iter->data);
+      
+      g_critical ("Moving %s to %s ...", frap_menu_move_get_old (move), 
frap_menu_move_get_new (move));
+
+      /* Determine submenu with the old name */
+      source = frap_menu_get_menu_with_name (menu, frap_menu_move_get_old 
(move));
+
+      g_critical ("source = 0x%x", source);
+
+      /* Skip if there is no such submenu */
+      if (G_LIKELY (source == NULL))
+        continue;
+
+      /* Determine destination submenu */
+      destination = frap_menu_get_menu_with_name (menu, frap_menu_move_get_new 
(move));
+
+      g_critical ("destination = 0x%x", destination);
+
+      /* If destination does not exist, simply reset the name of the source 
menu */
+      if (G_LIKELY (destination == NULL))
+        frap_menu_set_name (source, frap_menu_move_get_new (move));
+      else
+        {
+          /* TODO: See section "Merging" in the menu specification. */
+        }
+    }
+
+#if 0
   FrapMenu     *submenu;
   FrapMenu     *target_submenu;
   FrapMenuMove *move;
@@ -2532,6 +2676,7 @@
             }
         }
     }
+#endif
 }
 
 
@@ -2612,8 +2757,185 @@
 
   g_return_val_if_fail (FRAP_IS_MENU (menu), NULL);
 
-  /* collect the items in the pool */
+  /* Collect the items in the pool */
   frap_menu_item_pool_foreach (menu->priv->pool, (GHFunc) items_collect, 
&items);
 
   return items;
 }
+
+
+
+static void
+layout_items_collect (GSList        **dest_list,
+                      GSList         *src_list,
+                      FrapMenuLayout *layout)
+{
+  FrapMenuItem *item;
+  FrapMenu     *menu;
+  GSList       *iter;
+
+  for (iter = src_list; iter != NULL; iter = g_slist_next (iter))
+    {
+      if (FRAP_IS_MENU (iter->data))
+        {
+          menu = FRAP_MENU (iter->data);
+
+          if (G_LIKELY (!frap_menu_layout_get_menuname_used (layout, 
frap_menu_get_name (menu))))
+            *dest_list = g_slist_append (*dest_list, iter->data);
+        }
+      else if (FRAP_IS_MENU_ITEM (iter->data))
+        {
+          item = FRAP_MENU_ITEM (iter->data);
+
+          if (G_LIKELY (!frap_menu_layout_get_filename_used (layout, 
frap_menu_item_get_desktop_id (item))))
+            *dest_list = g_slist_append (*dest_list, iter->data);
+        }
+    }
+}
+
+
+GSList*
+frap_menu_get_layout_items (FrapMenu *menu)
+{
+  GSList *items = NULL;
+  GSList *menu_items;
+  GSList *nodes;
+  GSList *iter;
+
+  g_return_val_if_fail (FRAP_IS_MENU (menu), NULL);
+
+  /* Fetch layout nodes */
+  nodes = frap_menu_layout_get_nodes (menu->priv->layout);
+
+  /* Only process layout if there are any layout information at all */
+  if (G_UNLIKELY (nodes != NULL && g_slist_length (nodes) != 0))
+    {
+      g_debug ("Menu has layout");
+
+      /* Process layout nodes in order */
+      for (iter = nodes; iter != NULL; iter = g_slist_next (iter))
+        {
+          FrapMenuLayoutNode     *node = (FrapMenuLayoutNode *)iter->data;
+          FrapMenuLayoutNodeType  type;
+          FrapMenuLayoutMergeType merge_type;
+          FrapMenuItem           *item;
+          FrapMenu               *submenu;
+          FrapMenuSeparator      *separator;
+
+          /* Determine layout node type */
+          type = frap_menu_layout_node_get_type (node);
+
+          if (type == FRAP_MENU_LAYOUT_NODE_FILENAME)
+            {
+              /* Search for desktop ID in the item pool */
+              item = frap_menu_item_pool_lookup (menu->priv->pool, 
frap_menu_layout_node_get_filename (node));
+
+              /* If the item with this desktop ID is included in the menu, 
append it to the list */
+              if (G_LIKELY (item != NULL))
+                items = g_slist_append (items, item);
+            }
+          if (type == FRAP_MENU_LAYOUT_NODE_MENUNAME)
+            {
+              /* Search submenu with this name */
+              submenu = frap_menu_get_menu_with_name (menu, 
frap_menu_layout_node_get_menuname (node));
+
+              /* If there is such a menu, append it to the list */
+              if (G_LIKELY (submenu != NULL))
+                items = g_slist_append (items, submenu);
+            }
+          else if (type == FRAP_MENU_LAYOUT_NODE_SEPARATOR)
+            {
+              /* Append separator to the list */
+              items = g_slist_append (items, frap_menu_separator_get_default 
());
+            }
+          else if (type == FRAP_MENU_LAYOUT_NODE_MERGE)
+            {
+              /* Determine merge type */
+              merge_type = frap_menu_layout_node_get_merge_type (node);
+
+              if (merge_type == FRAP_MENU_LAYOUT_MERGE_ALL)
+                {
+                  /* Get all menu items of this menu */
+                  menu_items = frap_menu_get_items (menu);
+                  
+                  /* Append submenus */
+                  menu_items = g_slist_concat (menu_items, frap_menu_get_menus 
(menu));
+
+                  /* Sort menu items */
+                  menu_items = g_slist_sort (menu_items, (GCompareFunc) 
frap_menu_compare_items);
+
+                  /* Append menu items to the returned item list */
+                  layout_items_collect (&items, menu_items, 
menu->priv->layout);
+                }
+              else if (merge_type == FRAP_MENU_LAYOUT_MERGE_FILES)
+                {
+                  /* Get all menu items of this menu */
+                  menu_items = frap_menu_get_items (menu);
+
+                  /* Sort menu items */
+                  menu_items = g_slist_sort (menu_items, (GCompareFunc) 
frap_menu_compare_items);
+
+                  /* Append menu items to the returned item list */
+                  layout_items_collect (&items, menu_items, 
menu->priv->layout);
+                }
+              else if (merge_type == FRAP_MENU_LAYOUT_MERGE_MENUS)
+                {
+                  /* Get all submenus */
+                  menu_items = frap_menu_get_menus (menu);
+
+                  /* Sort menu items */
+                  menu_items = g_slist_sort (menu_items, (GCompareFunc) 
frap_menu_compare_items);
+
+                  /* Append submenus to the returned item list */
+                  layout_items_collect (&items, menu_items, 
menu->priv->layout);
+                }
+            }
+        }
+    }
+  else
+    {
+      /* No layout used. Fetch items, menus and sort them */
+      items = frap_menu_get_items (menu);
+      items = g_slist_concat (items, frap_menu_get_menus (menu));
+      items = g_slist_sort (items, (GCompareFunc) frap_menu_compare_items);
+    }
+
+  g_debug ("%s: %d layout items", frap_menu_get_name (menu), g_slist_length 
(items));
+
+  return items;
+}
+
+
+
+static gint
+frap_menu_compare_items (gconstpointer *a,
+                         gconstpointer *b)
+{
+  const gchar *name1;
+  const gchar *name2;
+
+  /* Determining display name of a */
+  if (FRAP_IS_MENU (a))
+    {
+      if (G_LIKELY (frap_menu_get_directory (FRAP_MENU (a)) != NULL))
+        name1 = frap_menu_directory_get_name (frap_menu_get_directory 
(FRAP_MENU (a)));
+      else
+        name1 = frap_menu_get_name (FRAP_MENU (a));
+    }
+  else
+    name1 = frap_menu_item_get_name (FRAP_MENU_ITEM (a));
+
+  /* Determining display name of b */
+  if (FRAP_IS_MENU (b))
+    {
+      if (G_LIKELY (frap_menu_get_directory (FRAP_MENU (b)) != NULL))
+        name2 = frap_menu_directory_get_name (frap_menu_get_directory 
(FRAP_MENU (b)));
+      else
+        name2 = frap_menu_get_name (FRAP_MENU (b));
+    }
+  else
+    name2 = frap_menu_item_get_name (FRAP_MENU_ITEM (b));
+
+  /* Compare display names and return the result */
+  return g_utf8_collate (name1, name2);
+}

Modified: xfdesktop/trunk/modules/menu/frapmenu/frap-menu.h
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/frap-menu.h   2007-03-18 21:50:03 UTC 
(rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/frap-menu.h   2007-03-19 02:29:49 UTC 
(rev 25200)
@@ -1,4 +1,4 @@
-/* $Id: frap-menu.h 24502 2007-01-16 10:08:36Z jannis $ */
+/* $Id: frap-menu.h 25185 2007-03-18 02:23:12Z jannis $ */
 /* vi:set expandtab sw=2 sts=2: */
 /*-
  * Copyright (c) 2006-2007 Jannis Pohlmann <[EMAIL PROTECTED]>
@@ -77,6 +77,7 @@
 FrapMenu          *frap_menu_get_parent            (FrapMenu          *menu);
 FrapMenuItemPool  *frap_menu_get_item_pool         (FrapMenu          *menu);
 GSList            *frap_menu_get_items             (FrapMenu          *menu);
+GSList            *frap_menu_get_layout_items      (FrapMenu          *menu);
 
 G_END_DECLS;
 

Modified: xfdesktop/trunk/modules/menu/frapmenu/libfrapmenu.h
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/libfrapmenu.h 2007-03-18 21:50:03 UTC 
(rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/libfrapmenu.h 2007-03-19 02:29:49 UTC 
(rev 25200)
@@ -1,4 +1,4 @@
-/* $Id: libfrapmenu.h 24502 2007-01-16 10:08:36Z jannis $ */
+/* $Id: libfrapmenu.h 25185 2007-03-18 02:23:12Z jannis $ */
 /* vi:set expandtab sw=2 sts=2: */
 /*-
  * Copyright (c) 2006-2007 Jannis Pohlmann <[EMAIL PROTECTED]>
@@ -33,6 +33,8 @@
 #include <frap-menu-and-rules.h>
 #include <frap-menu-not-rules.h>
 #include <frap-menu-directory.h>
+#include <frap-menu-layout.h>
+#include <frap-menu-separator.h>
 #include <frap-menu.h>
 
 #define LIBFRAPMENU_INSIDE_LIBFRAPMENU_H

Modified: xfdesktop/trunk/modules/menu/frapmenu/tdb/Makefile.am
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/tdb/Makefile.am       2007-03-18 
21:50:03 UTC (rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/tdb/Makefile.am       2007-03-19 
02:29:49 UTC (rev 25200)
@@ -2,7 +2,7 @@
 
 INCLUDES =                                                             \
        $(PLATFORM_CFLAGS)                                              \
-       -I$(top_srcdir)/libfrap/menu/
+       -I$(top_srcdir)/modules/menu/frapmenu
 
 noinst_LTLIBRARIES =                                                   \
        libtdb.la

Added: xfdesktop/trunk/modules/menu/frapmenu/tdb/README
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/tdb/README                            
(rev 0)
+++ xfdesktop/trunk/modules/menu/frapmenu/tdb/README    2007-03-19 02:29:49 UTC 
(rev 25200)
@@ -0,0 +1,167 @@
+tdb - a trivial database system
[EMAIL PROTECTED] December 1999
+==================================
+
+This is a simple database API. It was inspired by the realisation that
+in Samba we have several ad-hoc bits of code that essentially
+implement small databases for sharing structures between parts of
+Samba. As I was about to add another I realised that a generic
+database module was called for to replace all the ad-hoc bits.
+
+I based the interface on gdbm. I couldn't use gdbm as we need to be
+able to have multiple writers to the databases at one time.
+
+Compilation
+-----------
+
+add HAVE_MMAP=1 to use mmap instead of read/write
+add TDB_DEBUG=1 for verbose debug info
+add NOLOCK=1 to disable locking code
+
+Testing
+-------
+
+Compile tdbtest.c and link with gdbm for testing. tdbtest will perform
+identical operations via tdb and gdbm then make sure the result is the
+same
+
+Also included is tdbtool, which allows simple database manipulation
+on the commandline.
+
+tdbtest and tdbtool are not built as part of Samba, but are included
+for completeness.
+
+Interface
+---------
+
+The interface is very similar to gdbm except for the following:
+
+- different open interface. The tdb_open call is more similar to a
+  traditional open()
+- no tdbm_reorganise() function
+- no tdbm_sync() function. No operations are cached in the library anyway
+- added a tdb_traverse() function for traversing the whole database
+
+A general rule for using tdb is that the caller frees any returned
+TDB_DATA structures. Just call free(p.dptr) to free a TDB_DATA
+return value called p. This is the same as gdbm.
+
+here is a full list of tdb functions with brief descriptions.
+
+
+----------------------------------------------------------------------
+TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
+                     int open_flags, mode_t mode)
+
+   open the database, creating it if necessary 
+
+   The open_flags and mode are passed straight to the open call on the database
+   file. A flags value of O_WRONLY is invalid
+
+   The hash size is advisory, use zero for a default value. 
+
+   return is NULL on error
+
+   possible tdb_flags are:
+    TDB_CLEAR_IF_FIRST - clear database if we are the only one with it open
+    TDB_INTERNAL - don't use a file, instaed store the data in
+                   memory. The filename is ignored in this case.
+    TDB_NOLOCK - don't do any locking
+    TDB_NOMMAP - don't use mmap
+
+----------------------------------------------------------------------
+char *tdb_error(TDB_CONTEXT *tdb);
+
+     return a error string for the last tdb error
+
+----------------------------------------------------------------------
+int tdb_close(TDB_CONTEXT *tdb);
+
+   close a database
+
+----------------------------------------------------------------------
+int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf);
+
+   update an entry in place - this only works if the new data size
+   is <= the old data size and the key exists.
+   on failure return -1
+
+----------------------------------------------------------------------
+TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
+
+   fetch an entry in the database given a key 
+   if the return value has a null dptr then a error occurred
+
+   caller must free the resulting data
+
+----------------------------------------------------------------------
+int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
+
+   check if an entry in the database exists 
+
+   note that 1 is returned if the key is found and 0 is returned if not found
+   this doesn't match the conventions in the rest of this module, but is
+   compatible with gdbm
+
+----------------------------------------------------------------------
+int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb,
+                 TDB_DATA key, TDB_DATA dbuf, void *state), void *state);
+
+   traverse the entire database - calling fn(tdb, key, data, state) on each 
+   element.
+
+   return -1 on error or the record count traversed
+
+   if fn is NULL then it is not called
+
+   a non-zero return value from fn() indicates that the traversal should stop
+
+----------------------------------------------------------------------
+TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
+
+   find the first entry in the database and return its key
+
+   the caller must free the returned data
+
+----------------------------------------------------------------------
+TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
+
+   find the next entry in the database, returning its key
+
+   the caller must free the returned data
+
+----------------------------------------------------------------------
+int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
+
+   delete an entry in the database given a key
+
+----------------------------------------------------------------------
+int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
+
+   store an element in the database, replacing any existing element
+   with the same key 
+
+   If flag==TDB_INSERT then don't overwrite an existing entry
+   If flag==TDB_MODIFY then don't create a new entry
+
+   return 0 on success, -1 on failure
+
+----------------------------------------------------------------------
+int tdb_writelock(TDB_CONTEXT *tdb);
+
+   lock the database. If we already have it locked then don't do anything
+
+----------------------------------------------------------------------
+int tdb_writeunlock(TDB_CONTEXT *tdb);
+   unlock the database
+
+----------------------------------------------------------------------
+int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
+
+   lock one hash chain. This is meant to be used to reduce locking
+   contention - it cannot guarantee how many records will be locked
+
+----------------------------------------------------------------------
+int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
+
+   unlock one hash chain

Modified: xfdesktop/trunk/modules/menu/frapmenu/tdb/spinlock.c
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/tdb/spinlock.c        2007-03-18 
21:50:03 UTC (rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/tdb/spinlock.c        2007-03-19 
02:29:49 UTC (rev 25200)
@@ -56,7 +56,7 @@
 #include <unistd.h>
 #endif
 
-#include "spinlock.h"
+#include <tdb/spinlock.h>
 
 #ifdef USE_SPINLOCKS
 

Modified: xfdesktop/trunk/modules/menu/frapmenu/tdb/spinlock.h
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/tdb/spinlock.h        2007-03-18 
21:50:03 UTC (rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/tdb/spinlock.h        2007-03-19 
02:29:49 UTC (rev 25200)
@@ -25,7 +25,7 @@
 #ifndef __SPINLOCK_H__
 #define __SPINLOCK_H__
 
-#include "tdb.h"
+#include <tdb/tdb.h>
 
 #ifdef __cplusplus
 extern "C" {

Modified: xfdesktop/trunk/modules/menu/frapmenu/tdb/tdb.c
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/tdb/tdb.c     2007-03-18 21:50:03 UTC 
(rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/tdb/tdb.c     2007-03-19 02:29:49 UTC 
(rev 25200)
@@ -80,8 +80,8 @@
 #include <unistd.h>
 #endif
 
-#include "spinlock.h"
-#include "tdb.h"
+#include <tdb/spinlock.h>
+#include <tdb/tdb.h>
 
 #define TDB_MAGIC_FOOD "TDB file\n"
 #define TDB_VERSION (0x26011967 + 6)

Modified: xfdesktop/trunk/modules/menu/frapmenu/tdb/tdb.h
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/tdb/tdb.h     2007-03-18 21:50:03 UTC 
(rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/tdb/tdb.h     2007-03-19 02:29:49 UTC 
(rev 25200)
@@ -25,7 +25,7 @@
 #ifndef __TDB_H__
 #define __TDB_H__
 
-#include "tdbconfig.h"
+#include <tdb/tdbconfig.h>
 
 #include <signal.h>
 #include <unistd.h>

Modified: xfdesktop/trunk/modules/menu/frapmenu/tdb/tdbtool.c
===================================================================
--- xfdesktop/trunk/modules/menu/frapmenu/tdb/tdbtool.c 2007-03-18 21:50:03 UTC 
(rev 25199)
+++ xfdesktop/trunk/modules/menu/frapmenu/tdb/tdbtool.c 2007-03-19 02:29:49 UTC 
(rev 25200)
@@ -68,7 +68,7 @@
 #include <unistd.h>
 #endif
 
-#include "tdb.h"
+#include <tdb/tdb.h>
 
 /* a tdb tool for manipulating a tdb database */
 

Modified: xfdesktop/trunk/modules/menu/menu-data/xfce-applications.menu
===================================================================
--- xfdesktop/trunk/modules/menu/menu-data/xfce-applications.menu       
2007-03-18 21:50:03 UTC (rev 25199)
+++ xfdesktop/trunk/modules/menu/menu-data/xfce-applications.menu       
2007-03-19 02:29:49 UTC (rev 25200)
@@ -32,6 +32,12 @@
         <Include>
             <Category>Settings</Category>
         </Include>
+        
+        <Layout>
+            <Filename>xfce-settings-manager.desktop</Filename>
+            <Separator/>
+            <Merge type="all"/>
+        </Layout>
     </Menu>
     
     <Menu>

_______________________________________________
Xfce4-commits mailing list
Xfce4-commits@xfce.org
http://foo-projects.org/mailman/listinfo/xfce4-commits

Reply via email to