[Goodies-commits] r1770 - in xfce-menu/trunk: . libxfce4menu tests

Jannis Pohlmann jannis at xfce.org
Mon Jul 17 00:01:02 CEST 2006


Author: jannis
Date: 2006-07-16 22:01:01 +0000 (Sun, 16 Jul 2006)
New Revision: 1770

Added:
   xfce-menu/trunk/CMakeLists.txt
   xfce-menu/trunk/libxfce4menu/
   xfce-menu/trunk/libxfce4menu/CMakeLists.txt
   xfce-menu/trunk/libxfce4menu/libxfce4menu.h
   xfce-menu/trunk/libxfce4menu/xfce-menu-directory.c
   xfce-menu/trunk/libxfce4menu/xfce-menu-directory.h
   xfce-menu/trunk/libxfce4menu/xfce-menu.c
   xfce-menu/trunk/libxfce4menu/xfce-menu.h
   xfce-menu/trunk/tests/
   xfce-menu/trunk/tests/CMakeLists.txt
   xfce-menu/trunk/tests/load-root-menu-test.c
Log:
First implementations:

  * XfceMenuDirectory and XfceMenu classes (both partially)

I'm using CMake for now, to make project management a bit easier (I 
still don't feel too comfy with autotools).

The now added classes are only partially implemented and they don't 
support file monitoring yet. Here's what they *do* support:

  * Lookup the root menu (applications.menu)
  * Load parts of it (especially root menu name, directory, legacy
    and application directories).

The classes are implemented using GObject, so they are quite flexible
and can later be extended with filesystem monitoring, merge facilities
etc.



Added: xfce-menu/trunk/CMakeLists.txt
===================================================================
--- xfce-menu/trunk/CMakeLists.txt	                        (rev 0)
+++ xfce-menu/trunk/CMakeLists.txt	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,38 @@
+# Project name
+PROJECT(libxfce4menu)
+
+# Enable execution of test programs
+ENABLE_TESTING()
+
+# Include directories
+INCLUDE_DIRECTORIES(
+	.
+)
+
+# Load CMake modules
+Include(UsePkgConfig)
+
+# Find GLib
+PKGCONFIG(glib-2.0 GLIB_INCLUDES GLIB_LIBADD GLIB_LDFLAGS GLIB_CFLAGS)
+SET(CMAKE_C_FLAGS ${CMAKE_CFLAGS} ${GLIB_CFLAGS})
+
+# Find GThread
+PKGCONFIG(gthread GTHREAD_INCLUDES GTHREAD_LIBADD GTHREAD_LDFLAGS GTHREAD_CFLAGS)
+SET(CMAKE_C_FLAGS ${CMAKE_CFLAGS} ${GTHREAD_CFLAGS})
+
+# Find libxfce4util
+PKGCONFIG(libxfce4util-1.0 LIBXFCE4UTIL_INCLUDES LIBXFCE4UTIL_LIBADD
+	LIBXFCE4UTILS_LDFLAGS LIBXFCE4UTILS_CFLAGS)
+SET(CMAKE_C_FLAGS ${CMAKE_CFLAGS} ${LIBXFCE4UTIL_CFLAGS})
+
+# Find libexo
+PKGCONFIG(exo-0.3 EXO_INCLUDES EXO_LIBADD EXO_LDFLAGS EXO_CFLAGS)
+SET(CMAKE_C_FLAGS ${CMAKE_CFLAGS} ${EXO_CFLAGS})
+
+# Add definitions
+ADD_DEFINITIONS(
+	-DEXO_API_SUBJECT_TO_CHANGE
+)
+
+# Subdirectories (library, tests)
+SUBDIRS(libxfce4menu tests)

Added: xfce-menu/trunk/libxfce4menu/CMakeLists.txt
===================================================================
--- xfce-menu/trunk/libxfce4menu/CMakeLists.txt	                        (rev 0)
+++ xfce-menu/trunk/libxfce4menu/CMakeLists.txt	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,17 @@
+ADD_LIBRARY(xfce4menu SHARED
+	libxfce4menu.h
+	xfce-menu-directory.h
+	xfce-menu-directory.c
+	xfce-menu.h
+	xfce-menu.c
+)
+
+TARGET_LINK_LIBRARIES(xfce4menu 
+	${LIBXFCE4UTIL_LDFLAGS} 
+	${GLIB_LDFLAGS} 
+	${EXO_LDFLAGS}
+	${GTHREAD_LDFLAGS})
+
+ADD_DEFINITIONS(
+	-DLIBXFCE4MENU_COMPILATION
+)

Added: xfce-menu/trunk/libxfce4menu/libxfce4menu.h
===================================================================
--- xfce-menu/trunk/libxfce4menu/libxfce4menu.h	                        (rev 0)
+++ xfce-menu/trunk/libxfce4menu/libxfce4menu.h	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,32 @@
+/* $Id$ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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.
+ */
+
+#ifndef __LIBXFCE4MENU_LIBXFCE4MENU_H__
+#define __LIBXFCE4MENU_LIBXFCE4MENU_H__
+
+#define LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H
+
+#include <libxfce4menu/xfce-menu-directory.h>
+#include <libxfce4menu/xfce-menu.h>
+
+#define LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H
+
+#endif /* !__LIBXFCE4UTIL_LIBXFCE4UTIL_H__ */

Added: xfce-menu/trunk/libxfce4menu/xfce-menu-directory.c
===================================================================
--- xfce-menu/trunk/libxfce4menu/xfce-menu-directory.c	                        (rev 0)
+++ xfce-menu/trunk/libxfce4menu/xfce-menu-directory.c	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,518 @@
+/* $Id$ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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 <locale.h>
+#include <glib.h>
+#include <libxfce4util/libxfce4util.h>
+
+#include <libxfce4menu/xfce-menu-directory.h>
+
+
+
+void
+_xfce_menu_directory_init (void)
+{
+}
+
+
+
+void
+_xfce_menu_directory_shutdown (void)
+{
+}
+
+
+
+#define XFCE_MENU_DIRECTORY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_MENU_DIRECTORY, XfceMenuDirectoryPrivate))
+
+
+
+/* Desktop entry keys */
+static const gchar *desktop_entry_keys[] = 
+{
+  "Name",
+  "Comment",
+  "Icon",
+  "Categories",
+  "OnlyShowIn",
+  "NotShowIn",
+  NULL
+};
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+  PROP_FILENAME,
+  PROP_NAME,
+  PROP_COMMENT,
+  PROP_ICON,
+};
+
+
+
+static void       xfce_menu_directory_class_init       (XfceMenuDirectoryClass       *klass);
+static void       xfce_menu_directory_init             (XfceMenuDirectory            *directory);
+static void       xfce_menu_directory_finalize         (GObject                      *object);
+static void       xfce_menu_directory_get_property     (GObject                      *object,
+                                                        guint                         prop_id,
+                                                        GValue                       *value,
+                                                        GParamSpec                   *pspec);
+static void       xfce_menu_directory_set_property     (GObject                      *object,
+                                                        guint                         prop_id,
+                                                        const GValue                 *value,
+                                                        GParamSpec                   *pspec);
+
+static void       xfce_menu_directory_load             (XfceMenuDirectory            *directory);
+
+
+
+struct _XfceMenuDirectoryPrivate
+{
+  /* Directory filename */
+  gchar             *filename;
+
+  /* Directory name */
+  gchar             *name;
+
+  /* Directory description (comment) */
+  gchar             *comment;
+
+  /* Icon */
+  gchar             *icon;
+
+  /* TODO: OnlyShowIn, Categories */
+};
+
+struct _XfceMenuDirectoryClass
+{
+  GObjectClass __parent__;
+};
+
+struct _XfceMenuDirectory
+{
+  GObject          __parent__;
+
+  /* < private > */
+  XfceMenuDirectoryPrivate *priv;
+};
+
+
+
+static GObjectClass *xfce_menu_directory_parent_class = NULL;
+
+
+
+GType
+xfce_menu_directory_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (XfceMenuDirectoryClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) xfce_menu_directory_class_init,
+        NULL,
+        NULL,
+        sizeof (XfceMenuDirectory),
+        0,
+        (GInstanceInitFunc) xfce_menu_directory_init,
+        NULL,
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, I_("XfceMenuDirectory"), &info, 0);
+    }
+
+  return type;
+}
+
+
+
+static void
+xfce_menu_directory_class_init (XfceMenuDirectoryClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof(XfceMenuDirectoryPrivate));
+
+  /* Determine the parent type class */
+  xfce_menu_directory_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = xfce_menu_directory_finalize; 
+  gobject_class->get_property = xfce_menu_directory_get_property;
+  gobject_class->set_property = xfce_menu_directory_set_property;
+
+  /**
+   * XfceMenuDirectory:filename:
+   *
+   * The filename of an %XfceMenuDirectory object. Whenever this is redefined, the
+   * directory entry is parsed again.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILENAME,
+                                   g_param_spec_string ("filename",
+                                                        _("Filename"),
+                                                        _("Directory filename"),
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  /**
+   * XfceMenuDirectory:name:
+   *
+   * Name of the directory.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILENAME,
+                                   g_param_spec_string ("name",
+                                                        _("Name"),
+                                                        _("Directory name"),
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  /**
+   * XfceMenuDirectory:comment:
+   *
+   * Directory description (comment).
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILENAME,
+                                   g_param_spec_string ("comment",
+                                                        _("Description"),
+                                                        _("Directory description"),
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  /**
+   * XfceMenuDirectory:icon:
+   *
+   * Icon associated with this directory.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILENAME,
+                                   g_param_spec_string ("icon",
+                                                        _("Icon"),
+                                                        _("Directory icon"),
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+}
+
+
+
+static void
+xfce_menu_directory_init (XfceMenuDirectory *directory)
+{
+  directory->priv = XFCE_MENU_DIRECTORY_GET_PRIVATE (directory);
+  directory->priv->filename = NULL;
+  directory->priv->name = NULL;
+  directory->priv->icon = NULL;
+}
+
+
+
+static void
+xfce_menu_directory_finalize (GObject *object)
+{
+  XfceMenuDirectory *directory = XFCE_MENU_DIRECTORY (object);
+
+  /* Free filename */
+  if (G_LIKELY (directory->priv->filename != NULL))
+    g_free (directory->priv->filename);
+
+  /* Free name */
+  if (G_LIKELY (directory->priv->name != NULL))
+    g_free (directory->priv->name);
+
+  /* Free comment */
+  if (G_LIKELY (directory->priv->comment != NULL))
+    g_free (directory->priv->comment);
+
+  /* Free icon */
+  if (G_LIKELY (directory->priv->icon != NULL))
+    g_free (directory->priv->icon);
+
+  (*G_OBJECT_CLASS (xfce_menu_directory_parent_class)->finalize) (object);
+}
+
+
+
+static void
+xfce_menu_directory_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  XfceMenuDirectory *directory = XFCE_MENU_DIRECTORY (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILENAME:
+      g_value_set_string (value, xfce_menu_directory_get_filename (directory));
+      break;
+
+    case PROP_NAME:
+      g_value_set_string (value, xfce_menu_directory_get_name (directory));
+      break;
+
+    case PROP_COMMENT:
+      g_value_set_string (value, xfce_menu_directory_get_comment (directory));
+      break;
+
+    case PROP_ICON:
+      g_value_set_string (value, xfce_menu_directory_get_icon (directory));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+xfce_menu_directory_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  XfceMenuDirectory *directory = XFCE_MENU_DIRECTORY (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILENAME:
+      xfce_menu_directory_set_filename (directory, g_value_get_string (value));
+      break;
+
+    case PROP_NAME:
+      xfce_menu_directory_set_name (directory, g_value_get_string (value));
+      break;
+
+    case PROP_COMMENT:
+      xfce_menu_directory_set_comment (directory, g_value_get_string (value));
+      break;
+
+    case PROP_ICON:
+      xfce_menu_directory_set_icon (directory, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+XfceMenuDirectory*
+xfce_menu_directory_lookup (const gchar *name)
+{
+  XfceMenuDirectory *directory = NULL;
+
+  /* Build relative search path */
+  gchar *relative_path = g_build_path (G_DIR_SEPARATOR_S, "desktop-directories", name, NULL);
+
+  /* Search file in XDG_DATA_DIRS */
+  gchar *location = xfce_resource_lookup (XFCE_RESOURCE_DATA, relative_path);
+
+  /* Make sure we found the file */
+  if (G_LIKELY (location != NULL))
+    {
+      /* Allocate new directory object and load the desktop entry data */
+      directory = g_object_new (XFCE_TYPE_MENU_DIRECTORY, "filename", location);
+
+      /* Free the location */
+      g_free (location);
+    }
+
+  /* Free relative path */
+  g_free (relative_path);
+
+  return directory;
+}
+
+
+
+const gchar*
+xfce_menu_directory_get_filename (XfceMenuDirectory *directory)
+{
+  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), NULL);
+  return directory->priv->filename;
+}
+
+
+
+void
+xfce_menu_directory_set_filename (XfceMenuDirectory *directory, const gchar *filename)
+{
+  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
+  g_return_if_fail (filename != NULL);
+
+  /* Free old filename */
+  if (G_UNLIKELY (directory->priv->filename != NULL))
+    g_free (directory->priv->filename);
+
+  /* Set the new filename */
+  directory->priv->filename = g_strdup (filename);
+
+  /* Reload the menu */
+  xfce_menu_directory_load (directory);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (directory), "filename");
+}
+
+
+
+const gchar*
+xfce_menu_directory_get_name (XfceMenuDirectory *directory)
+{
+  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), NULL);
+  return directory->priv->name;
+}
+
+
+
+void
+xfce_menu_directory_set_name (XfceMenuDirectory *directory, const gchar *name)
+{
+  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
+  g_return_if_fail (name != NULL);
+
+  /* Free old name */
+  if (G_UNLIKELY (directory->priv->name != NULL))
+    g_free (directory->priv->name);
+
+  /* Set the new filename */
+  directory->priv->name = g_strdup (name);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (directory), "name");
+}
+
+
+
+const gchar*
+xfce_menu_directory_get_comment (XfceMenuDirectory *directory)
+{
+  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), NULL);
+  return directory->priv->comment;
+}
+
+
+
+void
+xfce_menu_directory_set_comment (XfceMenuDirectory *directory, const gchar *comment)
+{
+  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
+  g_return_if_fail (comment != NULL);
+
+  /* Free old name */
+  if (G_UNLIKELY (directory->priv->comment != NULL))
+    g_free (directory->priv->comment);
+
+  /* Set the new filename */
+  directory->priv->comment = g_strdup (comment);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (directory), "comment");
+}
+
+
+const gchar*
+xfce_menu_directory_get_icon (XfceMenuDirectory *directory)
+{
+  g_return_val_if_fail (XFCE_IS_MENU_DIRECTORY (directory), NULL);
+  return directory->priv->icon;
+}
+
+
+
+void
+xfce_menu_directory_set_icon (XfceMenuDirectory *directory, const gchar *icon)
+{
+  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
+  g_return_if_fail (icon != NULL);
+
+  /* Free old name */
+  if (G_UNLIKELY (directory->priv->icon != NULL))
+    g_free (directory->priv->icon);
+
+  /* Set the new filename */
+  directory->priv->icon = g_strdup (icon);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (directory), "icon");
+}
+
+
+
+static void
+xfce_menu_directory_load (XfceMenuDirectory *directory)
+{
+  XfceRc      *entry;
+  gchar      **values;
+
+  const gchar *name;
+  const gchar *comment;
+  const gchar *icon;
+
+  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
+  g_return_if_fail (directory->priv->filename != NULL);
+
+  entry = xfce_rc_simple_open (directory->priv->filename, TRUE);
+
+  if (G_UNLIKELY (entry == NULL))
+    {
+      g_critical ("Could not load directory desktop entry %s", directory->priv->filename);
+      return;
+    }
+
+  /* Treat the file as a desktop entry */
+  xfce_rc_set_group (entry, "Desktop Entry");
+
+  /* Read directory information */
+  name = xfce_rc_read_entry (entry, "Name", NULL);
+  comment = xfce_rc_read_entry (entry, "Comment", NULL);
+  icon = xfce_rc_read_entry (entry, "Icon", NULL);
+
+  /* Pass data over to the directory */
+  xfce_menu_directory_set_name (directory, name);
+  xfce_menu_directory_set_comment (directory, comment);
+  xfce_menu_directory_set_icon (directory, icon);
+
+  xfce_rc_close (entry);
+}
+
+
+

Added: xfce-menu/trunk/libxfce4menu/xfce-menu-directory.h
===================================================================
--- xfce-menu/trunk/libxfce4menu/xfce-menu-directory.h	                        (rev 0)
+++ xfce-menu/trunk/libxfce4menu/xfce-menu-directory.h	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,68 @@
+/* $Id$ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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.
+ */
+
+#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
+#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __XFCE_MENU_DIRECTORY_H__
+#define __XFCE_MENU_DIRECTORY_H__
+
+#include <exo/exo.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _XfceMenuDirectoryPrivate XfceMenuDirectoryPrivate;
+typedef struct _XfceMenuDirectoryClass   XfceMenuDirectoryClass;
+typedef struct _XfceMenuDirectory        XfceMenuDirectory;
+
+#define XFCE_TYPE_MENU_DIRECTORY            (xfce_menu_directory_get_type ())
+#define XFCE_MENU_DIRECTORY(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU_DIRECTORY, XfceMenuDirectory))
+#define XFCE_MENU_DIRECTORY_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU_DIRECTORY, XfceMenuDirectoryClass))
+#define XFCE_IS_MENU_DIRECTORY(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU_DIRECTORY))
+#define XFCE_IS_MENU_DIRECTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU_DIRECTORY))
+#define XFCE_MENU_DIRECTORY_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU_DIRECTORY, XfceMenuDirectoryClass))
+
+GType                    xfce_menu_directory_get_type        (void) G_GNUC_CONST;
+
+XfceMenuDirectory       *xfce_menu_directory_lookup          (const gchar       *name) G_GNUC_MALLOC;
+
+const gchar             *xfce_menu_directory_get_filename    (XfceMenuDirectory *directory);
+void                     xfce_menu_directory_set_filename    (XfceMenuDirectory *directory,
+                                                              const gchar       *name);
+const gchar             *xfce_menu_directory_get_name        (XfceMenuDirectory *directory);
+void                     xfce_menu_directory_set_name        (XfceMenuDirectory *directory,
+                                                              const gchar       *name);
+const gchar             *xfce_menu_directory_get_comment     (XfceMenuDirectory *directory);
+void                     xfce_menu_directory_set_comment     (XfceMenuDirectory *directory,
+                                                              const gchar       *comment);
+const gchar             *xfce_menu_directory_get_icon        (XfceMenuDirectory *directory);
+void                     xfce_menu_directory_set_icon        (XfceMenuDirectory *directory,
+                                                              const gchar       *icon);
+
+#if defined(LIBXFCE4MENU_COMPILATION)
+void _xfce_menu_directory_init     (void) G_GNUC_INTERNAL;
+void _xfce_menu_directory_shutdown (void) G_GNUC_INTERNAL;
+#endif
+
+G_END_DECLS;
+
+#endif /* !__XFCE_MENU_DIRECTORY_H__ */

Added: xfce-menu/trunk/libxfce4menu/xfce-menu.c
===================================================================
--- xfce-menu/trunk/libxfce4menu/xfce-menu.c	                        (rev 0)
+++ xfce-menu/trunk/libxfce4menu/xfce-menu.c	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,910 @@
+/* $Id$ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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 <libxfce4menu/xfce-menu-directory.h>
+#include <libxfce4menu/xfce-menu.h>
+
+
+
+static gint xfce_menu_ref_count = 0;
+
+
+
+/**
+ * xfce_menu_init:
+ *
+ * Initializes the libxfce4menu library.
+ **/
+void
+xfce_menu_init (void)
+{
+  if (g_atomic_int_exchange_and_add (&xfce_menu_ref_count, 1) == 0)
+    {
+      /* Initialize the GObject type system */
+      g_type_init ();
+
+      /* Initialize the directory module */
+      _xfce_menu_directory_init ();
+    }
+}
+
+
+
+/**
+ * xfce_menu_shutdown
+ *
+ * Shuts down the libxfce4menu library.
+ **/
+void
+xfce_menu_shutdown (void)
+{
+  if (g_atomic_int_dec_and_test (&xfce_menu_ref_count))
+    {
+      /* Shutdown the directory module */
+      _xfce_menu_directory_shutdown ();
+    }
+}
+
+
+
+#define XFCE_MENU_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), XFCE_TYPE_MENU, XfceMenuPrivate))
+
+
+
+/* Menu file parser states */
+typedef enum 
+{
+  XFCE_MENU_PARSE_STATE_START,
+  XFCE_MENU_PARSE_STATE_ROOT,
+  XFCE_MENU_PARSE_STATE_MENU,
+
+} XfceMenuParseState;
+
+/* Menu file node types */
+typedef enum
+{
+  XFCE_MENU_PARSE_NODE_TYPE_NONE,
+  XFCE_MENU_PARSE_NODE_TYPE_NAME,
+  XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY,
+  XFCE_MENU_PARSE_NODE_TYPE_APP_DIR,
+  XFCE_MENU_PARSE_NODE_TYPE_LEGACY_DIR,
+
+} XfceMenuParseNodeType;
+
+/* Menu file parse context */
+typedef struct _XfceMenuParseContext
+{
+  /* Menu to be parsed */
+  XfceMenu *root_menu;
+
+  /* Parser state (position in XML tree */
+  XfceMenuParseState state;
+
+  /* Current menu */
+  XfceMenu *menu;
+
+  /* Current node type (for text handler) */
+  XfceMenuParseNodeType node_type;
+
+} XfceMenuParseContext;
+
+
+
+/* Property identifiers */
+enum
+{
+  PROP_0,
+  PROP_FILENAME,
+  PROP_NAME,
+  PROP_DIRECTORY,
+  PROP_APP_DIRS, /* TODO Implement methods for this! */
+};
+
+
+
+static void xfce_menu_class_init              (XfceMenuClass       *klass);
+static void xfce_menu_instance_init           (XfceMenu            *menu);
+static void xfce_menu_finalize                (GObject             *object);
+static void xfce_menu_get_property            (GObject             *object,
+                                               guint                prop_id,
+                                               GValue              *value,
+                                               GParamSpec          *pspec);
+static void xfce_menu_set_property            (GObject             *object,
+                                               guint                prop_id,
+                                               const GValue        *value,
+                                               GParamSpec          *pspec);
+
+static void xfce_menu_load                    (XfceMenu            *menu);
+static void xfce_menu_start_element           (GMarkupParseContext *context,
+                                               const gchar         *element_name,
+                                               const gchar        **attribute_names,
+                                               const gchar        **attribute_values,
+                                               gpointer             user_data,
+                                               GError             **error);
+static void xfce_menu_characters              (GMarkupParseContext *context,
+                                               const gchar         *text,
+                                               gsize                text_len,
+                                               gpointer             user_data,
+                                               GError             **error);
+
+static void xfce_menu_append_app_dir          (XfceMenu            *menu,
+                                               const gchar         *dir);
+static void xfce_menu_append_legacy_dir       (XfceMenu            *menu,
+                                               const gchar         *dir);
+static void xfce_menu_append_kde_legacy_dirs  (XfceMenu            *menu);
+static void xfce_menu_append_default_app_dirs (XfceMenu            *menu);
+
+
+
+struct _XfceMenuPrivate
+{
+  /* Menu filename */
+  gchar             *filename;
+
+  /* Menu name */
+  gchar             *name;
+
+  /* Directory */
+  XfceMenuDirectory *directory;
+
+  /* Submenus */
+  GSList            *submenus;
+
+  /* Parent menu */
+  XfceMenu          *parent;
+
+  /* Legacy dirs */
+  GSList            *legacy_dirs;
+
+  /* App dirs */
+  GSList            *app_dirs;
+};
+
+struct _XfceMenuClass
+{
+  GObjectClass __parent__;
+};
+
+struct _XfceMenu
+{
+  GObject          __parent__;
+
+  /* < private > */
+  XfceMenuPrivate *priv;
+};
+
+
+
+static GObjectClass *xfce_menu_parent_class = NULL;
+
+
+
+GType
+xfce_menu_get_type (void)
+{
+  static GType type = G_TYPE_INVALID;
+
+  if (G_UNLIKELY (type == G_TYPE_INVALID))
+    {
+      static const GTypeInfo info =
+      {
+        sizeof (XfceMenuClass),
+        NULL,
+        NULL,
+        (GClassInitFunc) xfce_menu_class_init,
+        NULL,
+        NULL,
+        sizeof (XfceMenu),
+        0,
+        (GInstanceInitFunc) xfce_menu_instance_init,
+        NULL,
+      };
+
+      type = g_type_register_static (G_TYPE_OBJECT, I_("XfceMenu"), &info, 0);
+    }
+
+  return type;
+}
+
+
+
+static void
+xfce_menu_class_init (XfceMenuClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof(XfceMenuPrivate));
+
+  /* Determine the parent type class */
+  xfce_menu_parent_class = g_type_class_peek_parent (klass);
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize = xfce_menu_finalize; 
+  gobject_class->get_property = xfce_menu_get_property;
+  gobject_class->set_property = xfce_menu_set_property;
+
+  /**
+   * XfceMenu:filename:
+   *
+   * The filename of an %XfceMenu object. Whenever this is redefined, the
+   * menu is reloaded.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILENAME,
+                                   g_param_spec_string ("filename",
+                                                        _("Filename"),
+                                                        _("XML menu filename"),
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  /**
+   * XfceMenu:name:
+   *
+   * The name of the menu.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILENAME,
+                                   g_param_spec_string ("name",
+                                                        _("Name"),
+                                                        _("Menu name"),
+                                                        NULL,
+                                                        EXO_PARAM_READWRITE));
+
+  /**
+   * XfceMenu:directory:
+   *
+   * The directory entry associated with this menu. 
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_FILENAME,
+                                   g_param_spec_object ("directory",
+                                                        _("Directory"),
+                                                        _("Directory entry associated with this menu"),
+                                                        XFCE_TYPE_MENU_DIRECTORY,
+                                                        EXO_PARAM_READWRITE));
+}
+
+
+
+static void
+xfce_menu_instance_init (XfceMenu *menu)
+{
+  menu->priv = XFCE_MENU_GET_PRIVATE (menu);
+  menu->priv->filename = NULL;
+  menu->priv->name = NULL;
+  menu->priv->directory = NULL;
+  menu->priv->submenus = NULL;
+  menu->priv->parent = NULL;
+  menu->priv->legacy_dirs = NULL;
+  menu->priv->app_dirs = NULL;
+}
+
+
+
+static void
+xfce_menu_finalize (GObject *object)
+{
+  XfceMenu *menu = XFCE_MENU (object);
+
+  /* Free filename */
+  g_free (menu->priv->filename);
+
+  /* Free name */
+  g_free (menu->priv->name);
+
+  /* TODO Free other variables */
+
+  /* Free legacy dirs (check if this is the best way to free the list) */
+  g_slist_free (menu->priv->legacy_dirs);
+
+  /* Free app dirs */
+  g_slist_free (menu->priv->app_dirs);
+
+  (*G_OBJECT_CLASS (xfce_menu_parent_class)->finalize) (object);
+}
+
+
+
+static void
+xfce_menu_get_property (GObject    *object,
+                        guint       prop_id,
+                        GValue     *value,
+                        GParamSpec *pspec)
+{
+  XfceMenu *menu = XFCE_MENU (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILENAME:
+      g_value_set_string (value, xfce_menu_get_filename (menu));
+      break;
+
+    case PROP_NAME:
+      g_value_set_string (value, xfce_menu_get_name (menu));
+      break;
+
+    case PROP_DIRECTORY:
+      g_value_set_object (value, xfce_menu_get_directory (menu));
+      break;
+    
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+static void
+xfce_menu_set_property (GObject      *object,
+                        guint         prop_id,
+                        const GValue *value,
+                        GParamSpec   *pspec)
+{
+  XfceMenu *menu = XFCE_MENU (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILENAME:
+      xfce_menu_set_filename (menu, g_value_get_string (value));
+      break;
+
+    case PROP_NAME:
+      xfce_menu_set_name (menu, g_value_get_string (value));
+      break;
+
+    case PROP_DIRECTORY:
+      xfce_menu_set_directory (menu, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+
+XfceMenu*
+xfce_menu_get_root (void)
+{
+  /* TODO how would this need to be free'd later? */
+  static XfceMenu *root_menu = NULL;
+
+  if (G_UNLIKELY (root_menu == NULL))
+    {
+      /* Generate the location string of the root menu file */
+      gchar *filename = g_build_path (G_DIR_SEPARATOR_S, "menus", "applications.menu", NULL);
+
+      /* Search for the root menu file */
+      gchar *location = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, filename);
+
+      /* Make sure we found the menu file */
+      if (G_LIKELY (location != NULL))
+        {
+          /* Load the root menu */
+          root_menu = g_object_new (XFCE_TYPE_MENU, "filename", location, NULL);
+
+          /* Add weak pointer on the menu */
+          g_object_add_weak_pointer (G_OBJECT (root_menu), (gpointer) &root_menu);
+
+          /* Free location string */
+          g_free (location);
+        }
+      
+      /* Free filename */
+      g_free (filename);
+    }
+  else
+    g_object_ref (G_OBJECT (root_menu));
+  
+  return root_menu;
+}
+
+
+
+const gchar*
+xfce_menu_get_filename (XfceMenu *menu)
+{
+  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
+  return menu->priv->filename;
+}
+
+
+
+void
+xfce_menu_set_filename (XfceMenu *menu, const gchar *filename)
+{
+  g_return_if_fail (XFCE_IS_MENU (menu));
+  g_return_if_fail (filename != NULL);
+
+  /* Free old filename */
+  g_free (menu->priv->filename);
+
+  /* Set the new filename */
+  menu->priv->filename = g_strdup (filename);
+
+  /* Reload the menu */
+  xfce_menu_load (menu);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (menu), "filename");
+}
+
+
+
+const gchar*
+xfce_menu_get_name (XfceMenu *menu)
+{
+  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
+  return menu->priv->name;
+}
+
+
+
+void
+xfce_menu_set_name (XfceMenu *menu, const gchar *name)
+{
+  g_return_if_fail (XFCE_IS_MENU (menu));
+  g_return_if_fail (name != NULL);
+
+  /* Free old name */
+  g_free (menu->priv->name);
+
+  /* Set the new filename */
+  menu->priv->name = g_strdup (name);
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (menu), "name");
+}
+
+
+
+XfceMenuDirectory*
+xfce_menu_get_directory (XfceMenu *menu)
+{
+  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
+  return menu->priv->directory;
+}
+
+
+
+void
+xfce_menu_set_directory (XfceMenu          *menu,
+                         XfceMenuDirectory *directory)
+{
+  g_return_if_fail (XFCE_IS_MENU (menu));
+  g_return_if_fail (XFCE_IS_MENU_DIRECTORY (directory));
+  
+  if (G_UNLIKELY (menu->priv->directory != NULL))
+    g_object_unref (menu->priv->directory);
+
+  /* Remove the floating reference and acquire a normal one */
+  g_object_ref_sink (G_OBJECT (directory));
+
+  menu->priv->directory = directory;
+
+  /* Notify listeners */
+  g_object_notify (G_OBJECT (menu), "directory");
+}
+
+
+
+void
+xfce_menu_set_directory_by_name (XfceMenu    *menu,
+                                 const gchar *name)
+{
+  XfceMenuDirectory *directory;
+
+  g_return_if_fail (XFCE_IS_MENU (menu));
+  g_return_if_fail (name != NULL);
+
+  if (G_LIKELY ((directory = xfce_menu_directory_lookup (name)) != NULL))
+    xfce_menu_set_directory (menu, directory);
+}
+
+
+
+GSList*
+xfce_menu_get_legacy_dirs (XfceMenu *menu)
+{
+  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
+  return menu->priv->legacy_dirs;
+}
+
+
+
+GSList*
+xfce_menu_get_app_dirs (XfceMenu *menu)
+{
+  g_return_val_if_fail (XFCE_IS_MENU (menu), NULL);
+  return menu->priv->app_dirs;
+}
+
+
+
+static void
+xfce_menu_load (XfceMenu *menu)
+{
+  GError *error = NULL;
+
+  /* Parser structure (connect handlers etc.) */
+  GMarkupParseContext *context;
+  GMarkupParser parser = {
+      xfce_menu_start_element,
+#if 0
+      xfce_menu_end_element,
+#endif
+      NULL,
+      xfce_menu_characters,
+      NULL,
+      NULL
+  };
+  XfceMenuParseContext menu_context;
+
+  /* File content information */
+  gchar *contents;
+  gsize contents_length;
+  GIOStatus status;
+  GIOChannel *stream;
+
+  g_return_if_fail (XFCE_IS_MENU (menu));
+  g_return_if_fail (menu->priv->filename != NULL);
+
+  /* Try to open the menu file */
+  stream = g_io_channel_new_file (menu->priv->filename, "r", &error);
+
+  if (G_UNLIKELY (stream == NULL))
+    {
+      g_critical ("Failed to open menu file %s: %s", menu->priv->filename, error->message);
+      g_error_free (error);
+      return;
+    }
+
+  /* Try to read the menu file */
+  status = g_io_channel_read_to_end (stream, &contents, &contents_length, &error);
+  
+  /* Free IO handle */
+  g_io_channel_unref (stream);
+
+  if (G_UNLIKELY (status != G_IO_STATUS_NORMAL))
+    {
+      g_critical ("Failed to read menu file %s: %s", menu->priv->filename, error->message);
+      g_error_free (error);
+      return;
+    }
+
+  /* Define menu parse context */
+  menu_context.root_menu = menu;
+  menu_context.state = XFCE_MENU_PARSE_STATE_START;
+  menu_context.state = XFCE_MENU_PARSE_NODE_TYPE_NONE;
+
+  /* Allocate parse context */
+  context = g_markup_parse_context_new (&parser, 0, &menu_context, NULL);
+
+  /* Try to parse the menu file */
+  if (!g_markup_parse_context_parse (context, contents, contents_length, &error) || !g_markup_parse_context_end_parse (context, &error))
+    {
+      g_critical ("Failed to parse menu file %s: %s", menu->priv->filename, error->message);
+      g_error_free (error);
+    }
+  
+  /* Free file contents */
+  g_free (contents);
+
+  /* Free parse context */
+  g_markup_parse_context_free (context);
+}
+
+
+
+static void
+xfce_menu_start_element (GMarkupParseContext *context,
+                         const gchar         *element_name,
+                         const gchar        **attribute_names,
+                         const gchar        **attribute_values,
+                         gpointer             user_data,
+                         GError             **error)
+{
+  XfceMenuParseContext *menu_context = (XfceMenuParseContext *)user_data;
+
+  switch (menu_context->state) 
+    {
+    case XFCE_MENU_PARSE_STATE_START:
+      if (g_utf8_collate (element_name, "Menu") == 0)
+        {
+          menu_context->state = XFCE_MENU_PARSE_STATE_ROOT;
+          menu_context->menu = menu_context->root_menu;
+        }
+      break;
+    case XFCE_MENU_PARSE_STATE_ROOT:
+      if (g_utf8_collate (element_name, "Name") == 0)
+        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_NAME;
+      else if (g_utf8_collate (element_name, "Directory") == 0)
+        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY;
+      else if (g_utf8_collate (element_name, "DefaultAppDirs") == 0)
+        xfce_menu_append_default_app_dirs (menu_context->menu);
+      else if (g_utf8_collate (element_name, "AppDir") == 0)
+        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_APP_DIR;
+      else if (g_utf8_collate (element_name, "KDELegacyDirs") == 0)
+        xfce_menu_append_kde_legacy_dirs (menu_context->menu);
+      else if (g_utf8_collate (element_name, "LegacyDir") == 0)
+        menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_LEGACY_DIR;
+      else if (g_utf8_collate (element_name, "Menu") == 0)
+        {
+          menu_context->state = XFCE_MENU_PARSE_STATE_MENU;
+        }
+
+      break;
+    }
+}
+
+
+
+static void
+xfce_menu_characters (GMarkupParseContext *context,
+                      const gchar         *text,
+                      gsize                text_len,
+                      gpointer             user_data,
+                      GError             **error)
+{
+  XfceMenuParseContext *menu_context = (XfceMenuParseContext *)user_data;
+
+  /* Generate NULL-terminated string */
+  gchar *content = g_strndup (text, text_len);
+
+  switch (menu_context->node_type)
+    {
+    case XFCE_MENU_PARSE_NODE_TYPE_NAME:
+      xfce_menu_set_name (menu_context->menu, content);
+      break;
+
+    case XFCE_MENU_PARSE_NODE_TYPE_DIRECTORY:
+      xfce_menu_set_directory_by_name (menu_context->menu, content);
+      break;
+
+    case XFCE_MENU_PARSE_NODE_TYPE_APP_DIR:
+      xfce_menu_append_app_dir (menu_context->menu, content);
+      break;
+
+    case XFCE_MENU_PARSE_NODE_TYPE_LEGACY_DIR:
+      xfce_menu_append_legacy_dir (menu_context->menu, content);
+      break;
+    }
+
+  /* Free string */
+  g_free (content);
+
+  /* Invalidate node type (TODO remove this later, when end_element is
+   * available). */
+  menu_context->node_type = XFCE_MENU_PARSE_NODE_TYPE_NONE;
+}
+
+
+
+static void
+xfce_menu_append_legacy_dir (XfceMenu    *menu,
+                             const gchar *dir)
+{
+  /* Absolute path of the directory (free'd by the menu instance later) */
+  gchar *path;
+
+  g_return_if_fail (XFCE_IS_MENU (menu));
+  g_return_if_fail (menu->priv->filename != NULL);
+  g_return_if_fail (dir != NULL);
+
+  if (!g_path_is_absolute (dir))
+    {
+      /* Determine the absolute path (directory) of the menu file */
+      gchar *dirname = g_path_get_dirname (menu->priv->filename);
+
+      /* Construct absolute path */
+      path = g_build_path (G_DIR_SEPARATOR_S, dirname, dir, NULL);
+
+      /* Free absolute menu file directory path */
+      g_free (dirname);
+    }
+  else
+    path = g_strdup (dir);
+
+  /* Check if there already are legacy dirs */
+  if (G_LIKELY (menu->priv->legacy_dirs != NULL))
+    {
+      /* Remove all previous occurences of the directory from the list */
+      /* TODO: This probably is rather dirty and should be replaced with a more
+       * clean algorithm. */
+      GSList *iter = menu->priv->legacy_dirs;
+      while (iter != NULL) 
+        {
+          gchar *data = (gchar *)iter->data;
+          if (g_utf8_collate (data, dir) == 0)
+            {
+              GSList *tmp = g_slist_next (iter);
+              menu->priv->app_dirs = g_slist_remove_link (menu->priv->legacy_dirs, iter);
+              iter = tmp;
+            }
+          else
+            iter = iter->next;
+        }
+      
+      /* Append directory */
+      menu->priv->legacy_dirs = g_slist_append (menu->priv->legacy_dirs, path);
+    }
+  else
+    {
+      /* Create new GSList and append the absolute path of the directory */
+      menu->priv->legacy_dirs = g_slist_append (menu->priv->legacy_dirs, path);
+    }
+}
+
+
+
+static void
+xfce_menu_append_kde_legacy_dirs (XfceMenu *menu)
+{
+  static gchar **kde_legacy_dirs = NULL;
+
+  g_return_if_fail (XFCE_IS_MENU (menu));
+
+  if (G_UNLIKELY (kde_legacy_dirs == NULL))
+    {
+      gchar       *std_out;
+      gchar       *std_err;
+      gint         status;
+      GError      *error = NULL;
+      const gchar *kde_dir = g_getenv ("KDEDIR");
+      const gchar *path = g_getenv ("PATH");
+      gchar       *kde_path;
+
+      /* Determine value of KDEDIR */
+      if (G_UNLIKELY (kde_dir != NULL))
+        {
+          /* Build KDEDIR/bin path */
+          gchar *kde_bin_dir = g_build_path (G_DIR_SEPARATOR_S, kde_dir, "bin", NULL);
+          
+          /* Expand PATH to include KDEDIR/bin - if necessary */
+          gchar *occurence = g_strrstr (path, kde_bin_dir);
+          if (G_UNLIKELY (occurence == NULL))
+            {
+              /* PATH = $PATH:$KDEDIR/bin */
+              kde_path = g_strjoin (G_SEARCHPATH_SEPARATOR_S, path, kde_bin_dir);
+    
+              /* Set new $PATH value */
+              g_setenv ("PATH", kde_path, TRUE);
+
+              /* Free expanded PATH value */
+              g_free (kde_path);
+            }
+          else
+            g_free (occurence);
+              
+          /* Free KDEDIR/bin */
+          g_free (kde_bin_dir);
+        }
+
+      /* Parse output of kde-config */
+      if (g_spawn_command_line_sync ("kde-config --path apps", &std_out, &std_err, &status, &error))
+        kde_legacy_dirs = g_strsplit (g_strchomp (std_out), G_SEARCHPATH_SEPARATOR_S, 0);
+      else
+        g_error_free (error);
+
+      /* Free output buffers */
+      g_free (std_err);
+      g_free (std_out);
+    }
+
+  if (kde_legacy_dirs != NULL) /* This is neither likely nor unlikely */
+    {
+      int i;
+
+      /* Add all KDE legacy dirs to the list */
+      for (i = 0; i < g_strv_length (kde_legacy_dirs); i++) 
+        xfce_menu_append_legacy_dir (menu, kde_legacy_dirs[i]);
+    }
+}
+
+
+
+static void
+xfce_menu_append_app_dir (XfceMenu    *menu,
+                          const gchar *dir)
+{
+  /* Absolute path of the directory (free'd by the menu instance later) */
+  gchar *path;
+
+  g_return_if_fail (XFCE_IS_MENU (menu));
+  g_return_if_fail (menu->priv->filename != NULL);
+  g_return_if_fail (dir != NULL);
+
+  if (!g_path_is_absolute (dir))
+    {
+      /* Determine the absolute path (directory) of the menu file */
+      gchar *dirname = g_path_get_dirname (menu->priv->filename);
+
+      /* Construct absolute path */
+      path = g_build_path (G_DIR_SEPARATOR_S, dirname, dir, NULL);
+
+      /* Free absolute menu file directory path */
+      g_free (dirname);
+    }
+  else
+    path = g_strdup (dir);
+
+  /* Check if there already are app dirs */
+  if (G_LIKELY (menu->priv->app_dirs != NULL))
+    {
+      /* Remove all previous occurences of the directory from the list */
+      /* TODO: This probably is rather dirty and should be replaced with a more
+       * clean algorithm. */
+      GSList *iter = menu->priv->app_dirs;
+      while (iter != NULL) 
+        {
+          gchar *data = (gchar *)iter->data;
+          if (g_utf8_collate (data, dir) == 0)
+            {
+              GSList *tmp = g_slist_next (iter);
+              menu->priv->app_dirs = g_slist_remove_link (menu->priv->app_dirs, iter);
+              iter = tmp;
+            }
+          else
+            iter = iter->next;
+        }
+      
+      /* Append directory */
+      menu->priv->app_dirs = g_slist_append (menu->priv->app_dirs, path);
+    }
+  else
+    {
+      /* Create new GSList and append the absolute path of the directory */
+      menu->priv->app_dirs = g_slist_append (menu->priv->app_dirs, path);
+    }
+}
+
+
+
+static void 
+xfce_menu_append_default_app_dirs (XfceMenu *menu)
+{
+  int    i;
+  gchar *path;
+
+  const gchar * const *dirs;
+
+  g_return_if_fail (XFCE_IS_MENU (menu));
+
+  /* Append system-wide data dirs */
+  dirs = g_get_system_data_dirs ();
+  for (i = 0; dirs[i] != NULL; i++)
+    {
+      path = g_build_path (G_DIR_SEPARATOR_S, dirs[i], "applications", NULL);
+      xfce_menu_append_app_dir (menu, path);
+      g_free (path);
+    }
+
+  /* Append user data dir */
+  path = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), "applications", NULL);
+  xfce_menu_append_app_dir (menu, path);
+  g_free (path);
+}

Added: xfce-menu/trunk/libxfce4menu/xfce-menu.h
===================================================================
--- xfce-menu/trunk/libxfce4menu/xfce-menu.h	                        (rev 0)
+++ xfce-menu/trunk/libxfce4menu/xfce-menu.h	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,67 @@
+/* $Id$ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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.
+ */
+
+#if !defined(LIBXFCE4MENU_INSIDE_LIBXFCE4MENU_H) && !defined(LIBXFCE4MENU_COMPILATION)
+#error "Only <libxfce4menu/libxfce4menu.h> can be included directly. This file may disappear or change contents."
+#endif
+
+#ifndef __XFCE_MENU_H__
+#define __XFCE_MENU_H__
+
+#include <exo/exo.h>
+
+G_BEGIN_DECLS;
+
+typedef struct _XfceMenuPrivate XfceMenuPrivate;
+typedef struct _XfceMenuClass   XfceMenuClass;
+typedef struct _XfceMenu        XfceMenu;
+
+#define XFCE_TYPE_MENU            (xfce_menu_get_type ())
+#define XFCE_MENU(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), XFCE_TYPE_MENU, XfceMenu))
+#define XFCE_MENU_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), XFCE_TYPE_MENU, XfceMenuClass))
+#define XFCE_IS_MENU(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XFCE_TYPE_MENU))
+#define XFCE_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XFCE_TYPE_MENU))
+#define XFCE_MENU_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), XFCE_TYPE_MENU, XfceMenuClass))
+
+void               xfce_menu_init                  (void);
+void               xfce_menu_shutdown              (void);
+
+GType              xfce_menu_get_type              (void) G_GNUC_CONST;
+
+XfceMenu          *xfce_menu_get_root              (void);
+
+const gchar       *xfce_menu_get_filename          (XfceMenu          *menu);
+void               xfce_menu_set_filename          (XfceMenu          *menu,
+                                                    const gchar       *filename);
+const gchar       *xfce_menu_get_name              (XfceMenu          *menu);
+void               xfce_menu_set_name              (XfceMenu          *menu,
+                                                    const gchar       *name);
+XfceMenuDirectory *xfce_menu_get_directory         (XfceMenu          *menu);
+void               xfce_menu_set_directory         (XfceMenu          *menu,
+                                                    XfceMenuDirectory *directory);
+void               xfce_menu_set_directory_by_name (XfceMenu          *menu,
+                                                    const gchar       *name);
+GSList            *xfce_menu_get_legacy_dirs       (XfceMenu          *menu);
+GSList            *xfce_menu_get_app_dirs          (XfceMenu          *menu);
+
+G_END_DECLS;
+
+#endif /* !__XFCE_MENU_H__ */

Added: xfce-menu/trunk/tests/CMakeLists.txt
===================================================================
--- xfce-menu/trunk/tests/CMakeLists.txt	                        (rev 0)
+++ xfce-menu/trunk/tests/CMakeLists.txt	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,11 @@
+# Include paths
+INCLUDE_DIRECTORIES(
+	..
+)
+
+# Load root menu test
+ADD_EXECUTABLE(load_root_menu_test load-root-menu-test.c)
+ADD_TEST(load_root_menu_test
+	${EXECUTABLE_OUTPUT_PATH}/load_root_menu_test
+)
+TARGET_LINK_LIBRARIES(load_root_menu_test xfce4menu)

Added: xfce-menu/trunk/tests/load-root-menu-test.c
===================================================================
--- xfce-menu/trunk/tests/load-root-menu-test.c	                        (rev 0)
+++ xfce-menu/trunk/tests/load-root-menu-test.c	2006-07-16 22:01:01 UTC (rev 1770)
@@ -0,0 +1,63 @@
+/* $Id$ */
+/* vi:set expandtab sw=2 sts=2: */
+/*-
+ * Copyright (c) 2006 Jannis Pohlmann <jannis at xfce.org>
+ *
+ * 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 <locale.h>
+#include <gtk/gtk.h>
+
+#include <libxfce4menu/libxfce4menu.h>
+
+int 
+main(int    argc, 
+     char **argv)
+{
+  setlocale (LC_MESSAGES, "de");
+
+  xfce_menu_init ();
+
+  XfceMenu *menu = xfce_menu_get_root ();
+
+  g_debug ("Root menu name: %s", xfce_menu_get_name (menu));
+  g_debug ("Root menu filename: %s", xfce_menu_get_filename (menu));
+  g_debug ("Root menu legacy dirs:");
+
+  GSList *dir;
+  for (dir = xfce_menu_get_legacy_dirs (menu); dir != NULL; dir = g_slist_next (dir))
+    g_debug ("\t%s", dir->data);
+
+  g_debug ("Root menu app dirs:");
+  
+  for (dir = xfce_menu_get_app_dirs (menu); dir != NULL; dir = g_slist_next (dir))
+    g_debug ("\t%s", dir->data);
+
+  g_debug ("------------------------------------------------------------------------");
+  g_debug ("Root menu directory name: %s", xfce_menu_directory_get_name (xfce_menu_get_directory (menu)));
+  g_debug ("Root menu directory filename: %s", xfce_menu_directory_get_filename (xfce_menu_get_directory (menu)));
+  g_debug ("Root menu directory comment: %s", xfce_menu_directory_get_comment (xfce_menu_get_directory (menu)));
+  g_debug ("Root menu directory icon: %s", xfce_menu_directory_get_icon (xfce_menu_get_directory (menu)));
+
+  xfce_menu_shutdown ();
+
+  return 0;
+}




More information about the Goodies-commits mailing list