1
/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
3
* Copyright 2010 Canonical, Ltd.
5
* This program is free software: you can redistribute it and/or modify it
6
* under the terms of either or both of the following licenses:
8
* 1) the GNU Lesser General Public License version 3, as published by the
9
* Free Software Foundation; and/or
10
* 2) the GNU Lesser General Public License version 2.1, as published by
11
* the Free Software Foundation.
13
* This program is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranties of
15
* MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
16
* PURPOSE. See the applicable version of the GNU Lesser General Public
17
* License for more details.
19
* You should have received a copy of both the GNU Lesser General Public
20
* License version 3 and version 2.1 along with this program. If not, see
21
* <http://www.gnu.org/licenses/>
24
* David Barth <david.barth@canonical.com>
25
* Cody Russell <crussell@canonical.com>
28
#include <sys/types.h>
32
#include <glib/gstdio.h>
35
#include "about-me-menu-item.h"
37
static GObject* about_me_menu_item_constructor (GType type,
38
guint n_construct_properties,
39
GObjectConstructParam *construct_params);
40
static void about_me_menu_item_set_property (GObject *object,
44
static void about_me_menu_item_get_property (GObject *object,
49
struct _AboutMeMenuItemPrivate {
61
G_DEFINE_TYPE (AboutMeMenuItem, about_me_menu_item, GTK_TYPE_MENU_ITEM)
63
#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ABOUT_ME_TYPE_MENU_ITEM, AboutMeMenuItemPrivate))
66
about_me_menu_item_class_init (AboutMeMenuItemClass *item_class)
68
GObjectClass *gobject_class = G_OBJECT_CLASS (item_class);
70
gobject_class->constructor = about_me_menu_item_constructor;
71
gobject_class->set_property = about_me_menu_item_set_property;
72
gobject_class->get_property = about_me_menu_item_get_property;
74
g_object_class_install_property (gobject_class,
76
g_param_spec_string ("realname",
78
"The \"Realname\" for the user",
80
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
82
g_type_class_add_private (gobject_class, sizeof (AboutMeMenuItemPrivate));
86
about_me_menu_item_init (AboutMeMenuItem *self)
88
AboutMeMenuItemPrivate *priv = GET_PRIVATE (self);
92
priv->realname = NULL;
96
about_me_menu_item_set_property (GObject *object,
101
AboutMeMenuItem *menu_item = ABOUT_ME_MENU_ITEM (object);
102
AboutMeMenuItemPrivate *priv = GET_PRIVATE (menu_item);
107
g_assert (priv->realname == NULL);
108
priv->realname = g_strdup (g_value_get_string (value));
112
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
118
about_me_menu_item_get_property (GObject *object,
123
AboutMeMenuItem *menu_item = ABOUT_ME_MENU_ITEM (object);
124
AboutMeMenuItemPrivate *priv = GET_PRIVATE (menu_item);
129
g_value_set_string (value, priv->realname);
133
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
138
#define DEFAULT_PIXELS_PER_EM 10.0f
141
get_pixels_per_em (GtkWidget *widget)
143
g_return_val_if_fail (GTK_IS_WIDGET (widget), DEFAULT_PIXELS_PER_EM);
145
/* Note: taken from indicator-session */
146
GtkStyle * style = gtk_widget_get_style(widget);
148
PangoLayout * layout = pango_layout_new(gtk_widget_get_pango_context(widget));
149
pango_layout_set_text(layout, "M", -1);
150
pango_layout_set_font_description(layout, style->font_desc);
153
pango_layout_get_pixel_size(layout, &width, NULL);
155
gint point = pango_font_description_get_size(style->font_desc);
156
gdouble dpi = gdk_screen_get_resolution(gdk_screen_get_default());
158
return ((point * dpi) / 72.0f) / PANGO_SCALE;
164
load_icon (const gchar* filename,
167
GdkPixbuf* buffer = NULL;
168
GdkPixbuf* pixbuf = NULL;
169
GtkIconTheme* theme = NULL;
170
GError* error = NULL;
173
g_return_val_if_fail (filename, NULL);
175
theme = gtk_icon_theme_get_default ();
176
buffer = gtk_icon_theme_load_icon (theme,
179
GTK_ICON_LOOKUP_FORCE_SVG |
180
GTK_ICON_LOOKUP_GENERIC_FALLBACK |
181
GTK_ICON_LOOKUP_FORCE_SIZE,
185
g_print ("loading icon '%s' caused error: '%s'",
188
g_error_free (error);
194
/* copy and unref buffer so on an icon-theme change old
195
** icons are not kept in memory due to dangling
196
** references, this also makes sure we do not need to
197
** connect to GtkWidget::style-set signal for the
198
** GdkPixbuf we get from gtk_icon_theme_load_icon() */
199
pixbuf = gdk_pixbuf_copy (buffer);
200
g_object_unref (buffer);
207
about_me_menu_item_load_avatar (AboutMeMenuItem *self, const gchar *file)
209
g_return_val_if_fail (ABOUT_IS_ME_MENU_ITEM (self), FALSE);
211
AboutMeMenuItemPrivate *priv = GET_PRIVATE (self);
213
g_debug ("loading avatar from file %s", file);
216
if (! (g_stat (file, &buf) == 0 && buf.st_size > 0)) {
217
g_warning ("%s: not found or empty", file);
221
if (buf.st_size > 1024*1024) {
222
g_warning ("avatar file too large (%lld)", (long long)buf.st_size);
226
GError *error = NULL;
227
int size = get_pixels_per_em (priv->image) * 3;
229
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_scale (file, -1, size, TRUE,
231
if (pixbuf == NULL) {
233
g_warning ("Couldn't read file %s: %s", file, error->message);
234
g_error_free (error);
239
gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), pixbuf);
241
g_object_unref (pixbuf);
247
image_size_allocate (GtkWidget *widget,
248
GtkAllocation *allocation,
251
gint max = MAX (allocation->width, allocation->height);
253
gtk_widget_set_size_request (widget, max, max);
257
about_me_menu_item_constructor (GType type,
258
guint n_construct_properties,
259
GObjectConstructParam *construct_params)
264
AboutMeMenuItemPrivate *priv;
265
object = G_OBJECT_CLASS (about_me_menu_item_parent_class)->constructor (type,
266
n_construct_properties,
269
priv = GET_PRIVATE (object);
271
GtkWidget *frame = gtk_frame_new (NULL);
272
gdouble pixels_per_em = get_pixels_per_em (frame);
273
GdkPixbuf *pixbuf = load_icon ("stock_person-panel", pixels_per_em * 3);
275
pixbuf = load_icon ("stock_person", pixels_per_em * 3);
276
priv->image = gtk_image_new_from_pixbuf (pixbuf);
277
g_signal_connect (frame, "size-allocate", G_CALLBACK (image_size_allocate), NULL);
278
gtk_misc_set_padding (GTK_MISC (priv->image), 2, 2);
279
gtk_container_add (GTK_CONTAINER (frame), priv->image);
281
align = gtk_alignment_new (0, 0.3, 0, 0);
282
priv->label = gtk_label_new (priv->realname);
283
gtk_misc_set_padding (GTK_MISC (priv->label), 2, 2);
284
gtk_container_add (GTK_CONTAINER (align), priv->label);
286
hbox = gtk_hbox_new (FALSE, 0);
287
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
288
gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, TRUE, DEFAULT_PIXELS_PER_EM);
290
gtk_container_add (GTK_CONTAINER (object), hbox);
291
gtk_widget_show_all (GTK_WIDGET(object));
299
* about_me_menu_item_new:
300
* @realname: the name to display in the new menu item.
301
* @returns: a new #AboutMeMenuItem.
303
* Creates a new #AboutMeMenuItem with a name.
306
about_me_menu_item_new (const gchar *realname)
308
return g_object_new (ABOUT_ME_TYPE_MENU_ITEM,
309
"realname", realname,
313
#define __ABOUT_ME_MENU_ITEM_C__