aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/idoactionhelper.c7
-rw-r--r--src/idocalendarmenuitem.c4
-rw-r--r--src/idomenuitemfactory.c4
-rw-r--r--src/idoscalemenuitem.c73
-rw-r--r--src/idoswitchmenuitem.c142
-rw-r--r--src/idoswitchmenuitem.h9
-rw-r--r--src/idousermenuitem.c159
7 files changed, 243 insertions, 155 deletions
diff --git a/src/idoactionhelper.c b/src/idoactionhelper.c
index a4eb51d..afa4d68 100644
--- a/src/idoactionhelper.c
+++ b/src/idoactionhelper.c
@@ -29,6 +29,7 @@ struct _IdoActionHelper
GActionGroup *actions;
gchar *action_name;
GVariant *action_target;
+ guint idle_source_id;
};
G_DEFINE_TYPE (IdoActionHelper, ido_action_helper, G_TYPE_OBJECT)
@@ -123,6 +124,7 @@ call_action_added (gpointer user_data)
ido_action_helper_action_added (helper->actions, helper->action_name, helper);
+ helper->idle_source_id = 0;
return G_SOURCE_REMOVE;
}
@@ -146,7 +148,7 @@ ido_action_helper_constructed (GObject *object)
* state-changed signal during construction (nobody could have
* connected by then).
*/
- g_idle_add (call_action_added, helper);
+ helper->idle_source_id = g_idle_add (call_action_added, helper);
}
G_OBJECT_CLASS (ido_action_helper_parent_class)->constructed (object);
@@ -219,6 +221,9 @@ ido_action_helper_finalize (GObject *object)
{
IdoActionHelper *helper = IDO_ACTION_HELPER (object);
+ if (helper->idle_source_id)
+ g_source_remove (helper->idle_source_id);
+
g_object_unref (helper->widget);
g_signal_handlers_disconnect_by_data (helper->actions, helper);
diff --git a/src/idocalendarmenuitem.c b/src/idocalendarmenuitem.c
index 94f4f61..65dac7f 100644
--- a/src/idocalendarmenuitem.c
+++ b/src/idocalendarmenuitem.c
@@ -607,8 +607,8 @@ ido_calendar_menu_item_new_from_model (GMenuItem * menu_item,
GObject * o;
GtkWidget * calendar;
IdoCalendarMenuItem * ido_calendar;
- gchar * selection_action_name;
- gchar * activation_action_name;
+ gchar * selection_action_name = NULL;
+ gchar * activation_action_name = NULL;
/* get the select & activate action names */
g_menu_item_get_attribute (menu_item, "action", "s", &selection_action_name);
diff --git a/src/idomenuitemfactory.c b/src/idomenuitemfactory.c
index 376134e..11beaa8 100644
--- a/src/idomenuitemfactory.c
+++ b/src/idomenuitemfactory.c
@@ -31,6 +31,7 @@
#include "idoplaybackmenuitem.h"
#include "idoapplicationmenuitem.h"
#include "idosourcemenuitem.h"
+#include "idoswitchmenuitem.h"
#define IDO_TYPE_MENU_ITEM_FACTORY (ido_menu_item_factory_get_type ())
#define IDO_MENU_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_MENU_ITEM_FACTORY, IdoMenuItemFactory))
@@ -91,6 +92,9 @@ ido_menu_item_factory_create_menu_item (UbuntuMenuItemFactory *factory,
else if (g_str_equal (type, "com.canonical.indicator.messages.source"))
item = ido_source_menu_item_new_from_menu_model (menuitem, actions);
+ else if (g_str_equal (type, "com.canonical.indicator.switch"))
+ item = ido_switch_menu_item_new_from_menu_model (menuitem, actions);
+
return item;
}
diff --git a/src/idoscalemenuitem.c b/src/idoscalemenuitem.c
index dff4cb0..51e41b3 100644
--- a/src/idoscalemenuitem.c
+++ b/src/idoscalemenuitem.c
@@ -40,13 +40,11 @@ static void ido_scale_menu_item_get_property (GObject
guint prop_id,
GValue *value,
GParamSpec *pspec);
-static gboolean ido_scale_menu_item_parent_key_press_event (GtkWidget *widget,
- GdkEventKey *event,
- gpointer user_data);
-static void ido_scale_menu_item_select (GtkMenuItem *item);
-static void ido_scale_menu_item_deselect (GtkMenuItem *item);
-static void ido_scale_menu_item_parent_set (GtkWidget *widget,
- GtkWidget *old_parent);
+static gboolean ido_scale_menu_item_parent_key_press_event (GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer user_data);
+static void ido_scale_menu_item_select (GtkMenuItem *item);
+static void ido_scale_menu_item_deselect (GtkMenuItem *item);
static gboolean ido_scale_menu_item_button_press_event (GtkWidget *menuitem,
GdkEventButton *event);
static gboolean ido_scale_menu_item_button_release_event (GtkWidget *menuitem,
@@ -59,9 +57,8 @@ static void ido_scale_menu_item_primary_image_notify (GtkImage
static void ido_scale_menu_item_secondary_image_notify (GtkImage *image,
GParamSpec *pspec,
IdoScaleMenuItem *item);
-static void ido_scale_menu_item_notify (IdoScaleMenuItem *item,
- GParamSpec *pspec,
- gpointer user_data);
+static void ido_scale_menu_item_parent_set (GtkWidget *item,
+ GtkWidget *previous_parent);
static void update_packing (IdoScaleMenuItem *self,
IdoScaleMenuItemStyle style);
static void default_primary_clicked_handler (IdoScaleMenuItem *self);
@@ -273,10 +270,6 @@ ido_scale_menu_item_constructed (GObject *object)
G_CALLBACK (ido_scale_menu_item_toggle_size_allocate),
NULL);
- g_signal_connect (self, "notify",
- G_CALLBACK (ido_scale_menu_item_notify),
- NULL);
-
gtk_container_add (GTK_CONTAINER (self), hbox);
gtk_widget_add_events (GTK_WIDGET(self), GDK_SCROLL_MASK);
@@ -295,12 +288,12 @@ ido_scale_menu_item_class_init (IdoScaleMenuItemClass *item_class)
menuitem_class->select = ido_scale_menu_item_select;
menuitem_class->deselect = ido_scale_menu_item_deselect;
- widget_class->parent_set = ido_scale_menu_item_parent_set;
widget_class->button_press_event = ido_scale_menu_item_button_press_event;
widget_class->button_release_event = ido_scale_menu_item_button_release_event;
widget_class->motion_notify_event = ido_scale_menu_item_motion_notify_event;
widget_class->scroll_event = ido_scale_menu_item_scroll_event;
widget_class->size_allocate = ido_scale_menu_item_size_allocate;
+ widget_class->parent_set = ido_scale_menu_item_parent_set;
gobject_class->constructed = ido_scale_menu_item_constructed;
gobject_class->set_property = ido_scale_menu_item_set_property;
@@ -588,26 +581,6 @@ ido_scale_menu_item_deselect (GtkMenuItem *item)
GTK_MENU_ITEM_CLASS (ido_scale_menu_item_parent_class)->deselect (item);
}
-static void
-ido_scale_menu_item_parent_set (GtkWidget *widget,
- GtkWidget *old_parent)
-{
- GtkWidget *parent;
-
- /* Menus don't pass key events to their children. This works around
- * that by listening to key events on the parent widget. */
-
- if (old_parent)
- g_signal_handlers_disconnect_by_func (old_parent, ido_scale_menu_item_parent_key_press_event, widget);
-
- parent = gtk_widget_get_parent (widget);
- if (parent)
- {
- g_signal_connect (parent, "key-press-event",
- G_CALLBACK (ido_scale_menu_item_parent_key_press_event), widget);
- }
-}
-
static gboolean
ido_scale_menu_item_button_press_event (GtkWidget *menuitem,
GdkEventButton *event)
@@ -727,20 +700,28 @@ menu_hidden (GtkWidget *menu,
}
static void
-ido_scale_menu_item_notify (IdoScaleMenuItem *item,
- GParamSpec *pspec,
- gpointer user_data)
+ido_scale_menu_item_parent_set (GtkWidget *item,
+ GtkWidget *previous_parent)
+
{
- if (g_strcmp0 (pspec->name, "parent"))
+ GtkWidget *parent;
+
+ if (previous_parent)
{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (item));
+ g_signal_handlers_disconnect_by_func (previous_parent, menu_hidden, item);
+ g_signal_handlers_disconnect_by_func (previous_parent, ido_scale_menu_item_parent_key_press_event, item);
+ }
- if (parent)
- {
- g_signal_connect (parent, "hide",
- G_CALLBACK (menu_hidden),
- item);
- }
+ parent = gtk_widget_get_parent (item);
+
+ if (parent)
+ {
+ g_signal_connect (parent, "hide", G_CALLBACK (menu_hidden), item);
+
+ /* Menus don't pass key events to their children. This works around
+ * that by listening to key events on the parent widget. */
+ g_signal_connect (parent, "key-press-event",
+ G_CALLBACK (ido_scale_menu_item_parent_key_press_event), item);
}
}
diff --git a/src/idoswitchmenuitem.c b/src/idoswitchmenuitem.c
index 10ff1f3..d47392f 100644
--- a/src/idoswitchmenuitem.c
+++ b/src/idoswitchmenuitem.c
@@ -21,6 +21,7 @@
#include "config.h"
#include "idoswitchmenuitem.h"
+#include "idoactionhelper.h"
static gboolean ido_switch_menu_button_release_event (GtkWidget * widget,
GdkEventButton * event);
@@ -30,6 +31,8 @@ struct _IdoSwitchMenuItemPrivate
{
GtkWidget * box;
GtkWidget * content_area;
+ GtkWidget * label;
+ GtkWidget * image;
GtkWidget * switch_w;
};
@@ -63,7 +66,7 @@ ido_switch_menu_item_init (IdoSwitchMenuItem *item)
priv = item->priv = G_TYPE_INSTANCE_GET_PRIVATE (item, IDO_TYPE_SWITCH_MENU_ITEM, IdoSwitchMenuItemPrivate);
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
- priv->content_area = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ priv->content_area = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
priv->switch_w = gtk_switch_new ();
gtk_box_pack_start (GTK_BOX (priv->box), priv->content_area, TRUE, TRUE, 0);
@@ -120,12 +123,149 @@ ido_switch_menu_item_new (void)
*
* Get the #GtkContainer to add additional widgets into.
*
+ * This function is dperecated.
+ *
* Return Value: (transfer none): The #GtkContainer to add additional widgets into.
**/
GtkContainer *
ido_switch_menu_item_get_content_area (IdoSwitchMenuItem * item)
{
+ static gboolean warned = FALSE;
+
g_return_val_if_fail (IDO_IS_SWITCH_MENU_ITEM(item), NULL);
+ if (!warned)
+ {
+ g_warning ("%s is deprecated. Please don't use it, especially if you're using"
+ "ido_switch_menu_set_{label,icon}()", G_STRFUNC);
+ warned = TRUE;
+ }
+
return GTK_CONTAINER (item->priv->content_area);
}
+
+/**
+ * ido_switch_menu_item_set_label:
+ * @item: a #IdoSwitchMenuItem.
+ * @label: a string to set as the label of @item
+ *
+ * Set the label of @item to @label.
+ **/
+void
+ido_switch_menu_item_set_label (IdoSwitchMenuItem *item,
+ const gchar *label)
+{
+ IdoSwitchMenuItemPrivate *priv;
+
+ g_return_if_fail (IDO_IS_SWITCH_MENU_ITEM (item));
+ g_return_if_fail (label != NULL);
+
+ priv = item->priv;
+
+ if (priv->label == NULL)
+ {
+ priv->label = gtk_label_new (NULL);
+ gtk_widget_set_halign (priv->label, GTK_ALIGN_START);
+ gtk_widget_show (priv->label);
+ gtk_box_pack_end (GTK_BOX (priv->content_area), priv->label, TRUE, TRUE, 0);
+ }
+
+ gtk_label_set_text (GTK_LABEL (priv->label), label);
+}
+
+/**
+ * ido_switch_menu_item_set_icon:
+ * @item: a #IdoSwitchMenuItem.
+ * @icon: (allow-none): a #GIcon
+ *
+ * Set the icon of @item to @icon.
+ **/
+void
+ido_switch_menu_item_set_icon (IdoSwitchMenuItem *item,
+ GIcon *icon)
+{
+ IdoSwitchMenuItemPrivate *priv;
+
+ g_return_if_fail (IDO_IS_SWITCH_MENU_ITEM (item));
+ g_return_if_fail (icon == NULL || G_IS_ICON (icon));
+
+ priv = item->priv;
+
+ if (icon)
+ {
+ if (priv->image == NULL)
+ {
+ priv->image = gtk_image_new ();
+ gtk_widget_show (priv->image);
+ gtk_box_pack_start (GTK_BOX (priv->content_area), priv->image, FALSE, FALSE, 0);
+ }
+
+ gtk_image_set_from_gicon (GTK_IMAGE (priv->image), icon, GTK_ICON_SIZE_MENU);
+ }
+ else if (priv->image)
+ {
+ gtk_image_clear (GTK_IMAGE (priv->image));
+ }
+}
+
+static void
+ido_source_menu_item_state_changed (IdoActionHelper *helper,
+ GVariant *state,
+ gpointer user_data)
+{
+ IdoSwitchMenuItem *item = user_data;
+
+ if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN))
+ gtk_switch_set_active (GTK_SWITCH (item->priv->switch_w),
+ g_variant_get_boolean (state));
+}
+
+GtkMenuItem *
+ido_switch_menu_item_new_from_menu_model (GMenuItem *menuitem,
+ GActionGroup *actions)
+{
+ GtkMenuItem *item;
+ gchar *label;
+ GVariant *serialized_icon;
+ gchar *action = NULL;
+
+ item = g_object_new (IDO_TYPE_SWITCH_MENU_ITEM, NULL);
+
+ if (g_menu_item_get_attribute (menuitem, "label", "s", &label))
+ {
+ ido_switch_menu_item_set_label (IDO_SWITCH_MENU_ITEM (item), label);
+ g_free (label);
+ }
+
+ serialized_icon = g_menu_item_get_attribute_value (menuitem, "icon", NULL);
+ if (serialized_icon)
+ {
+ GIcon *icon;
+
+ icon = g_icon_deserialize (serialized_icon);
+ if (icon)
+ {
+ ido_switch_menu_item_set_icon (IDO_SWITCH_MENU_ITEM (item), icon);
+ g_object_unref (icon);
+ }
+
+ g_variant_unref (serialized_icon);
+ }
+
+ if (g_menu_item_get_attribute (menuitem, "action", "s", &action))
+ {
+ IdoActionHelper *helper;
+
+ helper = ido_action_helper_new (GTK_WIDGET (item), actions, action, NULL);
+ g_signal_connect (helper, "action-state-changed",
+ G_CALLBACK (ido_source_menu_item_state_changed), item);
+ g_signal_connect_object (item, "activate",
+ G_CALLBACK (ido_action_helper_activate), helper,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper);
+
+ g_free (action);
+ }
+
+ return item;
+}
diff --git a/src/idoswitchmenuitem.h b/src/idoswitchmenuitem.h
index 7e7e2d2..222b473 100644
--- a/src/idoswitchmenuitem.h
+++ b/src/idoswitchmenuitem.h
@@ -52,6 +52,15 @@ GType ido_switch_menu_item_get_type (void) G_GNUC_CONST;
GtkWidget *ido_switch_menu_item_new (void);
GtkContainer *ido_switch_menu_item_get_content_area (IdoSwitchMenuItem * item);
+GtkMenuItem * ido_switch_menu_item_new_from_menu_model (GMenuItem *menuitem,
+ GActionGroup *actions);
+
+void ido_switch_menu_item_set_label (IdoSwitchMenuItem *item,
+ const gchar *label);
+
+void ido_switch_menu_item_set_icon (IdoSwitchMenuItem *item,
+ GIcon *icon);
+
G_END_DECLS
#endif /* __IDO_SWITCH_MENU_ITEM_H__ */
diff --git a/src/idousermenuitem.c b/src/idousermenuitem.c
index c92a890..8d8673e 100644
--- a/src/idousermenuitem.c
+++ b/src/idousermenuitem.c
@@ -62,100 +62,6 @@ static gboolean ido_user_menu_item_primitive_draw_cb_gtk_3 (GtkWidget * image,
gpointer gself);
/***
-**** Avatar
-***/
-
-static GdkPixbuf *
-load_gicon (GtkWidget * self, GIcon * icon, GError ** error)
-{
- GtkSettings * settings;
- gint width;
- gint height;
- GdkScreen * screen;
- GtkIconTheme * icon_theme;
- GtkIconInfo * info;
- GtkStyleContext * style_context;
- GdkPixbuf * pixbuf;
-
- settings = gtk_widget_get_settings (self);
- if (settings == NULL) /* not attached to a toplevel yet */
- settings = gtk_settings_get_default ();
-
- if (!gtk_icon_size_lookup_for_settings (settings,
- GTK_ICON_SIZE_MENU,
- &width,
- &height))
- {
- /* arbitrary default size in case _size_lookup fails */
- width = 12;
- height = 12;
- }
-
- if ((screen = gtk_widget_get_screen (self)))
- icon_theme = gtk_icon_theme_get_for_screen (screen);
- else
- icon_theme = gtk_icon_theme_get_default ();
-
-
- info = gtk_icon_theme_lookup_by_gicon (icon_theme,
- icon,
- MIN (width, height),
- GTK_ICON_LOOKUP_USE_BUILTIN |
- GTK_ICON_LOOKUP_GENERIC_FALLBACK |
- GTK_ICON_LOOKUP_FORCE_SIZE);
-
- style_context = gtk_widget_get_style_context (self);
-
- pixbuf = gtk_icon_info_load_symbolic_for_context (info,
- style_context,
- NULL,
- error);
-
- g_clear_object (&info);
- return pixbuf;
-}
-
-static void
-update_avatar (IdoUserMenuItem * self)
-{
- IdoUserMenuItemPrivate * p = self->priv;
- GdkPixbuf * pixbuf;
- GtkImage * image;
-
- if (p->icon == NULL)
- {
- pixbuf = NULL;
- }
- else
- {
- GError * error = NULL;
-
- pixbuf = load_gicon (GTK_WIDGET(self), p->icon, &error);
-
- if (error != NULL)
- {
- g_warning ("Can't load user avatar icon: %s", error->message);
- g_error_free (error);
- }
- }
-
- image = GTK_IMAGE (p->user_image);
-
- if (pixbuf != NULL)
- {
- gtk_image_set_from_pixbuf (image, pixbuf);
- g_object_unref (G_OBJECT (pixbuf));
- }
- else
- {
- GIcon * icon;
- icon = g_themed_icon_new_with_default_fallbacks (FALLBACK_ICON_NAME);
- gtk_image_set_from_gicon (image, icon, GTK_ICON_SIZE_MENU);
- g_object_unref (icon);
- }
-}
-
-/***
**** GObject virtual functions
***/
@@ -301,6 +207,9 @@ ido_user_menu_item_init (IdoUserMenuItem *self)
// Create the UI elements.
priv->user_image = gtk_image_new ();
+ gtk_image_set_from_icon_name (GTK_IMAGE (priv->user_image),
+ FALLBACK_ICON_NAME,
+ GTK_ICON_SIZE_MENU);
priv->user_name = gtk_label_new (NULL);
@@ -337,11 +246,6 @@ ido_user_menu_item_init (IdoUserMenuItem *self)
g_signal_connect_after (GTK_WIDGET(self), "draw",
G_CALLBACK(ido_user_menu_item_primitive_draw_cb_gtk_3),
GTK_WIDGET(self));
-
- /* load_gicon()'s behavior depends on the current screen/toplevel/etc,
- so reload the avatar whenever the widget is realized */
- g_signal_connect_swapped (self, "realize",
- G_CALLBACK(update_avatar), self);
}
@@ -387,6 +291,40 @@ ido_user_menu_item_primitive_draw_cb_gtk_3 (GtkWidget * widget,
}
/***
+**** Avatar
+***/
+static gboolean
+ido_user_menu_item_set_icon_from_file_icon (IdoUserMenuItem *self,
+ GFileIcon *icon)
+{
+ GFile *file;
+ gchar *path;
+ gint width;
+ gint height;
+ GdkPixbuf *pixbuf;
+
+ file = g_file_icon_get_file (G_FILE_ICON (icon));
+ path = g_file_get_path (file);
+
+ /* width and height will always be set by this function */
+ gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (GTK_WIDGET (self)),
+ GTK_ICON_SIZE_MENU,
+ &width, &height);
+
+ pixbuf = gdk_pixbuf_new_from_file_at_scale (path, width, height, TRUE, NULL);
+ g_free (path);
+
+ if (pixbuf)
+ {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->user_image), pixbuf);
+ g_object_unref (pixbuf);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/***
**** PUBLIC API
***/
@@ -395,14 +333,25 @@ ido_user_menu_item_set_icon (IdoUserMenuItem * self, GIcon * icon)
{
IdoUserMenuItemPrivate * p = self->priv;
- if (p->icon != icon)
- {
- g_clear_object (&p->icon);
+ if (p->icon == icon)
+ return;
+
+ g_clear_object (&p->icon);
- if (icon != NULL)
- p->icon = g_object_ref (icon);
+ if (icon)
+ p->icon = g_object_ref (icon);
- update_avatar (self);
+ /* Avatars are always loaded from disk. Show the fallback when no icon
+ * is set, the icon is not a file icon, or the file could not be
+ * found.
+ */
+ if (icon == NULL ||
+ !G_IS_FILE_ICON (icon) ||
+ !ido_user_menu_item_set_icon_from_file_icon (self, G_FILE_ICON (icon)))
+ {
+ gtk_image_set_from_icon_name (GTK_IMAGE (p->user_image),
+ FALLBACK_ICON_NAME,
+ GTK_ICON_SIZE_MENU);
}
}