aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-glib/menuitem.c
diff options
context:
space:
mode:
authorTed Gould <ted@canonical.com>2009-05-12 11:23:10 -0500
committerTed Gould <ted@canonical.com>2009-05-12 11:23:10 -0500
commit3d0e0276fd7856831dcc845a24a252ad304b3bad (patch)
tree5ec06325d34b0fdab498045aa911fb534eb2ca48 /libdbusmenu-glib/menuitem.c
parentc5024e812fb046f6bccceafaf46ebbd966f465cf (diff)
parent53b4a13ca4541bcdf85ca3ee28cb6ffc81e6f5b0 (diff)
downloadlibdbusmenu-3d0e0276fd7856831dcc845a24a252ad304b3bad.tar.gz
libdbusmenu-3d0e0276fd7856831dcc845a24a252ad304b3bad.tar.bz2
libdbusmenu-3d0e0276fd7856831dcc845a24a252ad304b3bad.zip
Merging in my working branch that brings in basic object functionality passing across DBus.
Diffstat (limited to 'libdbusmenu-glib/menuitem.c')
-rw-r--r--libdbusmenu-glib/menuitem.c424
1 files changed, 424 insertions, 0 deletions
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
new file mode 100644
index 0000000..0894d2c
--- /dev/null
+++ b/libdbusmenu-glib/menuitem.c
@@ -0,0 +1,424 @@
+/*
+A library to communicate a menu object set accross DBus and
+track updates and maintain consistency.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "menuitem.h"
+
+/* Private */
+/**
+ DbusmenuMenuitemPrivate:
+ @id: The ID of this menu item
+ @children: A list of #DbusmenuMenuitem objects that are
+ children to this one.
+
+ These are the little secrets that we don't want getting
+ out of data that we have. They can still be gotten using
+ accessor functions, but are protected appropriately.
+*/
+typedef struct _DbusmenuMenuitemPrivate DbusmenuMenuitemPrivate;
+struct _DbusmenuMenuitemPrivate
+{
+ guint id;
+ GList * children;
+};
+
+/* Properties */
+enum {
+ PROP_0,
+ PROP_ID,
+};
+
+#define DBUSMENU_MENUITEM_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_MENUITEM, DbusmenuMenuitemPrivate))
+
+/* Prototypes */
+static void dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass);
+static void dbusmenu_menuitem_init (DbusmenuMenuitem *self);
+static void dbusmenu_menuitem_dispose (GObject *object);
+static void dbusmenu_menuitem_finalize (GObject *object);
+static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec);
+static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
+
+/* GObject stuff */
+G_DEFINE_TYPE (DbusmenuMenuitem, dbusmenu_menuitem, G_TYPE_OBJECT);
+
+static void
+dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (DbusmenuMenuitemPrivate));
+
+ object_class->dispose = dbusmenu_menuitem_dispose;
+ object_class->finalize = dbusmenu_menuitem_finalize;
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+
+ g_object_class_install_property (object_class, PROP_ID,
+ g_param_spec_uint("id", "ID for the menu item",
+ "This is a unique indentifier for the menu item.",
+ 0, 30000, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ return;
+}
+
+static guint menuitem_next_id = 1;
+
+static void
+dbusmenu_menuitem_init (DbusmenuMenuitem *self)
+{
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(self);
+
+ priv->id = 0;
+ priv->children = NULL;
+
+ return;
+}
+
+static void
+dbusmenu_menuitem_dispose (GObject *object)
+{
+
+ G_OBJECT_CLASS (dbusmenu_menuitem_parent_class)->dispose (object);
+ return;
+}
+
+static void
+dbusmenu_menuitem_finalize (GObject *object)
+{
+
+ G_OBJECT_CLASS (dbusmenu_menuitem_parent_class)->finalize (object);
+ return;
+}
+
+static void
+set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
+{
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(obj);
+
+ switch (id) {
+ case PROP_ID:
+ priv->id = g_value_get_uint(value);
+ if (priv->id > menuitem_next_id) {
+ menuitem_next_id = priv->id;
+ }
+ break;
+ }
+
+ return;
+}
+
+static void
+get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
+{
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(obj);
+
+ switch (id) {
+ case PROP_ID:
+ if (priv->id == 0) {
+ priv->id = menuitem_next_id++;
+ }
+ g_value_set_uint(value, priv->id);
+ break;
+ }
+
+ return;
+}
+
+
+/* Public interface */
+
+/**
+ dbusmenu_menuitem_new:
+
+ Create a new #DbusmenuMenuitem with all default values.
+
+ Return value: A newly allocated #DbusmenuMenuitem.
+*/
+DbusmenuMenuitem *
+dbusmenu_menuitem_new (void)
+{
+ return g_object_new(DBUSMENU_TYPE_MENUITEM, NULL);
+}
+
+/**
+ dbusmenu_menuitem_new_with_id:
+ @id: ID to use for this menuitem
+
+ This creates a blank #DbusmenuMenuitem with a specific ID.
+
+ Return value: A newly allocated #DbusmenuMenuitem.
+*/
+DbusmenuMenuitem *
+dbusmenu_menuitem_new_with_id (guint id)
+{
+ DbusmenuMenuitem * mi = g_object_new(DBUSMENU_TYPE_MENUITEM, "id", id, NULL);
+ g_debug("New Menuitem id %d goal id %d", dbusmenu_menuitem_get_id(mi), id);
+ return mi;
+}
+
+/**
+ dbusmenu_menuitem_get_id:
+ @mi: The #DbusmenuMenuitem to query.
+
+ Gets the unique ID for @mi.
+
+ Return value: The ID of the @mi.
+*/
+guint
+dbusmenu_menuitem_get_id (DbusmenuMenuitem * mi)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), 0);
+
+ GValue retval = {0};
+ g_value_init(&retval, G_TYPE_UINT);
+ g_object_get_property(G_OBJECT(mi), "id", &retval);
+ return g_value_get_uint(&retval);
+}
+
+/**
+ dbusmenu_menuitem_get_children:
+ @mi: The #DbusmenuMenuitem to query.
+
+ Returns simply the list of children that this menu item
+ has. The list is valid until another child related function
+ is called, where it might be changed.
+
+ Return value: A #GList of pointers to #DbusmenuMenuitem objects.
+*/
+GList *
+dbusmenu_menuitem_get_children (DbusmenuMenuitem * mi)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
+
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ return priv->children;
+}
+
+/**
+ dbusmenu_menuitem_take_children:
+ @mi: The #DbusmenMenuitem to take the children from.
+
+ While the name sounds devious that's exactly what this function
+ does. It takes the list of children from the @mi and clears the
+ internal list. The calling function is no in charge of the ref's
+ on the children it has taken. A lot of responsibility involved
+ in taking children.
+
+ Return value: A #GList of pointers to #DbusmenuMenuitem objects.
+*/
+GList *
+dbusmenu_menuitem_take_children (DbusmenuMenuitem * mi)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
+
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ GList * children = priv->children;
+ priv->children = NULL;
+ return children;
+}
+
+/**
+ dbusmenu_menuitem_get_position:
+ @mi: The #DbusmenuMenuitem to find the position of
+ @parent: The #DbusmenuMenuitem who's children contain @mi
+
+ This function returns the position of the menu item @mi
+ in the children of @parent. It will return zero if the
+ menu item can't be found.
+
+ Return value: The position of @mi in the children of @parent.
+*/
+guint
+dbusmenu_menuitem_get_position (DbusmenuMenuitem * mi, DbusmenuMenuitem * parent)
+{
+ /* TODO: I'm not too happy returning zeros here. But that's all I've got */
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), 0);
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(parent), 0);
+
+ GList * childs = dbusmenu_menuitem_get_children(parent);
+ if (childs == NULL) return 0;
+ guint count = 0;
+ for ( ; childs != NULL; childs = childs->next, count++) {
+ if (childs->data == mi) break;
+ }
+
+ if (childs == NULL) return 0;
+
+ return count;
+}
+
+/**
+ dbusmenu_menuitem_child_append:
+ @mi: The #DbusmenuMenuitem which will become a new parent
+ @child: The #DbusmenMenuitem that will be a child
+
+ This function adds @child to the list of children on @mi at
+ the end of that list.
+
+ Return value: Whether the child has been added successfully.
+*/
+gboolean
+dbusmenu_menuitem_child_append (DbusmenuMenuitem * mi, DbusmenuMenuitem * child)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(child), FALSE);
+
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ priv->children = g_list_append(priv->children, child);
+ return TRUE;
+}
+
+/**
+ dbusmenu_menuitem_child_delete:
+ @mi: The #DbusmenuMenuitem which has @child as a child
+ @child: The child #DbusmenuMenuitem that you want to no longer
+ be a child of @mi.
+
+ This function removes @child from the children list of @mi. It does
+ not call #g_object_unref on @child.
+
+ Return value: If we were able to delete @child.
+*/
+gboolean
+dbusmenu_menuitem_child_delete (DbusmenuMenuitem * mi, DbusmenuMenuitem * child)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(child), FALSE);
+
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ priv->children = g_list_remove(priv->children, child);
+ return TRUE;
+}
+
+/**
+ dbusmenu_menuitem_child_add_position:
+ @mi: The #DbusmenuMenuitem that we're adding the child @child to.
+ @child: The #DbusmenuMenuitem to make a child of @mi.
+ @position: Where in @mi object's list of chidren @child should be placed.
+
+ Puts @child in the list of children for @mi at the location
+ specified in @position. If there is not enough entires available
+ then @child will be placed at the end of the list.
+
+ Return value: Whether @child was added successfully.
+*/
+gboolean
+dbusmenu_menuitem_child_add_position (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint position)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(child), FALSE);
+
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ priv->children = g_list_insert(priv->children, child, position);
+ return TRUE;
+}
+
+/**
+ dbusmenu_menuitem_child_find:
+ @mi: The #DbusmenuMenuitem who's children to look on
+ @id: The ID of the child that we're looking for.
+
+ Search the children of @mi to find one with the ID of @id.
+ If it doesn't exist then we return #NULL.
+
+ Return value: The menu item with the ID @id or #NULL if it
+ can't be found.
+*/
+DbusmenuMenuitem *
+dbusmenu_menuitem_child_find (DbusmenuMenuitem * mi, guint id)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
+
+ GList * childs = dbusmenu_menuitem_get_children(mi);
+ if (childs == NULL) return NULL;
+
+ for ( ; childs == NULL; childs = g_list_next(childs)) {
+ DbusmenuMenuitem * lmi = DBUSMENU_MENUITEM(childs->data);
+ if (id == dbusmenu_menuitem_get_id(lmi)) {
+ return lmi;
+ }
+ }
+
+ return NULL;
+}
+
+gboolean
+dbusmenu_menuitem_property_set (DbusmenuMenuitem * mi, const gchar * property, const gchar * value)
+{
+
+ return FALSE;
+}
+
+const gchar *
+dbusmenu_menuitem_property_get (DbusmenuMenuitem * mi, const gchar * property)
+{
+
+ return NULL;
+}
+
+gboolean
+dbusmenu_menuitem_property_exist (DbusmenuMenuitem * mi, const gchar * property)
+{
+
+ return FALSE;
+}
+
+/**
+ dbusmenu_menuitem_buildxml:
+ @mi: #DbusmenuMenuitem to represent in XML
+ @array: A list of string that will be turned into an XML file
+
+ This function will add strings to the array @array. It will put
+ at least one entry if this menu item has no children. If it has
+ children it will put two for this entry, one representing the
+ start tag and one that is a closing tag. It will allow it's
+ children to place their own tags in the array in between those two.
+*/
+void
+dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array)
+{
+ g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
+
+ GList * children = dbusmenu_menuitem_get_children(mi);
+ if (children == NULL) {
+ g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\" />", dbusmenu_menuitem_get_id(mi)));
+ } else {
+ g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\">", dbusmenu_menuitem_get_id(mi)));
+ for ( ; children != NULL; children = children->next) {
+ dbusmenu_menuitem_buildxml(DBUSMENU_MENUITEM(children->data), array);
+ }
+ g_ptr_array_add(array, g_strdup("</menu>"));
+ }
+
+ return;
+}
+