diff options
author | Ted Gould <ted@canonical.com> | 2009-09-03 14:16:01 -0500 |
---|---|---|
committer | Ted Gould <ted@canonical.com> | 2009-09-03 14:16:01 -0500 |
commit | 6738b6bfb2d6a740119da23936c941f1ab56d4fa (patch) | |
tree | 4947b7ab224de9adf430600eec915a8fe2767f65 /libdbusmenu-gtk | |
parent | e7c1a0be55b9f48aa2efd74462e67181f9e7a4d2 (diff) | |
parent | cba32423d5f5efd72e3fc3210f93ec1522c270f4 (diff) | |
download | libdbusmenu-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.am | 7 | ||||
-rw-r--r-- | libdbusmenu-gtk/client.c | 120 | ||||
-rw-r--r-- | libdbusmenu-gtk/menuitem.c | 130 | ||||
-rw-r--r-- | libdbusmenu-gtk/menuitem.h | 39 |
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 |