X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkrecentchoosermenu.c;h=25dc025be4451ff44ba7f83f733c847e53b2dd60;hb=32aa7f0582febb614c41e4130ad34ac44ef6efd2;hp=fb2ab4f1e1cc3fd3caab7152e6a84f8a8786a950;hpb=13277b42e28a987c0e26f4e0ecb458b73d7f06ff;p=~andy%2Fgtk diff --git a/gtk/gtkrecentchoosermenu.c b/gtk/gtkrecentchoosermenu.c index fb2ab4f1e..25dc025be 100644 --- a/gtk/gtkrecentchoosermenu.c +++ b/gtk/gtkrecentchoosermenu.c @@ -13,17 +13,13 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include "config.h" #include -#include - #include "gtkrecentmanager.h" #include "gtkrecentfilter.h" #include "gtkrecentchooser.h" @@ -43,20 +39,43 @@ #include "gtkmenu.h" #include "gtkimage.h" #include "gtklabel.h" -#include "gtkobject.h" -#include "gtktooltips.h" +#include "gtktooltip.h" +#include "gtkactivatable.h" #include "gtktypebuiltins.h" #include "gtkprivate.h" -#include "gtkalias.h" + +/** + * SECTION:gtkrecentchoosermenu + * @Short_description: Displays recently used files in a menu + * @Title: GtkRecentChooserMenu + * @See_also:#GtkRecentChooser + * + * #GtkRecentChooserMenu is a widget suitable for displaying recently used files + * inside a menu. It can be used to set a sub-menu of a #GtkMenuItem using + * gtk_menu_item_set_submenu(), or as the menu of a #GtkMenuToolButton. + * + * Note that #GtkRecentChooserMenu does not have any methods of its own. Instead, + * you should use the functions that work on a #GtkRecentChooser. + * + * Note also that #GtkRecentChooserMenu does not support multiple filters, as it + * has no way to let the user choose between them as the #GtkRecentChooserWidget + * and #GtkRecentChooserDialog widgets do. Thus using gtk_recent_chooser_add_filter() + * on a #GtkRecentChooserMenu widget will yield the same effects as using + * gtk_recent_chooser_set_filter(), replacing any currently set filter + * with the supplied filter; gtk_recent_chooser_remove_filter() will remove + * any currently set #GtkRecentFilter object and will unset the current filter; + * gtk_recent_chooser_list_filters() will return a list containing a single + * #GtkRecentFilter object. + * + * Recently used files are supported since GTK+ 2.10. + */ + struct _GtkRecentChooserMenuPrivate { /* the recent manager object */ GtkRecentManager *manager; - /* size of the icons of the menu items */ - gint icon_size; - /* max size of the menu item label */ gint label_width; @@ -85,22 +104,21 @@ struct _GtkRecentChooserMenuPrivate gulong manager_changed_id; gulong populate_id; - - /* tooltips for our bookmark items*/ - GtkTooltips *tooltips; }; enum { PROP_0, + PROP_SHOW_NUMBERS, - PROP_SHOW_NUMBERS + /* activatable properties */ + PROP_ACTIVATABLE_RELATED_ACTION, + PROP_ACTIVATABLE_USE_ACTION_APPEARANCE }; -#define FALLBACK_ICON_SIZE 32 + #define FALLBACK_ITEM_LIMIT 10 #define DEFAULT_LABEL_WIDTH 30 -#define GTK_RECENT_CHOOSER_MENU_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RECENT_CHOOSER_MENU, GtkRecentChooserMenuPrivate)) static void gtk_recent_chooser_menu_finalize (GObject *object); static void gtk_recent_chooser_menu_dispose (GObject *object); @@ -154,18 +172,25 @@ static void set_recent_manager (GtkRecentChooserMenu *menu, static void chooser_set_sort_type (GtkRecentChooserMenu *menu, GtkRecentSortType sort_type); -static gint get_icon_size_for_widget (GtkWidget *widget); - static void item_activate_cb (GtkWidget *widget, gpointer user_data); static void manager_changed_cb (GtkRecentManager *manager, gpointer user_data); +static void gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface); +static void gtk_recent_chooser_update (GtkActivatable *activatable, + GtkAction *action, + const gchar *property_name); +static void gtk_recent_chooser_sync_action_properties (GtkActivatable *activatable, + GtkAction *action); + G_DEFINE_TYPE_WITH_CODE (GtkRecentChooserMenu, gtk_recent_chooser_menu, GTK_TYPE_MENU, G_IMPLEMENT_INTERFACE (GTK_TYPE_RECENT_CHOOSER, - gtk_recent_chooser_iface_init)) + gtk_recent_chooser_iface_init) + G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, + gtk_recent_chooser_activatable_iface_init)) static void @@ -185,6 +210,13 @@ gtk_recent_chooser_iface_init (GtkRecentChooserIface *iface) iface->list_filters = gtk_recent_chooser_menu_list_filters; } +static void +gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface) +{ + iface->update = gtk_recent_chooser_update; + iface->sync_action_properties = gtk_recent_chooser_sync_action_properties; +} + static void gtk_recent_chooser_menu_class_init (GtkRecentChooserMenuClass *klass) { @@ -199,7 +231,7 @@ gtk_recent_chooser_menu_class_init (GtkRecentChooserMenuClass *klass) _gtk_recent_chooser_install_properties (gobject_class); /** - * GtkRecentChooserMenu:show-numbers + * GtkRecentChooserMenu:show-numbers: * * Whether the first ten items in the menu should be prepended by * a number acting as a unique mnemonic. @@ -214,6 +246,10 @@ gtk_recent_chooser_menu_class_init (GtkRecentChooserMenuClass *klass) FALSE, GTK_PARAM_READWRITE)); + + g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action"); + g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance"); + g_type_class_add_private (klass, sizeof (GtkRecentChooserMenuPrivate)); } @@ -221,11 +257,13 @@ static void gtk_recent_chooser_menu_init (GtkRecentChooserMenu *menu) { GtkRecentChooserMenuPrivate *priv; - - priv = GTK_RECENT_CHOOSER_MENU_GET_PRIVATE (menu); - - menu->priv = priv; - + + menu->priv = G_TYPE_INSTANCE_GET_PRIVATE (menu, + GTK_TYPE_RECENT_CHOOSER_MENU, + GtkRecentChooserMenuPrivate); + + priv = menu->priv; + priv->show_icons= TRUE; priv->show_numbers = FALSE; priv->show_tips = FALSE; @@ -235,16 +273,12 @@ gtk_recent_chooser_menu_init (GtkRecentChooserMenu *menu) priv->limit = FALLBACK_ITEM_LIMIT; priv->sort_type = GTK_RECENT_SORT_NONE; - priv->icon_size = FALLBACK_ICON_SIZE; priv->label_width = DEFAULT_LABEL_WIDTH; priv->first_recent_item_pos = -1; priv->placeholder = NULL; priv->current_filter = NULL; - - priv->tooltips = gtk_tooltips_new (); - g_object_ref_sink (priv->tooltips); } static void @@ -287,12 +321,6 @@ gtk_recent_chooser_menu_dispose (GObject *object) priv->populate_id = 0; } - if (priv->tooltips) - { - g_object_unref (priv->tooltips); - priv->tooltips = NULL; - } - if (priv->current_filter) { g_object_unref (priv->current_filter); @@ -336,6 +364,7 @@ gtk_recent_chooser_menu_constructor (GType type, GINT_TO_POINTER (TRUE)); gtk_menu_shell_insert (GTK_MENU_SHELL (menu), priv->placeholder, 0); + gtk_widget_set_no_show_all (priv->placeholder, TRUE); gtk_widget_show (priv->placeholder); /* (re)populate the menu */ @@ -390,6 +419,12 @@ gtk_recent_chooser_menu_set_property (GObject *object, case GTK_RECENT_CHOOSER_PROP_FILTER: gtk_recent_chooser_menu_set_current_filter (menu, g_value_get_object (value)); break; + case PROP_ACTIVATABLE_RELATED_ACTION: + _gtk_recent_chooser_set_related_action (GTK_RECENT_CHOOSER (menu), g_value_get_object (value)); + break; + case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE: + _gtk_recent_chooser_set_use_action_appearance (GTK_RECENT_CHOOSER (menu), g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -432,13 +467,17 @@ gtk_recent_chooser_menu_get_property (GObject *object, g_value_set_boolean (value, priv->show_icons); break; case GTK_RECENT_CHOOSER_PROP_SELECT_MULTIPLE: - g_warning ("%s: Choosers of type `%s' do not support selecting multiple items.", - G_STRFUNC, - G_OBJECT_TYPE_NAME (object)); + g_value_set_boolean (value, FALSE); break; case GTK_RECENT_CHOOSER_PROP_FILTER: g_value_set_object (value, priv->current_filter); break; + case PROP_ACTIVATABLE_RELATED_ACTION: + g_value_set_object (value, _gtk_recent_chooser_get_related_action (GTK_RECENT_CHOOSER (menu))); + break; + case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE: + g_value_set_boolean (value, _gtk_recent_chooser_get_use_action_appearance (GTK_RECENT_CHOOSER (menu))); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -564,16 +603,16 @@ gtk_recent_chooser_menu_unselect_uri (GtkRecentChooser *chooser, static void gtk_recent_chooser_menu_select_all (GtkRecentChooser *chooser) { - g_warning (_("This function is not implemented for " - "widgets of class '%s'"), + g_warning ("This function is not implemented for " + "widgets of class '%s'", g_type_name (G_OBJECT_TYPE (chooser))); } static void gtk_recent_chooser_menu_unselect_all (GtkRecentChooser *chooser) { - g_warning (_("This function is not implemented for " - "widgets of class '%s'"), + g_warning ("This function is not implemented for " + "widgets of class '%s'", g_type_name (G_OBJECT_TYPE (chooser))); } @@ -690,11 +729,10 @@ gtk_recent_chooser_menu_set_current_filter (GtkRecentChooserMenu *menu, if (priv->current_filter) g_object_unref (G_OBJECT (priv->current_filter)); - if (filter) - { - priv->current_filter = filter; - g_object_ref_sink (priv->current_filter); - } + priv->current_filter = filter; + + if (priv->current_filter) + g_object_ref_sink (priv->current_filter); gtk_recent_chooser_menu_populate (menu); @@ -741,25 +779,20 @@ gtk_recent_chooser_menu_add_tip (GtkRecentChooserMenu *menu, GtkWidget *item) { GtkRecentChooserMenuPrivate *priv; - gchar *path, *tip_text; + gchar *path; g_assert (info != NULL); g_assert (item != NULL); priv = menu->priv; - if (!priv->tooltips) - return; - path = gtk_recent_info_get_uri_display (info); if (path) { - tip_text = g_strdup_printf (_("Open '%s'"), path); + gchar *tip_text = g_strdup_printf (_("Open '%s'"), path); - gtk_tooltips_set_tip (priv->tooltips, - item, - tip_text, - NULL); + gtk_widget_set_tooltip_text (item, tip_text); + gtk_widget_set_has_tooltip (item, priv->show_tips); g_free (path); g_free (tip_text); @@ -774,7 +807,7 @@ gtk_recent_chooser_menu_create_item (GtkRecentChooserMenu *menu, GtkRecentChooserMenuPrivate *priv; gchar *text; GtkWidget *item, *image, *label; - GdkPixbuf *icon; + GIcon *icon; g_assert (info != NULL); @@ -792,21 +825,17 @@ gtk_recent_chooser_menu_create_item (GtkRecentChooserMenu *menu, /* avoid clashing mnemonics */ if (count <= 10) - /* This is the label format that is used for the first 10 items + /* This is the label format that is used for the first 10 items * in a recent files menu. The %d is the number of the item, * the %s is the name of the item. Please keep the _ in front * of the number to give these menu items a mnemonic. - * - * Don't include the prefix "recent menu label|" in the translation. */ - text = g_strdup_printf (Q_("recent menu label|_%d. %s"), count, escaped); + text = g_strdup_printf (C_("recent menu label", "_%d. %s"), count, escaped); else - /* This is the format that is used for items in a recent files menu. - * The %d is the number of the item, the %s is the name of the item. - * - * Don't include the prefix "recent menu label|" in the translation. + /* This is the format that is used for items in a recent files menu. + * The %d is the number of the item, the %s is the name of the item. */ - text = g_strdup_printf (Q_("recent menu label|%d. %s"), count, escaped); + text = g_strdup_printf (C_("recent menu label", "%d. %s"), count, escaped); item = gtk_image_menu_item_new_with_mnemonic (text); @@ -821,10 +850,13 @@ gtk_recent_chooser_menu_create_item (GtkRecentChooserMenu *menu, g_free (text); + gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), + TRUE); + /* ellipsize the menu item label, in case the recent document * display name is huge. */ - label = GTK_BIN (item)->child; + label = gtk_bin_get_child (GTK_BIN (item)); if (GTK_IS_LABEL (label)) { gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END); @@ -833,11 +865,13 @@ gtk_recent_chooser_menu_create_item (GtkRecentChooserMenu *menu, if (priv->show_icons) { - icon = gtk_recent_info_get_icon (info, priv->icon_size); - - image = gtk_image_new_from_pixbuf (icon); + icon = gtk_recent_info_get_gicon (info); + + image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU); gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image); - g_object_unref (icon); + gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE); + if (icon) + g_object_unref (icon); } g_signal_connect (item, "activate", @@ -933,6 +967,30 @@ typedef struct GtkWidget *placeholder; } MenuPopulateData; +static MenuPopulateData * +create_menu_populate_data (GtkRecentChooserMenu *menu) +{ + MenuPopulateData *pdata; + + pdata = g_slice_new (MenuPopulateData); + pdata->items = NULL; + pdata->n_items = 0; + pdata->loaded_items = 0; + pdata->displayed_items = 0; + pdata->menu = menu; + pdata->placeholder = g_object_ref (menu->priv->placeholder); + + return pdata; +} + +static void +free_menu_populate_data (MenuPopulateData *pdata) +{ + if (pdata->placeholder) + g_object_unref (pdata->placeholder); + g_slice_free (MenuPopulateData, pdata); +} + static gboolean idle_populate_func (gpointer data) { @@ -945,8 +1003,6 @@ idle_populate_func (gpointer data) pdata = (MenuPopulateData *) data; priv = pdata->menu->priv; - priv->populate_id = 0; - if (!pdata->items) { pdata->items = gtk_recent_chooser_get_items (GTK_RECENT_CHOOSER (pdata->menu)); @@ -955,9 +1011,12 @@ idle_populate_func (gpointer data) /* show the placeholder here */ gtk_widget_show (pdata->placeholder); pdata->displayed_items = 1; + priv->populate_id = 0; return FALSE; } + else + gtk_widget_hide (pdata->placeholder); pdata->n_items = g_list_length (pdata->items); pdata->loaded_items = 0; @@ -994,8 +1053,9 @@ check_and_return: if (pdata->loaded_items == pdata->n_items) { - g_list_foreach (pdata->items, (GFunc) gtk_recent_info_unref, NULL); - g_list_free (pdata->items); + g_list_free_full (pdata->items, (GDestroyNotify) gtk_recent_info_unref); + + priv->populate_id = 0; retval = FALSE; } @@ -1010,14 +1070,16 @@ idle_populate_clean_up (gpointer data) { MenuPopulateData *pdata = data; - /* show the placeholder in case no item survived - * the filtering process in the idle loop - */ - if (!pdata->displayed_items) - gtk_widget_show (pdata->placeholder); - g_object_unref (pdata->placeholder); + if (pdata->menu->priv->populate_id == 0) + { + /* show the placeholder in case no item survived + * the filtering process in the idle loop + */ + if (!pdata->displayed_items) + gtk_widget_show (pdata->placeholder); + } - g_slice_free (MenuPopulateData, data); + free_menu_populate_data (pdata); } static void @@ -1026,23 +1088,14 @@ gtk_recent_chooser_menu_populate (GtkRecentChooserMenu *menu) MenuPopulateData *pdata; GtkRecentChooserMenuPrivate *priv = menu->priv; - if (menu->priv->populate_id) + if (priv->populate_id) return; - pdata = g_slice_new (MenuPopulateData); - pdata->items = NULL; - pdata->n_items = 0; - pdata->loaded_items = 0; - pdata->displayed_items = 0; - pdata->menu = menu; - pdata->placeholder = g_object_ref (priv->placeholder); + pdata = create_menu_populate_data (menu); - priv->icon_size = get_icon_size_for_widget (GTK_WIDGET (menu)); - - /* remove our menu items first and hide the placeholder */ + /* remove our menu items first */ gtk_recent_chooser_menu_dispose_items (menu); - gtk_widget_hide (priv->placeholder); - + priv->populate_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30, idle_populate_func, pdata, @@ -1105,41 +1158,56 @@ set_recent_manager (GtkRecentChooserMenu *menu, menu); } -static gint -get_icon_size_for_widget (GtkWidget *widget) +static void +foreach_set_shot_tips (GtkWidget *widget, + gpointer user_data) { - GtkSettings *settings; - gint width, height; - - if (gtk_widget_has_screen (widget)) - settings = gtk_settings_get_for_screen (gtk_widget_get_screen (widget)); - else - settings = gtk_settings_get_default (); + GtkRecentChooserMenu *menu = user_data; + GtkRecentChooserMenuPrivate *priv = menu->priv; + gboolean has_mark; - if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU, - &width, &height)) - return MAX (width, height); + /* toggle the tooltip only on the items we create */ + has_mark = + GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "gtk-recent-menu-mark")); - return FALLBACK_ICON_SIZE; + if (has_mark) + gtk_widget_set_has_tooltip (widget, priv->show_tips); } static void gtk_recent_chooser_menu_set_show_tips (GtkRecentChooserMenu *menu, gboolean show_tips) { - if (menu->priv->show_tips == show_tips) + GtkRecentChooserMenuPrivate *priv = menu->priv; + + if (priv->show_tips == show_tips) return; - g_assert (menu->priv->tooltips != NULL); - - if (show_tips) - gtk_tooltips_enable (menu->priv->tooltips); - else - gtk_tooltips_disable (menu->priv->tooltips); - - menu->priv->show_tips = show_tips; + priv->show_tips = show_tips; + gtk_container_foreach (GTK_CONTAINER (menu), foreach_set_shot_tips, menu); } +static void +gtk_recent_chooser_update (GtkActivatable *activatable, + GtkAction *action, + const gchar *property_name) +{ + if (strcmp (property_name, "sensitive") == 0) + gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action)); + + _gtk_recent_chooser_update (activatable, action, property_name); +} + +static void +gtk_recent_chooser_sync_action_properties (GtkActivatable *activatable, + GtkAction *action) +{ + gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action)); + + _gtk_recent_chooser_sync_action_properties (activatable, action); +} + + /* * Public API */ @@ -1240,6 +1308,3 @@ gtk_recent_chooser_menu_set_show_numbers (GtkRecentChooserMenu *menu, menu->priv->show_numbers = show_numbers; g_object_notify (G_OBJECT (menu), "show-numbers"); } - -#define __GTK_RECENT_CHOOSER_MENU_C__ -#include "gtkaliasdef.c"