aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-gtk
diff options
context:
space:
mode:
authorTed Gould <ted@canonical.com>2009-09-03 14:16:01 -0500
committerTed Gould <ted@canonical.com>2009-09-03 14:16:01 -0500
commit6738b6bfb2d6a740119da23936c941f1ab56d4fa (patch)
tree4947b7ab224de9adf430600eec915a8fe2767f65 /libdbusmenu-gtk
parente7c1a0be55b9f48aa2efd74462e67181f9e7a4d2 (diff)
parentcba32423d5f5efd72e3fc3210f93ec1522c270f4 (diff)
downloadlibdbusmenu-6738b6bfb2d6a740119da23936c941f1ab56d4fa.tar.gz
libdbusmenu-6738b6bfb2d6a740119da23936c941f1ab56d4fa.tar.bz2
libdbusmenu-6738b6bfb2d6a740119da23936c941f1ab56d4fa.zip
Merging in support for image items. Including encoding and decoding the images across DBus.
Diffstat (limited to 'libdbusmenu-gtk')
-rw-r--r--libdbusmenu-gtk/Makefile.am7
-rw-r--r--libdbusmenu-gtk/client.c120
-rw-r--r--libdbusmenu-gtk/menuitem.c130
-rw-r--r--libdbusmenu-gtk/menuitem.h39
4 files changed, 294 insertions, 2 deletions
diff --git a/libdbusmenu-gtk/Makefile.am b/libdbusmenu-gtk/Makefile.am
index c375428..918d071 100644
--- a/libdbusmenu-gtk/Makefile.am
+++ b/libdbusmenu-gtk/Makefile.am
@@ -9,13 +9,16 @@ libdbusmenu_gtkincludedir=$(includedir)/libdbusmenu-0.1/libdbusmenu-gtk/
libdbusmenu_gtkinclude_HEADERS = \
client.h \
- menu.h
+ menu.h \
+ menuitem.h
libdbusmenu_gtk_la_SOURCES = \
client.h \
client.c \
menu.h \
- menu.c
+ menu.c \
+ menuitem.h \
+ menuitem.c
libdbusmenu_gtk_la_LDFLAGS = \
-version-info $(LIBDBUSMENU_CURRENT):$(LIBDBUSMENU_REVISION):$(LIBDBUSMENU_AGE) \
diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c
index b3d55d9..44d952d 100644
--- a/libdbusmenu-gtk/client.c
+++ b/libdbusmenu-gtk/client.c
@@ -33,6 +33,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include <gtk/gtk.h>
#include "client.h"
+#include "menuitem.h"
/* Prototypes */
static void dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass);
@@ -302,6 +303,8 @@ dbusmenu_gtkclient_menuitem_get (DbusmenuGtkClient * client, DbusmenuMenuitem *
return mi;
}
+/* The base type handler that builds a plain ol'
+ GtkMenuItem to represent, well, the GtkMenuItem */
static gboolean
new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
{
@@ -321,6 +324,8 @@ new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusmenu
return TRUE;
}
+/* Type handler for the seperators where it builds
+ a GtkSeparator to act as the GtkMenuItem */
static gboolean
new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
{
@@ -340,9 +345,124 @@ new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm
return TRUE;
}
+/* This handler looks at property changes for items that are
+ image menu items. */
+static void
+image_property_handle (DbusmenuMenuitem * item, const gchar * property, const gchar * value, gpointer userdata)
+{
+ /* We're only looking at these two properties here */
+ g_return_if_fail(!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON) || !g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON_DATA));
+
+ if (value == NULL || value[0] == '\0') {
+ /* This means that we're unsetting a value. */
+ /* Try to use the other one */
+ if (g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON)) {
+ property = DBUSMENU_MENUITEM_PROP_ICON_DATA;
+ } else {
+ property = DBUSMENU_MENUITEM_PROP_ICON;
+ }
+ }
+
+ /* Grab the data of the items that we've got, so that
+ we can know how things need to change. */
+ GtkMenuItem * gimi = dbusmenu_gtkclient_menuitem_get (DBUSMENU_GTKCLIENT(userdata), item);
+ if (gimi == NULL) {
+ g_warning("Oddly we're handling image properties on a menuitem that doesn't have any GTK structures associated with it.");
+ return;
+ }
+ GtkWidget * gtkimage = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(gimi));
+
+ if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON_DATA)) {
+ /* If we have an image already built from a name that is
+ way better than a pixbuf. Keep it. */
+ if (gtk_image_get_storage_type(GTK_IMAGE(gtkimage)) == GTK_IMAGE_ICON_NAME) {
+ return;
+ }
+ }
+
+ /* Now figure out what to change */
+ if (!g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON)) {
+ const gchar * iconname = dbusmenu_menuitem_property_get(item, property);
+ if (iconname == NULL) {
+ /* If there is no name, by golly we want no
+ icon either. */
+ gtkimage = NULL;
+ } else {
+ /* If we don't have an image, we need to build
+ one so that we can set the name. Otherwise we
+ can just convert it to this name. */
+ if (gtkimage == NULL) {
+ gtkimage = gtk_image_new_from_icon_name(iconname, GTK_ICON_SIZE_MENU);
+ } else {
+ gtk_image_set_from_icon_name(GTK_IMAGE(gtkimage), iconname, GTK_ICON_SIZE_MENU);
+ }
+ }
+ } else {
+ GdkPixbuf * image = dbusmenu_menuitem_property_get_image(item, property);
+ if (image == NULL) {
+ /* If there is no pixbuf, by golly we want no
+ icon either. */
+ gtkimage = NULL;
+ } else {
+ /* Resize the pixbuf */
+ gint width, height;
+ gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
+ if (gdk_pixbuf_get_width(image) > width ||
+ gdk_pixbuf_get_height(image) > height) {
+ GdkPixbuf * newimage = gdk_pixbuf_scale_simple(image,
+ width,
+ height,
+ GDK_INTERP_BILINEAR);
+ g_object_unref(image);
+ image = newimage;
+ }
+
+ /* If we don't have an image, we need to build
+ one so that we can set the pixbuf. */
+ if (gtkimage == NULL) {
+ gtkimage = gtk_image_new_from_pixbuf(image);
+ } else {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(gtkimage), image);
+ }
+ }
+
+ }
+
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gimi), gtkimage);
+
+ return;
+}
+
+/* This is a type call back for the image type where
+ it uses the GtkImageMenuitem to create the menu item. */
static gboolean
new_item_image (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
+ /* Note: not checking parent, it's reasonable for it to be NULL */
+
+ GtkMenuItem * gmi;
+ gmi = GTK_MENU_ITEM(gtk_image_menu_item_new_with_label(dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_LABEL)));
+
+ if (gmi != NULL) {
+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+ } else {
+ return FALSE;
+ }
+
+ image_property_handle(newitem,
+ DBUSMENU_MENUITEM_PROP_ICON,
+ dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_ICON),
+ client);
+ image_property_handle(newitem,
+ DBUSMENU_MENUITEM_PROP_ICON_DATA,
+ dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_ICON_DATA),
+ client);
+ g_signal_connect(G_OBJECT(newitem),
+ DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED,
+ G_CALLBACK(image_property_handle),
+ client);
return TRUE;
}
diff --git a/libdbusmenu-gtk/menuitem.c b/libdbusmenu-gtk/menuitem.c
new file mode 100644
index 0000000..deded06
--- /dev/null
+++ b/libdbusmenu-gtk/menuitem.c
@@ -0,0 +1,130 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#include "menuitem.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.
+*/
+gboolean
+dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar * property, const GdkPixbuf * data)
+{
+ g_return_val_if_fail(GDK_IS_PIXBUF(data), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), FALSE);
+ g_return_val_if_fail(property != NULL && property[0] != '\0', FALSE);
+
+ GError * error = NULL;
+ gchar * png_data;
+ gsize png_data_len;
+
+ if (!gdk_pixbuf_save_to_buffer((GdkPixbuf *)data, &png_data, &png_data_len, "png", &error, NULL)) {
+ if (error == NULL) {
+ g_warning("Unable to create pixbuf data stream: %d", png_data_len);
+ } else {
+ g_warning("Unable to create pixbuf data stream: %s", error->message);
+ g_error_free(error);
+ error = NULL;
+ }
+
+ return FALSE;
+ }
+
+ gchar * prop_str = g_base64_encode((guchar *)png_data, png_data_len);
+ gboolean propreturn = FALSE;
+ propreturn = dbusmenu_menuitem_property_set(menuitem, property, prop_str);
+
+ g_free(prop_str);
+ g_free(png_data);
+
+ return propreturn;
+}
+
+/**
+ 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.
+*/
+GdkPixbuf *
+dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * property)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), NULL);
+ g_return_val_if_fail(property != NULL && property[0] != '\0', NULL);
+
+ const gchar * value = dbusmenu_menuitem_property_get(menuitem, property);
+
+ /* There is no icon */
+ if (value == NULL || value[0] == '\0') {
+ return NULL;
+ }
+
+ gsize length = 0;
+ guchar * icondata = g_base64_decode(value, &length);
+
+ GInputStream * input = g_memory_input_stream_new_from_data(icondata, length, NULL);
+ if (input == NULL) {
+ g_warning("Cound not create input stream from icon property data");
+ g_free(icondata);
+ return NULL;
+ }
+
+ GError * error = NULL;
+ GdkPixbuf * icon = gdk_pixbuf_new_from_stream(input, NULL, &error);
+
+ if (error != NULL) {
+ g_warning("Unable to build Pixbuf from icon data: %s", error->message);
+ g_error_free(error);
+ }
+
+ error = NULL;
+ g_input_stream_close(input, NULL, &error);
+ if (error != NULL) {
+ g_warning("Unable to close input stream: %s", error->message);
+ g_error_free(error);
+ }
+ g_free(icondata);
+
+ return icon;
+}
+
diff --git a/libdbusmenu-gtk/menuitem.h b/libdbusmenu-gtk/menuitem.h
new file mode 100644
index 0000000..ff458de
--- /dev/null
+++ b/libdbusmenu-gtk/menuitem.h
@@ -0,0 +1,39 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#ifndef __DBUSMENU_GTKMENUITEM_H__
+#define __DBUSMENU_GTKMENUITEM_H__ 1
+
+#include <glib.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <libdbusmenu-glib/menuitem.h>
+
+gboolean dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar * property, const GdkPixbuf * data);
+GdkPixbuf * dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * property);
+
+#endif