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