Commit 21672a2d authored by Colin Walters's avatar Colin Walters Committed by Vincent Untz

Convert to GObject, drop static Python bindings

GMenuTree is now a GObject.  Drop the static Python bindings, since
introspection gives us coverage of most of the API now.

https://bugzilla.gnome.org/show_bug.cgi?id=647968
parent 0a7e4736
SUBDIRS = libmenu desktop-directories layout util po
if HAVE_PYTHON
SUBDIRS += python simple-editor
endif
SUBDIRS += simple-editor
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection --enable-python
DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
EXTRA_DIST = \
HACKING \
......
......@@ -72,39 +72,8 @@ else
fi
AC_SUBST(DEBUG_CFLAGS)
AC_ARG_ENABLE(python,
[AC_HELP_STRING([--enable-python],
[build python bindings @<:@default=auto@:>@])],
[enable_deprecations=$enableval],
[enable_deprecations=auto])
# Detect if we can build Python bindings (need python and python headers)
if test "x$enable_python" = "xno" ; then
have_python=no
else
AC_MSG_NOTICE([Checking to see if we can build Python bindings])
have_python=no
AM_PATH_PYTHON(2.3)
if test "x$PYTHON" = "x" ; then
AC_MSG_WARN([Python not found])
else
AM_CHECK_PYTHON_HEADERS(have_python_headers=yes, have_python_headers=no)
if test "x$have_python_headers" = "xyes" ; then
have_python=yes
fi
fi
if test "x$have_python" = "xno" ; then
if test "x$enable_python" = "xyes" ; then
AC_MSG_ERROR([Building python explicitly requested, but can't build python bindings])
else
AC_MSG_WARN([Couldn't find the Python headers, not building Python bindings])
fi
fi
fi
AM_CONDITIONAL(HAVE_PYTHON, test x$have_python = xyes)
AM_PATH_PYTHON(2.3)
AM_CONDITIONAL(HAVE_PYTHON, test x$PYTHON != xyes)
# Because of the way Python implements polymorphism, we get the following warning:
# "warning: dereferencing type-punned pointer will break strict-aliasing rules"
......@@ -136,7 +105,6 @@ libmenu/libgnome-menu-uninstalled.pc
layout/Makefile
desktop-directories/Makefile
util/Makefile
python/Makefile
simple-editor/Makefile
simple-editor/GMenuSimpleEditor/Makefile
po/Makefile.in
......@@ -165,7 +133,6 @@ echo "
Use *_DISABLE_DEPRECATED: ${enable_deprecation_flags}
Turn on debugging: ${enable_debug}
Build python bindings: ${have_python}
Build introspection support: ${found_introspection}
"
......@@ -29,9 +29,24 @@
#include "menu-util.h"
#include "canonicalize.h"
struct GMenuTree
enum {
PROP_0,
PROP_NAME,
PROP_FLAGS
};
/* Signals */
enum
{
LAST_SIGNAL
};
static guint gmenu_tree_signals [LAST_SIGNAL] = { 0 };
struct _GMenuTree
{
guint refcount;
GObject parent_instance;
char *basename;
char *canonical_path;
......@@ -43,14 +58,11 @@ struct GMenuTree
MenuLayoutNode *layout;
GMenuTreeDirectory *root;
GSList *monitors;
gpointer user_data;
GDestroyNotify dnotify;
guint canonical : 1;
};
G_DEFINE_TYPE (GMenuTree, gmenu_tree, G_TYPE_OBJECT)
typedef struct
{
GMenuTreeChangedFunc callback;
......@@ -419,45 +431,61 @@ gmenu_tree_force_recanonicalize (GMenuTree *tree)
* Returns: (transfer full): A new #GMenuTree instance
*/
GMenuTree *
gmenu_tree_new (const char *menu_file,
gmenu_tree_new (const char *name,
GMenuTreeFlags flags)
{
GMenuTree *tree;
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (menu_file != NULL, NULL);
tree = g_new0 (GMenuTree, 1);
tree->flags = flags;
tree->refcount = 1;
tree->basename = g_strdup (menu_file);
return tree;
return g_object_new (GMENU_TYPE_TREE, "name", name, "flags", flags, NULL);
}
GMenuTree *
gmenu_tree_ref (GMenuTree *tree)
static void
gmenu_tree_set_property(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
g_return_val_if_fail (tree != NULL, NULL);
g_return_val_if_fail (tree->refcount > 0, NULL);
GMenuTree *self = GMENU_TREE (object);
tree->refcount++;
switch (prop_id)
{
case PROP_NAME:
self->basename = g_value_dup_string (value);
break;
return tree;
case PROP_FLAGS:
self->flags = g_value_get_flags (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
void
gmenu_tree_unref (GMenuTree *tree)
static void
gmenu_tree_get_property(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
g_return_if_fail (tree != NULL);
g_return_if_fail (tree->refcount >= 1);
GMenuTree *self = GMENU_TREE (object);
if (--tree->refcount > 0)
return;
switch (prop_id)
{
case PROP_NAME:
g_value_set_string (value, self->basename);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
if (tree->dnotify)
tree->dnotify (tree->user_data);
tree->user_data = NULL;
tree->dnotify = NULL;
static void
gmenu_tree_finalize (GObject *object)
{
GMenuTree *tree = GMENU_TREE (object);
gmenu_tree_force_recanonicalize (tree);
......@@ -469,35 +497,49 @@ gmenu_tree_unref (GMenuTree *tree)
g_free (tree->canonical_path);
tree->canonical_path = NULL;
g_slist_foreach (tree->monitors, (GFunc) g_free, NULL);
g_slist_free (tree->monitors);
tree->monitors = NULL;
g_free (tree);
G_OBJECT_CLASS (gmenu_tree_parent_class)->finalize (object);
}
void
gmenu_tree_set_user_data (GMenuTree *tree,
gpointer user_data,
GDestroyNotify dnotify)
static void
gmenu_tree_init (GMenuTree *self)
{
g_return_if_fail (tree != NULL);
if (tree->dnotify != NULL)
tree->dnotify (tree->user_data);
tree->dnotify = dnotify;
tree->user_data = user_data;
}
gpointer
gmenu_tree_get_user_data (GMenuTree *tree)
static void
gmenu_tree_class_init (GMenuTreeClass *klass)
{
g_return_val_if_fail (tree != NULL, NULL);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gmenu_tree_get_property;
gobject_class->set_property = gmenu_tree_set_property;
gobject_class->finalize = gmenu_tree_finalize;
/**
* GMenuTree:name
*
* The name of the menu file; must be a relative path. See
* the Desktop Menu specification.
*/
g_object_class_install_property (gobject_class,
PROP_NAME,
g_param_spec_string ("name", "", "",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
/**
* GMenuTree:flags
*
* Flags controlling the content of the menu.
*/
g_object_class_install_property (gobject_class,
PROP_FLAGS,
g_param_spec_flags ("flags", "", "",
GMENU_TYPE_TREE_FLAGS,
GMENU_TREE_FLAGS_NONE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
return tree->user_data;
}
const char *
gmenu_tree_get_menu_file (GMenuTree *tree)
{
......@@ -825,7 +867,7 @@ gmenu_tree_directory_get_tree (GMenuTreeDirectory *directory)
root = (GMenuTreeDirectoryRoot *) directory;
if (root->tree)
gmenu_tree_ref (root->tree);
g_object_ref (root->tree);
return root->tree;
}
......
......@@ -28,7 +28,23 @@
G_BEGIN_DECLS
typedef struct GMenuTree GMenuTree;
#define GMENU_TYPE_TREE (gmenu_tree_get_type ())
#define GMENU_TREE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GMENU_TYPE_TREE, GMenuTree))
#define GMENU_TREE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GMENU_TYPE_TREE, GMenuTreeClass))
#define GMENU_IS_TREE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GMENU_TYPE_TREE))
#define GMENU_IS_TREE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GMENU_TYPE_TREE))
#define GMENU_TREE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DESKTOP_APP_INFO, GMenuTreeClass))
typedef struct _GMenuTree GMenuTree;
typedef struct _GMenuTreeClass GMenuTreeClass;
struct _GMenuTreeClass
{
GObjectClass parent_class;
};
GType gmenu_tree_get_type (void) G_GNUC_CONST;
typedef struct GMenuTreeItem GMenuTreeItem;
typedef struct GMenuTreeDirectory GMenuTreeDirectory;
typedef struct GMenuTreeEntry GMenuTreeEntry;
......@@ -71,14 +87,6 @@ GType gmenu_tree_flags_get_type (void);
GMenuTree *gmenu_tree_new (const char *menu_file,
GMenuTreeFlags flags);
GMenuTree *gmenu_tree_ref (GMenuTree *tree);
void gmenu_tree_unref (GMenuTree *tree);
void gmenu_tree_set_user_data (GMenuTree *tree,
gpointer user_data,
GDestroyNotify dnotify);
gpointer gmenu_tree_get_user_data (GMenuTree *tree);
const char *gmenu_tree_get_menu_file (GMenuTree *tree);
GMenuTreeDirectory *gmenu_tree_get_root_directory (GMenuTree *tree);
GMenuTreeDirectory *gmenu_tree_get_directory_from_path (GMenuTree *tree,
......
......@@ -203,18 +203,9 @@ static MenuMonitor *
register_monitor (const char *path,
gboolean is_directory)
{
static gboolean initted = FALSE;
MenuMonitor *retval;
GFile *file;
if (!initted)
{
/* This is the only place where we're using GObject and the app can't
* know we're using it, so we need to init the type system ourselves. */
g_type_init ();
initted = TRUE;
}
retval = g_new0 (MenuMonitor, 1);
retval->path = g_strdup (path);
......
AM_CPPFLAGS = \
$(GIO_UNIX_CFLAGS) \
$(PYTHON_INCLUDES) \
-I$(srcdir)/../libmenu \
-DGMENU_I_KNOW_THIS_IS_UNSTABLE \
$(DISABLE_DEPRECATED_CFLAGS) \
$(DEBUG_CFLAGS)
AM_CFLAGS =
$(WARN_CFLAGS) \
$(NO_STRICT_ALIASING_CFLAGS)
gmenudir = $(pyexecdir)
gmenu_LTLIBRARIES = gmenu.la
gmenu_la_SOURCES = gmenu.c
gmenu_la_LDFLAGS = -module -avoid-version -fPIC -export-symbols-regex initgmenu
gmenu_la_LIBADD = $(GIO_UNIX_LIBS) $(PYTHON_LIBS) $(top_builddir)/libmenu/libgnome-menu.la
-include $(top_srcdir)/git.mk
/*
* Copyright (C) 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser 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.
*/
#include <config.h>
#include <Python.h>
#include <gmenu-tree.h>
typedef struct
{
PyObject_HEAD
GMenuTree *tree;
GSList *callbacks;
} PyGMenuTree;
typedef struct
{
PyObject *tree;
PyObject *callback;
PyObject *user_data;
} PyGMenuTreeCallback;
typedef struct
{
PyObject_HEAD
GMenuTreeItem *item;
} PyGMenuTreeItem;
typedef PyGMenuTreeItem PyGMenuTreeDirectory;
typedef PyGMenuTreeItem PyGMenuTreeEntry;
typedef PyGMenuTreeItem PyGMenuTreeSeparator;
typedef PyGMenuTreeItem PyGMenuTreeHeader;
typedef PyGMenuTreeItem PyGMenuTreeAlias;
static PyGMenuTree *pygmenu_tree_wrap (GMenuTree *tree);
static PyGMenuTreeDirectory *pygmenu_tree_directory_wrap (GMenuTreeDirectory *directory);
static PyGMenuTreeEntry *pygmenu_tree_entry_wrap (GMenuTreeEntry *entry);
static PyGMenuTreeSeparator *pygmenu_tree_separator_wrap (GMenuTreeSeparator *separator);
static PyGMenuTreeHeader *pygmenu_tree_header_wrap (GMenuTreeHeader *header);
static PyGMenuTreeAlias *pygmenu_tree_alias_wrap (GMenuTreeAlias *alias);
static inline PyObject *
lookup_item_type_str (const char *item_type_str)
{
PyObject *module;
module = PyDict_GetItemString (PyImport_GetModuleDict (), "gmenu");
return PyDict_GetItemString (PyModule_GetDict (module), item_type_str);
}
static void
pygmenu_tree_item_dealloc (PyGMenuTreeItem *self)
{
if (self->item != NULL)
{
gmenu_tree_item_set_user_data (self->item, NULL, NULL);
gmenu_tree_item_unref (self->item);
self->item = NULL;
}
PyObject_DEL (self);
}
static PyObject *
pygmenu_tree_item_get_type (PyObject *self,
PyObject *args)
{
PyGMenuTreeItem *item;
PyObject *retval;
if (args != NULL)
{
if (!PyArg_ParseTuple (args, ":gmenu.Item.get_type"))
return NULL;
}
item = (PyGMenuTreeItem *) self;
switch (gmenu_tree_item_get_type (item->item))
{
case GMENU_TREE_ITEM_DIRECTORY:
retval = lookup_item_type_str ("TYPE_DIRECTORY");
break;
case GMENU_TREE_ITEM_ENTRY:
retval = lookup_item_type_str ("TYPE_ENTRY");
break;
case GMENU_TREE_ITEM_SEPARATOR:
retval = lookup_item_type_str ("TYPE_SEPARATOR");
break;
case GMENU_TREE_ITEM_HEADER:
retval = lookup_item_type_str ("TYPE_HEADER");
break;
case GMENU_TREE_ITEM_ALIAS:
retval = lookup_item_type_str ("TYPE_ALIAS");
break;
default:
g_assert_not_reached ();
break;
}
Py_INCREF (retval);
return retval;
}
static PyObject *
pygmenu_tree_item_get_parent (PyObject *self,
PyObject *args)
{
PyGMenuTreeItem *item;
GMenuTreeDirectory *parent;
PyGMenuTreeDirectory *retval;
if (args != NULL)
{
if (!PyArg_ParseTuple (args, ":gmenu.Item.get_parent"))
return NULL;
}
item = (PyGMenuTreeItem *) self;
parent = gmenu_tree_item_get_parent (item->item);
if (parent == NULL)
{
Py_INCREF (Py_None);
return Py_None;
}
retval = pygmenu_tree_directory_wrap (parent);
gmenu_tree_item_unref (parent);
return (PyObject *) retval;
}
static struct PyMethodDef pygmenu_tree_item_methods[] =
{
{ "get_type", pygmenu_tree_item_get_type, METH_VARARGS },
{ "get_parent", pygmenu_tree_item_get_parent, METH_VARARGS },
{ NULL, NULL, 0 }
};
static PyTypeObject PyGMenuTreeItem_Type =
{
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"gmenu.Item", /* tp_name */
sizeof (PyGMenuTreeItem), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) pygmenu_tree_item_dealloc, /* tp_dealloc */
(printfunc)0, /* tp_print */
(getattrfunc)0, /* tp_getattr */
(setattrfunc)0, /* tp_setattr */
(cmpfunc)0, /* tp_compare */
(reprfunc)0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)0, /* tp_hash */
(ternaryfunc)0, /* tp_call */
(reprfunc)0, /* tp_str */
(getattrofunc)0, /* tp_getattro */
(setattrofunc)0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
NULL, /* Documentation string */
(traverseproc)0, /* tp_traverse */
(inquiry)0, /* tp_clear */
(richcmpfunc)0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)0, /* tp_iter */
(iternextfunc)0, /* tp_iternext */
pygmenu_tree_item_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
(PyTypeObject *)0, /* tp_base */
(PyObject *)0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
(inquiry)0, /* tp_is_gc */
(PyObject *)0, /* tp_bases */
};
static PyObject *
pygmenu_tree_directory_get_contents (PyObject *self,
PyObject *args)
{
PyGMenuTreeDirectory *directory;
PyObject *retval;
GSList *contents;
GSList *tmp;
if (args != NULL)
{
if (!PyArg_ParseTuple (args, ":gmenu.Directory.get_contents"))
return NULL;
}
directory = (PyGMenuTreeDirectory *) self;
retval = PyList_New (0);
contents = gmenu_tree_directory_get_contents (GMENU_TREE_DIRECTORY (directory->item));
tmp = contents;
while (tmp != NULL)
{
GMenuTreeItem *item = tmp->data;
PyObject *pyitem;
switch (gmenu_tree_item_get_type (item))
{
case GMENU_TREE_ITEM_DIRECTORY:
pyitem = (PyObject *) pygmenu_tree_directory_wrap (GMENU_TREE_DIRECTORY (item));
break;
case GMENU_TREE_ITEM_ENTRY:
pyitem = (PyObject *) pygmenu_tree_entry_wrap (GMENU_TREE_ENTRY (item));
break;
case GMENU_TREE_ITEM_SEPARATOR:
pyitem = (PyObject *) pygmenu_tree_separator_wrap (GMENU_TREE_SEPARATOR (item));
break;
case GMENU_TREE_ITEM_HEADER:
pyitem = (PyObject *) pygmenu_tree_header_wrap (GMENU_TREE_HEADER (item));
break;
case GMENU_TREE_ITEM_ALIAS:
pyitem = (PyObject *) pygmenu_tree_alias_wrap (GMENU_TREE_ALIAS (item));
break;
default:
g_assert_not_reached ();
break;
}
PyList_Append (retval, pyitem);
Py_DECREF (pyitem);
gmenu_tree_item_unref (item);
tmp = tmp->next;
}
g_slist_free (contents);
return retval;
}
static PyObject *
pygmenu_tree_directory_get_name (PyObject *self,
PyObject *args)
{
PyGMenuTreeDirectory *directory;
const char *name;
if (args != NULL)
{
if (!PyArg_ParseTuple (args, ":gmenu.Directory.get_name"))
return NULL;
}
directory = (PyGMenuTreeDirectory *) self;
name = gmenu_tree_directory_get_name (GMENU_TREE_DIRECTORY (directory->item));
if (name == NULL)
{
Py_INCREF (Py_None);
return Py_None;
}
return PyString_FromString (name);
}
static PyObject *
pygmenu_tree_directory_get_comment (PyObject *self,
PyObject *args)
{
PyGMenuTreeDirectory *directory;
const char *comment;
if (args != NULL)
{
if (!PyArg_ParseTuple (args, ":gmenu.Directory.get_comment"))
return NULL;
}
directory = (PyGMenuTreeDirectory *) self;
comment = gmenu_tree_directory_get_comment (GMENU_TREE_DIRECTORY (directory->item));
if (comment == NULL)
{
Py_INCREF (Py_None);
return Py_None;
}
return PyString_FromString (comment);
}
static PyObject *
pygmenu_tree_directory_get_icon (PyObject *self,
PyObject *args)
{
PyGMenuTreeDirectory *directory;
const char *icon;
if (args != NULL)
{
if (!PyArg_ParseTuple (args, ":gmenu.Directory.get_icon"))
return NULL;
}
directory = (PyGMenuTreeDirectory *) self;
icon = gmenu_tree_directory_get_icon (GMENU_TREE_DIRECTORY (directory->item));
if (icon == NULL)
{
Py_INCREF (Py_None);
return Py_None;
}
return PyString_FromString (icon);
}
static PyObject *
pygmenu_tree_directory_get_desktop_file_path (PyObject *self,
PyObject *args)
{
PyGMenuTreeDirectory *directory;
const char *path;
if (args != NULL)
{
if (!PyArg_ParseTuple (args, ":gmenu.Directory.get_desktop_file_path"))
return NULL;
}
directory = (PyGMenuTreeDirectory *) self;
path = gmenu_tree_directory_get_desktop_file_path (GMENU_TREE_DIRECTORY (directory->item));
if (path == NULL)
{
Py_INCREF (Py_None);
return Py_None;
}
return PyString_FromString (path);
}
static PyObject *
pygmenu_tree_directory_get_menu_id (PyObject *self,
PyObject *args)
{
PyGMenuTreeDirectory *directory;
const char *menu_id;
if (args != NULL)
{
if (!PyArg_ParseTuple (args, ":gmenu.Directory.get_menu_id"))
return NULL;
}
directory = (PyGMenuTreeDirectory *) self;
menu_id = gmenu_tree_directory_get_menu_id (GMENU_TREE_DIRECTORY (directory->item));
if (menu_id == NULL)
{
Py_INCREF (Py_None);
return Py_None;
}