aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--configure.ac16
-rw-r--r--libdbusmenu-glib/Makefile.am34
-rw-r--r--libdbusmenu-glib/client.c362
-rw-r--r--libdbusmenu-glib/client.h2
-rw-r--r--libdbusmenu-glib/dbus-menu.xml99
-rw-r--r--libdbusmenu-glib/defaults.c291
-rw-r--r--libdbusmenu-glib/defaults.h86
-rw-r--r--libdbusmenu-glib/menuitem-private.h5
-rw-r--r--libdbusmenu-glib/menuitem-proxy.c34
-rw-r--r--libdbusmenu-glib/menuitem.c876
-rw-r--r--libdbusmenu-glib/menuitem.h15
-rw-r--r--libdbusmenu-glib/server.c363
-rw-r--r--libdbusmenu-gtk/Makefile.am10
-rw-r--r--libdbusmenu-gtk/client.c110
-rw-r--r--libdbusmenu-gtk/genericmenuitem.c52
-rw-r--r--libdbusmenu-gtk/menu.c73
-rw-r--r--libdbusmenu-gtk/menuitem.c120
-rw-r--r--libdbusmenu-gtk/menuitem.h2
-rw-r--r--libdbusmenu-gtk/parser.c428
-rw-r--r--libdbusmenu-gtk/serializablemenuitem.c64
-rw-r--r--tests/Makefile.am37
-rw-r--r--tests/json-loader.c1
-rw-r--r--tests/test-glib-layout-client.c5
-rwxr-xr-xtests/test-glib-simple-items.py35
-rw-r--r--tests/test-gtk-label.json26
-rwxr-xr-xtests/test-gtk-shortcut-client.py52
-rw-r--r--tests/test-json-01.json2111
-rw-r--r--tools/dbusmenu-dumper.c6
29 files changed, 2686 insertions, 2630 deletions
diff --git a/.bzrignore b/.bzrignore
index 39be2d5..c5cc6ff 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -227,3 +227,4 @@ libdbusmenu-gtk/libdbusmenu_gtk_la-parser.lo
test-gtk-parser
test-gtk-parser-test
test-gtk-parser.xml
+libdbusmenu-glib/libdbusmenu_glib_la-defaults.lo
diff --git a/configure.ac b/configure.ac
index 619cb17..a1af560 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,11 +1,11 @@
-AC_INIT(libdbusmenu, 0.3.94, ted@canonical.com)
+AC_INIT(libdbusmenu, 0.3.98, ted@canonical.com)
AC_COPYRIGHT([Copyright 2009,2010 Canonical])
AC_PREREQ(2.62)
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(libdbusmenu, 0.3.94, [-Wno-portability])
+AM_INIT_AUTOMAKE(libdbusmenu, 0.3.98, [-Wno-portability])
AM_MAINTAINER_MODE
@@ -42,11 +42,9 @@ GNOME_DOC_INIT
###########################
GLIB_REQUIRED_VERSION=2.26
-XML_REQUIRED_VERSION=2.6
PKG_CHECK_MODULES(DBUSMENUGLIB, glib-2.0 >= $GLIB_REQUIRED_VERSION
- gio-2.0 >= $GLIB_REQUIRED_VERSION
- libxml-2.0 >= $XML_REQUIRED_VERSION)
+ gio-2.0 >= $GLIB_REQUIRED_VERSION)
AC_SUBST(DBUSMENUGLIB_CFLAGS)
AC_SUBST(DBUSMENUGLIB_LIBS)
@@ -65,16 +63,14 @@ AC_ARG_WITH([gtk],
[with_gtk=2])
AS_IF([test "x$with_gtk" = x3],
[PKG_CHECK_MODULES(DBUSMENUGTK, gtk+-3.0 >= $GTK3_REQUIRED_VERSION
- glib-2.0 >= $GLIB_REQUIRED_VERSION
- libxml-2.0 >= $XML_REQUIRED_VERSION)
+ glib-2.0 >= $GLIB_REQUIRED_VERSION)
AC_SUBST(DBUSMENUGTK_CFLAGS)
AC_SUBST(DBUSMENUGTK_LIBS)
AC_DEFINE(HAVE_GTK3, 1, [whether gtk3 is available])
],
[test "x$with_gtk" = x2],
[PKG_CHECK_MODULES(DBUSMENUGTK, gtk+-2.0 >= $GTK_REQUIRED_VERSION
- glib-2.0 >= $GLIB_REQUIRED_VERSION
- libxml-2.0 >= $XML_REQUIRED_VERSION)
+ glib-2.0 >= $GLIB_REQUIRED_VERSION)
AC_SUBST(DBUSMENUGTK_CFLAGS)
AC_SUBST(DBUSMENUGTK_LIBS)
],
@@ -136,7 +132,7 @@ AC_PATH_PROG([XSLT_PROC], [xsltproc])
###########################
LIBDBUSMENU_CURRENT=3
-LIBDBUSMENU_REVISION=2
+LIBDBUSMENU_REVISION=6
LIBDBUSMENU_AGE=0
AC_SUBST(LIBDBUSMENU_CURRENT)
diff --git a/libdbusmenu-glib/Makefile.am b/libdbusmenu-glib/Makefile.am
index a139f7c..5ddbeb8 100644
--- a/libdbusmenu-glib/Makefile.am
+++ b/libdbusmenu-glib/Makefile.am
@@ -24,6 +24,8 @@ libdbusmenu_glibinclude_HEADERS = \
libdbusmenu_glib_la_SOURCES = \
dbus-menu-clean.xml.h \
dbus-menu-clean.xml.c \
+ defaults.h \
+ defaults.c \
menuitem.h \
menuitem.c \
menuitem-marshal.h \
@@ -122,34 +124,34 @@ if INTROSPECTION_TEN
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) \
--warn-all \
--add-include-path=$(srcdir) \
- $(addprefix --c-include=libdbusmenu-glib/, $(introspection_sources)) \
+ $(addprefix --c-include=libdbusmenu-glib/, $(libdbusmenu_glibinclude_HEADERS)) \
--symbol-prefix=dbusmenu \
--identifier-prefix=Dbusmenu
else
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) \
--warn-all \
--add-include-path=$(srcdir) \
- $(addprefix --c-include=libdbusmenu-glib/, $(introspection_sources))
+ $(addprefix --c-include=libdbusmenu-glib/, $(libdbusmenu_glibinclude_HEADERS))
endif
INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir)
if HAVE_INTROSPECTION
-introspection_sources = $(libdbusmenu_glibinclude_HEADERS)
+introspection_sources = $(libdbusmenu_glibinclude_HEADERS) $(libdbusmenu_glib_la_SOURCES)
-Dbusmenu_Glib-0.4.gir: libdbusmenu-glib.la
-Dbusmenu_Glib_0_4_gir_INCLUDES = \
+Dbusmenu-0.4.gir: libdbusmenu-glib.la
+Dbusmenu_0_4_gir_INCLUDES = \
GObject-2.0
-Dbusmenu_Glib_0_4_gir_CFLAGS = $(DBUSMENUGLIB_CFLAGS) -I$(top_srcdir)
-Dbusmenu_Glib_0_4_gir_LIBS = libdbusmenu-glib.la
-Dbusmenu_Glib_0_4_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources))
-Dbusmenu_Glib_0_4_gir_NAMESPACE = Dbusmenu
-Dbusmenu_Glib_0_4_gir_VERSION = Glib-0.4
-Dbusmenu_Glib_0_4_gir_EXPORT_PACKAGES = dbusmenu-glib-0.4
-Dbusmenu_Glib_0_4_gir_SCANNER_FLAGS = $(INTROSPECTION_SCANNER_ARGS)
+Dbusmenu_0_4_gir_CFLAGS = $(DBUSMENUGLIB_CFLAGS) -I$(top_srcdir)
+Dbusmenu_0_4_gir_LIBS = libdbusmenu-glib.la
+Dbusmenu_0_4_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources))
+Dbusmenu_0_4_gir_NAMESPACE = Dbusmenu
+Dbusmenu_0_4_gir_VERSION = 0.4
+Dbusmenu_0_4_gir_EXPORT_PACKAGES = dbusmenu-glib-0.4
+Dbusmenu_0_4_gir_SCANNER_FLAGS = $(INTROSPECTION_SCANNER_ARGS)
-INTROSPECTION_GIRS += Dbusmenu-Glib-0.4.gir
+INTROSPECTION_GIRS += Dbusmenu-0.4.gir
girdir = $(datadir)/gir-1.0
gir_DATA = $(INTROSPECTION_GIRS)
@@ -168,10 +170,10 @@ endif
if HAVE_INTROSPECTION
vapidir = $(datadir)/vala/vapi
-vapi_DATA = Dbusmenu-Glib-0.4.vapi
+vapi_DATA = Dbusmenu-0.4.vapi
-Dbusmenu-Glib-0.4.vapi: Dbusmenu-Glib-0.4.gir
- $(VALA_API_GEN) --library=Dbusmenu-Glib-0.4 $<
+Dbusmenu-0.4.vapi: Dbusmenu-0.4.gir
+ $(VALA_API_GEN) --library=Dbusmenu-0.4 $<
CLEANFILES += $(vapi_DATA)
diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c
index b196c9f..0848294 100644
--- a/libdbusmenu-glib/client.c
+++ b/libdbusmenu-glib/client.c
@@ -32,9 +32,6 @@ License version 3 and version 2.1 along with this program. If not, see
#include <gio/gio.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-
#include "client.h"
#include "menuitem.h"
#include "menuitem-private.h"
@@ -129,6 +126,12 @@ struct _type_handler_t {
gchar * type;
};
+typedef struct _properties_callback_t properties_callback_t;
+struct _properties_callback_t {
+ DbusmenuClient * client;
+ GArray * listeners;
+};
+
#define DBUSMENU_CLIENT_GET_PRIVATE(o) (DBUSMENU_CLIENT(o)->priv)
#define DBUSMENU_INTERFACE "com.canonical.dbusmenu"
@@ -145,9 +148,8 @@ static void layout_update (GDBusProxy * proxy, guint revision, gint parent, Dbus
static void id_prop_update (GDBusProxy * proxy, gint id, gchar * property, GVariant * value, DbusmenuClient * client);
static void id_update (GDBusProxy * proxy, gint id, DbusmenuClient * client);
static void build_proxies (DbusmenuClient * client);
-static gint parse_node_get_id (xmlNodePtr node);
-static DbusmenuMenuitem * parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, GDBusProxy * proxy);
-static gint parse_layout (DbusmenuClient * client, const gchar * layout);
+static DbusmenuMenuitem * parse_layout_xml(DbusmenuClient * client, GVariant * layout, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, GDBusProxy * proxy);
+static gint parse_layout (DbusmenuClient * client, GVariant * layout);
static void update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data);
static void update_layout (DbusmenuClient * client);
static void menuitem_get_properties_cb (GVariant * properties, GError * error, gpointer data);
@@ -512,7 +514,8 @@ find_listener (GArray * listeners, guint index, gint id)
static void
get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data)
{
- GArray * listeners = (GArray *)user_data;
+ properties_callback_t * cbdata = (properties_callback_t *)user_data;
+ GArray * listeners = cbdata->listeners;
int i;
GError * error = NULL;
GVariant * params = NULL;
@@ -526,9 +529,8 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data)
properties_listener_t * listener = &g_array_index(listeners, properties_listener_t, i);
listener->callback(NULL, error, listener->user_data);
}
- g_array_free(listeners, TRUE);
g_error_free(error);
- return;
+ goto out;
}
/* Callback all the folks we can find */
@@ -575,8 +577,11 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data)
g_error_free(localerror);
}
+out:
/* Clean up */
g_array_free(listeners, TRUE);
+ g_object_unref(cbdata->client);
+ g_free(user_data);
return;
}
@@ -586,6 +591,7 @@ get_properties_callback (GObject *obj, GAsyncResult * res, gpointer user_data)
static gboolean
get_properties_idle (gpointer user_data)
{
+ properties_callback_t * cbdata = NULL;
DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(user_data);
g_return_val_if_fail(priv->menuproxy != NULL, TRUE);
@@ -616,6 +622,11 @@ get_properties_idle (gpointer user_data)
g_variant_builder_add_value(&builder, variant_props);
GVariant * variant_params = g_variant_builder_end(&builder);
+ cbdata = g_new(properties_callback_t, 1);
+ cbdata->listeners = priv->delayed_property_listeners;
+ cbdata->client = DBUSMENU_CLIENT(user_data);
+ g_object_ref(G_OBJECT(user_data));
+
g_dbus_proxy_call(priv->menuproxy,
"GetGroupProperties",
variant_params,
@@ -623,7 +634,7 @@ get_properties_idle (gpointer user_data)
-1, /* timeout */
NULL, /* cancellable */
get_properties_callback,
- priv->delayed_property_listeners);
+ cbdata);
/* Free properties */
gchar ** dataregion = (gchar **)g_array_free(priv->delayed_property_list, FALSE);
@@ -1015,11 +1026,60 @@ menuproxy_signal_cb (GDBusProxy * proxy, gchar * sender, gchar * signal, GVarian
{
g_return_if_fail(DBUSMENU_IS_CLIENT(user_data));
DbusmenuClient * client = DBUSMENU_CLIENT(user_data);
+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
if (g_strcmp0(signal, "LayoutUpdated") == 0) {
guint revision; gint parent;
g_variant_get(params, "(ui)", &revision, &parent);
layout_update(proxy, revision, parent, client);
+ } else if (priv->root == NULL) {
+ /* Drop out here, all the rest of these really need to have a root
+ node so we can just ignore them if there isn't one. */
+ } else if (g_strcmp0(signal, "ItemPropertiesUpdated") == 0) {
+ /* Remove before adding just incase there is a duplicate, against the
+ rules, but we can handle it so let's do it. */
+ GVariantIter ritems;
+ g_variant_iter_init(&ritems, g_variant_get_child_value(params, 1));
+
+ GVariant * ritem;
+ while ((ritem = g_variant_iter_next_value(&ritems)) != NULL) {
+ gint id = g_variant_get_int32(g_variant_get_child_value(ritem, 0));
+ DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
+
+ if (menuitem == NULL) {
+ continue;
+ }
+
+ GVariantIter properties;
+ g_variant_iter_init(&properties, g_variant_get_child_value(ritem, 1));
+ gchar * property;
+
+ while (g_variant_iter_next(&properties, "s", &property)) {
+ g_debug("Removing property '%s' on %d", property, id);
+ dbusmenu_menuitem_property_remove(menuitem, property);
+ }
+ }
+
+ GVariantIter items;
+ g_variant_iter_init(&items, g_variant_get_child_value(params, 0));
+
+ GVariant * item;
+ while ((item = g_variant_iter_next_value(&items)) != NULL) {
+ gint id = g_variant_get_int32(g_variant_get_child_value(item, 0));
+ GVariantIter properties;
+ g_variant_iter_init(&properties, g_variant_get_child_value(item, 1));
+ gchar * property;
+ GVariant * value;
+
+ while (g_variant_iter_next(&properties, "{sv}", &property, &value)) {
+ GVariant * internalvalue = value;
+ if (G_LIKELY(g_variant_is_of_type(value, G_VARIANT_TYPE_VARIANT))) {
+ /* Unboxing if needed */
+ internalvalue = g_variant_get_variant(value);
+ }
+ id_prop_update(proxy, id, property, internalvalue, client);
+ }
+ }
} else if (g_strcmp0(signal, "ItemPropertyUpdated") == 0) {
gint id; gchar * property; GVariant * value;
g_variant_get(params, "(isv)", &id, &property, &value);
@@ -1039,40 +1099,6 @@ menuproxy_signal_cb (GDBusProxy * proxy, gchar * sender, gchar * signal, GVarian
return;
}
-/* Get the ID attribute of the node, parse it and
- return it. Also we're checking to ensure the node
- is a 'menu' here. */
-static gint
-parse_node_get_id (xmlNodePtr node)
-{
- if (node == NULL) {
- return -1;
- }
- if (node->type != XML_ELEMENT_NODE) {
- return -1;
- }
- if (g_strcmp0((gchar *)node->name, "menu") != 0) {
- /* This kills some nodes early */
- g_warning("XML Node is not 'menu' it is '%s'", node->name);
- return -1;
- }
-
- xmlAttrPtr attrib;
- for (attrib = node->properties; attrib != NULL; attrib = attrib->next) {
- if (g_strcmp0((gchar *)attrib->name, "id") == 0) {
- if (attrib->children != NULL) {
- gint id = (guint)g_ascii_strtoll((gchar *)attrib->children->content, NULL, 10);
- /* g_debug ("Found ID: %d", id); */
- return id;
- }
- break;
- }
- }
-
- g_warning("Unable to find an ID on the node");
- return -1;
-}
-
/* This is the callback for the properties on a menu item. There
should be all of them in the Hash, and they we use foreach to
copy them into the menuitem.
@@ -1250,7 +1276,7 @@ dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name
edata->event = g_strdup(name);
edata->timestamp = timestamp;
edata->variant = variant;
- g_variant_ref(variant);
+ g_variant_ref_sink(variant);
g_dbus_proxy_call(priv->menuproxy,
"Event",
@@ -1375,10 +1401,14 @@ parse_layout_update (DbusmenuMenuitem * item, DbusmenuClient * client)
/* Parse recursively through the XML and make it into
objects as need be */
static DbusmenuMenuitem *
-parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, GDBusProxy * proxy)
+parse_layout_xml(DbusmenuClient * client, GVariant * layout, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, GDBusProxy * proxy)
{
+ if (layout == NULL) {
+ return NULL;
+ }
+
/* First verify and figure out what we've got */
- gint id = parse_node_get_id(node);
+ gint id = g_variant_get_int32(g_variant_get_child_value(layout, 0));
if (id < 0) {
return NULL;
}
@@ -1390,20 +1420,26 @@ parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * it
g_return_val_if_fail(id == dbusmenu_menuitem_get_id(item), NULL);
/* Some variables */
- xmlNodePtr children;
- guint position;
+ GVariantIter children;
+ g_variant_iter_init(&children, g_variant_get_child_value(layout, 2));
+ GVariant * child;
+
+ guint position = 0;
GList * oldchildren = g_list_copy(dbusmenu_menuitem_get_children(item));
/* g_debug("Starting old children: %d", g_list_length(oldchildren)); */
/* Go through all the XML Nodes and make sure that we have menuitems
to cover those XML nodes. */
- for (children = node->children, position = 0; children != NULL; children = children->next, position++) {
+ while ((child = g_variant_iter_next_value(&children)) != NULL) {
/* g_debug("Looking at child: %d", position); */
- gint childid = parse_node_get_id(children);
+ if (g_variant_is_of_type(child, G_VARIANT_TYPE_VARIANT)) {
+ child = g_variant_get_variant(child);
+ }
+
+ gint childid = g_variant_get_int32(g_variant_get_child_value(child, 0));
if (childid < 0) {
/* Don't increment the position when there isn't a valid
node in the XML tree. It's probably a comment. */
- position--;
continue;
}
DbusmenuMenuitem * childmi = NULL;
@@ -1436,6 +1472,8 @@ parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * it
dbusmenu_menuitem_child_reorder(item, childmi, position);
parse_layout_update(childmi, client);
}
+
+ position++;
}
/* Remove any children that are no longer used by this version of
@@ -1458,14 +1496,20 @@ parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * it
}
/* now it's time to recurse down the tree. */
- children = node->children;
+ g_variant_iter_init(&children, g_variant_get_child_value(layout, 2));
+
+ child = g_variant_iter_next_value(&children);
GList * childmis = dbusmenu_menuitem_get_children(item);
- while (children != NULL && childmis != NULL) {
- gint xmlid = parse_node_get_id(children);
+ while (child != NULL && childmis != NULL) {
+ if (g_variant_is_of_type(child, G_VARIANT_TYPE_VARIANT)) {
+ child = g_variant_get_variant(child);
+ }
+
+ gint xmlid = g_variant_get_int32(g_variant_get_child_value(child, 0));
/* If this isn't a valid menu item we need to move on
until we have one. This avoids things like comments. */
if (xmlid < 0) {
- children = children->next;
+ child = g_variant_iter_next_value(&children);
continue;
}
@@ -1474,13 +1518,14 @@ parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * it
g_debug("Recursing parse_layout_xml. XML ID: %d MI ID: %d", xmlid, miid);
#endif
- parse_layout_xml(client, children, DBUSMENU_MENUITEM(childmis->data), item, proxy);
+ parse_layout_xml(client, child, DBUSMENU_MENUITEM(childmis->data), item, proxy);
- children = children->next;
+ child = g_variant_iter_next_value(&children);
childmis = g_list_next(childmis);
}
- if (children != NULL) {
- g_warning("Sync failed, now we've got extra XML nodes.");
+
+ if (child != NULL) {
+ g_warning("Sync failed, now we've got extra layout nodes.");
}
if (childmis != NULL) {
g_warning("Sync failed, now we've got extra menu items.");
@@ -1492,7 +1537,7 @@ parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * it
/* Take the layout passed to us over DBus and turn it into
a set of beautiful objects */
static gint
-parse_layout (DbusmenuClient * client, const gchar * layout)
+parse_layout (DbusmenuClient * client, GVariant * layout)
{
#ifdef MASSIVEDEBUGGING
g_debug("Client Parsing a new layout");
@@ -1500,17 +1545,6 @@ parse_layout (DbusmenuClient * client, const gchar * layout)
DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
- xmlDocPtr xmldoc;
-
- /* No one should need more characters than this! */
- xmldoc = xmlReadMemory(layout, g_utf8_strlen(layout, 1024*1024), "dbusmenu.xml", NULL, 0);
-
- xmlNodePtr root = xmlDocGetRootElement(xmldoc);
-
- if (root == NULL) {
- g_warning("Unable to get root node of menu XML");
- }
-
DbusmenuMenuitem * oldroot = priv->root;
if (priv->root == NULL) {
@@ -1519,11 +1553,10 @@ parse_layout (DbusmenuClient * client, const gchar * layout)
parse_layout_update(priv->root, client);
}
- priv->root = parse_layout_xml(client, root, priv->root, NULL, priv->menuproxy);
- xmlFreeDoc(xmldoc);
+ priv->root = parse_layout_xml(client, layout, priv->root, NULL, priv->menuproxy);
if (priv->root == NULL) {
- g_warning("Unable to parse layout on client %s object %s: %s", priv->dbus_name, priv->dbus_object, layout);
+ g_warning("Unable to parse layout on client %s object %s: %s", priv->dbus_name, priv->dbus_object, g_variant_print(layout, TRUE));
}
if (priv->root != oldroot) {
@@ -1553,11 +1586,6 @@ update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data)
DbusmenuClient * client = DBUSMENU_CLIENT(data);
DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
- if (priv->layoutcall != NULL) {
- g_object_unref(priv->layoutcall);
- priv->layoutcall = NULL;
- }
-
GError * error = NULL;
GVariant * params = NULL;
@@ -1566,21 +1594,17 @@ update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data)
if (error != NULL) {
g_warning("Getting layout failed: %s", error->message);
g_error_free(error);
- return;
+ goto out;
}
- guint rev;
- gchar * xml;
+ guint rev = g_variant_get_uint32(g_variant_get_child_value(params, 0));
+ GVariant * layout = g_variant_get_child_value(params, 1);
- g_variant_get(params, "(us)", &rev, &xml);
- g_variant_unref(params);
-
- guint parseable = parse_layout(client, xml);
- g_free(xml);
+ guint parseable = parse_layout(client, layout);
if (parseable == 0) {
g_warning("Unable to parse layout!");
- return;
+ goto out;
}
priv->my_revision = rev;
@@ -1596,6 +1620,17 @@ update_layout_cb (GObject * proxy, GAsyncResult * res, gpointer data)
update_layout(client);
}
+out:
+ if (priv->layoutcall != NULL) {
+ g_object_unref(priv->layoutcall);
+ priv->layoutcall = NULL;
+ }
+
+ if (params != NULL) {
+ g_variant_unref(params);
+ }
+
+ g_object_unref(G_OBJECT(client));
return;
}
@@ -1622,9 +1657,20 @@ update_layout (DbusmenuClient * client)
priv->layoutcall = g_cancellable_new();
+ GVariantBuilder tupleb;
+ g_variant_builder_init(&tupleb, G_VARIANT_TYPE_TUPLE);
+
+ g_variant_builder_add_value(&tupleb, g_variant_new_int32(0)); // root
+ g_variant_builder_add_value(&tupleb, g_variant_new_int32(-1)); // recurse
+ g_variant_builder_add_value(&tupleb, g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0)); // props
+
+ GVariant * args = g_variant_builder_end(&tupleb);
+ // g_debug("Args (type: %s): %s", g_variant_get_type_string(args), g_variant_print(args, TRUE));
+
+ g_object_ref(G_OBJECT(client));
g_dbus_proxy_call(priv->menuproxy,
"GetLayout",
- g_variant_new("(i)", 0), /* root */
+ args,
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
priv->layoutcall, /* cancellable */
@@ -1636,17 +1682,17 @@ update_layout (DbusmenuClient * client)
/* Public API */
/**
- dbusmenu_client_new:
- @name: The DBus name for the server to connect to
- @object: The object on the server to monitor
-
- This function creates a new client that connects to a specific
- server on DBus. That server is at a specific location sharing
- a known object. The interface is assumed by the code to be
- the DBus menu interface. The newly created client will start
- sending out events as it syncs up with the server.
-
- Return value: A brand new #DbusmenuClient
+ * dbusmenu_client_new:
+ * @name: The DBus name for the server to connect to
+ * @object: The object on the server to monitor
+ *
+ * This function creates a new client that connects to a specific
+ * server on DBus. That server is at a specific location sharing
+ * a known object. The interface is assumed by the code to be
+ * the DBus menu interface. The newly created client will start
+ * sending out events as it syncs up with the server.
+ *
+ * Return value: A brand new #DbusmenuClient
*/
DbusmenuClient *
dbusmenu_client_new (const gchar * name, const gchar * object)
@@ -1660,21 +1706,21 @@ dbusmenu_client_new (const gchar * name, const gchar * object)
}
/**
- dbusmenu_client_get_root:
- @client: The #DbusmenuClient to get the root node from
-
- Grabs the root node for the specified client @client. This
- function may block. It will block if there is currently a
- call to update the layout, it will block on that layout
- updated and then return the newly updated layout. Chances
- are that this update is in the queue for the mainloop as
- it would have been requested some time ago, but in theory
- it could block longer.
-
- Return value: A #DbusmenuMenuitem representing the root of
- menu on the server. If there is no server or there is
- an error receiving its layout it'll return #NULL.
-*/
+ * dbusmenu_client_get_root:
+ * @client: The #DbusmenuClient to get the root node from
+ *
+ * Grabs the root node for the specified client @client. This
+ * function may block. It will block if there is currently a
+ * call to update the layout, it will block on that layout
+ * updated and then return the newly updated layout. Chances
+ * are that this update is in the queue for the mainloop as
+ * it would have been requested some time ago, but in theory
+ * it could block longer.
+ *
+ * Return value: (transfer none): A #DbusmenuMenuitem representing the root of
+ * menu on the server. If there is no server or there is
+ * an error receiving its layout it'll return #NULL.
+ */
DbusmenuMenuitem *
dbusmenu_client_get_root (DbusmenuClient * client)
{
@@ -1703,25 +1749,25 @@ type_handler_destroy (gpointer user_data)
}
/**
- dbusmenu_client_add_type_handler:
- @client: Client where we're getting types coming in
- @type: A text string that will be matched with the 'type'
- property on incoming menu items
- @newfunc: The function that will be executed with those new
- items when they come in.
-
- This function connects into the type handling of the #DbusmenuClient.
- Every new menuitem that comes in immediately gets asked for it's
- properties. When we get those properties we check the 'type'
- property and look to see if it matches a handler that is known
- by the client. If so, the @newfunc function is executed on that
- #DbusmenuMenuitem. If not, then the DbusmenuClient::new-menuitem
- signal is sent.
-
- In the future the known types will be sent to the server so that it
- can make choices about the menu item types availble.
-
- Return value: If registering the new type was successful.
+ * dbusmenu_client_add_type_handler:
+ * @client: Client where we're getting types coming in
+ * @type: A text string that will be matched with the 'type'
+ * property on incoming menu items
+ * @newfunc: The function that will be executed with those new
+ * items when they come in.
+ *
+ * This function connects into the type handling of the #DbusmenuClient.
+ * Every new menuitem that comes in immediately gets asked for it's
+ * properties. When we get those properties we check the 'type'
+ * property and look to see if it matches a handler that is known
+ * by the client. If so, the @newfunc function is executed on that
+ * #DbusmenuMenuitem. If not, then the DbusmenuClient::new-menuitem
+ * signal is sent.
+ *
+ * In the future the known types will be sent to the server so that it
+ * can make choices about the menu item types availble.
+ *
+ * Return value: If registering the new type was successful.
*/
gboolean
dbusmenu_client_add_type_handler (DbusmenuClient * client, const gchar * type, DbusmenuClientTypeHandler newfunc)
@@ -1730,29 +1776,29 @@ dbusmenu_client_add_type_handler (DbusmenuClient * client, const gchar * type, D
}
/**
- dbusmenu_client_add_type_handler_full:
- @client: Client where we're getting types coming in
- @type: A text string that will be matched with the 'type'
- property on incoming menu items
- @newfunc: The function that will be executed with those new
- items when they come in.
- @user_data: Data passed to @newfunc when it is called
- @destroy_func: A function that is called when the type handler is
- removed (usually on client destruction) which will free
- the resources in @user_data.
-
- This function connects into the type handling of the #DbusmenuClient.
- Every new menuitem that comes in immediately gets asked for it's
- properties. When we get those properties we check the 'type'
- property and look to see if it matches a handler that is known
- by the client. If so, the @newfunc function is executed on that
- #DbusmenuMenuitem. If not, then the DbusmenuClient::new-menuitem
- signal is sent.
-
- In the future the known types will be sent to the server so that it
- can make choices about the menu item types availble.
-
- Return value: If registering the new type was successful.
+ * dbusmenu_client_add_type_handler_full:
+ * @client: Client where we're getting types coming in
+ * @type: A text string that will be matched with the 'type'
+ * property on incoming menu items
+ * @newfunc: The function that will be executed with those new
+ * items when they come in.
+ * @user_data: Data passed to @newfunc when it is called
+ * @destroy_func: A function that is called when the type handler is
+ * removed (usually on client destruction) which will free
+ * the resources in @user_data.
+ *
+ * This function connects into the type handling of the #DbusmenuClient.
+ * Every new menuitem that comes in immediately gets asked for it's
+ * properties. When we get those properties we check the 'type'
+ * property and look to see if it matches a handler that is known
+ * by the client. If so, the @newfunc function is executed on that
+ * #DbusmenuMenuitem. If not, then the DbusmenuClient::new-menuitem
+ * signal is sent.
+ *
+ * In the future the known types will be sent to the server so that it
+ * can make choices about the menu item types availble.
+ *
+ * Return value: If registering the new type was successful.
*/
gboolean
dbusmenu_client_add_type_handler_full (DbusmenuClient * client, const gchar * type, DbusmenuClientTypeHandler newfunc, gpointer user_data, DbusmenuClientTypeDestroyHandler destroy_func)
diff --git a/libdbusmenu-glib/client.h b/libdbusmenu-glib/client.h
index 6d78edf..79c0ee2 100644
--- a/libdbusmenu-glib/client.h
+++ b/libdbusmenu-glib/client.h
@@ -145,7 +145,7 @@ gboolean dbusmenu_client_add_type_handler_full (DbusmenuClient * cli
const gchar * type,
DbusmenuClientTypeHandler newfunc,
gpointer user_data,
- DbusmenuClientTypeDestroyHandler destory_func);
+ DbusmenuClientTypeDestroyHandler destroy_func);
void dbusmenu_client_send_event (DbusmenuClient * client,
gint id,
const gchar * name,
diff --git a/libdbusmenu-glib/dbus-menu.xml b/libdbusmenu-glib/dbus-menu.xml
index 042a24c..da14c63 100644
--- a/libdbusmenu-glib/dbus-menu.xml
+++ b/libdbusmenu-glib/dbus-menu.xml
@@ -174,34 +174,38 @@ License version 3 and version 2.1 along with this program. If not, see
<!-- Functions -->
<method name="GetLayout">
- <dox:d><![CDATA[
- Provides an XML representation of the menu hierarchy
-
- XML syntax:
-
- @verbatim
-<menu id="0"> # Root container
- <menu id="1"> # First level menu, for example "File"
- <menu id="2"/> ~ Second level menu, for example "Open"
- <menu id="3"/>
- ...
- </menu>
- <menu id="4"> # Another first level menu, say "Edit"
- ...
- </menu>
- ...
-</menu>
- @endverbatim
- ]]></dox:d>
+ <dox:d>
+ Provides the layout and propertiers that are attached to the entries
+ that are in the layout. It only gives the items that are children
+ of the item that is specified in @parentId. It will return all of the
+ properties or specific ones depending of the value in @propertyNames.
+
+ The format is recursive, where the second 'v' is in the same format
+ as the original 'a(ia(sv)a(v))'. If the @recursive flag is set to
+ less than one then the second array will have zero entries.
+ </dox:d>
<arg type="i" name="parentId" direction="in">
<dox:d>The ID of the parent node for the layout. For
grabbing the layout from the root node use zero.</dox:d>
</arg>
+ <arg type="i" name="recurse" direction="in">
+ <dox:d>
+ The amount of levels of recursion to use. -1, as value would
+ deliver all the items under the @parentId.
+ </dox:d>
+ </arg>
+ <arg type="as" name="propertyNames" direction="in" >
+ <dox:d>
+ The list of item properties we are
+ interested in. If there are no entries in the list all of
+ the properties will be sent.
+ </dox:d>
+ </arg>
<arg type="u" name="revision" direction="out">
<dox:d>The revision number of the layout. For matching
with layoutUpdated signals.</dox:d>
</arg>
- <arg type="s" name="layout" direction="out">
+ <arg type="(ia{sv}av)" name="layout" direction="out">
<dox:d>The layout as an XML string of IDs.</dox:d>
</arg>
</method>
@@ -236,33 +240,21 @@ License version 3 and version 2.1 along with this program. If not, see
</arg>
</method>
- <method name="GetChildren">
- <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="DBusMenuItemList"/>
- <arg type="i" name="id" direction="in" />
- <arg type="as" name="propertyNames" direction="in" />
- <arg type="a(ia{sv})" name="properties" direction="out" />
- </method>
-
<method name="GetProperty">
- <arg type="i" name="id" direction="in" />
- <arg type="s" name="name" direction="in" />
- <arg type="v" name="value" direction="out" />
- </method>
-
- <method name="GetProperties">
<dox:d>
- Returns multiple properties in one call. This is more efficient than
- GetProperty.
-
+ Get a signal property on a single item. This is not useful if you're
+ going to implement this interface, it should only be used if you're
+ debugging via a commandline tool.
</dox:d>
- <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
- <arg type="i" name="id" direction="in" >
- <dox:d>The item whose properties we want to retrieve.</dox:d>
+ <arg type="i" name="id" direction="in">
+ <dox:d>the id of the item which received the event</dox:d>
</arg>
- <arg type="as" name="propertyNames" direction="in" >
- <dox:d>List of string name of the properties we want. If the list contains no entries, all properties are sent.</dox:d>
+ <arg type="s" name="name" direction="in">
+ <dox:d>the name of the property to get</dox:d>
+ </arg>
+ <arg type="v" name="value" direction="out">
+ <dox:d>the value of the property</dox:d>
</arg>
- <arg type="a{sv}" name="properties" direction="out" />
</method>
<method name="Event">
@@ -309,25 +301,16 @@ License version 3 and version 2.1 along with this program. If not, see
</method>
<!-- Signals -->
- <signal name="ItemPropertyUpdated">
- <dox:d>
- Triggered by the application to notify the applet that the property @a property
- from item @a id has changed to @a value.
- </dox:d>
- <arg type="i" name="id" direction="out" />
- <arg type="s" name="prop" direction="out" />
- <arg type="v" name="value" direction="out" />
- </signal>
-
- <signal name="ItemUpdated">
+ <signal name="ItemsPropertiesUpdated">
<dox:d>
- Triggered by the application to notify the applet that all properties of item
+ Triggered when there are lots of property updates across many items
+ so they all get grouped into a single dbus message. The format is
+ the ID of the item with a hashtable of names and values for those
+ properties.
</dox:d>
- <arg type="i" name="id" direction="out" >
- <dox:d>id which should be considered outdated</dox:d>
- </arg>
+ <arg type="a(ia(sv))" name="props" direction="out" />
+ <arg type="a(ia(s))" name="props_removed" direction="out" />
</signal>
-
<signal name="LayoutUpdated">
<dox:d>
Triggered by the application to notify display of a layout update, up to
diff --git a/libdbusmenu-glib/defaults.c b/libdbusmenu-glib/defaults.c
new file mode 100644
index 0000000..3ad5d76
--- /dev/null
+++ b/libdbusmenu-glib/defaults.c
@@ -0,0 +1,291 @@
+/*
+A library to communicate a menu object set accross DBus and
+track updates and maintain consistency.
+
+Copyright 2011 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 <glib/gi18n.h>
+
+#include "defaults.h"
+#include "menuitem.h"
+#include "client.h"
+
+struct _DbusmenuDefaultsPrivate {
+ GHashTable * types;
+};
+
+typedef struct _DefaultEntry DefaultEntry;
+struct _DefaultEntry {
+ GVariantType * type;
+ GVariant * value;
+};
+
+#define DBUSMENU_DEFAULTS_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_DEFAULTS, DbusmenuDefaultsPrivate))
+
+static void dbusmenu_defaults_class_init (DbusmenuDefaultsClass *klass);
+static void dbusmenu_defaults_init (DbusmenuDefaults *self);
+static void dbusmenu_defaults_dispose (GObject *object);
+static void dbusmenu_defaults_finalize (GObject *object);
+
+static DefaultEntry * entry_create (const GVariantType * type, GVariant * variant);
+static void entry_destroy (gpointer entry);
+
+G_DEFINE_TYPE (DbusmenuDefaults, dbusmenu_defaults, G_TYPE_OBJECT);
+
+static void
+dbusmenu_defaults_class_init (DbusmenuDefaultsClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (DbusmenuDefaultsPrivate));
+
+ object_class->dispose = dbusmenu_defaults_dispose;
+ object_class->finalize = dbusmenu_defaults_finalize;
+ return;
+}
+
+static void
+dbusmenu_defaults_init (DbusmenuDefaults *self)
+{
+ self->priv = DBUSMENU_DEFAULTS_GET_PRIVATE(self);
+
+ self->priv->types = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_hash_table_destroy);
+
+ /* Standard defaults */
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_VISIBLE, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ENABLED, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_LABEL, G_VARIANT_TYPE_STRING, g_variant_new_string(_("Label Empty")));
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_ICON_NAME, G_VARIANT_TYPE_STRING, NULL);
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE, G_VARIANT_TYPE_STRING, NULL);
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, G_VARIANT_TYPE_INT32, NULL);
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_SHORTCUT, G_VARIANT_TYPE_ARRAY, NULL);
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY, G_VARIANT_TYPE_STRING, NULL);
+
+ /* Separator defaults */
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_SEPARATOR, DBUSMENU_MENUITEM_PROP_VISIBLE, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
+
+ return;
+}
+
+static void
+dbusmenu_defaults_dispose (GObject *object)
+{
+ DbusmenuDefaults * self = DBUSMENU_DEFAULTS(object);
+
+ if (self->priv->types != NULL) {
+ g_hash_table_destroy(self->priv->types);
+ self->priv->types = NULL;
+ }
+
+ G_OBJECT_CLASS (dbusmenu_defaults_parent_class)->dispose (object);
+ return;
+}
+
+static void
+dbusmenu_defaults_finalize (GObject *object)
+{
+
+ G_OBJECT_CLASS (dbusmenu_defaults_parent_class)->finalize (object);
+ return;
+}
+
+/* Create a new entry based on the info provided */
+static DefaultEntry *
+entry_create (const GVariantType * type, GVariant * variant)
+{
+ DefaultEntry * defentry = g_new0(DefaultEntry, 1);
+
+ if (type != NULL) {
+ defentry->type = g_variant_type_copy(type);
+ }
+
+ if (variant != NULL) {
+ defentry->value = variant;
+ g_variant_ref_sink(variant);
+ }
+
+ return defentry;
+}
+
+/* Destroy an entry */
+static void
+entry_destroy (gpointer entry)
+{
+ DefaultEntry * defentry = (DefaultEntry *)entry;
+
+ if (defentry->type != NULL) {
+ g_variant_type_free(defentry->type);
+ defentry->type = NULL;
+ }
+
+ if (defentry->value != NULL) {
+ g_variant_unref(defentry->value);
+ defentry->value = NULL;
+ }
+
+ g_free(defentry);
+ return;
+}
+
+static DbusmenuDefaults * default_defaults = NULL;
+
+/**
+ * dbusmenu_defaults_ref_default:
+ *
+ * Get a reference to the default instance. If it doesn't exist this
+ * function will create it.
+ *
+ * Return value: (transfer full): A reference to the defaults
+ */
+DbusmenuDefaults *
+dbusmenu_defaults_ref_default (void)
+{
+ if (default_defaults == NULL) {
+ default_defaults = DBUSMENU_DEFAULTS(g_object_new(DBUSMENU_TYPE_DEFAULTS, NULL));
+ g_object_add_weak_pointer(G_OBJECT(default_defaults), (gpointer *)&default_defaults);
+ } else {
+ g_object_ref(default_defaults);
+ }
+
+ return default_defaults;
+}
+
+/**
+ * dbusmenu_defaults_default_set:
+ * @defaults: The #DbusmenuDefaults object to add to
+ * @type: (allow-none): The #DbusmenuMenuitem type for this default if #NULL will default to #DBUSMENU_CLIENT_TYPE_DEFAULT
+ * @property: Property name for the default
+ * @prop_type: (allow-none): Type of the property for runtime checking. To disable checking set to #NULL.
+ * @value: (allow-none): Default value for @property. #NULL if by default it is unset, but you want type checking from @prop_type.
+ *
+ * Sets up an entry in the defaults database for a given @property
+ * and menuitem type @type. @prop_type and @value can both be #NULL
+ * but both of them can not.
+ */
+void
+dbusmenu_defaults_default_set (DbusmenuDefaults * defaults, const gchar * type, const gchar * property, const GVariantType * prop_type, GVariant * value)
+{
+ g_return_if_fail(DBUSMENU_IS_DEFAULTS(defaults));
+ g_return_if_fail(property != NULL);
+ g_return_if_fail(prop_type != NULL || value != NULL);
+
+ if (type == NULL) {
+ type = DBUSMENU_CLIENT_TYPES_DEFAULT;
+ }
+
+ GHashTable * prop_table = (GHashTable *)g_hash_table_lookup(defaults->priv->types, type);
+
+ /* We've never had a default for this type, so we need
+ to create a table for it. */
+ if (prop_table == NULL) {
+ prop_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, entry_destroy);
+
+ g_hash_table_insert(prop_table, g_strdup(property), entry_create(prop_type, value));
+ g_hash_table_insert(defaults->priv->types, g_strdup(type), prop_table);
+ } else {
+ g_hash_table_replace(prop_table, g_strdup(property), entry_create(prop_type, value));
+ }
+
+ return;
+}
+
+/**
+ * dbusmenu_defaults_default_get:
+ * @defaults: The default database to use
+ * @type: (allow-none): The #DbusmenuMenuitem type for this default if #NULL will default to #DBUSMENU_CLIENT_TYPE_DEFAULT
+ * @property: Property name to lookup
+ *
+ * Gets an entry in the database for a give @property and @type.
+ *
+ * Return value: (transfer none): Returns a variant that does not
+ * have it's ref count increased. If you want to keep it, you should
+ * do that.
+ */
+GVariant *
+dbusmenu_defaults_default_get (DbusmenuDefaults * defaults, const gchar * type, const gchar * property)
+{
+ g_return_val_if_fail(DBUSMENU_IS_DEFAULTS(defaults), NULL);
+ g_return_val_if_fail(property != NULL, NULL);
+
+ if (type == NULL) {
+ type = DBUSMENU_CLIENT_TYPES_DEFAULT;
+ }
+
+ GHashTable * prop_table = (GHashTable *)g_hash_table_lookup(defaults->priv->types, type);
+
+ if (prop_table == NULL) {
+ return NULL;
+ }
+
+ DefaultEntry * entry = (DefaultEntry *)g_hash_table_lookup(prop_table, property);
+
+ if (entry == NULL) {
+ return NULL;
+ }
+
+ return entry->value;
+}
+
+/**
+ * dbusmenu_defaults_default_get_type:
+ * @defaults: The default database to use
+ * @type: (allow-none): The #DbusmenuMenuitem type for this default if #NULL will default to #DBUSMENU_CLIENT_TYPE_DEFAULT
+ * @property: Property name to lookup
+ *
+ * Gets the type for an entry in the database for a give @property and @type.
+ *
+ * Return value: (transfer none): Returns a type for the given
+ * @property value.
+ */
+GVariantType *
+dbusmenu_defaults_default_get_type (DbusmenuDefaults * defaults, const gchar * type, const gchar * property)
+{
+ g_return_val_if_fail(DBUSMENU_IS_DEFAULTS(defaults), NULL);
+ g_return_val_if_fail(property != NULL, NULL);
+
+ if (type == NULL) {
+ type = DBUSMENU_CLIENT_TYPES_DEFAULT;
+ }
+
+ GHashTable * prop_table = (GHashTable *)g_hash_table_lookup(defaults->priv->types, type);
+
+ if (prop_table == NULL) {
+ return NULL;
+ }
+
+ DefaultEntry * entry = (DefaultEntry *)g_hash_table_lookup(prop_table, property);
+
+ if (entry == NULL) {
+ return NULL;
+ }
+
+ return entry->type;
+}
+
diff --git a/libdbusmenu-glib/defaults.h b/libdbusmenu-glib/defaults.h
new file mode 100644
index 0000000..ab377f7
--- /dev/null
+++ b/libdbusmenu-glib/defaults.h
@@ -0,0 +1,86 @@
+/*
+A library to communicate a menu object set accross DBus and
+track updates and maintain consistency.
+
+Copyright 2011 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/>
+*/
+
+#ifndef __DBUSMENU_DEFAULTS_H__
+#define __DBUSMENU_DEFAULTS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define DBUSMENU_TYPE_DEFAULTS (dbusmenu_defaults_get_type ())
+#define DBUSMENU_DEFAULTS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUSMENU_TYPE_DEFAULTS, DbusmenuDefaults))
+#define DBUSMENU_DEFAULTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUSMENU_TYPE_DEFAULTS, DbusmenuDefaultsClass))
+#define DBUSMENU_IS_DEFAULTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUSMENU_TYPE_DEFAULTS))
+#define DBUSMENU_IS_DEFAULTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUSMENU_TYPE_DEFAULTS))
+#define DBUSMENU_DEFAULTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUSMENU_TYPE_DEFAULTS, DbusmenuDefaultsClass))
+
+typedef struct _DbusmenuDefaults DbusmenuDefaults;
+typedef struct _DbusmenuDefaultsClass DbusmenuDefaultsClass;
+typedef struct _DbusmenuDefaultsPrivate DbusmenuDefaultsPrivate;
+
+/**
+ * DbusmenuDefaultsClass:
+ *
+ * All of the signals and functions for #DbusmenuDefaults
+ */
+struct _DbusmenuDefaultsClass {
+ GObjectClass parent_class;
+};
+
+/**
+ * DbusmenuDefaults:
+ *
+ * A singleton to hold all of the defaults for the menuitems
+ * so they can use those easily.
+ */
+struct _DbusmenuDefaults {
+ GObject parent;
+
+ /*< Private >*/
+ DbusmenuDefaultsPrivate * priv;
+};
+
+GType dbusmenu_defaults_get_type (void);
+DbusmenuDefaults * dbusmenu_defaults_ref_default (void);
+void dbusmenu_defaults_default_set (DbusmenuDefaults * defaults,
+ const gchar * type,
+ const gchar * property,
+ const GVariantType * prop_type,
+ GVariant * value);
+GVariant * dbusmenu_defaults_default_get (DbusmenuDefaults * defaults,
+ const gchar * type,
+ const gchar * property);
+GVariantType * dbusmenu_defaults_default_get_type (DbusmenuDefaults * defaults,
+ const gchar * type,
+ const gchar * property);
+
+G_END_DECLS
+
+#endif
diff --git a/libdbusmenu-glib/menuitem-private.h b/libdbusmenu-glib/menuitem-private.h
index 2028464..89319dc 100644
--- a/libdbusmenu-glib/menuitem-private.h
+++ b/libdbusmenu-glib/menuitem-private.h
@@ -33,10 +33,11 @@ License version 3 and version 2.1 along with this program. If not, see
G_BEGIN_DECLS
-void dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array);
+GVariant * dbusmenu_menuitem_build_variant (DbusmenuMenuitem * mi, const gchar ** properties, gint recurse);
gboolean dbusmenu_menuitem_realized (DbusmenuMenuitem * mi);
void dbusmenu_menuitem_set_realized (DbusmenuMenuitem * mi);
-GVariant * dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi);
+GVariant * dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi, const gchar ** properties);
+gboolean dbusmenu_menuitem_property_is_default (DbusmenuMenuitem * mi, const gchar * property);
G_END_DECLS
diff --git a/libdbusmenu-glib/menuitem-proxy.c b/libdbusmenu-glib/menuitem-proxy.c
index 1d97c4c..ae6a334 100644
--- a/libdbusmenu-glib/menuitem-proxy.c
+++ b/libdbusmenu-glib/menuitem-proxy.c
@@ -325,14 +325,14 @@ remove_menuitem (DbusmenuMenuitemProxy * pmi)
}
/**
- dbusmenu_menuitem_proxy_new:
- @mi: The #DbusmenuMenuitem to proxy
-
- Builds a new #DbusmenuMenuitemProxy object that proxies
- all of the values for @mi.
-
- Return value: A new #DbusmenuMenuitemProxy object.
-*/
+ * dbusmenu_menuitem_proxy_new:
+ * @mi: The #DbusmenuMenuitem to proxy
+ *
+ * Builds a new #DbusmenuMenuitemProxy object that proxies
+ * all of the values for @mi.
+ *
+ * Return value: A new #DbusmenuMenuitemProxy object.
+ */
DbusmenuMenuitemProxy *
dbusmenu_menuitem_proxy_new (DbusmenuMenuitem * mi)
{
@@ -344,15 +344,15 @@ dbusmenu_menuitem_proxy_new (DbusmenuMenuitem * mi)
}
/**
- dbusmenu_menuitem_proxy_get_wrapped:
- @pmi: #DbusmenuMenuitemProxy to look into
-
- Accesses the private variable of which #DbusmenuMenuitem
- we are doing the proxying for.
-
- Return value: A #DbusmenuMenuitem object or a #NULL if we
- don't have one or there is an error.
-*/
+ * dbusmenu_menuitem_proxy_get_wrapped:
+ * @pmi: #DbusmenuMenuitemProxy to look into
+ *
+ * Accesses the private variable of which #DbusmenuMenuitem
+ * we are doing the proxying for.
+ *
+ * Return value: (transfer none): A #DbusmenuMenuitem object or a #NULL if we
+ * don't have one or there is an error.
+ */
DbusmenuMenuitem *
dbusmenu_menuitem_proxy_get_wrapped (DbusmenuMenuitemProxy * pmi)
{
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
index b153900..d8ae1a1 100644
--- a/libdbusmenu-glib/menuitem.c
+++ b/libdbusmenu-glib/menuitem.c
@@ -33,6 +33,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include "menuitem.h"
#include "menuitem-marshal.h"
#include "menuitem-private.h"
+#include "defaults.h"
#ifdef MASSIVEDEBUGGING
#define LABEL(x) dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(x), DBUSMENU_MENUITEM_PROP_LABEL)
@@ -59,6 +60,7 @@ struct _DbusmenuMenuitemPrivate
GHashTable * properties;
gboolean root;
gboolean realized;
+ DbusmenuDefaults * defaults;
};
/* Signals */
@@ -96,7 +98,7 @@ static void set_property (GObject * obj, guint id, const GValue * value, GParamS
static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
static void g_value_transform_STRING_BOOLEAN (const GValue * in, GValue * out);
static void g_value_transform_STRING_INT (const GValue * in, GValue * out);
-static void handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * value, guint timestamp);
+static void handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * variant, guint timestamp);
static void send_about_to_show (DbusmenuMenuitem * mi, void (*cb) (DbusmenuMenuitem * mi, gpointer user_data), gpointer cb_data);
/* GObject stuff */
@@ -330,6 +332,8 @@ dbusmenu_menuitem_init (DbusmenuMenuitem *self)
priv->root = FALSE;
priv->realized = FALSE;
+
+ priv->defaults = dbusmenu_defaults_ref_default();
return;
}
@@ -346,6 +350,11 @@ dbusmenu_menuitem_dispose (GObject *object)
g_list_free(priv->children);
priv->children = NULL;
+ if (priv->defaults != NULL) {
+ g_object_unref(priv->defaults);
+ priv->defaults = NULL;
+ }
+
G_OBJECT_CLASS (dbusmenu_menuitem_parent_class)->dispose (object);
return;
}
@@ -443,15 +452,28 @@ send_about_to_show (DbusmenuMenuitem * mi, void (*cb) (DbusmenuMenuitem * mi, gp
return;
}
+/* A helper function to get the type of the menuitem, this might
+ be a candidate for optimization in the future. */
+static const gchar *
+menuitem_get_type (DbusmenuMenuitem * mi)
+{
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ GVariant * currentval = (GVariant *)g_hash_table_lookup(priv->properties, DBUSMENU_MENUITEM_PROP_TYPE);
+ if (currentval != NULL) {
+ return g_variant_get_string(currentval, NULL);
+ }
+ return NULL;
+}
+
/* Public interface */
/**
- dbusmenu_menuitem_new:
-
- Create a new #DbusmenuMenuitem with all default values.
-
- Return value: A newly allocated #DbusmenuMenuitem.
-*/
+ * dbusmenu_menuitem_new:
+ *
+ * Create a new #DbusmenuMenuitem with all default values.
+ *
+ * Return value: A newly allocated #DbusmenuMenuitem.
+ */
DbusmenuMenuitem *
dbusmenu_menuitem_new (void)
{
@@ -459,13 +481,13 @@ dbusmenu_menuitem_new (void)
}
/**
- 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.
-*/
+ * 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 (gint id)
{
@@ -475,13 +497,13 @@ dbusmenu_menuitem_new_with_id (gint id)
}
/**
- dbusmenu_menuitem_get_id:
- @mi: The #DbusmenuMenuitem to query.
-
- Gets the unique ID for @mi.
-
- Return value: The ID of the @mi.
-*/
+ * dbusmenu_menuitem_get_id:
+ * @mi: The #DbusmenuMenuitem to query.
+ *
+ * Gets the unique ID for @mi.
+ *
+ * Return value: The ID of the @mi.
+ */
gint
dbusmenu_menuitem_get_id (DbusmenuMenuitem * mi)
{
@@ -498,17 +520,17 @@ dbusmenu_menuitem_get_id (DbusmenuMenuitem * mi)
}
/**
- dbusmenu_menuitem_realized:
- @mi: #DbusmenuMenuitem to check on
-
- This function returns whether the menuitem has been realized or
- not. This is significant mostly in client implementations that
- can use this additional state to see if the second layers of
- the implementation have been built yet.
-
- Return value: Returns whether or not the menu item has been realized
- yet or not.
-*/
+ * dbusmenu_menuitem_realized:
+ * @mi: #DbusmenuMenuitem to check on
+ *
+ * This function returns whether the menuitem has been realized or
+ * not. This is significant mostly in client implementations that
+ * can use this additional state to see if the second layers of
+ * the implementation have been built yet.
+ *
+ * Return value: Returns whether or not the menu item has been realized
+ * yet or not.
+ */
gboolean
dbusmenu_menuitem_realized (DbusmenuMenuitem * mi)
{
@@ -518,12 +540,12 @@ dbusmenu_menuitem_realized (DbusmenuMenuitem * mi)
}
/**
- dbusmenu_menuitem_set_realized:
- @mi: #DbusmenuMenuitem to realize
-
- Sets the internal variable tracking whether it's been realized and
- signals the DbusmenuMenuitem::realized event.
-*/
+ * dbusmenu_menuitem_set_realized:
+ * @mi: #DbusmenuMenuitem to realize
+ *
+ * Sets the internal variable tracking whether it's been realized and
+ * signals the DbusmenuMenuitem::realized event.
+ */
void
dbusmenu_menuitem_set_realized (DbusmenuMenuitem * mi)
{
@@ -538,15 +560,15 @@ dbusmenu_menuitem_set_realized (DbusmenuMenuitem * mi)
}
/**
- 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.
-*/
+ * 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: (transfer none): A #GList of pointers to #DbusmenuMenuitem objects.
+ */
GList *
dbusmenu_menuitem_get_children (DbusmenuMenuitem * mi)
{
@@ -565,22 +587,22 @@ take_children_signal (gpointer data, gpointer user_data)
g_debug("Menuitem %d (%s) signalling child removed %d (%s)", ID(user_data), LABEL(user_data), ID(data), LABEL(data));
#endif
g_signal_emit(G_OBJECT(user_data), signals[CHILD_REMOVED], 0, DBUSMENU_MENUITEM(data), TRUE);
- g_object_unref(G_OBJECT(data));
return;
}
/**
- 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 now 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.
-*/
+ * 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 now in charge of the ref's
+ * on the children it has taken. A lot of responsibility involved
+ * in taking children.
+ *
+ * Return value: (transfer full) (element-type Dbusmenu.Menuitem):
+ * A #GList of pointers to #DbusmenuMenuitem objects.
+ */
GList *
dbusmenu_menuitem_take_children (DbusmenuMenuitem * mi)
{
@@ -597,16 +619,16 @@ dbusmenu_menuitem_take_children (DbusmenuMenuitem * mi)
}
/**
- 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.
-*/
+ * 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)
{
@@ -636,15 +658,15 @@ dbusmenu_menuitem_get_position (DbusmenuMenuitem * mi, DbusmenuMenuitem * parent
}
/**
- dbusmenu_menuitem_get_position_realized:
- @mi: The #DbusmenuMenuitem to find the position of
- @parent: The #DbusmenuMenuitem who's children contain @mi
-
- This function is very similar to #dbusmenu_menuitem_get_position
- except that it only counts in the children that have been realized.
-
- Return value: The position of @mi in the realized children of @parent.
-*/
+ * dbusmenu_menuitem_get_position_realized:
+ * @mi: The #DbusmenuMenuitem to find the position of
+ * @parent: The #DbusmenuMenuitem who's children contain @mi
+ *
+ * This function is very similar to #dbusmenu_menuitem_get_position
+ * except that it only counts in the children that have been realized.
+ *
+ * Return value: The position of @mi in the realized children of @parent.
+ */
guint
dbusmenu_menuitem_get_position_realized (DbusmenuMenuitem * mi, DbusmenuMenuitem * parent)
{
@@ -680,15 +702,15 @@ dbusmenu_menuitem_get_position_realized (DbusmenuMenuitem * mi, DbusmenuMenuitem
}
/**
- 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.
-*/
+ * 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)
{
@@ -712,15 +734,15 @@ dbusmenu_menuitem_child_append (DbusmenuMenuitem * mi, DbusmenuMenuitem * child)
}
/**
- dbusmenu_menuitem_child_prepend:
- @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 beginning of that list.
-
- Return value: Whether the child has been added successfully.
-*/
+ * dbusmenu_menuitem_child_prepend:
+ * @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 beginning of that list.
+ *
+ * Return value: Whether the child has been added successfully.
+ */
gboolean
dbusmenu_menuitem_child_prepend (DbusmenuMenuitem * mi, DbusmenuMenuitem * child)
{
@@ -744,16 +766,16 @@ dbusmenu_menuitem_child_prepend (DbusmenuMenuitem * mi, DbusmenuMenuitem * child
}
/**
- 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.
-*/
+ * 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)
{
@@ -776,17 +798,17 @@ dbusmenu_menuitem_child_delete (DbusmenuMenuitem * mi, DbusmenuMenuitem * child)
}
/**
- 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.
-*/
+ * 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)
{
@@ -810,17 +832,17 @@ dbusmenu_menuitem_child_add_position (DbusmenuMenuitem * mi, DbusmenuMenuitem *
}
/**
- dbusmenu_menuitem_child_reorder:
- @base: The #DbusmenuMenuitem that has children needing realignment
- @child: The #DbusmenuMenuitem that is a child needing to be moved
- @position: The position in the list to place it in
-
- This function moves a child on the list of children. It is
- for a child that is already in the list, but simply needs a
- new location.
-
- Return value: Whether the move was successful.
-*/
+ * dbusmenu_menuitem_child_reorder:
+ * @mi: The #DbusmenuMenuitem that has children needing realignment
+ * @child: The #DbusmenuMenuitem that is a child needing to be moved
+ * @position: The position in the list to place it in
+ *
+ * This function moves a child on the list of children. It is
+ * for a child that is already in the list, but simply needs a
+ * new location.
+ *
+ * Return value: Whether the move was successful.
+ */
gboolean
dbusmenu_menuitem_child_reorder(DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint position)
{
@@ -850,16 +872,16 @@ dbusmenu_menuitem_child_reorder(DbusmenuMenuitem * mi, DbusmenuMenuitem * child,
}
/**
- 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.
-*/
+ * 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: (transfer none): The menu item with the ID @id or #NULL if it
+ * can't be found.
+ */
DbusmenuMenuitem *
dbusmenu_menuitem_child_find (DbusmenuMenuitem * mi, gint id)
{
@@ -903,18 +925,18 @@ find_id_helper (gpointer in_mi, gpointer in_find_id)
}
/**
- dbusmenu_menuitem_find_id:
- @mi: #DbusmenuMenuitem at the top of the tree to search
- @id: ID of the #DbusmenuMenuitem to search for
-
- This function searchs the whole tree of children that
- are attached to @mi. This could be quite a few nodes, all
- the way down the tree. It is a depth first search.
-
- Return value: The #DbusmenuMenuitem with the ID of @id
- or #NULL if there isn't such a menu item in the tree
- represented by @mi.
-*/
+ * dbusmenu_menuitem_find_id:
+ * @mi: #DbusmenuMenuitem at the top of the tree to search
+ * @id: ID of the #DbusmenuMenuitem to search for
+ *
+ * This function searchs the whole tree of children that
+ * are attached to @mi. This could be quite a few nodes, all
+ * the way down the tree. It is a depth first search.
+ *
+ * Return value: (transfer none): The #DbusmenuMenuitem with the ID of @id
+ * or #NULL if there isn't such a menu item in the tree
+ * represented by @mi.
+ */
DbusmenuMenuitem *
dbusmenu_menuitem_find_id (DbusmenuMenuitem * mi, gint id)
{
@@ -931,20 +953,20 @@ dbusmenu_menuitem_find_id (DbusmenuMenuitem * mi, gint id)
}
/**
- dbusmenu_menuitem_property_set:
- @mi: The #DbusmenuMenuitem to set the property on.
- @property: Name of the property to set.
- @value: The value of the property.
-
- Takes the pair of @property and @value and places them as a
- property on @mi. If a property already exists by that name,
- then the value is set to the new value. If not, the property
- is added. If the value is changed or the property was previously
- unset then the signal #DbusmenuMenuitem::prop-changed will be
- emitted by this function.
-
- Return value: A boolean representing if the property value was set.
-*/
+ * dbusmenu_menuitem_property_set:
+ * @mi: The #DbusmenuMenuitem to set the property on.
+ * @property: Name of the property to set.
+ * @value: The value of the property.
+ *
+ * Takes the pair of @property and @value and places them as a
+ * property on @mi. If a property already exists by that name,
+ * then the value is set to the new value. If not, the property
+ * is added. If the value is changed or the property was previously
+ * unset then the signal #DbusmenuMenuitem::prop-changed will be
+ * emitted by this function.
+ *
+ * Return value: A boolean representing if the property value was set.
+ */
gboolean
dbusmenu_menuitem_property_set (DbusmenuMenuitem * mi, const gchar * property, const gchar * value)
{
@@ -956,20 +978,20 @@ dbusmenu_menuitem_property_set (DbusmenuMenuitem * mi, const gchar * property, c
}
/**
- dbusmenu_menuitem_property_set_bool:
- @mi: The #DbusmenuMenuitem to set the property on.
- @property: Name of the property to set.
- @value: The value of the property.
-
- Takes a boolean @value and sets it on @property as a
- property on @mi. If a property already exists by that name,
- then the value is set to the new value. If not, the property
- is added. If the value is changed or the property was previously
- unset then the signal #DbusmenuMenuitem::prop-changed will be
- emitted by this function.
-
- Return value: A boolean representing if the property value was set.
-*/
+ * dbusmenu_menuitem_property_set_bool:
+ * @mi: The #DbusmenuMenuitem to set the property on.
+ * @property: Name of the property to set.
+ * @value: The value of the property.
+ *
+ * Takes a boolean @value and sets it on @property as a
+ * property on @mi. If a property already exists by that name,
+ * then the value is set to the new value. If not, the property
+ * is added. If the value is changed or the property was previously
+ * unset then the signal #DbusmenuMenuitem::prop-changed will be
+ * emitted by this function.
+ *
+ * Return value: A boolean representing if the property value was set.
+ */
gboolean
dbusmenu_menuitem_property_set_bool (DbusmenuMenuitem * mi, const gchar * property, const gboolean value)
{
@@ -978,20 +1000,20 @@ dbusmenu_menuitem_property_set_bool (DbusmenuMenuitem * mi, const gchar * proper
}
/**
- dbusmenu_menuitem_property_set_int:
- @mi: The #DbusmenuMenuitem to set the property on.
- @property: Name of the property to set.
- @value: The value of the property.
-
- Takes a boolean @value and sets it on @property as a
- property on @mi. If a property already exists by that name,
- then the value is set to the new value. If not, the property
- is added. If the value is changed or the property was previously
- unset then the signal #DbusmenuMenuitem::prop-changed will be
- emitted by this function.
-
- Return value: A boolean representing if the property value was set.
-*/
+ * dbusmenu_menuitem_property_set_int:
+ * @mi: The #DbusmenuMenuitem to set the property on.
+ * @property: Name of the property to set.
+ * @value: The value of the property.
+ *
+ * Takes a boolean @value and sets it on @property as a
+ * property on @mi. If a property already exists by that name,
+ * then the value is set to the new value. If not, the property
+ * is added. If the value is changed or the property was previously
+ * unset then the signal #DbusmenuMenuitem::prop-changed will be
+ * emitted by this function.
+ *
+ * Return value: A boolean representing if the property value was set.
+ */
gboolean
dbusmenu_menuitem_property_set_int (DbusmenuMenuitem * mi, const gchar * property, const gint value)
{
@@ -1000,20 +1022,20 @@ dbusmenu_menuitem_property_set_int (DbusmenuMenuitem * mi, const gchar * propert
}
/**
- dbusmenu_menuitem_property_set_variant:
- @mi: The #DbusmenuMenuitem to set the property on.
- @property: Name of the property to set.
- @value: The value of the property.
-
- Takes the pair of @property and @value and places them as a
- property on @mi. If a property already exists by that name,
- then the value is set to the new value. If not, the property
- is added. If the value is changed or the property was previously
- unset then the signal #DbusmenuMenuitem::prop-changed will be
- emitted by this function.
-
- Return value: A boolean representing if the property value was set.
-*/
+ * dbusmenu_menuitem_property_set_variant:
+ * @mi: The #DbusmenuMenuitem to set the property on.
+ * @property: Name of the property to set.
+ * @value: The value of the property.
+ *
+ * Takes the pair of @property and @value and places them as a
+ * property on @mi. If a property already exists by that name,
+ * then the value is set to the new value. If not, the property
+ * is added. If the value is changed or the property was previously
+ * unset then the signal #DbusmenuMenuitem::prop-changed will be
+ * emitted by this function.
+ *
+ * Return value: A boolean representing if the property value was set.
+ */
gboolean
dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * property, GVariant * value)
{
@@ -1022,17 +1044,49 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro
DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+ const gchar * type = menuitem_get_type(mi);
+
+ /* Check the expected type to see if we want to have a warning */
+ GVariantType * default_type = dbusmenu_defaults_default_get_type(priv->defaults, type, property);
+ if (default_type != NULL) {
+ /* If we have an expected type we should check to see if
+ the value we've been given is of the same type and generate
+ a warning if it isn't */
+ if (!g_variant_is_of_type(value, default_type)) {
+ g_warning("Setting menuitem property '%s' with value of type '%s' when expecting '%s'", property, g_variant_get_type_string(value), g_variant_type_peek_string(default_type));
+ }
+ }
+
+ /* Check the defaults database to see if we have a default
+ for this property. */
+ GVariant * default_value = dbusmenu_defaults_default_get(priv->defaults, type, property);
+ if (default_value != NULL) {
+ /* Now see if we're setting this to the same value as the
+ default. If we are then we just want to swallow this variant
+ and make the function behave like we're clearing it. */
+ if (g_variant_equal(default_value, value)) {
+ g_variant_ref_sink(value);
+ g_variant_unref(value);
+ value = NULL;
+ }
+ }
+
gboolean replaced = FALSE;
gpointer currentval = g_hash_table_lookup(priv->properties, property);
if (value != NULL) {
- gchar * lprop = g_strdup(property);
- g_variant_ref(value);
-
+ /* NOTE: We're only marking this as replaced if this is true
+ but we're actually replacing it no matter. This is so that
+ the variant passed in sticks around which the caller may
+ expect. They shouldn't, but it's low cost to remove bugs. */
if (currentval == NULL || !g_variant_equal((GVariant*)currentval, value)) {
- g_hash_table_replace(priv->properties, lprop, value);
replaced = TRUE;
}
+
+ gchar * lprop = g_strdup(property);
+ g_variant_ref_sink(value);
+
+ g_hash_table_replace(priv->properties, lprop, value);
} else {
if (currentval != NULL) {
g_hash_table_remove(priv->properties, property);
@@ -1045,25 +1099,33 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro
table. But the fact that there was a value is
the imporant part. */
if (currentval == NULL || replaced) {
- g_signal_emit(G_OBJECT(mi), signals[PROPERTY_CHANGED], 0, property, value, TRUE);
+ GVariant * signalval = value;
+
+ if (signalval == NULL) {
+ /* Might also be NULL, but if it is we're definitely
+ clearing this thing. */
+ signalval = default_value;
+ }
+
+ g_signal_emit(G_OBJECT(mi), signals[PROPERTY_CHANGED], 0, property, signalval, TRUE);
}
return TRUE;
}
/**
- dbusmenu_menuitem_property_get:
- @mi: The #DbusmenuMenuitem to look for the property on.
- @property: The property to grab.
-
- Look up a property on @mi and return the value of it if
- it exits. #NULL will be returned if the property doesn't
- exist.
-
- Return value: A string with the value of the property
- that shouldn't be free'd. Or #NULL if the property
- is not set or is not a string.
-*/
+ * dbusmenu_menuitem_property_get:
+ * @mi: The #DbusmenuMenuitem to look for the property on.
+ * @property: The property to grab.
+ *
+ * Look up a property on @mi and return the value of it if
+ * it exits. #NULL will be returned if the property doesn't
+ * exist.
+ *
+ * Return value: (transfer none): A string with the value of the property
+ * that shouldn't be free'd. Or #NULL if the property
+ * is not set or is not a string.
+ */
const gchar *
dbusmenu_menuitem_property_get (DbusmenuMenuitem * mi, const gchar * property)
{
@@ -1074,16 +1136,16 @@ dbusmenu_menuitem_property_get (DbusmenuMenuitem * mi, const gchar * property)
}
/**
- dbusmenu_menuitem_property_get_variant:
- @mi: The #DbusmenuMenuitem to look for the property on.
- @property: The property to grab.
-
- Look up a property on @mi and return the value of it if
- it exits. #NULL will be returned if the property doesn't
- exist.
-
- Return value: A GVariant for the property.
-*/
+ * dbusmenu_menuitem_property_get_variant:
+ * @mi: The #DbusmenuMenuitem to look for the property on.
+ * @property: The property to grab.
+ *
+ * Look up a property on @mi and return the value of it if
+ * it exits. #NULL will be returned if the property doesn't
+ * exist.
+ *
+ * Return value: (transfer none): A GVariant for the property.
+ */
GVariant *
dbusmenu_menuitem_property_get_variant (DbusmenuMenuitem * mi, const gchar * property)
{
@@ -1092,19 +1154,25 @@ dbusmenu_menuitem_property_get_variant (DbusmenuMenuitem * mi, const gchar * pro
DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
- return (GVariant *)g_hash_table_lookup(priv->properties, property);
-}
+ GVariant * currentval = (GVariant *)g_hash_table_lookup(priv->properties, property);
-/**
- dbusmenu_menuitem_property_get_bool:
- @mi: The #DbusmenuMenuitem to look for the property on.
- @property: The property to grab.
+ if (currentval == NULL) {
+ currentval = dbusmenu_defaults_default_get(priv->defaults, menuitem_get_type(mi), property);
+ }
- Look up a property on @mi and return the value of it if
- it exits. Returns #FALSE if the property doesn't exist.
+ return currentval;
+}
- Return value: The value of the property or #FALSE.
-*/
+/**
+ * dbusmenu_menuitem_property_get_bool:
+ * @mi: The #DbusmenuMenuitem to look for the property on.
+ * @property: The property to grab.
+ *
+ * Look up a property on @mi and return the value of it if
+ * it exits. Returns #FALSE if the property doesn't exist.
+ *
+ * Return value: The value of the property or #FALSE.
+ */
gboolean
dbusmenu_menuitem_property_get_bool (DbusmenuMenuitem * mi, const gchar * property)
{
@@ -1130,15 +1198,15 @@ dbusmenu_menuitem_property_get_bool (DbusmenuMenuitem * mi, const gchar * proper
}
/**
- dbusmenu_menuitem_property_get_int:
- @mi: The #DbusmenuMenuitem to look for the property on.
- @property: The property to grab.
-
- Look up a property on @mi and return the value of it if
- it exits. Returns zero if the property doesn't exist.
-
- Return value: The value of the property or zero.
-*/
+ * dbusmenu_menuitem_property_get_int:
+ * @mi: The #DbusmenuMenuitem to look for the property on.
+ * @property: The property to grab.
+ *
+ * Look up a property on @mi and return the value of it if
+ * it exits. Returns zero if the property doesn't exist.
+ *
+ * Return value: The value of the property or zero.
+ */
gint
dbusmenu_menuitem_property_get_int (DbusmenuMenuitem * mi, const gchar * property)
{
@@ -1160,15 +1228,15 @@ dbusmenu_menuitem_property_get_int (DbusmenuMenuitem * mi, const gchar * propert
/**
- dbusmenu_menuitem_property_exit:
- @mi: The #DbusmenuMenuitem to look for the property on.
- @property: The property to look for.
-
- Checkes to see if a particular property exists on @mi and
- returns #TRUE if so.
-
- Return value: A boolean checking to see if the property is available
-*/
+ * dbusmenu_menuitem_property_exit:
+ * @mi: The #DbusmenuMenuitem to look for the property on.
+ * @property: The property to look for.
+ *
+ * Checkes to see if a particular property exists on @mi and
+ * returns #TRUE if so.
+ *
+ * Return value: A boolean checking to see if the property is available
+ */
gboolean
dbusmenu_menuitem_property_exist (DbusmenuMenuitem * mi, const gchar * property)
{
@@ -1183,12 +1251,12 @@ dbusmenu_menuitem_property_exist (DbusmenuMenuitem * mi, const gchar * property)
}
/**
- dbusmenu_menuitem_property_remove:
- @mi: The #DbusmenuMenuitem to remove the property on.
- @property: The property to look for.
-
- Removes a property from the menuitem.
-*/
+ * dbusmenu_menuitem_property_remove:
+ * @mi: The #DbusmenuMenuitem to remove the property on.
+ * @property: The property to look for.
+ *
+ * Removes a property from the menuitem.
+ */
void
dbusmenu_menuitem_property_remove (DbusmenuMenuitem * mi, const gchar * property)
{
@@ -1203,15 +1271,16 @@ dbusmenu_menuitem_property_remove (DbusmenuMenuitem * mi, const gchar * property
}
/**
- dbusmenu_menuitem_properties_list:
- @mi: #DbusmenuMenuitem to list the properties on
-
- This functiong gets a list of the names of all the properties
- that are set on this menu item. This data on the list is owned
- by the menuitem but the list is not and should be freed using
- g_list_free() when the calling function is done with it.
-
- Return value: A list of strings or NULL if there are none.
+ * dbusmenu_menuitem_properties_list:
+ * @mi: #DbusmenuMenuitem to list the properties on
+ *
+ * This functiong gets a list of the names of all the properties
+ * that are set on this menu item. This data on the list is owned
+ * by the menuitem but the list is not and should be freed using
+ * g_list_free() when the calling function is done with it.
+ *
+ * Return value: (transfer container): A list of strings or NULL if there are
+ * none.
*/
GList *
dbusmenu_menuitem_properties_list (DbusmenuMenuitem * mi)
@@ -1231,24 +1300,24 @@ copy_helper (gpointer in_key, gpointer in_value, gpointer in_data)
GHashTable * table = (GHashTable *)in_data;
gchar * key = (gchar *)in_key;
GVariant * value = (GVariant *)in_value;
- g_variant_ref(value);
+ g_variant_ref_sink(value);
g_hash_table_insert(table, g_strdup(key), value);
return;
}
/**
- dbusmenu_menuitem_properties_copy:
- @mi: #DbusmenuMenuitem that we're interested in the properties of
-
- This function takes the properties of a #DbusmenuMenuitem
- and puts them into a #GHashTable that is referenced by the
- key of a string and has the value of a string. The hash
- table may not have any entries if there aren't any or there
- is an error in processing. It is the caller's responsibility
- to destroy the created #GHashTable.
-
- Return value: A brand new #GHashTable that contains all of the
- properties that are on this #DbusmenuMenuitem @mi.
+ * dbusmenu_menuitem_properties_copy:
+ * @mi: #DbusmenuMenuitem that we're interested in the properties of
+ *
+ * This function takes the properties of a #DbusmenuMenuitem
+ * and puts them into a #GHashTable that is referenced by the
+ * key of a string and has the value of a string. The hash
+ * table may not have any entries if there aren't any or there
+ * is an error in processing. It is the caller's responsibility
+ * to destroy the created #GHashTable.
+ *
+ * Return value: (transfer full): A brand new #GHashTable that contains all of
+ * theroperties that are on this #DbusmenuMenuitem @mi.
*/
GHashTable *
dbusmenu_menuitem_properties_copy (DbusmenuMenuitem * mi)
@@ -1268,21 +1337,23 @@ dbusmenu_menuitem_properties_copy (DbusmenuMenuitem * mi)
static void
variant_helper (gpointer in_key, gpointer in_value, gpointer user_data)
{
- g_variant_builder_add((GVariantBuilder *)user_data, "{sv}", in_key, in_value);
+ GVariant * value = g_variant_new_dict_entry(g_variant_new_string((gchar *)in_key),
+ g_variant_new_variant((GVariant *)in_value));
+ g_variant_builder_add_value((GVariantBuilder *)user_data, value);
return;
}
/**
- dbusmenu_menuitem_properties_variant:
- @mi: #DbusmenuMenuitem to get properties from
-
- Grabs the properties of the menuitem as a GVariant with the
- type "a{sv}".
-
- Return Value: A GVariant of type "a{sv}" or NULL on error.
-*/
+ * dbusmenu_menuitem_properties_variant:
+ * @mi: #DbusmenuMenuitem to get properties from
+ *
+ * Grabs the properties of the menuitem as a GVariant with the
+ * type "a{sv}".
+ *
+ * Return Value: (transfer full): A GVariant of type "a{sv}" or NULL on error.
+ */
GVariant *
-dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi)
+dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi, const gchar ** properties)
{
g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
@@ -1292,7 +1363,7 @@ dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi)
if (g_hash_table_size(priv->properties) > 0) {
GVariantBuilder builder;
- g_variant_builder_init(&builder, g_variant_type_new("a{sv}"));
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
g_hash_table_foreach(priv->properties, variant_helper, &builder);
@@ -1303,15 +1374,15 @@ dbusmenu_menuitem_properties_variant (DbusmenuMenuitem * mi)
}
/**
- dbusmenu_menuitem_set_root:
- @mi: #DbusmenuMenuitem to set whether it's root
- @root: Whether @mi is a root node or not
-
- This function sets the internal value of whether this is a
- root node or not.
-
- Return value: None
-*/
+ * dbusmenu_menuitem_set_root:
+ * @mi: #DbusmenuMenuitem to set whether it's root
+ * @root: Whether @mi is a root node or not
+ *
+ * This function sets the internal value of whether this is a
+ * root node or not.
+ *
+ * Return value: None
+ */
void
dbusmenu_menuitem_set_root (DbusmenuMenuitem * mi, gboolean root)
{
@@ -1322,14 +1393,14 @@ dbusmenu_menuitem_set_root (DbusmenuMenuitem * mi, gboolean root)
}
/**
- dbusmenu_menuitem_get_root:
- @mi: #DbusmenuMenuitem to see whether it's root
-
- This function returns the internal value of whether this is a
- root node or not.
-
- Return value: #TRUE if this is a root node
-*/
+ * dbusmenu_menuitem_get_root:
+ * @mi: #DbusmenuMenuitem to see whether it's root
+ *
+ * This function returns the internal value of whether this is a
+ * root node or not.
+ *
+ * Return value: #TRUE if this is a root node
+ */
gboolean
dbusmenu_menuitem_get_root (DbusmenuMenuitem * mi)
{
@@ -1340,38 +1411,62 @@ dbusmenu_menuitem_get_root (DbusmenuMenuitem * mi)
/**
- dbusmenu_menuitem_buildxml:
- @mi: #DbusmenuMenuitem to represent in XML
- @array: (element-type utf8): 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.
+ * dbusmenu_menuitem_buildvariant:
+ * @mi: #DbusmenuMenuitem to represent in a variant
+ * @properties: (element-type utf8): A list of string that will be put into
+ * a variant
+ *
+ * This function 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.
+ *
+ * Return value: (transfer full): Variant representing @properties
*/
-void
-dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array)
+GVariant *
+dbusmenu_menuitem_build_variant (DbusmenuMenuitem * mi, const gchar ** properties, gint recurse)
{
- g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), NULL);
gint id = 0;
if (!dbusmenu_menuitem_get_root(mi)) {
id = dbusmenu_menuitem_get_id(mi);
}
+ /* This is the tuple that'll build up being a representation of
+ this entry */
+ GVariantBuilder tupleb;
+ g_variant_builder_init(&tupleb, G_VARIANT_TYPE_TUPLE);
+
+ /* Add our ID */
+ g_variant_builder_add_value(&tupleb, g_variant_new_int32(id));
+
+ /* Figure out the properties */
+ GVariant * props = dbusmenu_menuitem_properties_variant(mi, properties);
+ if (props != NULL) {
+ g_variant_builder_add_value(&tupleb, props);
+ } else {
+ g_variant_builder_add_value(&tupleb, g_variant_parse(G_VARIANT_TYPE("a{sv}"), "[ ]", NULL, NULL, NULL));
+ }
+
+ /* Pillage the children */
GList * children = dbusmenu_menuitem_get_children(mi);
- if (children == NULL) {
- g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\"/>", id));
+ if (children == NULL && recurse != 0) {
+ g_variant_builder_add_value(&tupleb, g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0));
} else {
- g_ptr_array_add(array, g_strdup_printf("<menu id=\"%d\">", id));
+ GVariantBuilder childrenbuilder;
+ g_variant_builder_init(&childrenbuilder, G_VARIANT_TYPE_ARRAY);
+
for ( ; children != NULL; children = children->next) {
- dbusmenu_menuitem_buildxml(DBUSMENU_MENUITEM(children->data), array);
+ GVariant * child = dbusmenu_menuitem_build_variant(DBUSMENU_MENUITEM(children->data), properties, recurse - 1);
+
+ g_variant_builder_add_value(&childrenbuilder, g_variant_new_variant(child));
}
- g_ptr_array_add(array, g_strdup("</menu>"));
+
+ g_variant_builder_add_value(&tupleb, g_variant_builder_end(&childrenbuilder));
}
- return;
+ return g_variant_builder_end(&tupleb);
}
typedef struct {
@@ -1387,15 +1482,15 @@ foreach_helper (gpointer data, gpointer user_data)
}
/**
- dbusmenu_menuitem_foreach:
- @mi: The #DbusmenItem to start from
- @func: Function to call on every node in the tree
- @data: (closure): User data to pass to the function
-
- This calls the function @func on this menu item and all
- of the children of this item. And their children. And
- their children. And... you get the point. It will get
- called on the whole tree.
+ * dbusmenu_menuitem_foreach:
+ * @mi: The #DbusmenItem to start from
+ * @func: Function to call on every node in the tree
+ * @data: (closure): User data to pass to the function
+ *
+ * This calls the function @func on this menu item and all
+ * of the children of this item. And their children. And
+ * their children. And... you get the point. It will get
+ * called on the whole tree.
*/
void
dbusmenu_menuitem_foreach (DbusmenuMenuitem * mi, void (*func) (DbusmenuMenuitem * mi, gpointer data), gpointer data)
@@ -1411,23 +1506,23 @@ dbusmenu_menuitem_foreach (DbusmenuMenuitem * mi, void (*func) (DbusmenuMenuitem
}
/**
- dbusmenu_menuitem_handle_event:
- @mi: The #DbusmenuMenuitem to send the signal on.
- @name: The name of the signal
- @variant: A value that could be set for the event
- @timestamp: The timestamp of when the event happened
-
- This function is called to create an event. It is likely
- to be overrided by subclasses. The default menu item
- will respond to the activate signal and do:
-
- Emits the #DbusmenuMenuitem::item-activate signal on this
- menu item. Called by server objects when they get the
- appropriate DBus signals from the client.
-
- If you subclass this function you should really think
- about calling the parent function unless you have a good
- reason not to.
+ * dbusmenu_menuitem_handle_event:
+ * @mi: The #DbusmenuMenuitem to send the signal on.
+ * @name: The name of the signal
+ * @variant: A value that could be set for the event
+ * @timestamp: The timestamp of when the event happened
+ *
+ * This function is called to create an event. It is likely
+ * to be overrided by subclasses. The default menu item
+ * will respond to the activate signal and do:
+ *
+ * Emits the #DbusmenuMenuitem::item-activate signal on this
+ * menu item. Called by server objects when they get the
+ * appropriate DBus signals from the client.
+ *
+ * If you subclass this function you should really think
+ * about calling the parent function unless you have a good
+ * reason not to.
*/
void
dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * variant, guint timestamp)
@@ -1448,16 +1543,16 @@ dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, GVari
}
/**
- dbusmenu_menuitem_send_about_to_show:
- @mi: The #DbusmenuMenuitem to send the signal on.
- @cb: Callback to call when the call has returned.
- @cb_data: (closure): Data to pass to the callback.
-
- This function is used to send the even that the submenu
- of this item is about to be shown. Callers to this event
- should delay showing the menu until their callback is
- called if possible.
-*/
+ * dbusmenu_menuitem_send_about_to_show:
+ * @mi: The #DbusmenuMenuitem to send the signal on.
+ * @cb: Callback to call when the call has returned.
+ * @cb_data: (closure): Data to pass to the callback.
+ *
+ * This function is used to send the even that the submenu
+ * of this item is about to be shown. Callers to this event
+ * should delay showing the menu until their callback is
+ * called if possible.
+ */
void
dbusmenu_menuitem_send_about_to_show (DbusmenuMenuitem * mi, void (*cb) (DbusmenuMenuitem * mi, gpointer user_data), gpointer cb_data)
{
@@ -1477,14 +1572,14 @@ dbusmenu_menuitem_send_about_to_show (DbusmenuMenuitem * mi, void (*cb) (Dbusmen
}
/**
- dbusmenu_menuitem_show_to_user:
- @mi: #DbusmenuMenuitem to show
- @timestamp: The time that the user requested it to be shown
-
- Signals that this menu item should be shown to the user. If this is
- server side the server will then take it and send it over the
- bus.
-*/
+ * dbusmenu_menuitem_show_to_user:
+ * @mi: #DbusmenuMenuitem to show
+ * @timestamp: The time that the user requested it to be shown
+ *
+ * Signals that this menu item should be shown to the user. If this is
+ * server side the server will then take it and send it over the
+ * bus.
+ */
void
dbusmenu_menuitem_show_to_user (DbusmenuMenuitem * mi, guint timestamp)
{
@@ -1494,3 +1589,26 @@ dbusmenu_menuitem_show_to_user (DbusmenuMenuitem * mi, guint timestamp)
return;
}
+
+/* Checks to see if the value of this property is unique or just the
+ default value. */
+gboolean
+dbusmenu_menuitem_property_is_default (DbusmenuMenuitem * mi, const gchar * property)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE);
+ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi);
+
+ GVariant * currentval = (GVariant *)g_hash_table_lookup(priv->properties, property);
+ if (currentval != NULL) {
+ /* If we're storing it locally, then it shouldn't be a default */
+ return FALSE;
+ }
+
+ currentval = dbusmenu_defaults_default_get(priv->defaults, menuitem_get_type(mi), property);
+ if (currentval != NULL) {
+ return TRUE;
+ }
+
+ g_warn_if_reached();
+ return FALSE;
+}
diff --git a/libdbusmenu-glib/menuitem.h b/libdbusmenu-glib/menuitem.h
index dee7ee1..35d7ca8 100644
--- a/libdbusmenu-glib/menuitem.h
+++ b/libdbusmenu-glib/menuitem.h
@@ -112,14 +112,15 @@ struct _DbusmenuMenuitem
typedef void (*dbusmenu_menuitem_about_to_show_cb) (DbusmenuMenuitem * mi, gpointer user_data);
/**
- * dbusmenu_menuitem_buildxml_slot_t:
+ * dbusmenu_menuitem_buildvariant_slot_t:
* @mi: (in): Menu item that should be built from
- * @stringarray: (inout) (transfer none) (array) (element-type utf8): An array of strings that can be combined into an XML file.
*
* This is the function that is called to represent this menu item
- * as an XML fragment. Should call it's own children.
+ * as a variant. Should call it's own children.
+ *
+ * Return value: (transfer full) A variant representing this item and it's children
*/
-typedef void (*dbusmenu_menuitem_buildxml_slot_t) (DbusmenuMenuitem * mi, GPtrArray* stringarray);
+typedef GVariant * (*dbusmenu_menuitem_buildvariant_slot_t) (DbusmenuMenuitem * mi, gchar ** properties);
/**
* DbusmenuMenuitemClass:
@@ -157,8 +158,8 @@ struct _DbusmenuMenuitemClass
void (*realized) (void);
/* Virtual functions */
- dbusmenu_menuitem_buildxml_slot_t buildxml;
- void (*handle_event) (DbusmenuMenuitem * mi, const gchar * name, GVariant * value, guint timestamp);
+ dbusmenu_menuitem_buildvariant_slot_t buildvariant;
+ void (*handle_event) (DbusmenuMenuitem * mi, const gchar * name, GVariant * variant, guint timestamp);
void (*send_about_to_show) (DbusmenuMenuitem * mi, void (*cb) (DbusmenuMenuitem * mi, gpointer user_data), gpointer cb_data);
void (*show_to_user) (DbusmenuMenuitem * mi, guint timestamp, gpointer cb_data);
@@ -210,7 +211,7 @@ void dbusmenu_menuitem_set_root (DbusmenuMenuitem * mi, gboolean root);
gboolean dbusmenu_menuitem_get_root (DbusmenuMenuitem * mi);
void dbusmenu_menuitem_foreach (DbusmenuMenuitem * mi, void (*func) (DbusmenuMenuitem * mi, gpointer data), gpointer data);
-void dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * value, guint timestamp);
+void dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * variant, guint timestamp);
void dbusmenu_menuitem_send_about_to_show (DbusmenuMenuitem * mi, void (*cb) (DbusmenuMenuitem * mi, gpointer user_data), gpointer cb_data);
void dbusmenu_menuitem_show_to_user (DbusmenuMenuitem * mi, guint timestamp);
diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c
index adb9f91..aa39991 100644
--- a/libdbusmenu-glib/server.c
+++ b/libdbusmenu-glib/server.c
@@ -54,6 +54,9 @@ struct _DbusmenuServerPrivate
GDBusConnection * bus;
GCancellable * bus_lookup;
guint dbus_registration;
+
+ GArray * prop_array;
+ guint property_idle;
};
#define DBUSMENU_SERVER_GET_PRIVATE(o) (DBUSMENU_SERVER(o)->priv)
@@ -156,6 +159,7 @@ static void menuitem_signals_create (DbusmenuMenuitem * mi,
static void menuitem_signals_remove (DbusmenuMenuitem * mi,
gpointer data);
static GQuark error_quark (void);
+static void prop_array_teardown (GArray * prop_array);
static void bus_get_layout (DbusmenuServer * server,
GVariant * params,
GDBusMethodInvocation * invocation);
@@ -354,6 +358,17 @@ dbusmenu_server_dispose (GObject *object)
if (priv->layout_idle != 0) {
g_source_remove(priv->layout_idle);
+ priv->layout_idle = 0;
+ }
+
+ if (priv->property_idle != 0) {
+ g_source_remove(priv->property_idle);
+ priv->property_idle = 0;
+ }
+
+ if (priv->prop_array != NULL) {
+ prop_array_teardown(priv->prop_array);
+ priv->prop_array = NULL;
}
if (priv->root != NULL) {
@@ -418,6 +433,15 @@ set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
if (priv->root != NULL) {
dbusmenu_menuitem_foreach(priv->root, menuitem_signals_remove, obj);
dbusmenu_menuitem_set_root(priv->root, FALSE);
+
+ GList * properties = dbusmenu_menuitem_properties_list(priv->root);
+ GList * iter;
+ for (iter = properties; iter != NULL; iter = g_list_next(iter)) {
+ gchar * property = (gchar *)iter->data;
+ menuitem_property_changed(priv->root, property, NULL, DBUSMENU_SERVER(obj));
+ }
+ g_list_free(properties);
+
g_object_unref(G_OBJECT(priv->root));
priv->root = NULL;
}
@@ -426,6 +450,14 @@ set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
g_object_ref(G_OBJECT(priv->root));
dbusmenu_menuitem_set_root(priv->root, TRUE);
dbusmenu_menuitem_foreach(priv->root, menuitem_signals_create, obj);
+
+ GList * properties = dbusmenu_menuitem_properties_list(priv->root);
+ GList * iter;
+ for (iter = properties; iter != NULL; iter = g_list_next(iter)) {
+ gchar * property = (gchar *)iter->data;
+ menuitem_property_changed(priv->root, property, dbusmenu_menuitem_property_get_variant(priv->root, property), DBUSMENU_SERVER(obj));
+ }
+ g_list_free(properties);
} else {
g_debug("Setting root node to NULL");
}
@@ -440,17 +472,6 @@ set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
}
static void
-xmlarray_foreach_free (gpointer arrayentry, gpointer userdata)
-{
- if (arrayentry != NULL) {
- /* g_debug("Freeing pointer: %s", (gchar *)arrayentry); */
- g_free(arrayentry);
- }
-
- return;
-}
-
-static void
get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
{
DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(obj);
@@ -633,22 +654,264 @@ layout_update_signal (DbusmenuServer * server)
return;
}
-static void
-menuitem_property_changed (DbusmenuMenuitem * mi, gchar * property, GVariant * variant, DbusmenuServer * server)
+typedef struct _prop_idle_item_t prop_idle_item_t;
+struct _prop_idle_item_t {
+ gint id;
+ GArray * array;
+};
+
+typedef struct _prop_idle_prop_t prop_idle_prop_t;
+struct _prop_idle_prop_t {
+ gchar * property;
+ GVariant * variant;
+};
+
+/* Takes appart our data structure so we don't leak any
+ memory or references. */
+static void
+prop_array_teardown (GArray * prop_array)
{
- DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
+ int i, j;
+
+ for (i = 0; i < prop_array->len; i++) {
+ prop_idle_item_t * iitem = &g_array_index(prop_array, prop_idle_item_t, i);
+
+ for (j = 0; j < iitem->array->len; j++) {
+ prop_idle_prop_t * iprop = &g_array_index(iitem->array, prop_idle_prop_t, j);
+
+ g_free(iprop->property);
+
+ if (iprop->variant != NULL) {
+ g_variant_unref(iprop->variant);
+ }
+ }
+
+ g_array_free(iitem->array, TRUE);
+ }
+
+ g_array_free(prop_array, TRUE);
+
+ return;
+}
+
+/* Works in the idle to send a set of property updates so that they'll
+ all update in a single dbus message. */
+static gboolean
+menuitem_property_idle (gpointer user_data)
+{
+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(user_data);
+
+ /* Source will get removed as we return */
+ priv->property_idle = 0;
+
+ /* If there are no items, let's just not signal */
+ if (priv->prop_array == NULL) {
+ return FALSE;
+ }
+
+ int i, j;
+ GVariantBuilder itembuilder;
+ gboolean item_init = FALSE;
+
+ GVariantBuilder removeitembuilder;
+ gboolean removeitem_init = FALSE;
+
+ for (i = 0; i < priv->prop_array->len; i++) {
+ prop_idle_item_t * iitem = &g_array_index(priv->prop_array, prop_idle_item_t, i);
+
+ GVariantBuilder dictbuilder;
+ gboolean dictinit = FALSE;
+
+ GVariantBuilder removedictbuilder;
+ gboolean removedictinit = FALSE;
+
+ /* Go throught each item and see if it should go in the removal list
+ or the additive list. */
+ for (j = 0; j < iitem->array->len; j++) {
+ prop_idle_prop_t * iprop = &g_array_index(iitem->array, prop_idle_prop_t, j);
+
+ if (iprop->variant != NULL) {
+ if (!dictinit) {
+ g_variant_builder_init(&dictbuilder, G_VARIANT_TYPE_DICTIONARY);
+ dictinit = TRUE;
+ }
+
+ GVariant * entry = g_variant_new_dict_entry(g_variant_new_string(iprop->property),
+ g_variant_new_variant(iprop->variant));
+
+ g_variant_builder_add_value(&dictbuilder, entry);
+ } else {
+ if (!removedictinit) {
+ g_variant_builder_init(&removedictbuilder, G_VARIANT_TYPE_ARRAY);
+ removedictinit = TRUE;
+ }
+
+ g_variant_builder_add_value(&removedictbuilder, g_variant_new_string(iprop->property));
+ }
+ }
+
+ /* If we've got new values that are real values we need to add that
+ to the list of items to send the value of */
+ if (dictinit) {
+ GVariantBuilder tuplebuilder;
+ g_variant_builder_init(&tuplebuilder, G_VARIANT_TYPE_TUPLE);
+
+ g_variant_builder_add_value(&tuplebuilder, g_variant_new_int32(iitem->id));
+ g_variant_builder_add_value(&tuplebuilder, g_variant_builder_end(&dictbuilder));
+
+ if (!item_init) {
+ g_variant_builder_init(&itembuilder, G_VARIANT_TYPE_ARRAY);
+ item_init = TRUE;
+ }
+
+ g_variant_builder_add_value(&itembuilder, g_variant_builder_end(&tuplebuilder));
+ }
+
+ /* If we've got properties that have been removed then we need to add
+ them to the list of removed items */
+ if (removedictinit) {
+ GVariantBuilder tuplebuilder;
+ g_variant_builder_init(&tuplebuilder, G_VARIANT_TYPE_TUPLE);
+
+ g_variant_builder_add_value(&tuplebuilder, g_variant_new_int32(iitem->id));
+ g_variant_builder_add_value(&tuplebuilder, g_variant_builder_end(&removedictbuilder));
+
+ if (!removeitem_init) {
+ g_variant_builder_init(&removeitembuilder, G_VARIANT_TYPE_ARRAY);
+ removeitem_init = TRUE;
+ }
- g_signal_emit(G_OBJECT(server), signals[ID_PROP_UPDATE], 0, dbusmenu_menuitem_get_id(mi), property, variant, TRUE);
+ g_variant_builder_add_value(&removeitembuilder, g_variant_builder_end(&tuplebuilder));
+ }
+ }
+
+ GVariant * megadata[2];
+
+ if (item_init) {
+ megadata[0] = g_variant_builder_end(&itembuilder);
+ } else {
+ GError * error = NULL;
+ megadata[0] = g_variant_parse(G_VARIANT_TYPE("a(ia{sv})"), "[ ]", NULL, NULL, &error);
+
+ if (error != NULL) {
+ g_warning("Unable to parse '[ ]' as a 'a(ia{sv})': %s", error->message);
+ g_error_free(error);
+ }
+ }
+
+ if (removeitem_init) {
+ megadata[1] = g_variant_builder_end(&removeitembuilder);
+ } else {
+ GError * error = NULL;
+ megadata[1] = g_variant_parse(G_VARIANT_TYPE("a(ia(s))"), "[ ]", NULL, NULL, &error);
+
+ if (error != NULL) {
+ g_warning("Unable to parse '[ ]' as a 'a(ia(s))': %s", error->message);
+ g_error_free(error);
+ }
+ }
if (priv->dbusobject != NULL && priv->bus != NULL) {
g_dbus_connection_emit_signal(priv->bus,
NULL,
priv->dbusobject,
DBUSMENU_INTERFACE,
- "ItemPropertyUpdated",
- g_variant_new("(isv)", dbusmenu_menuitem_get_id(mi), property, variant),
+ "ItemPropertiesUpdated",
+ g_variant_new_tuple(megadata, 2),
NULL);
+ } else {
+ g_variant_unref(megadata[0]);
+ g_variant_unref(megadata[1]);
+ }
+
+ /* Clean everything up */
+ prop_array_teardown(priv->prop_array);
+ priv->prop_array = NULL;
+
+ return FALSE;
+}
+
+static void
+menuitem_property_changed (DbusmenuMenuitem * mi, gchar * property, GVariant * variant, DbusmenuServer * server)
+{
+ int i;
+ gint item_id;
+
+ DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
+
+ item_id = dbusmenu_menuitem_get_id(mi);
+
+ g_signal_emit(G_OBJECT(server), signals[ID_PROP_UPDATE], 0, item_id, property, variant, TRUE);
+
+ /* See if we have a property array, if not, we need to
+ build one of these suckers */
+ if (priv->prop_array == NULL) {
+ priv->prop_array = g_array_new(FALSE, FALSE, sizeof(prop_idle_item_t));
}
+
+ /* Look to see if we already have this item in the list
+ and use it if so */
+ prop_idle_item_t * item = NULL;
+ for (i = 0; i < priv->prop_array->len; i++) {
+ prop_idle_item_t * iitem = &g_array_index(priv->prop_array, prop_idle_item_t, i);
+ if (iitem->id == item_id) {
+ item = iitem;
+ break;
+ }
+ }
+
+ GArray * properties = NULL;
+ /* If not, we'll need to build ourselves one */
+ if (item == NULL) {
+ prop_idle_item_t myitem;
+ myitem.id = item_id;
+ myitem.array = g_array_new(FALSE, FALSE, sizeof(prop_idle_prop_t));
+
+ g_array_append_val(priv->prop_array, myitem);
+ properties = myitem.array;
+ } else {
+ properties = item->array;
+ }
+
+ /* Check to see if this property is in the list */
+ prop_idle_prop_t * prop = NULL;
+ for (i = 0; i < properties->len; i++) {
+ prop_idle_prop_t * iprop = &g_array_index(properties, prop_idle_prop_t, i);
+ if (g_strcmp0(iprop->property, property) == 0) {
+ prop = iprop;
+ break;
+ }
+ }
+
+ /* If it's the default value we want to treat it like a clearing
+ of the value so that it doesn't get sent over dbus and waste
+ bandwidth */
+ if (dbusmenu_menuitem_property_is_default(mi, property)) {
+ variant = NULL;
+ }
+
+ /* If so, we need to swap the value */
+ if (prop != NULL) {
+ g_variant_unref(prop->variant);
+ prop->variant = variant;
+ } else {
+ /* else we need to add it */
+ prop_idle_prop_t myprop;
+ myprop.property = g_strdup(property);
+ myprop.variant = variant;
+
+ g_array_append_val(properties, myprop);
+ }
+ if (variant != NULL) {
+ g_variant_ref_sink(variant);
+ }
+
+ /* Check to see if the idle is already queued, and queue it
+ if not. */
+ if (priv->property_idle == 0) {
+ priv->property_idle = g_idle_add(menuitem_property_idle, server);
+ }
+
return;
}
@@ -757,26 +1020,28 @@ bus_get_layout (DbusmenuServer * server, GVariant * params, GDBusMethodInvocatio
{
DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
- gint parent = 0;
- g_variant_get(params, "(i)", &parent);
+ /* Input */
+ gint parent = g_variant_get_int32(g_variant_get_child_value(params, 0));
+ gint recurse = g_variant_get_int32(g_variant_get_child_value(params, 1));
+ const gchar ** props = g_variant_get_strv(g_variant_get_child_value(params, 2), NULL);
+ /* Output */
guint revision = priv->layout_revision;
- GPtrArray * xmlarray = g_ptr_array_new();
+ GVariant * items = NULL;
- if (parent == 0) {
- if (priv->root == NULL) {
- /* g_debug("Getting layout without root node!"); */
- g_ptr_array_add(xmlarray, g_strdup("<menu id=\"0\"/>"));
- } else {
- dbusmenu_menuitem_buildxml(priv->root, xmlarray);
- }
- } else {
- DbusmenuMenuitem * item = NULL;
- if (priv->root != NULL) {
- item = dbusmenu_menuitem_find_id(priv->root, parent);
- }
+ if (priv->root != NULL) {
+ items = dbusmenu_menuitem_build_variant(priv->root, props, recurse);
+ }
- if (item == NULL) {
+ /* What happens if we don't have anything? */
+ if (items == NULL) {
+ if (parent == 0) {
+ /* We should always have a root, so we'll make up one for
+ right now. */
+ items = g_variant_parse(G_VARIANT_TYPE("(ia{sv}av)"), "(0, [], [])", NULL, NULL, NULL);
+ } else {
+ /* If we were looking for a specific ID that's an error that
+ we should send back, so let's do that. */
g_dbus_method_invocation_return_error(invocation,
error_quark(),
INVALID_MENUITEM_ID,
@@ -784,23 +1049,19 @@ bus_get_layout (DbusmenuServer * server, GVariant * params, GDBusMethodInvocatio
parent);
return;
}
- dbusmenu_menuitem_buildxml(item, xmlarray);
}
- g_ptr_array_add(xmlarray, NULL);
- /* build string */
- gchar * layout = g_strjoinv("", (gchar **)xmlarray->pdata);
+ /* Build the final variant tuple */
+ GVariantBuilder tuplebuilder;
+ g_variant_builder_init(&tuplebuilder, G_VARIANT_TYPE_TUPLE);
- g_ptr_array_foreach(xmlarray, xmlarray_foreach_free, NULL);
- g_ptr_array_free(xmlarray, TRUE);
+ g_variant_builder_add_value(&tuplebuilder, g_variant_new_uint32(revision));
+ g_variant_builder_add_value(&tuplebuilder, items);
+ GVariant * retval = g_variant_builder_end(&tuplebuilder);
+ // g_debug("Sending layout type: %s", g_variant_get_type_string(retval));
g_dbus_method_invocation_return_value(invocation,
- g_variant_new("(us)",
- revision,
- layout));
-
- g_free(layout);
-
+ retval);
return;
}
@@ -874,7 +1135,7 @@ bus_get_properties (DbusmenuServer * server, GVariant * params, GDBusMethodInvoc
return;
}
- GVariant * dict = dbusmenu_menuitem_properties_variant(mi);
+ GVariant * dict = dbusmenu_menuitem_properties_variant(mi, NULL);
g_dbus_method_invocation_return_value(invocation, g_variant_new("(a{sv})", dict));
@@ -922,7 +1183,7 @@ bus_get_group_properties (DbusmenuServer * server, GVariant * params, GDBusMetho
GVariantBuilder wbuilder;
g_variant_builder_init(&wbuilder, G_VARIANT_TYPE_TUPLE);
g_variant_builder_add(&wbuilder, "i", id);
- GVariant * props = dbusmenu_menuitem_properties_variant(mi);
+ GVariant * props = dbusmenu_menuitem_properties_variant(mi, NULL);
if (props == NULL) {
GError * error = NULL;
@@ -946,9 +1207,9 @@ bus_get_group_properties (DbusmenuServer * server, GVariant * params, GDBusMetho
ret = g_variant_builder_end(&builder);
} else {
GError * error = NULL;
- ret = g_variant_parse(g_variant_type_new("a(ia(sv))"), "[]", NULL, NULL, NULL);
+ ret = g_variant_parse(g_variant_type_new("a(ia{sv})"), "[]", NULL, NULL, NULL);
if (error != NULL) {
- g_warning("Unable to parse '[]' as a 'a(ia(sv))': %s", error->message);
+ g_warning("Unable to parse '[]' as a 'a(ia{sv})': %s", error->message);
g_error_free(error);
ret = NULL;
}
@@ -982,7 +1243,7 @@ serialize_menuitem(gpointer data, gpointer user_data)
gint id = dbusmenu_menuitem_get_id(mi);
g_variant_builder_add_value(&tuple, g_variant_new_int32(id));
- GVariant * props = dbusmenu_menuitem_properties_variant(mi);
+ GVariant * props = dbusmenu_menuitem_properties_variant(mi, NULL);
g_variant_builder_add_value(&tuple, props);
g_variant_builder_add_value(builder, g_variant_builder_end(&tuple));
@@ -1105,7 +1366,7 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i
event_data->variant = g_variant_get_variant(event_data->variant);
}
- g_variant_ref(event_data->variant);
+ g_variant_ref_sink(event_data->variant);
g_timeout_add(0, event_local_handler, event_data);
diff --git a/libdbusmenu-gtk/Makefile.am b/libdbusmenu-gtk/Makefile.am
index f3556e9..50a8f2c 100644
--- a/libdbusmenu-gtk/Makefile.am
+++ b/libdbusmenu-gtk/Makefile.am
@@ -78,27 +78,27 @@ if INTROSPECTION_TEN
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) \
--warn-all \
--add-include-path=$(top_builddir)/libdbusmenu-glib \
- $(addprefix --c-include=libdbusmenu-gtk/, $(introspection_sources)) \
+ $(addprefix --c-include=libdbusmenu-gtk/, $(libdbusmenu_gtkinclude_HEADERS)) \
--symbol-prefix=dbusmenu \
--identifier-prefix=DbusmenuGtk
else
INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) \
--warn-all \
--add-include-path=$(top_builddir)/libdbusmenu-glib \
- $(addprefix --c-include=libdbusmenu-gtk/, $(introspection_sources))
+ $(addprefix --c-include=libdbusmenu-gtk/, $(libdbusmenu_gtkinclude_HEADERS))
endif
INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir) --includedir=$(top_builddir)/libdbusmenu-glib
if HAVE_INTROSPECTION
-introspection_sources = $(libdbusmenu_gtkinclude_HEADERS)
+introspection_sources = $(filter-out genericmenuitem.%, $(libdbusmenu_gtkinclude_HEADERS) $(libdbusmenu_gtk_la_SOURCES))
DbusmenuGtk$(VER)-0.4.gir: libdbusmenu-gtk$(VER).la
DbusmenuGtk_0_4_gir_INCLUDES = \
GObject-2.0 \
$(GTKGIR) \
- Dbusmenu-Glib-0.4
+ Dbusmenu-0.4
DbusmenuGtk_0_4_gir_CFLAGS = $(DBUSMENUGTK_CFLAGS) -I$(top_srcdir)
DbusmenuGtk_0_4_gir_LIBS = libdbusmenu-gtk$(VER).la
DbusmenuGtk_0_4_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources))
@@ -141,7 +141,7 @@ DbusmenuGtk$(VER)-0.4.vapi: DbusmenuGtk$(VER)-0.4.tmp.gir Makefile.am
--pkg gdk-pixbuf-2.0 \
--pkg $(GTKVALA) \
--pkg atk \
- --pkg Dbusmenu-Glib-0.4 \
+ --pkg Dbusmenu-0.4 \
--vapidir=$(top_builddir)/libdbusmenu-glib \
$<
diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c
index 7ab2fe9..50978ff 100644
--- a/libdbusmenu-gtk/client.c
+++ b/libdbusmenu-gtk/client.c
@@ -219,13 +219,13 @@ refresh_shortcut (DbusmenuGtkClient * client, DbusmenuMenuitem * mi)
/**
- dbusmenu_gtkclient_set_accel_group:
- @client: To set the group on
- @agroup: The new acceleration group
-
- Sets the acceleration group for the menu items with accelerators
- on this client.
-*/
+ * dbusmenu_gtkclient_set_accel_group:
+ * @client: To set the group on
+ * @agroup: The new acceleration group
+ *
+ * Sets the acceleration group for the menu items with accelerators
+ * on this client.
+ */
void
dbusmenu_gtkclient_set_accel_group (DbusmenuGtkClient * client, GtkAccelGroup * agroup)
{
@@ -256,14 +256,14 @@ dbusmenu_gtkclient_set_accel_group (DbusmenuGtkClient * client, GtkAccelGroup *
}
/**
- dbusmenu_gtkclient_get_accel_group:
- @client: Client to query for an accelerator group
-
- Gets the accel group for this client.
-
- Return value: Either a valid group or #NULL on error or
- none set.
-*/
+ * dbusmenu_gtkclient_get_accel_group:
+ * @client: Client to query for an accelerator group
+ *
+ * Gets the accel group for this client.
+ *
+ * Return value: (transfer none): Either a valid group or #NULL on error or
+ * none set.
+ */
GtkAccelGroup *
dbusmenu_gtkclient_get_accel_group (DbusmenuGtkClient * client)
{
@@ -493,21 +493,21 @@ destroy_gmi (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
#endif
/**
- dbusmenu_gtkclient_newitem_base:
- @client: The client handling everything on this connection
- @item: The #DbusmenuMenuitem to attach the GTK-isms to
- @gmi: A #GtkMenuItem representing the GTK world's view of this menuitem
- @parent: The parent #DbusmenuMenuitem
-
- This function provides some of the basic connectivity for being in
- the GTK world. Things like visibility and sensitivity of the item are
- handled here so that the subclasses don't have to. If you're building
- your on GTK menu item you can use this function to apply those basic
- attributes so that you don't have to deal with them either.
-
- This also handles passing the "activate" signal back to the
- #DbusmenuMenuitem side of thing.
-*/
+ * dbusmenu_gtkclient_newitem_base:
+ * @client: The client handling everything on this connection
+ * @item: The #DbusmenuMenuitem to attach the GTK-isms to
+ * @gmi: A #GtkMenuItem representing the GTK world's view of this menuitem
+ * @parent: The parent #DbusmenuMenuitem
+ *
+ * This function provides some of the basic connectivity for being in
+ * the GTK world. Things like visibility and sensitivity of the item are
+ * handled here so that the subclasses don't have to. If you're building
+ * your on GTK menu item you can use this function to apply those basic
+ * attributes so that you don't have to deal with them either.
+ *
+ * This also handles passing the "activate" signal back to the
+ * #DbusmenuMenuitem side of thing.
+ */
void
dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem * item, GtkMenuItem * gmi, DbusmenuMenuitem * parent)
{
@@ -617,15 +617,15 @@ move_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint new, guint ol
/* Public API */
/**
- dbusmenu_gtkclient_new:
- @dbus_name: Name of the #DbusmenuServer on DBus
- @dbus_name: Name of the object on the #DbusmenuServer
-
- Creates a new #DbusmenuGtkClient object and creates a #DbusmenuClient
- that connects across DBus to a #DbusmenuServer.
-
- Return value: A new #DbusmenuGtkClient sync'd with a server
-*/
+ * dbusmenu_gtkclient_new:
+ * @dbus_name: Name of the #DbusmenuServer on DBus
+ * @dbus_object: Name of the object on the #DbusmenuServer
+ *
+ * Creates a new #DbusmenuGtkClient object and creates a #DbusmenuClient
+ * that connects across DBus to a #DbusmenuServer.
+ *
+ * Return value: A new #DbusmenuGtkClient sync'd with a server
+ */
DbusmenuGtkClient *
dbusmenu_gtkclient_new (gchar * dbus_name, gchar * dbus_object)
{
@@ -636,15 +636,15 @@ dbusmenu_gtkclient_new (gchar * dbus_name, gchar * dbus_object)
}
/**
- dbusmenu_gtkclient_menuitem_get:
- @client: A #DbusmenuGtkClient with the item in it.
- @item: #DbusmenuMenuitem to get associated #GtkMenuItem on.
-
- This grabs the #GtkMenuItem that is associated with the
- #DbusmenuMenuitem.
-
- Return value: The #GtkMenuItem that can be played with.
-*/
+ * dbusmenu_gtkclient_menuitem_get:
+ * @client: A #DbusmenuGtkClient with the item in it.
+ * @item: #DbusmenuMenuitem to get associated #GtkMenuItem on.
+ *
+ * This grabs the #GtkMenuItem that is associated with the
+ * #DbusmenuMenuitem.
+ *
+ * Return value: (transfer none): The #GtkMenuItem that can be played with.
+ */
GtkMenuItem *
dbusmenu_gtkclient_menuitem_get (DbusmenuGtkClient * client, DbusmenuMenuitem * item)
{
@@ -660,13 +660,13 @@ dbusmenu_gtkclient_menuitem_get (DbusmenuGtkClient * client, DbusmenuMenuitem *
}
/**
- dbusmenu_gtkclient_menuitem_get_submenu:
- @client: A #DbusmenuGtkClient with the item in it.
- @item: #DbusmenuMenuitem to get associated #GtkMenu on.
-
- This grabs the submenu associated with the menuitem.
-
- Return value: The #GtkMenu if there is one.
+ * dbusmenu_gtkclient_menuitem_get_submenu:
+ * @client: A #DbusmenuGtkClient with the item in it.
+ * @item: #DbusmenuMenuitem to get associated #GtkMenu on.
+ *
+ * This grabs the submenu associated with the menuitem.
+ *
+ * Return value: (transfer none): The #GtkMenu if there is one.
*/
GtkMenu *
dbusmenu_gtkclient_menuitem_get_submenu (DbusmenuGtkClient * client, DbusmenuMenuitem * item)
diff --git a/libdbusmenu-gtk/genericmenuitem.c b/libdbusmenu-gtk/genericmenuitem.c
index 2af70f3..2fd6fba 100644
--- a/libdbusmenu-gtk/genericmenuitem.c
+++ b/libdbusmenu-gtk/genericmenuitem.c
@@ -278,12 +278,12 @@ activate (GtkMenuItem * menu_item)
}
/**
- genericmenuitem_set_check_type:
- @item: #Genericmenuitem to set the type on
- @check_type: Which type of check should be displayed
-
- This function changes the type of the checkmark that
- appears in the left hand gutter for the menuitem.
+ * genericmenuitem_set_check_type:
+ * @item: #Genericmenuitem to set the type on
+ * @check_type: Which type of check should be displayed
+ *
+ * This function changes the type of the checkmark that
+ * appears in the left hand gutter for the menuitem.
*/
void
genericmenuitem_set_check_type (Genericmenuitem * item, GenericmenuitemCheckType check_type)
@@ -317,14 +317,14 @@ genericmenuitem_set_check_type (Genericmenuitem * item, GenericmenuitemCheckType
}
/**
- genericmenuitem_set_state:
- @item: #Genericmenuitem to set the type on
- @check_type: What is the state of the check
-
- Sets the state of the check in the menu item. It does
- not require, but isn't really useful if the type of
- check that the menuitem is set to #GENERICMENUITEM_CHECK_TYPE_NONE.
-*/
+ * genericmenuitem_set_state:
+ * @item: #Genericmenuitem to set the type on
+ * @check_type: What is the state of the check
+ *
+ * Sets the state of the check in the menu item. It does
+ * not require, but isn't really useful if the type of
+ * check that the menuitem is set to #GENERICMENUITEM_CHECK_TYPE_NONE.
+ */
void
genericmenuitem_set_state (Genericmenuitem * item, GenericmenuitemState state)
{
@@ -377,11 +377,11 @@ set_image_helper (GtkWidget * widget, gpointer data)
}
/**
- genericmenuitem_set_image:
- @item: A #Genericmenuitem
- @image: The image to set as the image of @item
-
- Sets the image of the menu item.
+ * genericmenuitem_set_image:
+ * @item: A #Genericmenuitem
+ * @image: The image to set as the image of @item
+ *
+ * Sets the image of the menu item.
*/
void
genericmenuitem_set_image (Genericmenuitem * menu_item, GtkWidget * image)
@@ -439,13 +439,13 @@ genericmenuitem_set_image (Genericmenuitem * menu_item, GtkWidget * image)
}
/**
- genericmenuitem_get_image:
- @item: A #Genericmenuitem
-
- Returns the image if there is one.
-
- Return value: A pointer to the image of the item or #NULL
- if there isn't one.
+ * genericmenuitem_get_image:
+ * @item: A #Genericmenuitem
+ *
+ * Returns the image if there is one.
+ *
+ * Return value: (transfer none): A pointer to the image of the item or #NULL
+ * if there isn't one.
*/
GtkWidget *
genericmenuitem_get_image (Genericmenuitem * menu_item)
diff --git a/libdbusmenu-gtk/menu.c b/libdbusmenu-gtk/menu.c
index 9c4f7f8..c2720ac 100644
--- a/libdbusmenu-gtk/menu.c
+++ b/libdbusmenu-gtk/menu.c
@@ -46,6 +46,7 @@ enum {
/* Private */
struct _DbusmenuGtkMenuPrivate {
DbusmenuGtkClient * client;
+ DbusmenuMenuitem * root;
gchar * dbus_object;
gchar * dbus_name;
@@ -63,6 +64,8 @@ static void get_property (GObject * obj, guint id, GValue * value, GParamSpec *
/* Internal */
static void build_client (DbusmenuGtkMenu * self);
static void child_realized (DbusmenuMenuitem * child, gpointer userdata);
+static void remove_child_signals (gpointer data, gpointer user_data);
+static void root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGtkMenu * menu);
/* GObject Stuff */
G_DEFINE_TYPE (DbusmenuGtkMenu, dbusmenu_gtkmenu, GTK_TYPE_MENU);
@@ -127,6 +130,12 @@ dbusmenu_gtkmenu_dispose (GObject *object)
{
DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(object);
+ /* Remove signals from the root */
+ if (priv->root != NULL) {
+ /* This will clear the root */
+ root_changed(priv->client, NULL, DBUSMENU_GTKMENU(object));
+ }
+
if (priv->client != NULL) {
g_object_unref(G_OBJECT(priv->client));
priv->client = NULL;
@@ -271,6 +280,10 @@ root_child_delete (DbusmenuMenuitem * root, DbusmenuMenuitem * child, DbusmenuGt
#ifdef MASSIVEDEBUGGING
g_debug("Root child deleted");
#endif
+
+ /* Remove signal for realized */
+ remove_child_signals(child, menu);
+
DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu);
GtkWidget * item = GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child));
if (item != NULL) {
@@ -308,15 +321,41 @@ child_realized (DbusmenuMenuitem * child, gpointer userdata)
return;
}
+/* Remove any signals we attached to children -- just realized right now */
+static void
+remove_child_signals (gpointer data, gpointer user_data)
+{
+ g_signal_handlers_disconnect_by_func(G_OBJECT(data), child_realized, user_data);
+ return;
+}
+
/* When the root menuitem changes we need to resetup things so that
we're back in the game. */
static void
root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGtkMenu * menu) {
+ DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu);
+
+ /* Clear out our interest in the old root */
+ if (priv->root != NULL) {
+ GList * children = dbusmenu_menuitem_get_children(priv->root);
+ g_list_foreach(children, remove_child_signals, menu);
+
+ g_signal_handlers_disconnect_by_func(G_OBJECT(priv->root), root_child_added, menu);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(priv->root), root_child_moved, menu);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(priv->root), root_child_delete, menu);
+
+ g_object_unref(priv->root);
+ priv->root = NULL;
+ }
+
if (newroot == NULL) {
gtk_widget_hide(GTK_WIDGET(menu));
return;
}
+ priv->root = newroot;
+ g_object_ref(priv->root);
+
g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(root_child_added), menu);
g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(root_child_moved), menu);
g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(root_child_delete), menu);
@@ -359,15 +398,15 @@ build_client (DbusmenuGtkMenu * self)
/* Public API */
/**
- dbusmenu_gtkmenu_new:
- @dbus_name: Name of the #DbusmenuServer on DBus
- @dbus_name: Name of the object on the #DbusmenuServer
-
- Creates a new #DbusmenuGtkMenu object and creates a #DbusmenuClient
- that connects across DBus to a #DbusmenuServer.
-
- Return value: A new #DbusmenuGtkMenu sync'd with a server
-*/
+ * dbusmenu_gtkmenu_new:
+ * @dbus_name: Name of the #DbusmenuServer on DBus
+ * @dbus_object: Name of the object on the #DbusmenuServer
+ *
+ * Creates a new #DbusmenuGtkMenu object and creates a #DbusmenuClient
+ * that connects across DBus to a #DbusmenuServer.
+ *
+ * Return value: A new #DbusmenuGtkMenu sync'd with a server
+ */
DbusmenuGtkMenu *
dbusmenu_gtkmenu_new (gchar * dbus_name, gchar * dbus_object)
{
@@ -378,14 +417,14 @@ dbusmenu_gtkmenu_new (gchar * dbus_name, gchar * dbus_object)
}
/**
- dbusmenu_gtkmenu_get_client:
- @menu: The #DbusmenuGtkMenu to get the client from
-
- An accessor for the client that this menu is using to
- communicate with the server.
-
- Return value: A valid #DbusmenuGtkClient or NULL on error.
-*/
+ * dbusmenu_gtkmenu_get_client:
+ * @menu: The #DbusmenuGtkMenu to get the client from
+ *
+ * An accessor for the client that this menu is using to
+ * communicate with the server.
+ *
+ * Return value: (transfer none): A valid #DbusmenuGtkClient or NULL on error.
+ */
DbusmenuGtkClient *
dbusmenu_gtkmenu_get_client (DbusmenuGtkMenu * menu)
{
diff --git a/libdbusmenu-gtk/menuitem.c b/libdbusmenu-gtk/menuitem.c
index fa5eb89..508b43f 100644
--- a/libdbusmenu-gtk/menuitem.c
+++ b/libdbusmenu-gtk/menuitem.c
@@ -31,17 +31,17 @@ License version 3 and version 2.1 along with this program. If not, see
#include <gtk/gtk.h>
/**
- dbusmenu_menuitem_property_set_image:
- @menuitem: The #DbusmenuMenuitem to set the property on.
- @property: Name of the property to set.
- @data: The image to place on the property.
-
- This function takes the pixbuf that is stored in @data and
- turns it into a base64 encoded PNG so that it can be placed
- onto a standard #DbusmenuMenuitem property.
-
- Return value: Whether the function was able to set the property
- or not.
+ * dbusmenu_menuitem_property_set_image:
+ * @menuitem: The #DbusmenuMenuitem to set the property on.
+ * @property: Name of the property to set.
+ * @data: The image to place on the property.
+ *
+ * This function takes the pixbuf that is stored in @data and
+ * turns it into a base64 encoded PNG so that it can be placed
+ * onto a standard #DbusmenuMenuitem property.
+ *
+ * Return value: Whether the function was able to set the property
+ * or not.
*/
gboolean
dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar * property, const GdkPixbuf * data)
@@ -77,17 +77,17 @@ dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar *
}
/**
- dbusmenu_menuitem_property_get_image:
- @menuitem: The #DbusmenuMenuite to look for the property on
- @property: The name of the property to look for.
-
- This function looks on the menu item for a property by the
- name of @property. If one exists it tries to turn it into
- a #GdkPixbuf. It assumes that the property is a base64 encoded
- PNG file like the one created by #dbusmenu_menuite_property_set_image.
-
- Return value: A pixbuf or #NULL to signal error.
-*/
+ * dbusmenu_menuitem_property_get_image:
+ * @menuitem: The #DbusmenuMenuitem to look for the property on
+ * @property: The name of the property to look for.
+ *
+ * This function looks on the menu item for a property by the
+ * name of @property. If one exists it tries to turn it into
+ * a #GdkPixbuf. It assumes that the property is a base64 encoded
+ * PNG file like the one created by #dbusmenu_menuite_property_set_image.
+ *
+ * Return value: (transfer full): A pixbuf or #NULL to signal error.
+ */
GdkPixbuf *
dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * property)
{
@@ -131,16 +131,16 @@ dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar *
}
/**
- dbusmenu_menuitem_property_set_shortcut_string:
- @menuitem: The #DbusmenuMenuitem to set the shortcut on
- @shortcut: String describing the shortcut
-
- This function takes a GTK shortcut string as defined in
- #gtk_accelerator_parse and turns that into the information
- required to send it over DBusmenu.
-
- Return value: Whether it was successful at setting the property.
-*/
+ * dbusmenu_menuitem_property_set_shortcut_string:
+ * @menuitem: The #DbusmenuMenuitem to set the shortcut on
+ * @shortcut: String describing the shortcut
+ *
+ * This function takes a GTK shortcut string as defined in
+ * #gtk_accelerator_parse and turns that into the information
+ * required to send it over DBusmenu.
+ *
+ * Return value: Whether it was successful at setting the property.
+ */
gboolean
dbusmenu_menuitem_property_set_shortcut_string (DbusmenuMenuitem * menuitem, const gchar * shortcut)
{
@@ -161,16 +161,16 @@ dbusmenu_menuitem_property_set_shortcut_string (DbusmenuMenuitem * menuitem, con
}
/**
- dbusmenu_menuitem_property_set_shortcut:
- @menuitem: The #DbusmenuMenuitem to set the shortcut on
- @key: The keycode of the key to send
- @modifier: A bitmask of modifiers used to activate the item
-
- Takes the modifer described by @key and @modifier and places that into
- the format sending across Dbus for shortcuts.
-
- Return value: Whether it was successful at setting the property.
-*/
+ * dbusmenu_menuitem_property_set_shortcut:
+ * @menuitem: The #DbusmenuMenuitem to set the shortcut on
+ * @key: The keycode of the key to send
+ * @modifier: A bitmask of modifiers used to activate the item
+ *
+ * Takes the modifer described by @key and @modifier and places that into
+ * the format sending across Dbus for shortcuts.
+ *
+ * Return value: Whether it was successful at setting the property.
+ */
gboolean
dbusmenu_menuitem_property_set_shortcut (DbusmenuMenuitem * menuitem, guint key, GdkModifierType modifier)
{
@@ -213,16 +213,16 @@ find_closure (GtkAccelKey * key, GClosure * closure, gpointer user_data)
}
/**
- dbusmenu_menuitem_property_set_shortcut_menuitem:
- @menuitem: The #DbusmenuMenuitem to set the shortcut on
- @gmi: A menu item to steal the shortcut off of
-
- Takes the shortcut that is installed on a menu item and calls
- #dbusmenu_menuitem_property_set_shortcut with it. It also sets
- up listeners to watch it change.
-
- Return value: Whether it was successful at setting the property.
-*/
+ * dbusmenu_menuitem_property_set_shortcut_menuitem:
+ * @menuitem: The #DbusmenuMenuitem to set the shortcut on
+ * @gmi: A menu item to steal the shortcut off of
+ *
+ * Takes the shortcut that is installed on a menu item and calls
+ * #dbusmenu_menuitem_property_set_shortcut with it. It also sets
+ * up listeners to watch it change.
+ *
+ * Return value: Whether it was successful at setting the property.
+ */
gboolean
dbusmenu_menuitem_property_set_shortcut_menuitem (DbusmenuMenuitem * menuitem, const GtkMenuItem * gmi)
{
@@ -260,14 +260,14 @@ dbusmenu_menuitem_property_set_shortcut_menuitem (DbusmenuMenuitem * menuitem, c
}
/**
- dbusmenu_menuitem_property_get_shortcut:
- @menuitem: The #DbusmenuMenuitem to get the shortcut off
- @key: Location to put the key value
- @modifier: Location to put the modifier mask
-
- This function gets a GTK shortcut as a key and a mask
- for use to set the accelerators.
-*/
+ * dbusmenu_menuitem_property_get_shortcut:
+ * @menuitem: The #DbusmenuMenuitem to get the shortcut off
+ * @key: (out): Location to put the key value
+ * @modifier: (out): Location to put the modifier mask
+ *
+ * This function gets a GTK shortcut as a key and a mask
+ * for use to set the accelerators.
+ */
void
dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * key, GdkModifierType * modifier)
{
diff --git a/libdbusmenu-gtk/menuitem.h b/libdbusmenu-gtk/menuitem.h
index 4fc42f9..6f009df 100644
--- a/libdbusmenu-gtk/menuitem.h
+++ b/libdbusmenu-gtk/menuitem.h
@@ -43,7 +43,7 @@ GdkPixbuf * dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, c
gboolean dbusmenu_menuitem_property_set_shortcut (DbusmenuMenuitem * menuitem, guint key, GdkModifierType modifier);
gboolean dbusmenu_menuitem_property_set_shortcut_string (DbusmenuMenuitem * menuitem, const gchar * shortcut);
gboolean dbusmenu_menuitem_property_set_shortcut_menuitem (DbusmenuMenuitem * menuitem, const GtkMenuItem * gmi);
-void dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * key, GdkModifierType * modifiers);
+void dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * key, GdkModifierType * modifier);
G_END_DECLS
diff --git a/libdbusmenu-gtk/parser.c b/libdbusmenu-gtk/parser.c
index 5d71585..f516dde 100644
--- a/libdbusmenu-gtk/parser.c
+++ b/libdbusmenu-gtk/parser.c
@@ -31,6 +31,16 @@ License version 3 and version 2.1 along with this program. If not, see
#include "serializablemenuitem.h"
#define CACHED_MENUITEM "dbusmenu-gtk-parser-cached-item"
+#define PARSER_DATA "dbusmenu-gtk-parser-data"
+
+typedef struct _ParserData
+{
+ GtkWidget *label;
+ GtkAction *action;
+ GtkWidget *widget;
+ GtkWidget *shell;
+ GtkWidget *image;
+} ParserData;
typedef struct _RecurseContext
{
@@ -42,19 +52,25 @@ static void parse_menu_structure_helper (GtkWidget * widget, RecurseContext * re
static DbusmenuMenuitem * construct_dbusmenu_for_widget (GtkWidget * widget);
static void accel_changed (GtkWidget * widget,
gpointer data);
-static gboolean update_stock_item (DbusmenuMenuitem * menuitem,
- GtkWidget * widget);
static void checkbox_toggled (GtkWidget * widget,
DbusmenuMenuitem * mi);
-static void update_icon_name (DbusmenuMenuitem * menuitem,
- GtkWidget * widget);
+static void update_icon (DbusmenuMenuitem * menuitem,
+ GtkImage * image);
static GtkWidget * find_menu_label (GtkWidget * widget);
static void label_notify_cb (GtkWidget * widget,
GParamSpec * pspec,
gpointer data);
+static void image_notify_cb (GtkWidget * widget,
+ GParamSpec * pspec,
+ gpointer data);
static void action_notify_cb (GtkAction * action,
GParamSpec * pspec,
gpointer data);
+static void child_added_cb (GtkContainer * menu,
+ GtkWidget * widget,
+ gpointer data);
+static void theme_changed_cb (GtkIconTheme * theme,
+ gpointer data);
static void item_activated (DbusmenuMenuitem * item,
guint timestamp,
gpointer user_data);
@@ -69,16 +85,16 @@ static void menuitem_notify_cb (GtkWidget * widget,
gpointer data);
/**
- dbusmenu_gtk_parse_menu_structure:
- @widget: A #GtkMenuItem or #GtkMenuShell to turn into a #DbusmenuMenuitem
-
- Goes through the GTK structures and turns them into the appropraite
- Dbusmenu structures along with setting up all the relationships
- between the objects. It also stores the dbusmenu items as a cache
- on the GTK items so that they'll be reused if necissary.
-
- Return value: A dbusmenu item representing the menu structure
-*/
+ * dbusmenu_gtk_parse_menu_structure:
+ * @widget: A #GtkMenuItem or #GtkMenuShell to turn into a #DbusmenuMenuitem
+ *
+ * Goes through the GTK structures and turns them into the appropraite
+ * Dbusmenu structures along with setting up all the relationships
+ * between the objects. It also stores the dbusmenu items as a cache
+ * on the GTK items so that they'll be reused if necissary.
+ *
+ * Return value: (transfer full): A dbusmenu item representing the menu structure
+ */
DbusmenuMenuitem *
dbusmenu_gtk_parse_menu_structure (GtkWidget * widget)
{
@@ -101,7 +117,34 @@ dbusmenu_cache_freed (gpointer data, GObject * obj)
/* If the dbusmenu item is killed we don't need to remove
the weak ref as well. */
g_object_steal_data(G_OBJECT(data), CACHED_MENUITEM);
- g_signal_handlers_disconnect_by_func(data, G_CALLBACK(widget_notify_cb), obj);
+
+ ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(obj), PARSER_DATA);
+
+ if (pdata != NULL && pdata->label != NULL) {
+ g_signal_handlers_disconnect_by_func(pdata->label, G_CALLBACK(label_notify_cb), obj);
+ g_object_remove_weak_pointer(G_OBJECT(pdata->label), (gpointer*)&pdata->label);
+ }
+
+ if (pdata != NULL && pdata->action != NULL) {
+ g_signal_handlers_disconnect_by_func(pdata->action, G_CALLBACK(action_notify_cb), obj);
+ g_object_remove_weak_pointer(G_OBJECT(pdata->action), (gpointer*)&pdata->action);
+ }
+
+ if (pdata != NULL && pdata->widget != NULL) {
+ g_signal_handlers_disconnect_by_func(pdata->widget, G_CALLBACK(widget_notify_cb), obj);
+ g_object_remove_weak_pointer(G_OBJECT(pdata->widget), (gpointer*)&pdata->widget);
+ }
+
+ if (pdata != NULL && pdata->shell != NULL) {
+ g_signal_handlers_disconnect_by_func(pdata->shell, G_CALLBACK(child_added_cb), obj);
+ g_object_remove_weak_pointer(G_OBJECT(pdata->shell), (gpointer*)&pdata->shell);
+ }
+
+ if (pdata != NULL && pdata->image != NULL) {
+ g_signal_handlers_disconnect_by_func(pdata->image, G_CALLBACK(image_notify_cb), obj);
+ g_object_remove_weak_pointer(G_OBJECT(pdata->image), (gpointer*)&pdata->image);
+ }
+
return;
}
@@ -110,11 +153,59 @@ dbusmenu_cache_freed (gpointer data, GObject * obj)
static void
object_cache_freed (gpointer data)
{
- if (!G_IS_OBJECT(data)) return;
- g_object_weak_unref(G_OBJECT(data), dbusmenu_cache_freed, data);
+ // TODO: make this have access to both data and obj so we can call these
+ //if (!G_IS_OBJECT(obj)) return;
+ //g_object_weak_unref(G_OBJECT(obj), dbusmenu_cache_freed, data);
+ //dbusmenu_cache_freed(data, obj);
+
+ g_signal_handlers_disconnect_by_func(gtk_icon_theme_get_default(), G_CALLBACK(theme_changed_cb), data);
+
return;
}
+/* Gets the positon of the child with its' parent if it has one.
+ Returns -1 if the position is unable to be calculated. */
+static gint
+get_child_position (GtkWidget * child)
+{
+ GtkWidget * parent = gtk_widget_get_parent (child);
+ if (parent == NULL || !GTK_IS_CONTAINER (parent))
+ return -1;
+
+ GList * children = gtk_container_get_children (GTK_CONTAINER (parent));
+ GList * iter;
+ gint position = 0;
+
+ for (iter = children; iter != NULL; iter = iter->next) {
+ if (iter->data == child)
+ break;
+ ++position;
+ }
+
+ g_list_free (children);
+
+ if (iter == NULL)
+ return -1;
+ else
+ return position;
+}
+
+/* Creates a new menu item that is attached to the widget and has
+ the data linkages hooked up. Also allocates the ParserData */
+static DbusmenuMenuitem *
+new_menuitem (GtkWidget * widget)
+{
+ DbusmenuMenuitem * item = dbusmenu_menuitem_new();
+
+ ParserData *pdata = g_new0 (ParserData, 1);
+ g_object_set_data_full(G_OBJECT(item), PARSER_DATA, pdata, g_free);
+
+ g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, item, object_cache_freed);
+ g_object_weak_ref(G_OBJECT(item), dbusmenu_cache_freed, widget);
+
+ return item;
+}
+
static void
parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
{
@@ -133,10 +224,11 @@ parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
*/
if (recurse->parent == NULL && GTK_IS_MENU_BAR(widget)) {
GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
+ GList *iter;
- for (; children != NULL; children = children->next) {
+ for (iter = children; iter != NULL; iter = iter->next) {
gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget),
- children->data,
+ iter->data,
TRUE);
}
@@ -144,9 +236,18 @@ parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
}
if (recurse->parent == NULL) {
- recurse->parent = dbusmenu_menuitem_new();
+ recurse->parent = new_menuitem(widget);
}
+ ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(recurse->parent), PARSER_DATA);
+
+ pdata->shell = widget;
+ g_signal_connect (G_OBJECT (widget),
+ "child-added",
+ G_CALLBACK (child_added_cb),
+ recurse->parent);
+ g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->shell);
+
gtk_container_foreach (GTK_CONTAINER (widget),
(GtkCallback)parse_menu_structure_helper,
recurse);
@@ -166,8 +267,6 @@ parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
/* We don't have one, so we'll need to build it */
if (thisitem == NULL) {
thisitem = construct_dbusmenu_for_widget (widget);
- g_object_set_data_full(G_OBJECT(widget), CACHED_MENUITEM, thisitem, object_cache_freed);
- g_object_weak_ref(G_OBJECT(thisitem), dbusmenu_cache_freed, widget);
if (!gtk_widget_get_visible (widget)) {
g_signal_connect (G_OBJECT (widget),
@@ -199,8 +298,14 @@ parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
g_object_set_data (G_OBJECT (thisitem),
"dbusmenu-parent",
recurse->parent);
- dbusmenu_menuitem_child_append (recurse->parent,
- thisitem);
+ gint pos = get_child_position (widget);
+ if (pos >= 0)
+ dbusmenu_menuitem_child_add_position (recurse->parent,
+ thisitem,
+ pos);
+ else
+ dbusmenu_menuitem_child_append (recurse->parent,
+ thisitem);
}
}
@@ -237,7 +342,9 @@ construct_dbusmenu_for_widget (GtkWidget * widget)
/* If it's a standard GTK Menu Item we need to do some of our own work */
if (GTK_IS_MENU_ITEM (widget))
{
- DbusmenuMenuitem *mi = dbusmenu_menuitem_new ();
+ DbusmenuMenuitem *mi = new_menuitem(widget);
+
+ ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(mi), PARSER_DATA);
gboolean visible = FALSE;
gboolean sensitive = FALSE;
@@ -252,8 +359,6 @@ construct_dbusmenu_for_widget (GtkWidget * widget)
}
else
{
- gboolean label_set = FALSE;
-
g_signal_connect (widget,
"accel-closures-changed",
G_CALLBACK (accel_changed),
@@ -278,45 +383,43 @@ construct_dbusmenu_for_widget (GtkWidget * widget)
if (GTK_IS_IMAGE_MENU_ITEM (widget))
{
GtkWidget *image;
- GtkImageType image_type;
image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget));
if (GTK_IS_IMAGE (image))
{
- image_type = gtk_image_get_storage_type (GTK_IMAGE (image));
-
- if (image_type == GTK_IMAGE_STOCK)
- {
- label_set = update_stock_item (mi, image);
- }
- else if (image_type == GTK_IMAGE_ICON_NAME)
- {
- update_icon_name (mi, image);
- }
- else if (image_type == GTK_IMAGE_PIXBUF)
- {
- dbusmenu_menuitem_property_set_image (mi,
- DBUSMENU_MENUITEM_PROP_ICON_DATA,
- gtk_image_get_pixbuf (GTK_IMAGE (image)));
- }
+ update_icon (mi, GTK_IMAGE (image));
+
+ /* Watch for theme changes because if gicon changes, we want to send a
+ different pixbuf. */
+ g_signal_connect(G_OBJECT(gtk_icon_theme_get_default()),
+ "changed", G_CALLBACK(theme_changed_cb), widget);
+
+ pdata->image = image;
+ g_signal_connect (G_OBJECT (image),
+ "notify",
+ G_CALLBACK (image_notify_cb),
+ mi);
+ g_object_add_weak_pointer(G_OBJECT (image), (gpointer*)&pdata->image);
}
}
GtkWidget *label = find_menu_label (widget);
- dbusmenu_menuitem_property_set (mi,
- "label",
- label ? gtk_label_get_text (GTK_LABEL (label)) : NULL);
-
if (label)
{
// Sometimes, an app will directly find and modify the label
// (like empathy), so watch the label especially for that.
+ dbusmenu_menuitem_property_set (mi,
+ "label",
+ gtk_label_get_text (GTK_LABEL (label)));
+
+ pdata->label = label;
g_signal_connect (G_OBJECT (label),
"notify",
G_CALLBACK (label_notify_cb),
mi);
+ g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label);
}
if (GTK_IS_ACTIVATABLE (widget))
@@ -332,10 +435,12 @@ construct_dbusmenu_for_widget (GtkWidget * widget)
visible = gtk_action_is_visible (action);
sensitive = gtk_action_is_sensitive (action);
+ pdata->action = action;
g_signal_connect_object (action, "notify",
G_CALLBACK (action_notify_cb),
mi,
G_CONNECT_AFTER);
+ g_object_add_weak_pointer(G_OBJECT (action), (gpointer*)&pdata->action);
}
}
}
@@ -367,16 +472,19 @@ construct_dbusmenu_for_widget (GtkWidget * widget)
DBUSMENU_MENUITEM_PROP_ENABLED,
sensitive);
+ pdata->widget = widget;
g_signal_connect (widget,
"notify",
G_CALLBACK (widget_notify_cb),
mi);
+ g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->widget);
+
return mi;
}
/* If it's none of those we're going to just create a
generic menuitem as a place holder for it. */
- return dbusmenu_menuitem_new();
+ return new_menuitem(widget);
}
static void
@@ -408,48 +516,6 @@ accel_changed (GtkWidget *widget,
dbusmenu_menuitem_property_set_shortcut_menuitem (mi, GTK_MENU_ITEM (widget));
}
-static gboolean
-update_stock_item (DbusmenuMenuitem *menuitem,
- GtkWidget *widget)
-{
- GtkStockItem stock;
- GtkImage *image;
-
- g_return_val_if_fail (GTK_IS_IMAGE (widget), FALSE);
-
- image = GTK_IMAGE (widget);
-
- if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK)
- return FALSE;
-
- gchar * stock_id = NULL;
- gtk_image_get_stock(image, &stock_id, NULL);
-
- gtk_stock_lookup (stock_id, &stock);
-
- if (should_show_image (image))
- dbusmenu_menuitem_property_set (menuitem,
- DBUSMENU_MENUITEM_PROP_ICON_NAME,
- stock_id);
- else
- dbusmenu_menuitem_property_remove (menuitem,
- DBUSMENU_MENUITEM_PROP_ICON_NAME);
-
- const gchar *label = dbusmenu_menuitem_property_get (menuitem,
- DBUSMENU_MENUITEM_PROP_LABEL);
-
- if (stock.label != NULL && label != NULL)
- {
- dbusmenu_menuitem_property_set (menuitem,
- DBUSMENU_MENUITEM_PROP_LABEL,
- stock.label);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
static void
checkbox_toggled (GtkWidget *widget, DbusmenuMenuitem *mi)
{
@@ -459,27 +525,86 @@ checkbox_toggled (GtkWidget *widget, DbusmenuMenuitem *mi)
}
static void
-update_icon_name (DbusmenuMenuitem *menuitem,
- GtkWidget *widget)
+update_icon (DbusmenuMenuitem *menuitem, GtkImage *image)
{
- GtkImage *image;
-
- g_return_if_fail (GTK_IS_IMAGE (widget));
-
- image = GTK_IMAGE (widget);
+ GdkPixbuf * pixbuf = NULL;
+ const gchar * icon_name = NULL;
+ GtkStockItem stock;
+ GIcon * gicon;
+ GtkIconInfo * info;
+ gint width;
+
+ if (image != NULL && should_show_image (image)) {
+ switch (gtk_image_get_storage_type (image)) {
+ case GTK_IMAGE_PIXBUF:
+ pixbuf = g_object_ref (gtk_image_get_pixbuf (image));
+ break;
+
+ case GTK_IMAGE_ICON_NAME:
+ gtk_image_get_icon_name (image, &icon_name, NULL);
+ break;
+
+ case GTK_IMAGE_STOCK:
+ gtk_image_get_stock (image, (gchar **) &icon_name, NULL);
+ if (gtk_stock_lookup (icon_name, &stock)) {
+ /* Now set label too */
+ const gchar * label = NULL;
+ label = dbusmenu_menuitem_property_get (menuitem,
+ DBUSMENU_MENUITEM_PROP_LABEL);
+ if (stock.label != NULL && label != NULL) {
+ dbusmenu_menuitem_property_set (menuitem,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ stock.label);
+ }
+ }
+ break;
+
+ case GTK_IMAGE_GICON:
+ /* Load up a pixbuf and send that over. We don't bother differentiating
+ between icon-name gicons and pixbuf gicons because even when given a
+ icon-name gicon, there's no easy way to lookup which icon-name among
+ its set is present and should be used among the icon themes available.
+ So instead, we render to a pixbuf and watch icon theme changes. */
+ gtk_image_get_gicon (image, &gicon, NULL);
+ gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, NULL);
+ info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
+ gicon, width,
+ GTK_ICON_LOOKUP_FORCE_SIZE);
+ if (info != NULL) {
+ pixbuf = gtk_icon_info_load_icon (info, NULL);
+ gtk_icon_info_free (info);
+ }
+ break;
- if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME)
- return;
+ default:
+ g_debug ("Could not handle image type %i\n", gtk_image_get_storage_type (image));
+ break;
+ }
+ }
- if (should_show_image (image)) {
- const gchar * icon_name = NULL;
- gtk_image_get_icon_name(image, &icon_name, NULL);
+ if (icon_name != NULL) {
dbusmenu_menuitem_property_set (menuitem,
DBUSMENU_MENUITEM_PROP_ICON_NAME,
icon_name);
- } else {
+ dbusmenu_menuitem_property_remove (menuitem,
+ DBUSMENU_MENUITEM_PROP_ICON_DATA);
+ }
+ else if (pixbuf != NULL) {
dbusmenu_menuitem_property_remove (menuitem,
DBUSMENU_MENUITEM_PROP_ICON_NAME);
+ dbusmenu_menuitem_property_set_image (menuitem,
+ DBUSMENU_MENUITEM_PROP_ICON_DATA,
+ pixbuf);
+ }
+ else {
+ dbusmenu_menuitem_property_remove (menuitem,
+ DBUSMENU_MENUITEM_PROP_ICON_NAME);
+ dbusmenu_menuitem_property_remove (menuitem,
+ DBUSMENU_MENUITEM_PROP_ICON_DATA);
+ }
+
+ if (pixbuf != NULL) {
+ g_object_unref (pixbuf);
}
}
@@ -528,6 +653,29 @@ label_notify_cb (GtkWidget *widget,
}
static void
+image_notify_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ DbusmenuMenuitem *mi = (DbusmenuMenuitem *)data;
+
+ if (pspec->name == g_intern_static_string ("file") ||
+ pspec->name == g_intern_static_string ("gicon") ||
+ pspec->name == g_intern_static_string ("icon-name") ||
+ pspec->name == g_intern_static_string ("icon-set") ||
+ pspec->name == g_intern_static_string ("image") ||
+ pspec->name == g_intern_static_string ("mask") ||
+ pspec->name == g_intern_static_string ("pixbuf") ||
+ pspec->name == g_intern_static_string ("pixbuf-animation") ||
+ pspec->name == g_intern_static_string ("pixmap") ||
+ pspec->name == g_intern_static_string ("stock") ||
+ pspec->name == g_intern_static_string ("storage-type"))
+ {
+ update_icon (mi, GTK_IMAGE (widget));
+ }
+}
+
+static void
action_notify_cb (GtkAction *action,
GParamSpec *pspec,
gpointer data)
@@ -621,13 +769,12 @@ widget_notify_cb (GtkWidget *widget,
DBUSMENU_MENUITEM_PROP_VISIBLE,
gtk_widget_get_visible (widget));
}
- else if (pspec->name == g_intern_static_string ("stock"))
+ else if (pspec->name == g_intern_static_string ("image") ||
+ pspec->name == g_intern_static_string ("always-show-image"))
{
- update_stock_item (child, widget);
- }
- else if (pspec->name == g_intern_static_string ("icon-name"))
- {
- update_icon_name (child, widget);
+ GtkWidget *image;
+ image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget));
+ update_icon (child, GTK_IMAGE (image));
}
else if (pspec->name == g_intern_static_string ("parent"))
{
@@ -649,6 +796,67 @@ widget_notify_cb (GtkWidget *widget,
}
}
}
+ else if (pspec->name == g_intern_static_string ("submenu"))
+ {
+ /* The underlying submenu got swapped out. Let's see what it is now. */
+ /* First, delete any children that may exist currently. */
+ DbusmenuMenuitem * item = DBUSMENU_MENUITEM(g_object_get_data(G_OBJECT(widget), CACHED_MENUITEM));
+ if (item != NULL)
+ {
+ GList * children = dbusmenu_menuitem_take_children (item);
+ GList * child = children;
+ while (child != NULL) {
+ g_object_unref (G_OBJECT(child->data));
+ child = child->next;
+ }
+ g_list_free(children);
+ }
+
+ /* Now parse new submenu. */
+ RecurseContext recurse = {0};
+ recurse.toplevel = gtk_widget_get_toplevel(widget);
+ recurse.parent = item;
+
+ if (item != NULL) {
+ GtkWidget * menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+ parse_menu_structure_helper(menu, &recurse);
+ } else {
+ /* Note: it would be really odd that we wouldn't have a cached
+ item, but we should handle that appropriately. */
+ parse_menu_structure_helper(widget, &recurse);
+ g_object_unref(G_OBJECT(recurse.parent));
+ }
+ }
+}
+
+/* A child item was added to a menu we're watching. Let's try to integrate it. */
+static void
+child_added_cb (GtkContainer *menu, GtkWidget *widget, gpointer data)
+{
+ DbusmenuMenuitem *menuitem = (DbusmenuMenuitem *)data;
+
+ RecurseContext recurse = {0};
+ recurse.toplevel = gtk_widget_get_toplevel(GTK_WIDGET(menu));
+ recurse.parent = menuitem;
+
+ parse_menu_structure_helper(widget, &recurse);
+}
+
+static void
+theme_changed_cb (GtkIconTheme *theme, gpointer data)
+{
+ GtkWidget *image;
+
+ image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (data));
+
+ gpointer pmi = g_object_get_data(G_OBJECT(data), CACHED_MENUITEM);
+ if (pmi != NULL) {
+ update_icon(DBUSMENU_MENUITEM(pmi), GTK_IMAGE(image));
+ }
+
+ /* Switch signal to new theme */
+ g_signal_handlers_disconnect_by_func(theme, G_CALLBACK(theme_changed_cb), data);
+ g_signal_connect(gtk_icon_theme_get_default(), "changed", G_CALLBACK(theme_changed_cb), data);
}
static gboolean
diff --git a/libdbusmenu-gtk/serializablemenuitem.c b/libdbusmenu-gtk/serializablemenuitem.c
index cfd864d..29f83a8 100644
--- a/libdbusmenu-gtk/serializablemenuitem.c
+++ b/libdbusmenu-gtk/serializablemenuitem.c
@@ -33,7 +33,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include "client.h"
#include "serializablemenuitem.h"
-/**
+/*
DbusmenuGtkSerializableMenuItemPrivate:
@mi: Menuitem to watch the property changes from
*/
@@ -166,18 +166,18 @@ get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
}
/**
- dbusmenu_gtk_serializable_menu_item_build_menuitem:
- @smi: #DbusmenuGtkSerializableMenuItem to build a #DbusmenuMenuitem mirroring
-
- This function is for menu items that are instanciated from
- GTK and have their properites set using GTK functions. This
- builds a #DbusmenuMenuitem that then has the properties that
- should be sent over the bus to create a new item of this
- type on the other side.
-
- Return value: (transfer full) A #DbusmenuMenuitem who's values will be
- set by this object.
-*/
+ * dbusmenu_gtk_serializable_menu_item_build_menuitem:
+ * @smi: #DbusmenuGtkSerializableMenuItem to build a #DbusmenuMenuitem mirroring
+ *
+ * This function is for menu items that are instanciated from
+ * GTK and have their properites set using GTK functions. This
+ * builds a #DbusmenuMenuitem that then has the properties that
+ * should be sent over the bus to create a new item of this
+ * type on the other side.
+ *
+ * Return value: (transfer full): A #DbusmenuMenuitem who's values will be
+ * set by this object.
+ */
DbusmenuMenuitem *
dbusmenu_gtk_serializable_menu_item_build_menuitem (DbusmenuGtkSerializableMenuItem * smi)
{
@@ -225,15 +225,15 @@ type_destroy_handler (DbusmenuClient * client, const gchar * type, gpointer user
}
/**
- dbusmenu_gtk_serializable_menu_item_register_to_client:
- @client: #DbusmenuClient that we should register a type at.
- @item_type: The #GType of a class that is a subclass of #DbusmenuGtkSerializableMenuItem
-
- Registers a generic handler for dealing with all subclasses of
- #DbusmenuGtkSerializableMenuItem. This handler responds to the callback,
- creates a new object and attaches it to the appropriate #DbusmenuMenuitem
- object.
-*/
+ * dbusmenu_gtk_serializable_menu_item_register_to_client:
+ * @client: #DbusmenuClient that we should register a type at.
+ * @item_type: The #GType of a class that is a subclass of #DbusmenuGtkSerializableMenuItem
+ *
+ * Registers a generic handler for dealing with all subclasses of
+ * #DbusmenuGtkSerializableMenuItem. This handler responds to the callback,
+ * creates a new object and attaches it to the appropriate #DbusmenuMenuitem
+ * object.
+ */
void
dbusmenu_gtk_serializable_menu_item_register_to_client (DbusmenuClient * client, GType item_type)
{
@@ -265,16 +265,16 @@ dbusmenu_gtk_serializable_menu_item_register_to_client (DbusmenuClient * client,
}
/**
- dbusmenu_gtk_serializable_menu_item_set_menuitem:
- @smi: #DbusmenuGtkSerializableMenuItem to set the @DbusmenuGtkSerializableMenuItem::dbusmenu-menuitem of
- @mi: Menuitem to get the properties from
-
- This function is used on the server side to signal to the object
- that it should get its' property change events from @mi instead
- of expecting calls to its' API. A call to this function sets the
- property and subclasses should listen to the notify signal to
- pick up this property being set.
-*/
+ * dbusmenu_gtk_serializable_menu_item_set_menuitem:
+ * @smi: #DbusmenuGtkSerializableMenuItem to set the @DbusmenuGtkSerializableMenuItem::dbusmenu-menuitem of
+ * @mi: Menuitem to get the properties from
+ *
+ * This function is used on the server side to signal to the object
+ * that it should get its' property change events from @mi instead
+ * of expecting calls to its' API. A call to this function sets the
+ * property and subclasses should listen to the notify signal to
+ * pick up this property being set.
+ */
void
dbusmenu_gtk_serializable_menu_item_set_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi)
{
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 62142dc..61b3e69 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -2,6 +2,8 @@
DBUS_RUNNER=dbus-test-runner
CLEANFILES=
+DISTCLEANFILES=
+EXTRA_DIST =
TESTS = \
test-glib-objects-test \
@@ -15,9 +17,11 @@ TESTS = \
test-gtk-objects-test \
test-gtk-label \
test-gtk-shortcut \
+ test-gtk-shortcut-python \
test-gtk-reorder \
test-gtk-submenu \
- test-gtk-parser-test
+ test-gtk-parser-test \
+ test-glib-simple-items.py
check_PROGRAMS = \
glib-server-nomenu \
@@ -48,6 +52,9 @@ check_PROGRAMS = \
XVFB_RUN=". $(srcdir)/run-xvfb.sh"
+# for the GI tests, prefer/use the typelibs from the local build tree
+TESTS_ENVIRONMENT = env GI_TYPELIB_PATH=$(top_builddir)/libdbusmenu-glib:$(top_builddir)/libdbusmenu-gtk:$(GI_TYPELIB_PATH)
+
######################
# JSON Loader lib
######################
@@ -260,6 +267,8 @@ test_glib_objects_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
$(DBUSMENUGLIB_LIBS)
+DISTCLEANFILES += $(OBJECT_XML_REPORT)
+
######################
# Test Glib Properties
######################
@@ -358,6 +367,8 @@ test_glib_simple_items_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
$(DBUSMENUGLIB_LIBS)
+EXTRA_DIST += test-glib-simple-items.py
+
######################
# Test GTK Object
######################
@@ -386,6 +397,8 @@ test_gtk_objects_LDADD = \
$(DBUSMENUGLIB_LIBS) \
$(DBUSMENUGTK_LIBS)
+DISTCLEANFILES += $(GTK_OBJECT_XML_REPORT)
+
######################
# Test GTK Parser
######################
@@ -414,6 +427,7 @@ test_gtk_parser_LDADD = \
$(DBUSMENUGLIB_LIBS) \
$(DBUSMENUGTK_LIBS)
+DISTCLEANFILES += $(GTK_PARSER_XML_REPORT)
#########################
# Test GTK Label
@@ -497,6 +511,19 @@ test_gtk_shortcut_client_LDADD = \
$(DBUSMENUTESTS_LIBS)
#########################
+# Test GTK Shortcut Python
+#########################
+
+test-gtk-shortcut-python: test-gtk-shortcut-server test-gtk-shortcut-client.py Makefile.am
+ @echo "#!/bin/bash" > $@
+ @echo $(XVFB_RUN) >> $@
+ @echo $(DBUS_RUNNER) --task $(srcdir)/test-gtk-shortcut-client.py --task-name Client --task ./test-gtk-shortcut-server --task-name Server --ignore-return >> $@
+ @chmod +x $@
+
+EXTRA_DIST += test-gtk-shortcut-client.py
+CLEANFILES += test-gtk-shortcut-client.pyc
+
+#########################
# Test GTK Reorder
#########################
@@ -590,7 +617,7 @@ jsondir = $(datadir)/${PACKAGE}/json/
json_DATA = \
test-gtk-label.json
-EXTRA_DIST = \
+EXTRA_DIST += \
$(examples_DATA) \
run-xvfb.sh \
$(json_DATA) \
@@ -622,8 +649,6 @@ CLEANFILES += \
distclean-local:
-rm -rf $(builddir)/mago.results
-DISTCLEANFILES = \
- $(TESTS) \
- $(OBJECT_XML_REPORT) \
- $(GTK_OBJECT_XML_REPORT)
+DISTCLEANFILES += \
+ $(filter-out %.py, $(TESTS))
diff --git a/tests/json-loader.c b/tests/json-loader.c
index 14e90e0..36157dc 100644
--- a/tests/json-loader.c
+++ b/tests/json-loader.c
@@ -109,7 +109,6 @@ set_props (DbusmenuMenuitem * mi, JsonObject * node)
if (variant != NULL) {
dbusmenu_menuitem_property_set_variant(mi, member, variant);
- g_variant_unref(variant);
}
}
diff --git a/tests/test-glib-layout-client.c b/tests/test-glib-layout-client.c
index 5ea0cf8..3afe042 100644
--- a/tests/test-glib-layout-client.c
+++ b/tests/test-glib-layout-client.c
@@ -81,6 +81,11 @@ layout_updated (DbusmenuClient * client, gpointer data)
g_debug("Layout Updated");
DbusmenuMenuitem * menuroot = dbusmenu_client_get_root(client);
+ if (menuroot == NULL) {
+ g_debug("Root NULL, waiting");
+ return;
+ }
+
layout_t * layout = &layouts[layouton];
if (!verify_root_to_layout(menuroot, layout)) {
diff --git a/tests/test-glib-simple-items.py b/tests/test-glib-simple-items.py
new file mode 100755
index 0000000..d7ad7d7
--- /dev/null
+++ b/tests/test-glib-simple-items.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+# This is the Python GI version of test-glib-simple-items.c
+
+import gobject
+from gi.repository import Dbusmenu
+
+dummies = ['Bob', 'Jim', 'Alvin', 'Mary']
+
+def dummy_users(root):
+ count = 0
+ for user in dummies:
+ mi = Dbusmenu.Menuitem()
+ print 'Creating item: %d %s' % (mi.get_id(), user)
+ print '\tRoot ID:', root.get_id()
+ mi.property_set('label', user)
+ root.child_add_position(mi, count)
+ assert mi.property_get('label') == user
+ count += 1
+
+def quititall(mainloop):
+ mainloop.quit()
+ return False
+
+# main
+
+server = Dbusmenu.Server.new('/test/object')
+root_menuitem = Dbusmenu.Menuitem()
+server.set_root(root_menuitem)
+print 'Root ID:', root_menuitem.get_id()
+
+dummy_users(root_menuitem)
+
+mainloop = gobject.MainLoop()
+gobject.timeout_add_seconds(1, quititall, mainloop)
+mainloop.run()
diff --git a/tests/test-gtk-label.json b/tests/test-gtk-label.json
index 755bd44..0189fbe 100644
--- a/tests/test-gtk-label.json
+++ b/tests/test-gtk-label.json
@@ -45,7 +45,7 @@
"label": "value27"},
{"id": 28, "type": "standard",
"label": "value28"},
- {"id": 29, "type": "standard", "visible": "false",
+ {"id": 29, "type": "standard", "visible": false,
"label": "value29"}
]
},
@@ -54,45 +54,45 @@
"submenu": [
{"id": 40,
"type": "standard",
- "enabled": "true",
+ "enabled": true,
"label": "value40"},
{"id": 41,
"type": "standard",
- "enabled": "false",
+ "enabled": false,
"label": "value41"},
{"id": 42,
"type": "standard",
- "enabled": "true",
+ "enabled": true,
"label": "value42"},
{"id": 43,
"type": "standard",
- "enabled": "false",
+ "enabled": false,
"label": "value43"},
{"id": 44,
"type": "standard",
- "enabled": "true",
+ "enabled": true,
"label": "value44"},
{"id": 45,
"type": "standard",
- "enabled": "false",
+ "enabled": false,
"label": "value45"},
{"id": 46,
"type": "standard",
- "enabled": "true",
+ "enabled": true,
"label": "value46"},
{"id": 47,
"type": "standard",
- "enabled": "false",
+ "enabled": false,
"label": "value47"},
{"id": 48,
"type": "standard",
- "enabled": "true",
+ "enabled": true,
"label": "value48"},
{"id": 49,
"type": "standard",
- "visible": "false",
- "enabled": "false",
- "label": "value49"}
+ "visible": false,
+ "enabled": false,
+ "label": "value49 - hidden"}
]
},
{"id": 3, "type": "standard",
diff --git a/tests/test-gtk-shortcut-client.py b/tests/test-gtk-shortcut-client.py
new file mode 100755
index 0000000..885d227
--- /dev/null
+++ b/tests/test-gtk-shortcut-client.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+
+# A test for libdbusmenu to ensure its quality. This is the Python GI version
+# of test-gtk-shortcut-client.c
+#
+# Copyright 2011 Canonical Ltd.
+# Authors:
+# Martin Pitt <martin.pitt@ubuntu.com>
+
+import sys
+import gobject
+from gi.repository import Gtk, DbusmenuGtk
+Gtk.require_version('2.0')
+
+passed = True
+main_loop = gobject.MainLoop()
+
+def timer_func(data):
+ passed = True
+ main_loop.quit()
+ return False
+
+# main
+print 'Building Window'
+window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
+menubar = Gtk.MenuBar()
+menuitem = Gtk.MenuItem(label='Test')
+
+dmenu = DbusmenuGtk.Menu(dbus_name='glib.label.test', dbus_object='/org/test')
+dclient = dmenu.get_client()
+agroup = Gtk.AccelGroup()
+dclient.set_accel_group(agroup)
+
+menuitem.set_submenu(dmenu)
+menuitem.show()
+menubar.append(menuitem)
+menubar.show()
+window.add(menubar)
+window.set_title('libdbusmenu-gtk test')
+window.add_accel_group(agroup)
+window.show_all()
+
+gobject.timeout_add_seconds(10, timer_func, window)
+
+print 'Entering Mainloop'
+main_loop.run()
+
+if passed:
+ print 'Quiting'
+else:
+ print "Quiting as we're a failure"
+ sys.exit(1)
diff --git a/tests/test-json-01.json b/tests/test-json-01.json
index b626d20..e3b1e17 100644
--- a/tests/test-json-01.json
+++ b/tests/test-json-01.json
@@ -5,30 +5,22 @@
{
"id": 5,
"children-display": 'submenu',
- "enabled": true,
"label": 'File',
- "visible": true,
"submenu": [
{
"id": 6,
- "enabled": true,
"label": 'Quit',
- "shortcut": [['Control', 'q']],
- "visible": true
+ "shortcut": [['Control', 'q']]
},
{
"id": 7,
- "enabled": true,
"label": 'Close all',
- "shortcut": [['Control', 'Shift', 'w']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'w']]
},
{
"id": 8,
- "enabled": true,
"label": 'Close',
- "shortcut": [['Control', 'w']],
- "visible": true
+ "shortcut": [['Control', 'w']]
},
{
"id": 9,
@@ -36,22 +28,16 @@
},
{
"id": 10,
- "enabled": true,
- "label": 'Send by Email...',
- "visible": true
+ "label": 'Send by Email...'
},
{
"id": 11,
- "enabled": true,
"label": 'Print...',
- "shortcut": [['Control', 'p']],
- "visible": true
+ "shortcut": [['Control', 'p']]
},
{
"id": 12,
- "enabled": true,
- "label": 'Page Setup',
- "visible": true
+ "label": 'Page Setup'
},
{
"id": 13,
@@ -59,35 +45,25 @@
},
{
"id": 14,
- "enabled": true,
- "label": 'Revert',
- "visible": true
+ "label": 'Revert'
},
{
"id": 15,
- "enabled": true,
- "label": 'Save as Template...',
- "visible": true
+ "label": 'Save as Template...'
},
{
"id": 16,
- "enabled": true,
- "label": 'Save a Copy...',
- "visible": true
+ "label": 'Save a Copy...'
},
{
"id": 17,
- "enabled": true,
"label": 'Save As...',
- "shortcut": [['Control', 'Shift', 's']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 's']]
},
{
"id": 18,
- "enabled": true,
"label": 'Save',
- "shortcut": [['Control', 's']],
- "visible": true
+ "shortcut": [['Control', 's']]
},
{
"id": 19,
@@ -96,15 +72,11 @@
{
"id": 20,
"children-display": 'submenu',
- "enabled": true,
"label": 'Open Recent',
- "visible": true,
"submenu": [
{
"id": 21,
- "enabled": true,
- "label": 'Document History',
- "visible": true
+ "label": 'Document History'
},
{
"id": 22,
@@ -112,168 +84,118 @@
},
{
"id": 23,
- "enabled": true,
"label": 'giggity.jpg',
- "shortcut": [['Control', '2']],
- "visible": true
+ "shortcut": [['Control', '2']]
},
{
"id": 24,
- "enabled": true,
"label": 'Icon Height.svg',
- "shortcut": [['Control', '1']],
- "visible": true
+ "shortcut": [['Control', '1']]
}
]
},
{
"id": 25,
- "enabled": true,
- "label": 'Open Location...',
- "visible": true
+ "label": 'Open Location...'
},
{
"id": 26,
- "enabled": true,
"label": 'Open as Layers...',
- "shortcut": [['Control', 'Alt', 'o']],
- "visible": true
+ "shortcut": [['Control', 'Alt', 'o']]
},
{
"id": 27,
- "enabled": true,
"label": 'Open...',
- "shortcut": [['Control', 'o']],
- "visible": true
+ "shortcut": [['Control', 'o']]
},
{
"id": 28,
"children-display": 'submenu',
- "enabled": true,
"label": 'Create',
- "visible": true,
"submenu": [
{
"id": 29,
"children-display": 'submenu',
- "enabled": true,
"label": 'Web Page Themes',
- "visible": true,
"submenu": [
{
"id": 30,
"children-display": 'submenu',
- "enabled": true,
"label": 'Classic.Gimp.Org',
- "visible": true,
"submenu": [
{
"id": 31,
- "enabled": true,
- "label": 'Tube Sub-Sub-Button Label...',
- "visible": true
+ "label": 'Tube Sub-Sub-Button Label...'
},
{
"id": 32,
- "enabled": true,
- "label": 'Tube Sub-Button Label...',
- "visible": true
+ "label": 'Tube Sub-Button Label...'
},
{
"id": 33,
- "enabled": true,
- "label": 'Tube Button Label...',
- "visible": true
+ "label": 'Tube Button Label...'
},
{
"id": 34,
- "enabled": true,
- "label": 'Small Header...',
- "visible": true
+ "label": 'Small Header...'
},
{
"id": 35,
- "enabled": true,
- "label": 'General Tube Labels...',
- "visible": true
+ "label": 'General Tube Labels...'
},
{
"id": 36,
- "enabled": true,
- "label": 'Big Header...',
- "visible": true
+ "label": 'Big Header...'
}
]
},
{
"id": 37,
"children-display": 'submenu',
- "enabled": true,
"label": 'Beveled Pattern',
- "visible": true,
"submenu": [
{
"id": 38,
- "enabled": true,
- "label": 'Hrule...',
- "visible": true
+ "label": 'Hrule...'
},
{
"id": 39,
- "enabled": true,
- "label": 'Heading...',
- "visible": true
+ "label": 'Heading...'
},
{
"id": 40,
- "enabled": true,
- "label": 'Button...',
- "visible": true
+ "label": 'Button...'
},
{
"id": 41,
- "enabled": true,
- "label": 'Bullet...',
- "visible": true
+ "label": 'Bullet...'
},
{
"id": 42,
- "enabled": true,
- "label": 'Arrow...',
- "visible": true
+ "label": 'Arrow...'
}
]
},
{
"id": 43,
"children-display": 'submenu',
- "enabled": true,
"label": 'Alien Glow',
- "visible": true,
"submenu": [
{
"id": 44,
- "enabled": true,
- "label": 'Hrule...',
- "visible": true
+ "label": 'Hrule...'
},
{
"id": 45,
- "enabled": true,
- "label": 'Button...',
- "visible": true
+ "label": 'Button...'
},
{
"id": 46,
- "enabled": true,
- "label": 'Bullet...',
- "visible": true
+ "label": 'Bullet...'
},
{
"id": 47,
- "enabled": true,
- "label": 'Arrow...',
- "visible": true
+ "label": 'Arrow...'
}
]
}
@@ -282,255 +204,173 @@
{
"id": 48,
"children-display": 'submenu',
- "enabled": true,
"label": 'Patterns',
- "visible": true,
"submenu": [
{
"id": 49,
- "enabled": true,
- "label": 'Truchet...',
- "visible": true
+ "label": 'Truchet...'
},
{
"id": 50,
- "enabled": true,
- "label": 'Swirly...',
- "visible": true
+ "label": 'Swirly...'
},
{
"id": 51,
- "enabled": true,
- "label": 'Swirl-Tile...',
- "visible": true
+ "label": 'Swirl-Tile...'
},
{
"id": 52,
- "enabled": true,
- "label": 'Render Map...',
- "visible": true
+ "label": 'Render Map...'
},
{
"id": 53,
- "enabled": true,
- "label": 'Land...',
- "visible": true
+ "label": 'Land...'
},
{
"id": 54,
- "enabled": true,
- "label": 'Flatland...',
- "visible": true
+ "label": 'Flatland...'
},
{
"id": 55,
- "enabled": true,
- "label": 'Camouflage...',
- "visible": true
+ "label": 'Camouflage...'
},
{
"id": 56,
- "enabled": true,
- "label": '3D Truchet...',
- "visible": true
+ "label": '3D Truchet...'
}
]
},
{
"id": 57,
"children-display": 'submenu',
- "enabled": true,
"label": 'Logos',
- "visible": true,
"submenu": [
{
"id": 58,
- "enabled": true,
- "label": 'Web Title Header...',
- "visible": true
+ "label": 'Web Title Header...'
},
{
"id": 59,
- "enabled": true,
- "label": 'Textured...',
- "visible": true
+ "label": 'Textured...'
},
{
"id": 60,
- "enabled": true,
- "label": 'Text Circle...',
- "visible": true
+ "label": 'Text Circle...'
},
{
"id": 61,
- "enabled": true,
- "label": 'Starscape...',
- "visible": true
+ "label": 'Starscape...'
},
{
"id": 62,
- "enabled": true,
- "label": 'Speed Text...',
- "visible": true
+ "label": 'Speed Text...'
},
{
"id": 63,
- "enabled": true,
- "label": 'SOTA Chrome...',
- "visible": true
+ "label": 'SOTA Chrome...'
},
{
"id": 64,
- "enabled": true,
- "label": 'Particle Trace...',
- "visible": true
+ "label": 'Particle Trace...'
},
{
"id": 65,
- "enabled": true,
- "label": 'Newsprint Text...',
- "visible": true
+ "label": 'Newsprint Text...'
},
{
"id": 66,
- "enabled": true,
- "label": 'Neon...',
- "visible": true
+ "label": 'Neon...'
},
{
"id": 67,
- "enabled": true,
- "label": 'Imigre-26...',
- "visible": true
+ "label": 'Imigre-26...'
},
{
"id": 68,
- "enabled": true,
- "label": 'Gradient Bevel...',
- "visible": true
+ "label": 'Gradient Bevel...'
},
{
"id": 69,
- "enabled": true,
- "label": 'Glowing Hot...',
- "visible": true
+ "label": 'Glowing Hot...'
},
{
"id": 70,
- "enabled": true,
- "label": 'Glossy...',
- "visible": true
+ "label": 'Glossy...'
},
{
"id": 71,
- "enabled": true,
- "label": 'Frosty...',
- "visible": true
+ "label": 'Frosty...'
},
{
"id": 72,
- "enabled": true,
- "label": 'Crystal...',
- "visible": true
+ "label": 'Crystal...'
},
{
"id": 73,
- "enabled": true,
- "label": 'Cool Metal...',
- "visible": true
+ "label": 'Cool Metal...'
},
{
"id": 74,
- "enabled": true,
- "label": 'Comic Book...',
- "visible": true
+ "label": 'Comic Book...'
},
{
"id": 75,
- "enabled": true,
- "label": 'Chrome...',
- "visible": true
+ "label": 'Chrome...'
},
{
"id": 76,
- "enabled": true,
- "label": 'Chip Away...',
- "visible": true
+ "label": 'Chip Away...'
},
{
"id": 77,
- "enabled": true,
- "label": 'Chalk...',
- "visible": true
+ "label": 'Chalk...'
},
{
"id": 78,
- "enabled": true,
- "label": 'Carved...',
- "visible": true
+ "label": 'Carved...'
},
{
"id": 79,
- "enabled": true,
- "label": 'Bovination...',
- "visible": true
+ "label": 'Bovination...'
},
{
"id": 80,
- "enabled": true,
- "label": 'Blended...',
- "visible": true
+ "label": 'Blended...'
},
{
"id": 81,
- "enabled": true,
- "label": 'Basic I...',
- "visible": true
+ "label": 'Basic I...'
},
{
"id": 82,
- "enabled": true,
- "label": 'Basic II...',
- "visible": true
+ "label": 'Basic II...'
},
{
"id": 83,
- "enabled": true,
- "label": 'Alien Neon...',
- "visible": true
+ "label": 'Alien Neon...'
},
{
"id": 84,
- "enabled": true,
- "label": 'Alien Glow...',
- "visible": true
+ "label": 'Alien Glow...'
},
{
"id": 85,
- "enabled": true,
- "label": '3D Outline...',
- "visible": true
+ "label": '3D Outline...'
}
]
},
{
"id": 86,
"children-display": 'submenu',
- "enabled": true,
"label": 'Buttons',
- "visible": true,
"submenu": [
{
"id": 87,
- "enabled": true,
- "label": 'Simple Beveled Button...',
- "visible": true
+ "label": 'Simple Beveled Button...'
},
{
"id": 88,
- "enabled": true,
- "label": 'Round Button...',
- "visible": true
+ "label": 'Round Button...'
}
]
},
@@ -541,72 +381,53 @@
{
"id": 90,
"children-display": 'submenu',
- "enabled": true,
"label": 'xscanimage',
- "visible": true,
"submenu": [
{
"id": 91,
"enabled": false,
- "label": 'Device dialog...',
- "visible": true
+ "label": 'Device dialog...'
}
]
},
{
"id": 92,
- "enabled": true,
- "label": 'Screenshot...',
- "visible": true
+ "label": 'Screenshot...'
},
{
"id": 93,
- "enabled": true,
"label": 'From Clipboard',
- "shortcut": [['Control', 'Shift', 'v']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'v']]
}
]
},
{
"id": 94,
- "enabled": true,
"label": 'New...',
- "shortcut": [['Control', 'n']],
- "visible": true
+ "shortcut": [['Control', 'n']]
}
]
},
{
"id": 95,
"children-display": 'submenu',
- "enabled": true,
"label": 'Edit',
- "visible": true,
"submenu": [
{
"id": 96,
- "enabled": true,
- "label": 'Units',
- "visible": true
+ "label": 'Units'
},
{
"id": 97,
- "enabled": true,
- "label": 'Modules',
- "visible": true
+ "label": 'Modules'
},
{
"id": 98,
- "enabled": true,
- "label": 'Keyboard Shortcuts',
- "visible": true
+ "label": 'Keyboard Shortcuts'
},
{
"id": 99,
- "enabled": true,
- "label": 'Preferences',
- "visible": true
+ "label": 'Preferences'
},
{
"id": 100,
@@ -615,42 +436,32 @@
{
"id": 101,
"enabled": false,
- "label": 'Stroke Path...',
- "visible": true
+ "label": 'Stroke Path...'
},
{
"id": 102,
"enabled": false,
- "label": 'Stroke Selection...',
- "visible": true
+ "label": 'Stroke Selection...'
},
{
"id": 103,
- "enabled": true,
"label": 'Fill with Pattern',
- "shortcut": [['Control', 'semicolon']],
- "visible": true
+ "shortcut": [['Control', 'semicolon']]
},
{
"id": 104,
- "enabled": true,
"label": 'Fill with BG Color',
- "shortcut": [['Control', 'period']],
- "visible": true
+ "shortcut": [['Control', 'period']]
},
{
"id": 105,
- "enabled": true,
"label": 'Fill with FG Color',
- "shortcut": [['Control', 'comma']],
- "visible": true
+ "shortcut": [['Control', 'comma']]
},
{
"id": 106,
- "enabled": true,
"label": 'Clear',
- "shortcut": [['Delete']],
- "visible": true
+ "shortcut": [['Delete']]
},
{
"id": 107,
@@ -659,103 +470,73 @@
{
"id": 108,
"children-display": 'submenu',
- "enabled": true,
"label": 'Buffer',
- "visible": true,
"submenu": [
{
"id": 109,
- "enabled": true,
- "label": 'Paste Named...',
- "visible": true
+ "label": 'Paste Named...'
},
{
"id": 110,
- "enabled": true,
- "label": 'Copy Visible Named...',
- "visible": true
+ "label": 'Copy Visible Named...'
},
{
"id": 111,
- "enabled": true,
- "label": 'Copy Named...',
- "visible": true
+ "label": 'Copy Named...'
},
{
"id": 112,
- "enabled": true,
- "label": 'Cut Named...',
- "visible": true
+ "label": 'Cut Named...'
}
]
},
{
"id": 113,
"children-display": 'submenu',
- "enabled": true,
"label": 'Paste as',
- "visible": true,
"submenu": [
{
"id": 114,
- "enabled": true,
- "label": 'New Pattern...',
- "visible": true
+ "label": 'New Pattern...'
},
{
"id": 115,
- "enabled": true,
- "label": 'New Brush...',
- "visible": true
+ "label": 'New Brush...'
},
{
"id": 116,
- "enabled": true,
- "label": 'New Layer',
- "visible": true
+ "label": 'New Layer'
},
{
"id": 117,
- "enabled": true,
"label": 'New Image',
- "shortcut": [['Control', 'Shift', 'v']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'v']]
}
]
},
{
"id": 118,
- "enabled": true,
- "label": 'Paste Into',
- "visible": true
+ "label": 'Paste Into'
},
{
"id": 119,
- "enabled": true,
"label": 'Paste',
- "shortcut": [['Control', 'v']],
- "visible": true
+ "shortcut": [['Control', 'v']]
},
{
"id": 120,
- "enabled": true,
"label": 'Copy Visible',
- "shortcut": [['Control', 'Shift', 'c']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'c']]
},
{
"id": 121,
- "enabled": true,
"label": 'Copy',
- "shortcut": [['Control', 'c']],
- "visible": true
+ "shortcut": [['Control', 'c']]
},
{
"id": 122,
- "enabled": true,
"label": 'Cut',
- "shortcut": [['Control', 'x']],
- "visible": true
+ "shortcut": [['Control', 'x']]
},
{
"id": 123,
@@ -763,59 +544,47 @@
},
{
"id": 124,
- "enabled": true,
- "label": 'Undo History',
- "visible": true
+ "label": 'Undo History'
},
{
"id": 3,
"enabled": false,
- "label": '_Fade...',
- "visible": true
+ "label": '_Fade...'
},
{
"id": 2,
"enabled": false,
"label": '_Redo',
- "shortcut": [['Control', 'y']],
- "visible": true
+ "shortcut": [['Control', 'y']]
},
{
"id": 1,
"enabled": false,
"label": '_Undo',
- "shortcut": [['Control', 'z']],
- "visible": true
+ "shortcut": [['Control', 'z']]
}
]
},
{
"id": 125,
"children-display": 'submenu',
- "enabled": true,
"label": 'Select',
- "visible": true,
"submenu": [
{
"id": 126,
"enabled": false,
- "label": 'To Path',
- "visible": true
+ "label": 'To Path'
},
{
"id": 127,
- "enabled": true,
- "label": 'Save to Channel',
- "visible": true
+ "label": 'Save to Channel'
},
{
"id": 128,
- "enabled": true,
"label": 'Toggle Quick Mask',
"shortcut": [['Shift', 'q']],
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 129,
@@ -823,39 +592,32 @@
},
{
"id": 130,
- "enabled": true,
- "label": 'Distort...',
- "visible": true
+ "label": 'Distort...'
},
{
"id": 131,
"enabled": false,
- "label": 'Border...',
- "visible": true
+ "label": 'Border...'
},
{
"id": 132,
"enabled": false,
- "label": 'Grow...',
- "visible": true
+ "label": 'Grow...'
},
{
"id": 133,
"enabled": false,
- "label": 'Shrink...',
- "visible": true
+ "label": 'Shrink...'
},
{
"id": 134,
"enabled": false,
- "label": 'Sharpen',
- "visible": true
+ "label": 'Sharpen'
},
{
"id": 135,
"enabled": false,
- "label": 'Feather...',
- "visible": true
+ "label": 'Feather...'
},
{
"id": 136,
@@ -863,106 +625,81 @@
},
{
"id": 137,
- "enabled": true,
- "label": 'Selection Editor',
- "visible": true
+ "label": 'Selection Editor'
},
{
"id": 138,
"enabled": false,
"label": 'From Path',
- "shortcut": [['Shift', 'v']],
- "visible": true
+ "shortcut": [['Shift', 'v']]
},
{
"id": 139,
- "enabled": true,
"label": 'By Color',
- "shortcut": [['Shift', 'o']],
- "visible": true
+ "shortcut": [['Shift', 'o']]
},
{
"id": 140,
"enabled": false,
"label": 'Float',
- "shortcut": [['Control', 'Shift', 'l']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'l']]
},
{
"id": 141,
- "enabled": true,
"label": 'Invert',
- "shortcut": [['Control', 'i']],
- "visible": true
+ "shortcut": [['Control', 'i']]
},
{
"id": 142,
"enabled": false,
"label": 'None',
- "shortcut": [['Control', 'Shift', 'a']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'a']]
},
{
"id": 143,
- "enabled": true,
"label": 'All',
- "shortcut": [['Control', 'a']],
- "visible": true
+ "shortcut": [['Control', 'a']]
}
]
},
{
"id": 144,
"children-display": 'submenu',
- "enabled": true,
"label": 'View',
- "visible": true,
"submenu": [
{
"id": 145,
- "enabled": true,
"label": 'Show Statusbar',
"toggle-state": 1,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 146,
- "enabled": true,
"label": 'Show Scrollbars',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 147,
- "enabled": true,
"label": 'Show Rulers',
"shortcut": [['Control', 'Shift', 'r']],
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 148,
- "enabled": true,
"label": 'Show Menubar',
"toggle-state": 1,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 149,
"children-display": 'submenu',
- "enabled": true,
"label": 'Padding Color',
- "visible": true,
"submenu": [
{
"id": 150,
- "enabled": true,
- "label": 'As in Preferences',
- "visible": true
+ "label": 'As in Preferences'
},
{
"id": 151,
@@ -970,27 +707,19 @@
},
{
"id": 152,
- "enabled": true,
- "label": 'Select Custom Color...',
- "visible": true
+ "label": 'Select Custom Color...'
},
{
"id": 153,
- "enabled": true,
- "label": 'Dark Check Color',
- "visible": true
+ "label": 'Dark Check Color'
},
{
"id": 154,
- "enabled": true,
- "label": 'Light Check Color',
- "visible": true
+ "label": 'Light Check Color'
},
{
"id": 155,
- "enabled": true,
- "label": 'From Theme',
- "visible": true
+ "label": 'From Theme'
}
]
},
@@ -1000,35 +729,27 @@
},
{
"id": 157,
- "enabled": true,
"label": 'Snap to Active Path',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 158,
- "enabled": true,
"label": 'Snap to Canvas Edges',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 159,
- "enabled": true,
"label": 'Snap to Grid',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 160,
- "enabled": true,
"label": 'Snap to Guides',
"toggle-state": 1,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 161,
@@ -1036,45 +757,35 @@
},
{
"id": 162,
- "enabled": true,
"label": 'Show Sample Points',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 163,
- "enabled": true,
"label": 'Show Grid',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 164,
- "enabled": true,
"label": 'Show Guides',
"shortcut": [['Control', 'Shift', 't']],
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 165,
- "enabled": true,
"label": 'Show Layer Boundary',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 166,
- "enabled": true,
"label": 'Show Selection',
"shortcut": [['Control', 't']],
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 167,
@@ -1082,15 +793,11 @@
},
{
"id": 168,
- "enabled": true,
- "label": 'Display Filters...',
- "visible": true
+ "label": 'Display Filters...'
},
{
"id": 169,
- "enabled": true,
- "label": 'Navigation Window',
- "visible": true
+ "label": 'Navigation Window'
},
{
"id": 170,
@@ -1099,27 +806,21 @@
{
"id": 171,
"children-display": 'submenu',
- "enabled": true,
"label": 'Fullscreen',
"shortcut": [['F11']],
"toggle-state": 0,
"toggle-type": 'checkmark',
- "visible": true,
"submenu": [
{
"id": 172,
- "enabled": true,
- "label": 'Open Display...',
- "visible": true
+ "label": 'Open Display...'
}
]
},
{
"id": 173,
- "enabled": true,
"label": 'Shrink Wrap',
- "shortcut": [['Control', 'e']],
- "visible": true
+ "shortcut": [['Control', 'e']]
},
{
"id": 174,
@@ -1128,17 +829,13 @@
{
"id": 175,
"children-display": 'submenu',
- "enabled": true,
"label": '_Zoom (67%)',
- "visible": true,
"submenu": [
{
"id": 176,
- "enabled": true,
"label": 'Othe_r (67%)...',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 177,
@@ -1146,76 +843,58 @@
},
{
"id": 178,
- "enabled": true,
"label": '1:16 (6.25%)',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 179,
- "enabled": true,
"label": '1:8 (12.5%)',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 180,
- "enabled": true,
"label": '1:4 (25%)',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 181,
- "enabled": true,
"label": '1:2 (50%)',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 182,
- "enabled": true,
"label": '1:1 (100%)',
"shortcut": [['1']],
"toggle-state": 1,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 183,
- "enabled": true,
"label": '2:1 (200%)',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 184,
- "enabled": true,
"label": '4:1 (400%)',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 185,
- "enabled": true,
"label": '8:1 (800%)',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 186,
- "enabled": true,
"label": '16:1 (1600%)',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 187,
@@ -1223,106 +902,76 @@
},
{
"id": 188,
- "enabled": true,
- "label": 'Fill Window',
- "visible": true
+ "label": 'Fill Window'
},
{
"id": 189,
- "enabled": true,
"label": 'Fit Image in Window',
- "shortcut": [['Control', 'Shift', 'e']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'e']]
},
{
"id": 190,
- "enabled": true,
"label": 'Zoom In',
- "shortcut": [['plus']],
- "visible": true
+ "shortcut": [['plus']]
},
{
"id": 191,
- "enabled": true,
"label": 'Zoom Out',
- "shortcut": [['minus']],
- "visible": true
+ "shortcut": [['minus']]
},
{
"id": 4,
- "enabled": true,
"label": 'Re_vert Zoom (67%)',
- "shortcut": [['grave']],
- "visible": true
+ "shortcut": [['grave']]
}
]
},
{
"id": 192,
- "enabled": true,
"label": 'Dot for Dot',
"toggle-state": 1,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 193,
- "enabled": true,
- "label": 'New View',
- "visible": true
+ "label": 'New View'
}
]
},
{
"id": 194,
"children-display": 'submenu',
- "enabled": true,
"label": 'Image',
- "visible": true,
"submenu": [
{
"id": 195,
- "enabled": true,
"label": 'Image Properties',
- "shortcut": [['Alt', 'Return']],
- "visible": true
+ "shortcut": [['Alt', 'Return']]
},
{
"id": 196,
- "enabled": true,
- "label": 'Configure Grid...',
- "visible": true
+ "label": 'Configure Grid...'
},
{
"id": 197,
"children-display": 'submenu',
- "enabled": true,
"label": 'Guides',
- "visible": true,
"submenu": [
{
"id": 198,
- "enabled": true,
- "label": 'Remove all Guides',
- "visible": true
+ "label": 'Remove all Guides'
},
{
"id": 199,
- "enabled": true,
- "label": 'New Guides from Selection',
- "visible": true
+ "label": 'New Guides from Selection'
},
{
"id": 200,
- "enabled": true,
- "label": 'New Guide...',
- "visible": true
+ "label": 'New Guide...'
},
{
"id": 201,
- "enabled": true,
- "label": 'New Guide (by Percent)...',
- "visible": true
+ "label": 'New Guide (by Percent)...'
}
]
},
@@ -1332,22 +981,16 @@
},
{
"id": 203,
- "enabled": true,
- "label": 'Align Visible Layers...',
- "visible": true
+ "label": 'Align Visible Layers...'
},
{
"id": 204,
- "enabled": true,
- "label": 'Flatten Image',
- "visible": true
+ "label": 'Flatten Image'
},
{
"id": 205,
- "enabled": true,
"label": 'Merge Visible Layers...',
- "shortcut": [['Control', 'm']],
- "visible": true
+ "shortcut": [['Control', 'm']]
},
{
"id": 206,
@@ -1355,21 +998,16 @@
},
{
"id": 207,
- "enabled": true,
- "label": 'Zealous Crop',
- "visible": true
+ "label": 'Zealous Crop'
},
{
"id": 208,
- "enabled": true,
- "label": 'Autocrop Image',
- "visible": true
+ "label": 'Autocrop Image'
},
{
"id": 209,
"enabled": false,
- "label": 'Crop to Selection',
- "visible": true
+ "label": 'Crop to Selection'
},
{
"id": 210,
@@ -1377,33 +1015,24 @@
},
{
"id": 211,
- "enabled": true,
- "label": 'Scale Image...',
- "visible": true
+ "label": 'Scale Image...'
},
{
"id": 212,
- "enabled": true,
- "label": 'Print Size...',
- "visible": true
+ "label": 'Print Size...'
},
{
"id": 213,
"enabled": false,
- "label": 'Fit Canvas to Selection',
- "visible": true
+ "label": 'Fit Canvas to Selection'
},
{
"id": 214,
- "enabled": true,
- "label": 'Fit Canvas to Layers',
- "visible": true
+ "label": 'Fit Canvas to Layers'
},
{
"id": 215,
- "enabled": true,
- "label": 'Canvas Size...',
- "visible": true
+ "label": 'Canvas Size...'
},
{
"id": 216,
@@ -1412,15 +1041,11 @@
{
"id": 217,
"children-display": 'submenu',
- "enabled": true,
"label": 'Transform',
- "visible": true,
"submenu": [
{
"id": 218,
- "enabled": true,
- "label": 'Guillotine',
- "visible": true
+ "label": 'Guillotine'
},
{
"id": 219,
@@ -1428,21 +1053,15 @@
},
{
"id": 220,
- "enabled": true,
- "label": 'Rotate 180?',
- "visible": true
+ "label": 'Rotate 180?'
},
{
"id": 221,
- "enabled": true,
- "label": 'Rotate 90? counter-clockwise',
- "visible": true
+ "label": 'Rotate 90? counter-clockwise'
},
{
"id": 222,
- "enabled": true,
- "label": 'Rotate 90? clockwise',
- "visible": true
+ "label": 'Rotate 90? clockwise'
},
{
"id": 223,
@@ -1450,36 +1069,26 @@
},
{
"id": 224,
- "enabled": true,
- "label": 'Flip Vertically',
- "visible": true
+ "label": 'Flip Vertically'
},
{
"id": 225,
- "enabled": true,
- "label": 'Flip Horizontally',
- "visible": true
+ "label": 'Flip Horizontally'
}
]
},
{
"id": 226,
"children-display": 'submenu',
- "enabled": true,
"label": 'Mode',
- "visible": true,
"submenu": [
{
"id": 227,
- "enabled": true,
- "label": 'Convert to Color Profile...',
- "visible": true
+ "label": 'Convert to Color Profile...'
},
{
"id": 228,
- "enabled": true,
- "label": 'Assign Color Profile...',
- "visible": true
+ "label": 'Assign Color Profile...'
},
{
"id": 229,
@@ -1487,75 +1096,56 @@
},
{
"id": 230,
- "enabled": true,
"label": 'Indexed...',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 231,
- "enabled": true,
"label": 'Grayscale',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 232,
- "enabled": true,
"label": 'RGB',
"toggle-state": 1,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
}
]
},
{
"id": 233,
- "enabled": true,
"label": 'Duplicate',
- "shortcut": [['Control', 'd']],
- "visible": true
+ "shortcut": [['Control', 'd']]
}
]
},
{
"id": 234,
"children-display": 'submenu',
- "enabled": true,
"label": 'Layer',
- "visible": true,
"submenu": [
{
"id": 235,
- "enabled": true,
- "label": 'Autocrop Layer',
- "visible": true
+ "label": 'Autocrop Layer'
},
{
"id": 236,
"enabled": false,
- "label": 'Crop to Selection',
- "visible": true
+ "label": 'Crop to Selection'
},
{
"id": 237,
- "enabled": true,
- "label": 'Scale Layer...',
- "visible": true
+ "label": 'Scale Layer...'
},
{
"id": 238,
- "enabled": true,
- "label": 'Layer to Image Size',
- "visible": true
+ "label": 'Layer to Image Size'
},
{
"id": 239,
- "enabled": true,
- "label": 'Layer Boundary Size...',
- "visible": true
+ "label": 'Layer Boundary Size...'
},
{
"id": 240,
@@ -1564,16 +1154,12 @@
{
"id": 241,
"children-display": 'submenu',
- "enabled": true,
"label": 'Transform',
- "visible": true,
"submenu": [
{
"id": 242,
- "enabled": true,
"label": 'Offset...',
- "shortcut": [['Control', 'Shift', 'o']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'o']]
},
{
"id": 243,
@@ -1581,27 +1167,19 @@
},
{
"id": 244,
- "enabled": true,
- "label": 'Arbitrary Rotation...',
- "visible": true
+ "label": 'Arbitrary Rotation...'
},
{
"id": 245,
- "enabled": true,
- "label": 'Rotate 180?',
- "visible": true
+ "label": 'Rotate 180?'
},
{
"id": 246,
- "enabled": true,
- "label": 'Rotate 90? counter-clockwise',
- "visible": true
+ "label": 'Rotate 90? counter-clockwise'
},
{
"id": 247,
- "enabled": true,
- "label": 'Rotate 90? clockwise',
- "visible": true
+ "label": 'Rotate 90? clockwise'
},
{
"id": 248,
@@ -1609,48 +1187,34 @@
},
{
"id": 249,
- "enabled": true,
- "label": 'Flip Vertically',
- "visible": true
+ "label": 'Flip Vertically'
},
{
"id": 250,
- "enabled": true,
- "label": 'Flip Horizontally',
- "visible": true
+ "label": 'Flip Horizontally'
}
]
},
{
"id": 251,
"children-display": 'submenu',
- "enabled": true,
"label": 'Transparency',
- "visible": true,
"submenu": [
{
"id": 252,
- "enabled": true,
- "label": 'Intersect with Selection',
- "visible": true
+ "label": 'Intersect with Selection'
},
{
"id": 253,
- "enabled": true,
- "label": 'Subtract from Selection',
- "visible": true
+ "label": 'Subtract from Selection'
},
{
"id": 254,
- "enabled": true,
- "label": 'Add to Selection',
- "visible": true
+ "label": 'Add to Selection'
},
{
"id": 255,
- "enabled": true,
- "label": 'Alpha to Selection',
- "visible": true
+ "label": 'Alpha to Selection'
},
{
"id": 256,
@@ -1658,66 +1222,51 @@
},
{
"id": 257,
- "enabled": true,
- "label": 'Threshold Alpha...',
- "visible": true
+ "label": 'Threshold Alpha...'
},
{
"id": 258,
- "enabled": true,
- "label": 'Semi-Flatten',
- "visible": true
+ "label": 'Semi-Flatten'
},
{
"id": 259,
- "enabled": true,
- "label": 'Color to Alpha...',
- "visible": true
+ "label": 'Color to Alpha...'
},
{
"id": 260,
- "enabled": true,
- "label": 'Remove Alpha Channel',
- "visible": true
+ "label": 'Remove Alpha Channel'
},
{
"id": 261,
"enabled": false,
- "label": 'Add Alpha Channel',
- "visible": true
+ "label": 'Add Alpha Channel'
}
]
},
{
"id": 262,
"children-display": 'submenu',
- "enabled": true,
"label": 'Mask',
- "visible": true,
"submenu": [
{
"id": 263,
"enabled": false,
- "label": 'Intersect with Selection',
- "visible": true
+ "label": 'Intersect with Selection'
},
{
"id": 264,
"enabled": false,
- "label": 'Subtract from Selection',
- "visible": true
+ "label": 'Subtract from Selection'
},
{
"id": 265,
"enabled": false,
- "label": 'Add to Selection',
- "visible": true
+ "label": 'Add to Selection'
},
{
"id": 266,
"enabled": false,
- "label": 'Mask to Selection',
- "visible": true
+ "label": 'Mask to Selection'
},
{
"id": 267,
@@ -1728,24 +1277,21 @@
"enabled": false,
"label": 'Disable Layer Mask',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 269,
"enabled": false,
"label": 'Edit Layer Mask',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 270,
"enabled": false,
"label": 'Show Layer Mask',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 271,
@@ -1754,35 +1300,27 @@
{
"id": 272,
"enabled": false,
- "label": 'Delete Layer Mask',
- "visible": true
+ "label": 'Delete Layer Mask'
},
{
"id": 273,
"enabled": false,
- "label": 'Apply Layer Mask',
- "visible": true
+ "label": 'Apply Layer Mask'
},
{
"id": 274,
- "enabled": true,
- "label": 'Add Layer Mask...',
- "visible": true
+ "label": 'Add Layer Mask...'
}
]
},
{
"id": 275,
"children-display": 'submenu',
- "enabled": true,
"label": 'Stack',
- "visible": true,
"submenu": [
{
"id": 276,
- "enabled": true,
- "label": 'Reverse Layer Order',
- "visible": true
+ "label": 'Reverse Layer Order'
},
{
"id": 277,
@@ -1791,26 +1329,22 @@
{
"id": 278,
"enabled": false,
- "label": 'Layer to Bottom',
- "visible": true
+ "label": 'Layer to Bottom'
},
{
"id": 279,
"enabled": false,
- "label": 'Layer to Top',
- "visible": true
+ "label": 'Layer to Top'
},
{
"id": 280,
"enabled": false,
- "label": 'Lower Layer',
- "visible": true
+ "label": 'Lower Layer'
},
{
"id": 281,
"enabled": false,
- "label": 'Raise Layer',
- "visible": true
+ "label": 'Raise Layer'
},
{
"id": 282,
@@ -1820,29 +1354,25 @@
"id": 283,
"enabled": false,
"label": 'Select Bottom Layer',
- "shortcut": [['End']],
- "visible": true
+ "shortcut": [['End']]
},
{
"id": 284,
"enabled": false,
"label": 'Select Top Layer',
- "shortcut": [['Home']],
- "visible": true
+ "shortcut": [['Home']]
},
{
"id": 285,
"enabled": false,
"label": 'Select Next Layer',
- "shortcut": [['Page_Down']],
- "visible": true
+ "shortcut": [['Page_Down']]
},
{
"id": 286,
"enabled": false,
"label": 'Select Previous Layer',
- "shortcut": [['Page_Up']],
- "visible": true
+ "shortcut": [['Page_Up']]
}
]
},
@@ -1854,94 +1384,70 @@
{
"id": 288,
"enabled": false,
- "label": 'Empty',
- "visible": true
+ "label": 'Empty'
}
]
},
{
"id": 289,
- "enabled": true,
- "label": 'Delete Layer',
- "visible": true
+ "label": 'Delete Layer'
},
{
"id": 290,
"enabled": false,
- "label": 'Merge Down',
- "visible": true
+ "label": 'Merge Down'
},
{
"id": 291,
"enabled": false,
"label": 'Anchor Layer',
- "shortcut": [['Control', 'h']],
- "visible": true
+ "shortcut": [['Control', 'h']]
},
{
"id": 292,
- "enabled": true,
"label": 'Duplicate Layer',
- "shortcut": [['Control', 'Shift', 'd']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'd']]
},
{
"id": 293,
- "enabled": true,
- "label": 'New from Visible',
- "visible": true
+ "label": 'New from Visible'
},
{
"id": 294,
- "enabled": true,
"label": 'New Layer...',
- "shortcut": [['Control', 'Shift', 'n']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'n']]
}
]
},
{
"id": 295,
"children-display": 'submenu',
- "enabled": true,
"label": 'Colors',
- "visible": true,
"submenu": [
{
"id": 296,
- "enabled": true,
- "label": 'Retinex...',
- "visible": true
+ "label": 'Retinex...'
},
{
"id": 297,
- "enabled": true,
- "label": 'Maximum RGB...',
- "visible": true
+ "label": 'Maximum RGB...'
},
{
"id": 298,
"enabled": false,
- "label": 'Hot...',
- "visible": true
+ "label": 'Hot...'
},
{
"id": 299,
- "enabled": true,
- "label": 'Filter Pack...',
- "visible": true
+ "label": 'Filter Pack...'
},
{
"id": 300,
- "enabled": true,
- "label": 'Color to Alpha...',
- "visible": true
+ "label": 'Color to Alpha...'
},
{
"id": 301,
- "enabled": true,
- "label": 'Colorify...',
- "visible": true
+ "label": 'Colorify...'
},
{
"id": 302,
@@ -1950,78 +1456,54 @@
{
"id": 303,
"children-display": 'submenu',
- "enabled": true,
"label": 'Info',
- "visible": true,
"submenu": [
{
"id": 304,
- "enabled": true,
- "label": 'Smooth Palette...',
- "visible": true
+ "label": 'Smooth Palette...'
},
{
"id": 305,
- "enabled": true,
- "label": 'Colorcube Analysis...',
- "visible": true
+ "label": 'Colorcube Analysis...'
},
{
"id": 306,
- "enabled": true,
- "label": 'Border Average...',
- "visible": true
+ "label": 'Border Average...'
},
{
"id": 307,
- "enabled": true,
- "label": 'Histogram',
- "visible": true
+ "label": 'Histogram'
}
]
},
{
"id": 308,
"children-display": 'submenu',
- "enabled": true,
"label": 'Map',
- "visible": true,
"submenu": [
{
"id": 309,
- "enabled": true,
- "label": 'Sample Colorize...',
- "visible": true
+ "label": 'Sample Colorize...'
},
{
"id": 310,
- "enabled": true,
- "label": 'Rotate Colors...',
- "visible": true
+ "label": 'Rotate Colors...'
},
{
"id": 311,
- "enabled": true,
- "label": 'Palette Map',
- "visible": true
+ "label": 'Palette Map'
},
{
"id": 312,
- "enabled": true,
- "label": 'Gradient Map',
- "visible": true
+ "label": 'Gradient Map'
},
{
"id": 313,
- "enabled": true,
- "label": 'Color Exchange...',
- "visible": true
+ "label": 'Color Exchange...'
},
{
"id": 314,
- "enabled": true,
- "label": 'Alien Map...',
- "visible": true
+ "label": 'Alien Map...'
},
{
"id": 315,
@@ -2030,92 +1512,68 @@
{
"id": 316,
"enabled": false,
- "label": 'Set Colormap...',
- "visible": true
+ "label": 'Set Colormap...'
},
{
"id": 317,
"enabled": false,
- "label": 'Rearrange Colormap...',
- "visible": true
+ "label": 'Rearrange Colormap...'
}
]
},
{
"id": 318,
"children-display": 'submenu',
- "enabled": true,
"label": 'Components',
- "visible": true,
"submenu": [
{
"id": 319,
"enabled": false,
- "label": 'Recompose',
- "visible": true
+ "label": 'Recompose'
},
{
"id": 320,
- "enabled": true,
- "label": 'Decompose...',
- "visible": true
+ "label": 'Decompose...'
},
{
"id": 321,
"enabled": false,
- "label": 'Compose...',
- "visible": true
+ "label": 'Compose...'
},
{
"id": 322,
- "enabled": true,
- "label": 'Channel Mixer...',
- "visible": true
+ "label": 'Channel Mixer...'
}
]
},
{
"id": 323,
"children-display": 'submenu',
- "enabled": true,
"label": 'Auto',
- "visible": true,
"submenu": [
{
"id": 324,
- "enabled": true,
- "label": 'Stretch HSV',
- "visible": true
+ "label": 'Stretch HSV'
},
{
"id": 325,
- "enabled": true,
- "label": 'Stretch Contrast',
- "visible": true
+ "label": 'Stretch Contrast'
},
{
"id": 326,
- "enabled": true,
- "label": 'Normalize',
- "visible": true
+ "label": 'Normalize'
},
{
"id": 327,
- "enabled": true,
- "label": 'Color Enhance',
- "visible": true
+ "label": 'Color Enhance'
},
{
"id": 328,
- "enabled": true,
- "label": 'White Balance',
- "visible": true
+ "label": 'White Balance'
},
{
"id": 329,
- "enabled": true,
- "label": 'Equalize',
- "visible": true
+ "label": 'Equalize'
}
]
},
@@ -2125,11 +1583,9 @@
},
{
"id": 331,
- "enabled": true,
"label": 'Use GEGL',
"toggle-state": 0,
- "toggle-type": 'checkmark',
- "visible": true
+ "toggle-type": 'checkmark'
},
{
"id": 332,
@@ -2137,15 +1593,11 @@
},
{
"id": 333,
- "enabled": true,
- "label": 'Value Invert',
- "visible": true
+ "label": 'Value Invert'
},
{
"id": 334,
- "enabled": true,
- "label": 'Invert',
- "visible": true
+ "label": 'Invert'
},
{
"id": 335,
@@ -2153,87 +1605,61 @@
},
{
"id": 336,
- "enabled": true,
- "label": 'Desaturate...',
- "visible": true
+ "label": 'Desaturate...'
},
{
"id": 337,
- "enabled": true,
- "label": 'Posterize...',
- "visible": true
+ "label": 'Posterize...'
},
{
"id": 338,
- "enabled": true,
- "label": 'Curves...',
- "visible": true
+ "label": 'Curves...'
},
{
"id": 339,
- "enabled": true,
- "label": 'Levels...',
- "visible": true
+ "label": 'Levels...'
},
{
"id": 340,
- "enabled": true,
- "label": 'Threshold...',
- "visible": true
+ "label": 'Threshold...'
},
{
"id": 341,
- "enabled": true,
- "label": 'Brightness-Contrast...',
- "visible": true
+ "label": 'Brightness-Contrast...'
},
{
"id": 342,
- "enabled": true,
- "label": 'Colorize...',
- "visible": true
+ "label": 'Colorize...'
},
{
"id": 343,
- "enabled": true,
- "label": 'Hue-Saturation...',
- "visible": true
+ "label": 'Hue-Saturation...'
},
{
"id": 344,
- "enabled": true,
- "label": 'Color Balance...',
- "visible": true
+ "label": 'Color Balance...'
}
]
},
{
"id": 345,
"children-display": 'submenu',
- "enabled": true,
"label": 'Tools',
- "visible": true,
"submenu": [
{
"id": 346,
- "enabled": true,
"label": 'Swap Colors',
- "shortcut": [['x']],
- "visible": true
+ "shortcut": [['x']]
},
{
"id": 347,
- "enabled": true,
"label": 'Default Colors',
- "shortcut": [['d']],
- "visible": true
+ "shortcut": [['d']]
},
{
"id": 348,
- "enabled": true,
"label": 'Toolbox',
- "shortcut": [['Control', 'b']],
- "visible": true
+ "shortcut": [['Control', 'b']]
},
{
"id": 349,
@@ -2241,326 +1667,232 @@
},
{
"id": 350,
- "enabled": true,
- "label": 'GEGL Operation...',
- "visible": true
+ "label": 'GEGL Operation...'
},
{
"id": 351,
- "enabled": true,
"label": 'Text',
- "shortcut": [['t']],
- "visible": true
+ "shortcut": [['t']]
},
{
"id": 352,
- "enabled": true,
"label": 'Measure',
- "shortcut": [['Shift', 'm']],
- "visible": true
+ "shortcut": [['Shift', 'm']]
},
{
"id": 353,
- "enabled": true,
"label": 'Zoom',
- "shortcut": [['z']],
- "visible": true
+ "shortcut": [['z']]
},
{
"id": 354,
- "enabled": true,
"label": 'Color Picker',
- "shortcut": [['o']],
- "visible": true
+ "shortcut": [['o']]
},
{
"id": 355,
- "enabled": true,
"label": 'Paths',
- "shortcut": [['b']],
- "visible": true
+ "shortcut": [['b']]
},
{
"id": 356,
"children-display": 'submenu',
- "enabled": true,
"label": 'Color Tools',
- "visible": true,
"submenu": [
{
"id": 357,
- "enabled": true,
- "label": 'Desaturate...',
- "visible": true
+ "label": 'Desaturate...'
},
{
"id": 358,
- "enabled": true,
- "label": 'Posterize...',
- "visible": true
+ "label": 'Posterize...'
},
{
"id": 359,
- "enabled": true,
- "label": 'Curves...',
- "visible": true
+ "label": 'Curves...'
},
{
"id": 360,
- "enabled": true,
- "label": 'Levels...',
- "visible": true
+ "label": 'Levels...'
},
{
"id": 361,
- "enabled": true,
- "label": 'Threshold...',
- "visible": true
+ "label": 'Threshold...'
},
{
"id": 362,
- "enabled": true,
- "label": 'Brightness-Contrast...',
- "visible": true
+ "label": 'Brightness-Contrast...'
},
{
"id": 363,
- "enabled": true,
- "label": 'Colorize...',
- "visible": true
+ "label": 'Colorize...'
},
{
"id": 364,
- "enabled": true,
- "label": 'Hue-Saturation...',
- "visible": true
+ "label": 'Hue-Saturation...'
},
{
"id": 365,
- "enabled": true,
- "label": 'Color Balance...',
- "visible": true
+ "label": 'Color Balance...'
}
]
},
{
"id": 366,
"children-display": 'submenu',
- "enabled": true,
"label": 'Transform Tools',
- "visible": true,
"submenu": [
{
"id": 367,
- "enabled": true,
"label": 'Flip',
- "shortcut": [['Shift', 'f']],
- "visible": true
+ "shortcut": [['Shift', 'f']]
},
{
"id": 368,
- "enabled": true,
"label": 'Perspective',
- "shortcut": [['Shift', 'p']],
- "visible": true
+ "shortcut": [['Shift', 'p']]
},
{
"id": 369,
- "enabled": true,
"label": 'Shear',
- "shortcut": [['Shift', 's']],
- "visible": true
+ "shortcut": [['Shift', 's']]
},
{
"id": 370,
- "enabled": true,
"label": 'Scale',
- "shortcut": [['Shift', 't']],
- "visible": true
+ "shortcut": [['Shift', 't']]
},
{
"id": 371,
- "enabled": true,
"label": 'Rotate',
- "shortcut": [['Shift', 'r']],
- "visible": true
+ "shortcut": [['Shift', 'r']]
},
{
"id": 372,
- "enabled": true,
"label": 'Crop',
- "shortcut": [['Shift', 'c']],
- "visible": true
+ "shortcut": [['Shift', 'c']]
},
{
"id": 373,
- "enabled": true,
"label": 'Move',
- "shortcut": [['m']],
- "visible": true
+ "shortcut": [['m']]
},
{
"id": 374,
- "enabled": true,
"label": 'Align',
- "shortcut": [['q']],
- "visible": true
+ "shortcut": [['q']]
}
]
},
{
"id": 375,
"children-display": 'submenu',
- "enabled": true,
"label": 'Paint Tools',
- "visible": true,
"submenu": [
{
"id": 376,
- "enabled": true,
"label": 'Dodge / Burn',
- "shortcut": [['Shift', 'd']],
- "visible": true
+ "shortcut": [['Shift', 'd']]
},
{
"id": 377,
- "enabled": true,
"label": 'Smudge',
- "shortcut": [['s']],
- "visible": true
+ "shortcut": [['s']]
},
{
"id": 378,
- "enabled": true,
"label": 'Blur / Sharpen',
- "shortcut": [['Shift', 'u']],
- "visible": true
+ "shortcut": [['Shift', 'u']]
},
{
"id": 379,
- "enabled": true,
- "label": 'Perspective Clone',
- "visible": true
+ "label": 'Perspective Clone'
},
{
"id": 380,
- "enabled": true,
"label": 'Heal',
- "shortcut": [['h']],
- "visible": true
+ "shortcut": [['h']]
},
{
"id": 381,
- "enabled": true,
"label": 'Clone',
- "shortcut": [['c']],
- "visible": true
+ "shortcut": [['c']]
},
{
"id": 382,
- "enabled": true,
"label": 'Ink',
- "shortcut": [['k']],
- "visible": true
+ "shortcut": [['k']]
},
{
"id": 383,
- "enabled": true,
"label": 'Airbrush',
- "shortcut": [['a']],
- "visible": true
+ "shortcut": [['a']]
},
{
"id": 384,
- "enabled": true,
"label": 'Eraser',
- "shortcut": [['Shift', 'e']],
- "visible": true
+ "shortcut": [['Shift', 'e']]
},
{
"id": 385,
- "enabled": true,
"label": 'Paintbrush',
- "shortcut": [['p']],
- "visible": true
+ "shortcut": [['p']]
},
{
"id": 386,
- "enabled": true,
"label": 'Pencil',
- "shortcut": [['n']],
- "visible": true
+ "shortcut": [['n']]
},
{
"id": 387,
- "enabled": true,
"label": 'Blend',
- "shortcut": [['l']],
- "visible": true
+ "shortcut": [['l']]
},
{
"id": 388,
- "enabled": true,
"label": 'Bucket Fill',
- "shortcut": [['Shift', 'b']],
- "visible": true
+ "shortcut": [['Shift', 'b']]
}
]
},
{
"id": 389,
"children-display": 'submenu',
- "enabled": true,
"label": 'Selection Tools',
- "visible": true,
"submenu": [
{
"id": 390,
- "enabled": true,
"label": 'Intelligent Scissors',
- "shortcut": [['i']],
- "visible": true
+ "shortcut": [['i']]
},
{
"id": 391,
- "enabled": true,
"label": 'By Color Select',
- "shortcut": [['Shift', 'o']],
- "visible": true
+ "shortcut": [['Shift', 'o']]
},
{
"id": 392,
- "enabled": true,
"label": 'Fuzzy Select',
- "shortcut": [['u']],
- "visible": true
+ "shortcut": [['u']]
},
{
"id": 393,
- "enabled": true,
- "label": 'Foreground Select',
- "visible": true
+ "label": 'Foreground Select'
},
{
"id": 394,
- "enabled": true,
"label": 'Free Select',
- "shortcut": [['f']],
- "visible": true
+ "shortcut": [['f']]
},
{
"id": 395,
- "enabled": true,
"label": 'Ellipse Select',
- "shortcut": [['e']],
- "visible": true
+ "shortcut": [['e']]
},
{
"id": 396,
- "enabled": true,
"label": 'Rectangle Select',
- "shortcut": [['r']],
- "visible": true
+ "shortcut": [['r']]
}
]
}
@@ -2569,49 +1901,35 @@
{
"id": 397,
"children-display": 'submenu',
- "enabled": true,
"label": 'Filters',
- "visible": true,
"submenu": [
{
"id": 398,
"children-display": 'submenu',
- "enabled": true,
"label": 'Script-Fu',
- "visible": true,
"submenu": [
{
"id": 399,
- "enabled": true,
- "label": 'Start Server...',
- "visible": true
+ "label": 'Start Server...'
},
{
"id": 400,
- "enabled": true,
- "label": 'Refresh Scripts',
- "visible": true
+ "label": 'Refresh Scripts'
},
{
"id": 401,
- "enabled": true,
- "label": 'Console',
- "visible": true
+ "label": 'Console'
}
]
},
{
"id": 402,
"children-display": 'submenu',
- "enabled": true,
"label": 'Python-Fu',
- "visible": true,
"submenu": [
{
"id": 403,
- "enabled": true,
- "label": 'Console',
- "visible": true
+ "label": 'Console'
}
]
},
@@ -2622,123 +1940,83 @@
{
"id": 405,
"children-display": 'submenu',
- "enabled": true,
"label": 'Alpha to Logo',
- "visible": true,
"submenu": [
{
"id": 406,
- "enabled": true,
- "label": 'Textured...',
- "visible": true
+ "label": 'Textured...'
},
{
"id": 407,
- "enabled": true,
- "label": 'Particle Trace...',
- "visible": true
+ "label": 'Particle Trace...'
},
{
"id": 408,
- "enabled": true,
- "label": 'Neon...',
- "visible": true
+ "label": 'Neon...'
},
{
"id": 409,
- "enabled": true,
- "label": 'Gradient Bevel...',
- "visible": true
+ "label": 'Gradient Bevel...'
},
{
"id": 410,
- "enabled": true,
- "label": 'Glowing Hot...',
- "visible": true
+ "label": 'Glowing Hot...'
},
{
"id": 411,
- "enabled": true,
- "label": 'Glossy...',
- "visible": true
+ "label": 'Glossy...'
},
{
"id": 412,
- "enabled": true,
- "label": 'Frosty...',
- "visible": true
+ "label": 'Frosty...'
},
{
"id": 413,
- "enabled": true,
- "label": 'Cool Metal...',
- "visible": true
+ "label": 'Cool Metal...'
},
{
"id": 414,
- "enabled": true,
- "label": 'Comic Book...',
- "visible": true
+ "label": 'Comic Book...'
},
{
"id": 415,
- "enabled": true,
- "label": 'Chrome...',
- "visible": true
+ "label": 'Chrome...'
},
{
"id": 416,
- "enabled": true,
- "label": 'Chip Away...',
- "visible": true
+ "label": 'Chip Away...'
},
{
"id": 417,
- "enabled": true,
- "label": 'Chalk...',
- "visible": true
+ "label": 'Chalk...'
},
{
"id": 418,
- "enabled": true,
- "label": 'Bovination...',
- "visible": true
+ "label": 'Bovination...'
},
{
"id": 419,
- "enabled": true,
- "label": 'Blended...',
- "visible": true
+ "label": 'Blended...'
},
{
"id": 420,
- "enabled": true,
- "label": 'Basic I...',
- "visible": true
+ "label": 'Basic I...'
},
{
"id": 421,
- "enabled": true,
- "label": 'Basic II...',
- "visible": true
+ "label": 'Basic II...'
},
{
"id": 422,
- "enabled": true,
- "label": 'Alien Neon...',
- "visible": true
+ "label": 'Alien Neon...'
},
{
"id": 423,
- "enabled": true,
- "label": 'Alien Glow...',
- "visible": true
+ "label": 'Alien Glow...'
},
{
"id": 424,
- "enabled": true,
- "label": '3D Outline...',
- "visible": true
+ "label": '3D Outline...'
}
]
},
@@ -2749,33 +2027,23 @@
{
"id": 426,
"children-display": 'submenu',
- "enabled": true,
"label": 'Animation',
- "visible": true,
"submenu": [
{
"id": 427,
- "enabled": true,
- "label": 'Unoptimize',
- "visible": true
+ "label": 'Unoptimize'
},
{
"id": 428,
- "enabled": true,
- "label": 'Playback...',
- "visible": true
+ "label": 'Playback...'
},
{
"id": 429,
- "enabled": true,
- "label": 'Optimize (for GIF)',
- "visible": true
+ "label": 'Optimize (for GIF)'
},
{
"id": 430,
- "enabled": true,
- "label": 'Optimize (Difference)',
- "visible": true
+ "label": 'Optimize (Difference)'
},
{
"id": 431,
@@ -2783,111 +2051,77 @@
},
{
"id": 432,
- "enabled": true,
- "label": 'Waves...',
- "visible": true
+ "label": 'Waves...'
},
{
"id": 433,
- "enabled": true,
- "label": 'Spinning Globe...',
- "visible": true
+ "label": 'Spinning Globe...'
},
{
"id": 434,
- "enabled": true,
- "label": 'Rippling...',
- "visible": true
+ "label": 'Rippling...'
},
{
"id": 435,
- "enabled": true,
- "label": 'Burn-In...',
- "visible": true
+ "label": 'Burn-In...'
},
{
"id": 436,
- "enabled": true,
- "label": 'Blend...',
- "visible": true
+ "label": 'Blend...'
}
]
},
{
"id": 437,
"children-display": 'submenu',
- "enabled": true,
"label": 'Web',
- "visible": true,
"submenu": [
{
"id": 438,
- "enabled": true,
- "label": 'Slice...',
- "visible": true
+ "label": 'Slice...'
},
{
"id": 439,
- "enabled": true,
- "label": 'Semi-Flatten',
- "visible": true
+ "label": 'Semi-Flatten'
},
{
"id": 440,
- "enabled": true,
- "label": 'Image Map...',
- "visible": true
+ "label": 'Image Map...'
}
]
},
{
"id": 441,
"children-display": 'submenu',
- "enabled": true,
"label": 'Render',
- "visible": true,
"submenu": [
{
"id": 442,
- "enabled": true,
- "label": 'Spyrogimp...',
- "visible": true
+ "label": 'Spyrogimp...'
},
{
"id": 443,
- "enabled": true,
- "label": 'Sphere Designer...',
- "visible": true
+ "label": 'Sphere Designer...'
},
{
"id": 444,
- "enabled": true,
- "label": 'Line Nova...',
- "visible": true
+ "label": 'Line Nova...'
},
{
"id": 445,
- "enabled": true,
- "label": 'Lava...',
- "visible": true
+ "label": 'Lava...'
},
{
"id": 446,
- "enabled": true,
- "label": 'Gfig...',
- "visible": true
+ "label": 'Gfig...'
},
{
"id": 447,
- "enabled": true,
- "label": 'Fractal Explorer...',
- "visible": true
+ "label": 'Fractal Explorer...'
},
{
"id": 448,
- "enabled": true,
- "label": 'Circuit...',
- "visible": true
+ "label": 'Circuit...'
},
{
"id": 449,
@@ -2896,111 +2130,77 @@
{
"id": 450,
"children-display": 'submenu',
- "enabled": true,
"label": 'Pattern',
- "visible": true,
"submenu": [
{
"id": 451,
- "enabled": true,
- "label": 'Sinus...',
- "visible": true
+ "label": 'Sinus...'
},
{
"id": 452,
- "enabled": true,
- "label": 'Qbist...',
- "visible": true
+ "label": 'Qbist...'
},
{
"id": 453,
- "enabled": true,
- "label": 'Maze...',
- "visible": true
+ "label": 'Maze...'
},
{
"id": 454,
- "enabled": true,
- "label": 'Jigsaw...',
- "visible": true
+ "label": 'Jigsaw...'
},
{
"id": 455,
- "enabled": true,
- "label": 'Grid...',
- "visible": true
+ "label": 'Grid...'
},
{
"id": 456,
- "enabled": true,
- "label": 'Diffraction Patterns...',
- "visible": true
+ "label": 'Diffraction Patterns...'
},
{
"id": 457,
- "enabled": true,
- "label": 'CML Explorer...',
- "visible": true
+ "label": 'CML Explorer...'
},
{
"id": 458,
- "enabled": true,
- "label": 'Checkerboard...',
- "visible": true
+ "label": 'Checkerboard...'
}
]
},
{
"id": 459,
"children-display": 'submenu',
- "enabled": true,
"label": 'Nature',
- "visible": true,
"submenu": [
{
"id": 460,
- "enabled": true,
- "label": 'IFS Fractal...',
- "visible": true
+ "label": 'IFS Fractal...'
},
{
"id": 461,
- "enabled": true,
- "label": 'Flame...',
- "visible": true
+ "label": 'Flame...'
}
]
},
{
"id": 462,
"children-display": 'submenu',
- "enabled": true,
"label": 'Clouds',
- "visible": true,
"submenu": [
{
"id": 463,
- "enabled": true,
- "label": 'Solid Noise...',
- "visible": true
+ "label": 'Solid Noise...'
},
{
"id": 464,
- "enabled": true,
- "label": 'Plasma...',
- "visible": true
+ "label": 'Plasma...'
},
{
"id": 465,
- "enabled": true,
- "label": 'Fog...',
- "visible": true
+ "label": 'Fog...'
},
{
"id": 466,
- "enabled": true,
- "label": 'Difference Clouds...',
- "visible": true
+ "label": 'Difference Clouds...'
}
]
}
@@ -3009,360 +2209,252 @@
{
"id": 467,
"children-display": 'submenu',
- "enabled": true,
"label": 'Map',
- "visible": true,
"submenu": [
{
"id": 468,
- "enabled": true,
- "label": 'Warp...',
- "visible": true
+ "label": 'Warp...'
},
{
"id": 469,
- "enabled": true,
- "label": 'Tile...',
- "visible": true
+ "label": 'Tile...'
},
{
"id": 470,
- "enabled": true,
- "label": 'Small Tiles...',
- "visible": true
+ "label": 'Small Tiles...'
},
{
"id": 471,
- "enabled": true,
- "label": 'Paper Tile...',
- "visible": true
+ "label": 'Paper Tile...'
},
{
"id": 472,
- "enabled": true,
- "label": 'Map Object...',
- "visible": true
+ "label": 'Map Object...'
},
{
"id": 473,
- "enabled": true,
- "label": 'Make Seamless',
- "visible": true
+ "label": 'Make Seamless'
},
{
"id": 474,
- "enabled": true,
- "label": 'Illusion...',
- "visible": true
+ "label": 'Illusion...'
},
{
"id": 475,
- "enabled": true,
- "label": 'Fractal Trace...',
- "visible": true
+ "label": 'Fractal Trace...'
},
{
"id": 476,
- "enabled": true,
- "label": 'Displace...',
- "visible": true
+ "label": 'Displace...'
},
{
"id": 477,
- "enabled": true,
- "label": 'Bump Map...',
- "visible": true
+ "label": 'Bump Map...'
}
]
},
{
"id": 478,
"children-display": 'submenu',
- "enabled": true,
"label": 'Decor',
- "visible": true,
"submenu": [
{
"id": 479,
"enabled": false,
- "label": 'Stencil Chrome...',
- "visible": true
+ "label": 'Stencil Chrome...'
},
{
"id": 480,
"enabled": false,
- "label": 'Stencil Carve...',
- "visible": true
+ "label": 'Stencil Carve...'
},
{
"id": 481,
"enabled": false,
- "label": 'Slide...',
- "visible": true
+ "label": 'Slide...'
},
{
"id": 482,
"enabled": false,
- "label": 'Round Corners...',
- "visible": true
+ "label": 'Round Corners...'
},
{
"id": 483,
- "enabled": true,
- "label": 'Old Photo...',
- "visible": true
+ "label": 'Old Photo...'
},
{
"id": 484,
- "enabled": true,
- "label": 'Fuzzy Border...',
- "visible": true
+ "label": 'Fuzzy Border...'
},
{
"id": 485,
- "enabled": true,
- "label": 'Coffee Stain...',
- "visible": true
+ "label": 'Coffee Stain...'
},
{
"id": 486,
- "enabled": true,
- "label": 'Add Border...',
- "visible": true
+ "label": 'Add Border...'
},
{
"id": 487,
- "enabled": true,
- "label": 'Add Bevel...',
- "visible": true
+ "label": 'Add Bevel...'
}
]
},
{
"id": 488,
"children-display": 'submenu',
- "enabled": true,
"label": 'Artistic',
- "visible": true,
"submenu": [
{
"id": 489,
- "enabled": true,
- "label": 'Weave...',
- "visible": true
+ "label": 'Weave...'
},
{
"id": 490,
- "enabled": true,
- "label": 'Van Gogh (LIC)...',
- "visible": true
+ "label": 'Van Gogh (LIC)...'
},
{
"id": 491,
- "enabled": true,
- "label": 'Softglow...',
- "visible": true
+ "label": 'Softglow...'
},
{
"id": 492,
- "enabled": true,
- "label": 'Predator...',
- "visible": true
+ "label": 'Predator...'
},
{
"id": 493,
- "enabled": true,
- "label": 'Photocopy...',
- "visible": true
+ "label": 'Photocopy...'
},
{
"id": 494,
- "enabled": true,
- "label": 'Oilify...',
- "visible": true
+ "label": 'Oilify...'
},
{
"id": 495,
- "enabled": true,
- "label": 'GIMPressionist...',
- "visible": true
+ "label": 'GIMPressionist...'
},
{
"id": 496,
- "enabled": true,
- "label": 'Cubism...',
- "visible": true
+ "label": 'Cubism...'
},
{
"id": 497,
- "enabled": true,
- "label": 'Clothify...',
- "visible": true
+ "label": 'Clothify...'
},
{
"id": 498,
- "enabled": true,
- "label": 'Cartoon...',
- "visible": true
+ "label": 'Cartoon...'
},
{
"id": 499,
- "enabled": true,
- "label": 'Apply Canvas...',
- "visible": true
+ "label": 'Apply Canvas...'
}
]
},
{
"id": 500,
"children-display": 'submenu',
- "enabled": true,
"label": 'Combine',
- "visible": true,
"submenu": [
{
"id": 501,
- "enabled": true,
- "label": 'Filmstrip...',
- "visible": true
+ "label": 'Filmstrip...'
},
{
"id": 502,
- "enabled": true,
- "label": 'Depth Merge...',
- "visible": true
+ "label": 'Depth Merge...'
}
]
},
{
"id": 503,
"children-display": 'submenu',
- "enabled": true,
"label": 'Generic',
- "visible": true,
"submenu": [
{
"id": 504,
- "enabled": true,
- "label": 'Erode',
- "visible": true
+ "label": 'Erode'
},
{
"id": 505,
- "enabled": true,
- "label": 'Dilate',
- "visible": true
+ "label": 'Dilate'
},
{
"id": 506,
- "enabled": true,
- "label": 'Convolution Matrix...',
- "visible": true
+ "label": 'Convolution Matrix...'
}
]
},
{
"id": 507,
"children-display": 'submenu',
- "enabled": true,
"label": 'Edge-Detect',
- "visible": true,
"submenu": [
{
"id": 508,
- "enabled": true,
- "label": 'Sobel...',
- "visible": true
+ "label": 'Sobel...'
},
{
"id": 509,
- "enabled": true,
- "label": 'Neon...',
- "visible": true
+ "label": 'Neon...'
},
{
"id": 510,
- "enabled": true,
- "label": 'Laplace',
- "visible": true
+ "label": 'Laplace'
},
{
"id": 511,
- "enabled": true,
- "label": 'Edge...',
- "visible": true
+ "label": 'Edge...'
},
{
"id": 512,
- "enabled": true,
- "label": 'Difference of Gaussians...',
- "visible": true
+ "label": 'Difference of Gaussians...'
}
]
},
{
"id": 513,
"children-display": 'submenu',
- "enabled": true,
"label": 'Noise',
- "visible": true,
"submenu": [
{
"id": 514,
- "enabled": true,
- "label": 'Spread...',
- "visible": true
+ "label": 'Spread...'
},
{
"id": 515,
- "enabled": true,
- "label": 'Slur...',
- "visible": true
+ "label": 'Slur...'
},
{
"id": 516,
- "enabled": true,
- "label": 'RGB Noise...',
- "visible": true
+ "label": 'RGB Noise...'
},
{
"id": 517,
- "enabled": true,
- "label": 'Pick...',
- "visible": true
+ "label": 'Pick...'
},
{
"id": 518,
- "enabled": true,
- "label": 'Hurl...',
- "visible": true
+ "label": 'Hurl...'
},
{
"id": 519,
- "enabled": true,
- "label": 'HSV Noise...',
- "visible": true
+ "label": 'HSV Noise...'
}
]
},
{
"id": 520,
"children-display": 'submenu',
- "enabled": true,
"label": 'Light and Shadow',
- "visible": true,
"submenu": [
{
"id": 521,
- "enabled": true,
- "label": 'Glass Tile...',
- "visible": true
+ "label": 'Glass Tile...'
},
{
"id": 522,
- "enabled": true,
- "label": 'Apply Lens...',
- "visible": true
+ "label": 'Apply Lens...'
},
{
"id": 523,
@@ -3370,21 +2462,15 @@
},
{
"id": 524,
- "enabled": true,
- "label": 'Xach-Effect...',
- "visible": true
+ "label": 'Xach-Effect...'
},
{
"id": 525,
- "enabled": true,
- "label": 'Perspective...',
- "visible": true
+ "label": 'Perspective...'
},
{
"id": 526,
- "enabled": true,
- "label": 'Drop Shadow...',
- "visible": true
+ "label": 'Drop Shadow...'
},
{
"id": 527,
@@ -3392,252 +2478,173 @@
},
{
"id": 528,
- "enabled": true,
- "label": 'Supernova...',
- "visible": true
+ "label": 'Supernova...'
},
{
"id": 529,
- "enabled": true,
- "label": 'Sparkle...',
- "visible": true
+ "label": 'Sparkle...'
},
{
"id": 530,
- "enabled": true,
- "label": 'Lighting Effects...',
- "visible": true
+ "label": 'Lighting Effects...'
},
{
"id": 531,
- "enabled": true,
- "label": 'Lens Flare...',
- "visible": true
+ "label": 'Lens Flare...'
},
{
"id": 532,
- "enabled": true,
- "label": 'Gradient Flare...',
- "visible": true
+ "label": 'Gradient Flare...'
}
]
},
{
"id": 533,
"children-display": 'submenu',
- "enabled": true,
"label": 'Distorts',
- "visible": true,
"submenu": [
{
"id": 534,
- "enabled": true,
- "label": 'Wind...',
- "visible": true
+ "label": 'Wind...'
},
{
"id": 535,
- "enabled": true,
- "label": 'Whirl and Pinch...',
- "visible": true
+ "label": 'Whirl and Pinch...'
},
{
"id": 536,
- "enabled": true,
- "label": 'Waves...',
- "visible": true
+ "label": 'Waves...'
},
{
"id": 537,
- "enabled": true,
- "label": 'Video...',
- "visible": true
+ "label": 'Video...'
},
{
"id": 538,
- "enabled": true,
- "label": 'Value Propagate...',
- "visible": true
+ "label": 'Value Propagate...'
},
{
"id": 539,
- "enabled": true,
- "label": 'Shift...',
- "visible": true
+ "label": 'Shift...'
},
{
"id": 540,
- "enabled": true,
- "label": 'Ripple...',
- "visible": true
+ "label": 'Ripple...'
},
{
"id": 541,
- "enabled": true,
- "label": 'Polar Coordinates...',
- "visible": true
+ "label": 'Polar Coordinates...'
},
{
"id": 542,
- "enabled": true,
- "label": 'Pagecurl...',
- "visible": true
+ "label": 'Pagecurl...'
},
{
"id": 543,
- "enabled": true,
- "label": 'Newsprint...',
- "visible": true
+ "label": 'Newsprint...'
},
{
"id": 544,
- "enabled": true,
- "label": 'Mosaic...',
- "visible": true
+ "label": 'Mosaic...'
},
{
"id": 545,
- "enabled": true,
- "label": 'Lens Distortion...',
- "visible": true
+ "label": 'Lens Distortion...'
},
{
"id": 546,
- "enabled": true,
- "label": 'IWarp...',
- "visible": true
+ "label": 'IWarp...'
},
{
"id": 547,
- "enabled": true,
- "label": 'Erase Every Other Row...',
- "visible": true
+ "label": 'Erase Every Other Row...'
},
{
"id": 548,
- "enabled": true,
- "label": 'Engrave...',
- "visible": true
+ "label": 'Engrave...'
},
{
"id": 549,
- "enabled": true,
- "label": 'Emboss...',
- "visible": true
+ "label": 'Emboss...'
},
{
"id": 550,
- "enabled": true,
- "label": 'Curve Bend...',
- "visible": true
+ "label": 'Curve Bend...'
},
{
"id": 551,
- "enabled": true,
- "label": 'Blinds...',
- "visible": true
+ "label": 'Blinds...'
}
]
},
{
"id": 552,
"children-display": 'submenu',
- "enabled": true,
"label": 'Enhance',
- "visible": true,
"submenu": [
{
"id": 553,
- "enabled": true,
- "label": 'Unsharp Mask...',
- "visible": true
+ "label": 'Unsharp Mask...'
},
{
"id": 554,
- "enabled": true,
- "label": 'Sharpen...',
- "visible": true
+ "label": 'Sharpen...'
},
{
"id": 555,
- "enabled": true,
- "label": 'Red Eye Removal...',
- "visible": true
+ "label": 'Red Eye Removal...'
},
{
"id": 556,
"enabled": false,
- "label": 'NL Filter...',
- "visible": true
+ "label": 'NL Filter...'
},
{
"id": 557,
- "enabled": true,
- "label": 'Destripe...',
- "visible": true
+ "label": 'Destripe...'
},
{
"id": 558,
- "enabled": true,
- "label": 'Despeckle...',
- "visible": true
+ "label": 'Despeckle...'
},
{
"id": 559,
- "enabled": true,
- "label": 'Deinterlace...',
- "visible": true
+ "label": 'Deinterlace...'
},
{
"id": 560,
- "enabled": true,
- "label": 'Antialias',
- "visible": true
+ "label": 'Antialias'
}
]
},
{
"id": 561,
"children-display": 'submenu',
- "enabled": true,
"label": 'Blur',
- "visible": true,
"submenu": [
{
"id": 562,
- "enabled": true,
- "label": 'Tileable Blur...',
- "visible": true
+ "label": 'Tileable Blur...'
},
{
"id": 563,
- "enabled": true,
- "label": 'Selective Gaussian Blur...',
- "visible": true
+ "label": 'Selective Gaussian Blur...'
},
{
"id": 564,
- "enabled": true,
- "label": 'Pixelize...',
- "visible": true
+ "label": 'Pixelize...'
},
{
"id": 565,
- "enabled": true,
- "label": 'Motion Blur...',
- "visible": true
+ "label": 'Motion Blur...'
},
{
"id": 566,
- "enabled": true,
- "label": 'Gaussian Blur...',
- "visible": true
+ "label": 'Gaussian Blur...'
},
{
"id": 567,
- "enabled": true,
- "label": 'Blur',
- "visible": true
+ "label": 'Blur'
}
]
},
@@ -3647,9 +2654,7 @@
},
{
"id": 569,
- "enabled": true,
- "label": 'Reset all Filters',
- "visible": true
+ "label": 'Reset all Filters'
},
{
"id": 570,
@@ -3657,13 +2662,11 @@
"enabled": false,
"label": 'Re-Show Last',
"shortcut": [['Control', 'Shift', 'f']],
- "visible": true,
"submenu": [
{
"id": 571,
"enabled": false,
- "label": 'Empty',
- "visible": true
+ "label": 'Empty'
}
]
},
@@ -3671,24 +2674,19 @@
"id": 572,
"enabled": false,
"label": 'Repeat Last',
- "shortcut": [['Control', 'f']],
- "visible": true
+ "shortcut": [['Control', 'f']]
}
]
},
{
"id": 573,
"children-display": 'submenu',
- "enabled": true,
"label": 'Windows',
- "visible": true,
"submenu": [
{
"id": 574,
- "enabled": true,
"label": 'Toolbox',
- "shortcut": [['Control', 'b']],
- "visible": true
+ "shortcut": [['Control', 'b']]
},
{
"id": 575,
@@ -3697,39 +2695,27 @@
{
"id": 576,
"children-display": 'submenu',
- "enabled": true,
"label": 'Dockable Dialogs',
- "visible": true,
"submenu": [
{
"id": 577,
- "enabled": true,
- "label": 'Error Console',
- "visible": true
+ "label": 'Error Console'
},
{
"id": 578,
- "enabled": true,
- "label": 'Tools',
- "visible": true
+ "label": 'Tools'
},
{
"id": 579,
- "enabled": true,
- "label": 'Templates',
- "visible": true
+ "label": 'Templates'
},
{
"id": 580,
- "enabled": true,
- "label": 'Document History',
- "visible": true
+ "label": 'Document History'
},
{
"id": 581,
- "enabled": true,
- "label": 'Images',
- "visible": true
+ "label": 'Images'
},
{
"id": 582,
@@ -3737,48 +2723,34 @@
},
{
"id": 583,
- "enabled": true,
- "label": 'Buffers',
- "visible": true
+ "label": 'Buffers'
},
{
"id": 584,
- "enabled": true,
- "label": 'Fonts',
- "visible": true
+ "label": 'Fonts'
},
{
"id": 585,
- "enabled": true,
- "label": 'Palettes',
- "visible": true
+ "label": 'Palettes'
},
{
"id": 586,
- "enabled": true,
"label": 'Gradients',
- "shortcut": [['Control', 'g']],
- "visible": true
+ "shortcut": [['Control', 'g']]
},
{
"id": 587,
- "enabled": true,
"label": 'Patterns',
- "shortcut": [['Control', 'Shift', 'p']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'p']]
},
{
"id": 588,
- "enabled": true,
"label": 'Brushes',
- "shortcut": [['Control', 'Shift', 'b']],
- "visible": true
+ "shortcut": [['Control', 'Shift', 'b']]
},
{
"id": 589,
- "enabled": true,
- "label": 'Colors',
- "visible": true
+ "label": 'Colors'
},
{
"id": 590,
@@ -3786,64 +2758,44 @@
},
{
"id": 591,
- "enabled": true,
- "label": 'Sample Points',
- "visible": true
+ "label": 'Sample Points'
},
{
"id": 592,
- "enabled": true,
- "label": 'Pointer',
- "visible": true
+ "label": 'Pointer'
},
{
"id": 593,
- "enabled": true,
- "label": 'Undo History',
- "visible": true
+ "label": 'Undo History'
},
{
"id": 594,
- "enabled": true,
- "label": 'Navigation',
- "visible": true
+ "label": 'Navigation'
},
{
"id": 595,
- "enabled": true,
- "label": 'Selection Editor',
- "visible": true
+ "label": 'Selection Editor'
},
{
"id": 596,
- "enabled": true,
- "label": 'Histogram',
- "visible": true
+ "label": 'Histogram'
},
{
"id": 597,
- "enabled": true,
- "label": 'Colormap',
- "visible": true
+ "label": 'Colormap'
},
{
"id": 598,
- "enabled": true,
- "label": 'Paths',
- "visible": true
+ "label": 'Paths'
},
{
"id": 599,
- "enabled": true,
- "label": 'Channels',
- "visible": true
+ "label": 'Channels'
},
{
"id": 600,
- "enabled": true,
"label": 'Layers',
- "shortcut": [['Control', 'l']],
- "visible": true
+ "shortcut": [['Control', 'l']]
},
{
"id": 601,
@@ -3851,30 +2803,23 @@
},
{
"id": 602,
- "enabled": true,
- "label": 'Device Status',
- "visible": true
+ "label": 'Device Status'
},
{
"id": 603,
- "enabled": true,
- "label": 'Tool Options',
- "visible": true
+ "label": 'Tool Options'
}
]
},
{
"id": 604,
"children-display": 'submenu',
- "enabled": true,
"label": 'Recently Closed Docks',
- "visible": true,
"submenu": [
{
"id": 605,
"enabled": false,
- "label": 'Empty',
- "visible": true
+ "label": 'Empty'
}
]
}
@@ -3883,91 +2828,63 @@
{
"id": 606,
"children-display": 'submenu',
- "enabled": true,
"label": 'Help',
- "visible": true,
"submenu": [
{
"id": 607,
"children-display": 'submenu',
- "enabled": true,
"label": 'User Manual',
- "visible": true,
"submenu": [
{
"id": 608,
- "enabled": true,
- "label": 'Working with Digital Camera Photos',
- "visible": true
+ "label": 'Working with Digital Camera Photos'
},
{
"id": 609,
- "enabled": true,
- "label": 'Using Paths',
- "visible": true
+ "label": 'Using Paths'
},
{
"id": 610,
- "enabled": true,
- "label": 'Preparing your Images for the Web',
- "visible": true
+ "label": 'Preparing your Images for the Web'
},
{
"id": 611,
- "enabled": true,
- "label": 'How to Use Dialogs',
- "visible": true
+ "label": 'How to Use Dialogs'
},
{
"id": 612,
- "enabled": true,
- "label": 'Drawing Simple Objects',
- "visible": true
+ "label": 'Drawing Simple Objects'
},
{
"id": 613,
- "enabled": true,
- "label": 'Create, Open and Save Files',
- "visible": true
+ "label": 'Create, Open and Save Files'
},
{
"id": 614,
- "enabled": true,
- "label": 'Basic Concepts',
- "visible": true
+ "label": 'Basic Concepts'
}
]
},
{
"id": 615,
"children-display": 'submenu',
- "enabled": true,
"label": 'GIMP Online',
- "visible": true,
"submenu": [
{
"id": 616,
- "enabled": true,
- "label": 'User Manual Web Site',
- "visible": true
+ "label": 'User Manual Web Site'
},
{
"id": 617,
- "enabled": true,
- "label": 'Plug-in Registry',
- "visible": true
+ "label": 'Plug-in Registry'
},
{
"id": 618,
- "enabled": true,
- "label": 'Main Web Site',
- "visible": true
+ "label": 'Main Web Site'
},
{
"id": 619,
- "enabled": true,
- "label": 'Developer Web Site',
- "visible": true
+ "label": 'Developer Web Site'
}
]
},
@@ -3977,15 +2894,11 @@
},
{
"id": 621,
- "enabled": true,
- "label": 'Procedure Browser',
- "visible": true
+ "label": 'Procedure Browser'
},
{
"id": 622,
- "enabled": true,
- "label": 'Plug-In Browser',
- "visible": true
+ "label": 'Plug-In Browser'
},
{
"id": 623,
@@ -3993,29 +2906,21 @@
},
{
"id": 624,
- "enabled": true,
- "label": 'About',
- "visible": true
+ "label": 'About'
},
{
"id": 625,
- "enabled": true,
- "label": 'Tip of the Day',
- "visible": true
+ "label": 'Tip of the Day'
},
{
"id": 626,
- "enabled": true,
"label": 'Context Help',
- "shortcut": [['Shift', 'F1']],
- "visible": true
+ "shortcut": [['Shift', 'F1']]
},
{
"id": 627,
- "enabled": true,
"label": 'Help',
- "shortcut": [['F1']],
- "visible": true
+ "shortcut": [['F1']]
}
]
}
diff --git a/tools/dbusmenu-dumper.c b/tools/dbusmenu-dumper.c
index bd986e8..2db437d 100644
--- a/tools/dbusmenu-dumper.c
+++ b/tools/dbusmenu-dumper.c
@@ -270,10 +270,12 @@ init_dbus_vars_from_window(Window window)
error = NULL;
GVariant * retval;
+ GVariant * args[1];
+ args[0] = g_variant_new("u", window);
retval = g_dbus_proxy_call_sync(proxy,
"GetMenuForWindow",
- g_variant_new("u", window),
+ g_variant_new_tuple(args, 1),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
@@ -285,7 +287,7 @@ init_dbus_vars_from_window(Window window)
return FALSE;
}
- g_variant_get(retval, "so", &dbusname, &dbusobject);
+ g_variant_get(retval, "(so)", &dbusname, &dbusobject);
g_variant_unref(retval);
g_object_unref(proxy);