From 1e56f31341ecdb60456929a3d6d07bb16409b399 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Sat, 14 Jan 2012 23:51:10 +0100 Subject: Add the possibility to set an icon on indicator-menu-item --- src/indicator-menu-item.c | 83 +++++++++++++++++++++++++++++++++++++++++++ src/indicator-menu-item.h | 5 +++ src/indicator-printers-menu.c | 1 + src/indicator-printers.c | 77 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 165 insertions(+), 1 deletion(-) diff --git a/src/indicator-menu-item.c b/src/indicator-menu-item.c index 72faad6..afdf980 100644 --- a/src/indicator-menu-item.c +++ b/src/indicator-menu-item.c @@ -11,6 +11,7 @@ G_DEFINE_TYPE (IndicatorMenuItem, indicator_menu_item, GTK_TYPE_MENU_ITEM) struct _IndicatorMenuItemPrivate { + GtkImage *image; GtkWidget *label; GtkWidget *right_label; gboolean right_is_lozenge; @@ -19,6 +20,8 @@ struct _IndicatorMenuItemPrivate enum { PROP_0, + PROP_ICON, + PROP_ICON_NAME, PROP_LABEL, PROP_RIGHT, PROP_RIGHT_IS_LOZENGE, @@ -99,10 +102,19 @@ indicator_menu_item_get_property (GObject *object, GValue *value, GParamSpec *pspec) { + IndicatorMenuItem *self = INDICATOR_MENU_ITEM (object); IndicatorMenuItemPrivate *priv = MENU_ITEM_PRIVATE (object); switch (property_id) { + case PROP_ICON: + g_value_set_object (value, indicator_menu_item_get_icon (self)); + break; + + case PROP_ICON_NAME: + g_value_set_string (value, indicator_menu_item_get_icon_name (self)); + break; + case PROP_LABEL: g_value_set_string (value, gtk_label_get_label (GTK_LABEL (priv->label))); break; @@ -131,6 +143,16 @@ indicator_menu_item_set_property (GObject *object, switch (property_id) { + case PROP_ICON: + indicator_menu_item_set_icon (INDICATOR_MENU_ITEM (object), + g_value_get_object (value)); + break; + + case PROP_ICON_NAME: + indicator_menu_item_set_icon_name (INDICATOR_MENU_ITEM (object), + g_value_get_string (value)); + break; + case PROP_LABEL: indicator_menu_item_set_label (INDICATOR_MENU_ITEM (object), g_value_get_string (value)); @@ -158,6 +180,7 @@ indicator_menu_item_dispose (GObject *object) { IndicatorMenuItemPrivate *priv = MENU_ITEM_PRIVATE (object); + g_clear_object (&priv->image); g_clear_object (&priv->label); g_clear_object (&priv->right_label); @@ -176,6 +199,18 @@ indicator_menu_item_class_init (IndicatorMenuItemClass *klass) object_class->set_property = indicator_menu_item_set_property; object_class->dispose = indicator_menu_item_dispose; + properties[PROP_ICON] = g_param_spec_object ("icon", + "Icon", + "Icon for this menu item", + GDK_TYPE_PIXBUF, + G_PARAM_READWRITE); + + properties[PROP_ICON_NAME] = g_param_spec_string ("icon-name", + "Icon name", + "Name of the themed icon", + "", + G_PARAM_READWRITE); + properties[PROP_LABEL] = g_param_spec_string ("label", "Label", "The text for the main label", @@ -211,6 +246,10 @@ indicator_menu_item_init (IndicatorMenuItem *self) hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, spacing); + priv->image = g_object_new (GTK_TYPE_IMAGE, NULL); + g_object_ref_sink (priv->image); + gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (priv->image), FALSE, FALSE, 0); + priv->label = g_object_new (GTK_TYPE_LABEL, "xalign", 0.0, NULL); @@ -265,3 +304,47 @@ indicator_menu_item_set_right (IndicatorMenuItem *self, g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_RIGHT]); } + +GdkPixbuf * +indicator_menu_item_get_icon (IndicatorMenuItem *self) +{ + IndicatorMenuItemPrivate *priv = MENU_ITEM_PRIVATE (self); + if (gtk_image_get_storage_type (priv->image) == GTK_IMAGE_PIXBUF) + return gtk_image_get_pixbuf (priv->image); + else + return NULL; +} + + +void +indicator_menu_item_set_icon (IndicatorMenuItem *self, + GdkPixbuf *icon) +{ + IndicatorMenuItemPrivate *priv = MENU_ITEM_PRIVATE (self); + gtk_image_set_from_pixbuf (priv->image, icon); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ICON]); +} + + +const gchar * +indicator_menu_item_get_icon_name (IndicatorMenuItem *self) +{ + IndicatorMenuItemPrivate *priv = MENU_ITEM_PRIVATE (self); + const gchar *name = NULL; + + if (gtk_image_get_storage_type (priv->image) == GTK_IMAGE_ICON_NAME) + gtk_image_get_icon_name (priv->image, &name, NULL); + + return name; +} + + +void +indicator_menu_item_set_icon_name (IndicatorMenuItem *self, + const gchar *name) +{ + IndicatorMenuItemPrivate *priv = MENU_ITEM_PRIVATE (self); + gtk_image_set_from_icon_name (priv->image, name, GTK_ICON_SIZE_MENU); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ICON_NAME]); +} + diff --git a/src/indicator-menu-item.h b/src/indicator-menu-item.h index 39c456a..a5f3407 100644 --- a/src/indicator-menu-item.h +++ b/src/indicator-menu-item.h @@ -48,6 +48,11 @@ IndicatorMenuItem *indicator_menu_item_new (void); void indicator_menu_item_set_right (IndicatorMenuItem *self, const gchar *text); void indicator_menu_item_set_label (IndicatorMenuItem *self, const gchar *text); +const gchar * indicator_menu_item_get_icon_name (IndicatorMenuItem *self); +void indicator_menu_item_set_icon (IndicatorMenuItem *self, GdkPixbuf *icon); +GdkPixbuf * indicator_menu_item_get_icon (IndicatorMenuItem *self); +void indicator_menu_item_set_icon_name (IndicatorMenuItem *self, const gchar *name); + G_END_DECLS #endif diff --git a/src/indicator-printers-menu.c b/src/indicator-printers-menu.c index c6a76da..b8a2360 100644 --- a/src/indicator-printers-menu.c +++ b/src/indicator-printers-menu.c @@ -81,6 +81,7 @@ add_printer_menuitem (IndicatorPrintersMenu *self, DbusmenuMenuitem *child; child = dbusmenu_menuitem_new (); + dbusmenu_menuitem_property_set (child, "indicator-icon-name", "printer"); dbusmenu_menuitem_property_set (child, "indicator-label", printer); dbusmenu_menuitem_property_set (child, "indicator-right", "Paused"); dbusmenu_menuitem_property_set (child, "type", "indicator-item"); diff --git a/src/indicator-printers.c b/src/indicator-printers.c index 3a642ac..6ae984c 100644 --- a/src/indicator-printers.c +++ b/src/indicator-printers.c @@ -79,6 +79,55 @@ indicator_printers_class_init (IndicatorPrintersClass *klass) } +static GdkPixbuf * +gdk_pixbuf_new_from_encoded_data (guchar *data, + gsize length) +{ + GInputStream * input; + GError *err = NULL; + GdkPixbuf *img; + + input = g_memory_input_stream_new_from_data(data, length, NULL); + if (input == NULL) + return NULL; + + img = gdk_pixbuf_new_from_stream(input, NULL, &err); + if (err) { + g_warning("%s", err->message); + g_error_free(err); + } + + g_object_unref(input); + return img; +} + + +static GdkPixbuf * +g_variant_get_image (GVariant *value) +{ + const gchar *strvalue = NULL; + gsize length = 0; + guchar *icondata; + GdkPixbuf *img; + + if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) + strvalue = g_variant_get_string(value, NULL); + + if (!strvalue || !*strvalue) { + g_warning ("%s: value does not contain a base64 encoded image", + __func__); + return NULL; + } + + icondata = g_base64_decode(strvalue, &length); + img = gdk_pixbuf_new_from_encoded_data (icondata, length); + + g_free(icondata); + return img; +} + + + static gboolean is_string_property (const gchar *name, const gchar *prop, @@ -89,6 +138,16 @@ is_string_property (const gchar *name, } +static gboolean +is_image_property (const gchar *name, + const gchar *prop, + GVariant *value) +{ + return !g_strcmp0 (name, prop) && + g_variant_is_of_type (value, G_VARIANT_TYPE_STRING); +} + + static void indicator_prop_change_cb (DbusmenuMenuitem *mi, gchar *prop, @@ -101,6 +160,13 @@ indicator_prop_change_cb (DbusmenuMenuitem *mi, indicator_menu_item_set_label (menuitem, g_variant_get_string (value, NULL)); else if (is_string_property (prop, "indicator-right", value)) indicator_menu_item_set_right (menuitem, g_variant_get_string (value, NULL)); + else if (is_string_property (prop, "indicator-icon-name", value)) + indicator_menu_item_set_icon_name (menuitem, g_variant_get_string (value, NULL)); + else if (is_image_property (prop, "indicator-icon", value)) { + GdkPixbuf *pb = g_variant_get_image (value); + indicator_menu_item_set_icon (menuitem, pb); + g_object_unref (pb); + } } @@ -111,18 +177,27 @@ new_indicator_item (DbusmenuMenuitem *newitem, gpointer user_data) { GtkWidget *menuitem; - const gchar *text, *right_text; + const gchar *icon_name, *text, *right_text; + GVariant *icon; gboolean is_lozenge; + icon_name = dbusmenu_menuitem_property_get (newitem, "indicator-icon-name"); + icon = dbusmenu_menuitem_property_get_variant (newitem, "indicator-icon"); text = dbusmenu_menuitem_property_get (newitem, "indicator-label"); right_text = dbusmenu_menuitem_property_get (newitem, "indicator-right"); is_lozenge = dbusmenu_menuitem_property_get_bool (newitem, "indicator-right-is-lozenge"); menuitem = g_object_new (INDICATOR_TYPE_MENU_ITEM, + "icon-name", icon_name, "label", text, "right", right_text, "right-is-lozenge", is_lozenge, NULL); + if (icon) { + GdkPixbuf *pb = g_variant_get_image (icon); + indicator_menu_item_set_icon (INDICATOR_MENU_ITEM (menuitem), pb); + g_object_unref (pb); + } gtk_widget_show_all (menuitem); dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), -- cgit v1.2.3