diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/idoactionhelper.c | 7 | ||||
-rw-r--r-- | src/idocalendarmenuitem.c | 4 | ||||
-rw-r--r-- | src/idomenuitemfactory.c | 4 | ||||
-rw-r--r-- | src/idoscalemenuitem.c | 73 | ||||
-rw-r--r-- | src/idoswitchmenuitem.c | 142 | ||||
-rw-r--r-- | src/idoswitchmenuitem.h | 9 | ||||
-rw-r--r-- | src/idousermenuitem.c | 159 |
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); } } |