Back to index

indicator-session  12.10.0
user-widget.c
Go to the documentation of this file.
00001 /*
00002 Copyright 2011 Canonical Ltd.
00003 
00004 Authors:
00005     Conor Curran <conor.curran@canonical.com>
00006     Mirco Müller <mirco.mueller@canonical.com>
00007     Charles Kerr <charles.kerr@canonical.com>
00008 
00009 This program is free software: you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License version 3, as published
00011 by the Free Software Foundation.
00012 
00013 This program is distributed in the hope that it will be useful, but
00014 WITHOUT ANY WARRANTY; without even the implied warranties of
00015 MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
00016 PURPOSE.  See the GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License along
00019 with this program.  If not, see <http://www.gnu.org/licenses/>.
00020 */
00021 
00022 #ifdef HAVE_CONFIG_H
00023  #include "config.h"
00024 #endif
00025 
00026 #include <gtk/gtk.h>
00027 
00028 #include <libindicator/indicator-image-helper.h>
00029 
00030 #include "shared-names.h"
00031 #include "user-widget.h"
00032 
00033 
00034 typedef struct _UserWidgetPrivate UserWidgetPrivate;
00035 
00036 struct _UserWidgetPrivate
00037 {
00038   DbusmenuMenuitem* twin_item;
00039   GtkWidget* user_image;
00040   GtkWidget* user_name;
00041   GtkWidget* container;
00042   GtkWidget* tick_icon;
00043   gboolean logged_in;
00044   gboolean sessions_active;
00045 };
00046 
00047 #define USER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USER_WIDGET_TYPE, UserWidgetPrivate))
00048 
00049 /* Prototypes */
00050 static void user_widget_class_init    (UserWidgetClass *klass);
00051 static void user_widget_init          (UserWidget *self);
00052 static void user_widget_dispose       (GObject *object);
00053 static void user_widget_finalize      (GObject *object);
00054 
00055 static void user_widget_set_twin_item (UserWidget* self,
00056                                        DbusmenuMenuitem* twin_item);
00057 
00058 static gboolean user_widget_primitive_draw_cb_gtk_3 (GtkWidget *image,
00059                                                          cairo_t* cr,
00060                                                          gpointer user_data);
00061 
00062 G_DEFINE_TYPE (UserWidget, user_widget, GTK_TYPE_MENU_ITEM);
00063 
00064 static void
00065 user_widget_class_init (UserWidgetClass *klass)
00066 {
00067   GObjectClass * gobject_class = G_OBJECT_CLASS (klass);
00068 
00069   g_type_class_add_private (klass, sizeof (UserWidgetPrivate));
00070 
00071   gobject_class->dispose = user_widget_dispose;
00072   gobject_class->finalize = user_widget_finalize;
00073 }
00074 
00075 static void
00076 user_widget_init (UserWidget *self)
00077 {
00078   self->priv = USER_WIDGET_GET_PRIVATE(self);
00079 
00080   UserWidgetPrivate * priv = self->priv;
00081 
00082   priv->user_image = NULL;
00083   priv->user_name  = NULL;
00084   priv->logged_in = FALSE;
00085   priv->sessions_active = FALSE;
00086   priv->container = NULL;
00087   priv->tick_icon = NULL;
00088 
00089   // Create the UI elements.
00090   priv->user_image = gtk_image_new ();
00091   gtk_misc_set_alignment(GTK_MISC(priv->user_image), 0.0, 0.0);
00092   gtk_misc_set_padding (GTK_MISC(priv->user_image),0, 4.0);
00093 
00094   priv->user_name = gtk_label_new ("");
00095 
00096   priv->container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
00097 
00098   priv->tick_icon = gtk_image_new_from_icon_name ("account-logged-in",
00099                                                    GTK_ICON_SIZE_MENU);
00100   gtk_misc_set_alignment(GTK_MISC(priv->tick_icon), 1.0, 0.5);
00101 
00102   // Pack it together
00103   gtk_box_pack_start (GTK_BOX (priv->container),
00104                       priv->user_image,
00105                       FALSE,
00106                       FALSE,
00107                       0);
00108   gtk_box_pack_start (GTK_BOX (priv->container),
00109                       priv->user_name,
00110                       FALSE,
00111                       FALSE,
00112                       3);
00113   gtk_box_pack_end (GTK_BOX(priv->container),
00114                     priv->tick_icon,
00115                     FALSE,
00116                     FALSE, 5);
00117 
00118   gtk_widget_show_all (priv->container);
00119   gtk_container_add (GTK_CONTAINER (self), priv->container);
00120   gtk_widget_show_all (priv->tick_icon);
00121   gtk_widget_set_no_show_all (priv->tick_icon, TRUE);
00122   gtk_widget_hide (priv->tick_icon);
00123 
00124 
00125   // Fetch the drawing context.
00126   g_signal_connect_after (GTK_WIDGET(self), "draw",
00127                           G_CALLBACK(user_widget_primitive_draw_cb_gtk_3),
00128                           GTK_WIDGET(self));
00129 }
00130 
00131 static void
00132 user_widget_dispose (GObject *object)
00133 {
00134   G_OBJECT_CLASS (user_widget_parent_class)->dispose (object);
00135 }
00136 
00137 // TODO tidy up image and name
00138 static void
00139 user_widget_finalize (GObject *object)
00140 {
00141   G_OBJECT_CLASS (user_widget_parent_class)->finalize (object);
00142 }
00143 
00144 
00145 /*****************************************************************/
00146 
00147 // TODO handle drawing of green check mark
00148 static gboolean
00149 user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget,
00150                                      cairo_t* cr,
00151                                      gpointer user_data)
00152 {
00153   g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE);
00154   UserWidget* meta = USER_WIDGET(user_data);
00155   UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta);
00156 
00157   // Draw dot only when user is the current user.
00158   if (dbusmenu_menuitem_property_get_bool (priv->twin_item, USER_ITEM_PROP_IS_CURRENT_USER))
00159     {
00160       gdouble x, y;
00161       GtkStyle * style = gtk_widget_get_style (widget);
00162 
00163       GtkAllocation allocation;
00164       gtk_widget_get_allocation (widget, &allocation);
00165       x = allocation.x + 13;
00166       y = allocation.height / 2;
00167 
00168       cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI);
00169 
00170       cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
00171                                 style->fg[gtk_widget_get_state(widget)].green/65535.0,
00172                                 style->fg[gtk_widget_get_state(widget)].blue/65535.0);
00173       cairo_fill (cr);
00174     }
00175 
00176   return FALSE;
00177 }
00178 
00179 /***
00180 ****
00181 ***/
00182 
00183 static const int ICON_SIZE = 24;
00184 
00185 static void
00186 update_icon (UserWidget * self, DbusmenuMenuitem * mi)
00187 {
00188   GdkPixbuf * pixbuf = NULL;
00189 
00190   /* first, try the menuitem's icon property */
00191   const gchar * icon_name = dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_ICON);
00192   if (icon_name)
00193     {
00194       GError* error = NULL;
00195       pixbuf = gdk_pixbuf_new_from_file_at_size (icon_name, ICON_SIZE, ICON_SIZE, &error);
00196       if (error != NULL)
00197         {
00198           g_warning ("Couldn't load the image \"%s\": %s", icon_name, error->message);
00199           g_clear_error (&error);
00200         }
00201     }
00202 
00203   /* as a fallback, try to use the default user icon */
00204   if (pixbuf == NULL)
00205     {
00206       pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
00207                                          USER_ITEM_ICON_DEFAULT,
00208                                          ICON_SIZE,
00209                                          GTK_ICON_LOOKUP_FORCE_SIZE,
00210                                          NULL);
00211     }
00212 
00213   if (pixbuf != NULL)
00214     {
00215       gtk_image_set_from_pixbuf (GTK_IMAGE(self->priv->user_image), pixbuf);
00216       g_object_unref (pixbuf);
00217     }
00218 }
00219 
00220 static void
00221 update_logged_in (UserWidget * self, DbusmenuMenuitem * mi)
00222 {
00223   const gboolean b = dbusmenu_menuitem_property_get_bool (mi, USER_ITEM_PROP_LOGGED_IN);
00224 
00225   g_debug ("User \"%s\" %s active sessions",
00226            dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_NAME),
00227            b ? "has" : "doesn't have");
00228 
00229   gtk_widget_set_visible (self->priv->tick_icon, b);
00230 }
00231 
00232 static void
00233 update_name (UserWidget * self, DbusmenuMenuitem * mi)
00234 {
00235   gtk_label_set_label (GTK_LABEL(self->priv->user_name),
00236                        dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_NAME));
00237 }
00238 
00239 static void
00240 user_widget_property_update (DbusmenuMenuitem  * mi,
00241                              const gchar       * property,
00242                              GVariant          * value,
00243                              UserWidget        * self)
00244 {
00245   g_return_if_fail (IS_USER_WIDGET (self));
00246 
00247   if (!g_strcmp0 (property, USER_ITEM_PROP_LOGGED_IN))
00248     {
00249       update_logged_in (self, mi);
00250     }
00251   else if (!g_strcmp0 (property, USER_ITEM_PROP_ICON))
00252     {
00253       update_icon (self, mi);
00254     }
00255   else if (!g_strcmp0 (property, USER_ITEM_PROP_NAME))
00256     {
00257       update_name (self, mi);
00258     }
00259   else
00260     {
00261       g_debug ("%s FIXME: unhandled property change %s", G_STRFUNC, property);
00262     }
00263 }
00264 
00265 static void
00266 user_widget_set_twin_item (UserWidget * self, DbusmenuMenuitem * mi)
00267 {
00268   self->priv->twin_item = mi;
00269 
00270   update_icon      (self, mi);
00271   update_name      (self, mi);
00272   update_logged_in (self, mi);
00273 
00274   g_signal_connect (G_OBJECT(mi), "property-changed",
00275                     G_CALLBACK(user_widget_property_update), self);
00276 }
00277 
00282 GtkWidget*
00283 user_widget_new (DbusmenuMenuitem *item)
00284 {
00285   GtkWidget* widget =  g_object_new(USER_WIDGET_TYPE, NULL);
00286   user_widget_set_twin_item ( USER_WIDGET(widget), item );
00287   return widget;
00288 }