]> Pileus Git - ~andy/gtk/blob - gtk/gtkrecentaction.c
Merge branch 'master' into broadway2
[~andy/gtk] / gtk / gtkrecentaction.c
1 /* GTK - The GIMP Toolkit
2  * Recent chooser action for GtkUIManager
3  *
4  * Copyright (C) 2007, Emmanuele Bassi
5  * 
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include "config.h"
23
24 #include "gtkintl.h"
25 #include "gtkrecentaction.h"
26 #include "gtkimagemenuitem.h"
27 #include "gtkmenutoolbutton.h"
28 #include "gtkrecentchooser.h"
29 #include "gtkrecentchoosermenu.h"
30 #include "gtkrecentchooserutils.h"
31 #include "gtkrecentchooserprivate.h"
32 #include "gtkprivate.h"
33
34 /**
35  * SECTION:gtkrecentaction
36  * @Short_description: An action of which represents a list of recently used files
37  * @Title: GtkRecentAction
38  *
39  * A #GtkRecentAction represents a list of recently used files, which
40  * can be shown by widgets such as #GtkRecentChooserDialog or
41  * #GtkRecentChooserMenu.
42  *
43  * To construct a submenu showing recently used files, use a #GtkRecentAction
44  * as the action for a <menuitem>. To construct a menu toolbutton showing
45  * the recently used files in the popup menu, use a #GtkRecentAction as the
46  * action for a <toolitem> element.
47  */
48
49
50 #define FALLBACK_ITEM_LIMIT     10
51
52
53 struct _GtkRecentActionPrivate
54 {
55   GtkRecentManager *manager;
56
57   guint show_numbers   : 1;
58
59   /* RecentChooser properties */
60   guint show_private   : 1;
61   guint show_not_found : 1;
62   guint show_tips      : 1;
63   guint show_icons     : 1;
64   guint local_only     : 1;
65
66   gint limit;
67
68   GtkRecentSortType sort_type;
69   GtkRecentSortFunc sort_func;
70   gpointer          sort_data;
71   GDestroyNotify    data_destroy;
72
73   GtkRecentFilter *current_filter;
74
75   GSList *choosers;
76   GtkRecentChooser *current_chooser;
77 };
78
79 enum
80 {
81   PROP_0,
82
83   PROP_SHOW_NUMBERS
84 };
85
86 static void gtk_recent_chooser_iface_init (GtkRecentChooserIface *iface);
87
88 G_DEFINE_TYPE_WITH_CODE (GtkRecentAction,
89                          gtk_recent_action,
90                          GTK_TYPE_ACTION,
91                          G_IMPLEMENT_INTERFACE (GTK_TYPE_RECENT_CHOOSER,
92                                                 gtk_recent_chooser_iface_init));
93
94 static gboolean
95 gtk_recent_action_set_current_uri (GtkRecentChooser  *chooser,
96                                    const gchar       *uri,
97                                    GError           **error)
98 {
99   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
100   GtkRecentActionPrivate *priv = action->priv;
101   GSList *l;
102
103   for (l = priv->choosers; l; l = l->next)
104     {
105       GtkRecentChooser *recent_chooser = l->data;
106
107       if (!gtk_recent_chooser_set_current_uri (recent_chooser, uri, error))
108         return FALSE;
109     }
110
111   return TRUE;
112 }
113
114 static gchar *
115 gtk_recent_action_get_current_uri (GtkRecentChooser *chooser)
116 {
117   GtkRecentAction *recent_action = GTK_RECENT_ACTION (chooser);
118   GtkRecentActionPrivate *priv = recent_action->priv;
119
120   if (priv->current_chooser)
121     return gtk_recent_chooser_get_current_uri (priv->current_chooser);
122
123   return NULL;
124 }
125
126 static gboolean
127 gtk_recent_action_select_uri (GtkRecentChooser  *chooser,
128                               const gchar       *uri,
129                               GError           **error)
130 {
131   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
132   GtkRecentActionPrivate *priv = action->priv;
133   GSList *l;
134
135   for (l = priv->choosers; l; l = l->next)
136     {
137       GtkRecentChooser *recent_chooser = l->data;
138
139       if (!gtk_recent_chooser_select_uri (recent_chooser, uri, error))
140         return FALSE;
141     }
142
143   return TRUE;
144 }
145
146 static void
147 gtk_recent_action_unselect_uri (GtkRecentChooser *chooser,
148                                 const gchar      *uri)
149 {
150   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
151   GtkRecentActionPrivate *priv = action->priv;
152   GSList *l;
153
154   for (l = priv->choosers; l; l = l->next)
155     {
156       GtkRecentChooser *chooser = l->data;
157       
158       gtk_recent_chooser_unselect_uri (chooser, uri);
159     }
160 }
161
162 static void
163 gtk_recent_action_select_all (GtkRecentChooser *chooser)
164 {
165   g_warning (_("This function is not implemented for "
166                "widgets of class '%s'"),
167              g_type_name (G_OBJECT_TYPE (chooser)));
168 }
169
170 static void
171 gtk_recent_action_unselect_all (GtkRecentChooser *chooser)
172 {
173   g_warning (_("This function is not implemented for "
174                "widgets of class '%s'"),
175              g_type_name (G_OBJECT_TYPE (chooser)));
176 }
177
178
179 static GList *
180 gtk_recent_action_get_items (GtkRecentChooser *chooser)
181 {
182   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
183   GtkRecentActionPrivate *priv = action->priv;
184
185   return _gtk_recent_chooser_get_items (chooser,
186                                         priv->current_filter,
187                                         priv->sort_func,
188                                         priv->sort_data);
189 }
190
191 static GtkRecentManager *
192 gtk_recent_action_get_recent_manager (GtkRecentChooser *chooser)
193 {
194   return GTK_RECENT_ACTION (chooser)->priv->manager;
195 }
196
197 static void
198 gtk_recent_action_set_sort_func (GtkRecentChooser  *chooser,
199                                  GtkRecentSortFunc  sort_func,
200                                  gpointer           sort_data,
201                                  GDestroyNotify     data_destroy)
202 {
203   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
204   GtkRecentActionPrivate *priv = action->priv;
205   GSList *l;
206   
207   if (priv->data_destroy)
208     {
209       priv->data_destroy (priv->sort_data);
210       priv->data_destroy = NULL;
211     }
212       
213   priv->sort_func = NULL;
214   priv->sort_data = NULL;
215   
216   if (sort_func)
217     {
218       priv->sort_func = sort_func;
219       priv->sort_data = sort_data;
220       priv->data_destroy = data_destroy;
221     }
222
223   for (l = priv->choosers; l; l = l->next)
224     {
225       GtkRecentChooser *chooser_menu = l->data;
226       
227       gtk_recent_chooser_set_sort_func (chooser_menu, priv->sort_func,
228                                         priv->sort_data,
229                                         priv->data_destroy);
230     }
231 }
232
233 static void
234 set_current_filter (GtkRecentAction *action,
235                     GtkRecentFilter *filter)
236 {
237   GtkRecentActionPrivate *priv = action->priv;
238
239   g_object_ref (action);
240
241   if (priv->current_filter)
242     g_object_unref (priv->current_filter);
243
244   priv->current_filter = filter;
245
246   if (priv->current_filter)
247     g_object_ref_sink (priv->current_filter);
248
249   g_object_notify (G_OBJECT (action), "filter");
250
251   g_object_unref (action);
252 }
253
254 static void
255 gtk_recent_action_add_filter (GtkRecentChooser *chooser,
256                               GtkRecentFilter  *filter)
257 {
258   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
259   GtkRecentActionPrivate *priv = action->priv;
260
261   if (priv->current_filter != filter)
262     set_current_filter (GTK_RECENT_ACTION (chooser), filter);
263 }
264
265 static void
266 gtk_recent_action_remove_filter (GtkRecentChooser *chooser,
267                                  GtkRecentFilter  *filter)
268 {
269   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
270   GtkRecentActionPrivate *priv = action->priv;
271
272   if (priv->current_filter == filter)
273     set_current_filter (GTK_RECENT_ACTION (chooser), NULL);
274 }
275
276 static GSList *
277 gtk_recent_action_list_filters (GtkRecentChooser *chooser)
278 {
279   GtkRecentAction *action = GTK_RECENT_ACTION (chooser);
280   GtkRecentActionPrivate *priv = action->priv;
281   GSList *retval = NULL;
282   GtkRecentFilter *current_filter;
283
284   current_filter = priv->current_filter;
285   retval = g_slist_prepend (retval, current_filter);
286
287   return retval;
288 }
289
290
291 static void
292 gtk_recent_chooser_iface_init (GtkRecentChooserIface *iface)
293 {
294   iface->set_current_uri = gtk_recent_action_set_current_uri;
295   iface->get_current_uri = gtk_recent_action_get_current_uri;
296   iface->select_uri = gtk_recent_action_select_uri;
297   iface->unselect_uri = gtk_recent_action_unselect_uri;
298   iface->select_all = gtk_recent_action_select_all;
299   iface->unselect_all = gtk_recent_action_unselect_all;
300   iface->get_items = gtk_recent_action_get_items;
301   iface->get_recent_manager = gtk_recent_action_get_recent_manager;
302   iface->set_sort_func = gtk_recent_action_set_sort_func;
303   iface->add_filter = gtk_recent_action_add_filter;
304   iface->remove_filter = gtk_recent_action_remove_filter;
305   iface->list_filters = gtk_recent_action_list_filters;
306 }
307
308 static void
309 gtk_recent_action_activate (GtkAction *action)
310 {
311   GtkRecentAction *recent_action = GTK_RECENT_ACTION (action);
312   GtkRecentActionPrivate *priv = recent_action->priv;
313
314   /* we have probably been invoked by a menu tool button or by a
315    * direct call of gtk_action_activate(); since no item has been
316    * selected, we must unset the current recent chooser pointer
317    */
318   priv->current_chooser = NULL;
319 }
320
321 static void
322 delegate_selection_changed (GtkRecentAction  *action,
323                             GtkRecentChooser *chooser)
324 {
325   GtkRecentActionPrivate *priv = action->priv;
326
327   priv->current_chooser = chooser;
328
329   g_signal_emit_by_name (action, "selection-changed");
330 }
331
332 static void
333 delegate_item_activated (GtkRecentAction  *action,
334                          GtkRecentChooser *chooser)
335 {
336   GtkRecentActionPrivate *priv = action->priv;
337
338   priv->current_chooser = chooser;
339
340   g_signal_emit_by_name (action, "item-activated");
341 }
342
343 static void
344 gtk_recent_action_connect_proxy (GtkAction *action,
345                                  GtkWidget *widget)
346 {
347   GtkRecentAction *recent_action = GTK_RECENT_ACTION (action);
348   GtkRecentActionPrivate *priv = recent_action->priv;
349
350   /* it can only be a recent chooser implementor anyway... */
351   if (GTK_IS_RECENT_CHOOSER (widget) &&
352       !g_slist_find (priv->choosers, widget))
353     {
354       if (priv->sort_func)
355         {
356           gtk_recent_chooser_set_sort_func (GTK_RECENT_CHOOSER (widget),
357                                             priv->sort_func,
358                                             priv->sort_data,
359                                             priv->data_destroy);
360         }
361
362       g_signal_connect_swapped (widget, "selection_changed",
363                                 G_CALLBACK (delegate_selection_changed),
364                                 action);
365       g_signal_connect_swapped (widget, "item-activated",
366                                 G_CALLBACK (delegate_item_activated),
367                                 action);
368     }
369
370   if (GTK_ACTION_CLASS (gtk_recent_action_parent_class)->connect_proxy)
371     GTK_ACTION_CLASS (gtk_recent_action_parent_class)->connect_proxy (action, widget);
372 }
373
374 static void
375 gtk_recent_action_disconnect_proxy (GtkAction *action,
376                                     GtkWidget *widget)
377 {
378   GtkRecentAction *recent_action = GTK_RECENT_ACTION (action);
379   GtkRecentActionPrivate *priv = recent_action->priv;
380
381   /* if it was one of the recent choosers we created, remove it
382    * from the list
383    */
384   if (g_slist_find (priv->choosers, widget))
385     priv->choosers = g_slist_remove (priv->choosers, widget);
386
387   if (GTK_ACTION_CLASS (gtk_recent_action_parent_class)->disconnect_proxy)
388     GTK_ACTION_CLASS (gtk_recent_action_parent_class)->disconnect_proxy (action, widget);
389 }
390
391 static GtkWidget *
392 gtk_recent_action_create_menu (GtkAction *action)
393 {
394   GtkRecentAction *recent_action = GTK_RECENT_ACTION (action);
395   GtkRecentActionPrivate *priv = recent_action->priv;
396   GtkWidget *widget;
397
398   widget = g_object_new (GTK_TYPE_RECENT_CHOOSER_MENU,
399                          "show-private", priv->show_private,
400                          "show-not-found", priv->show_not_found,
401                          "show-tips", priv->show_tips,
402                          "show-icons", priv->show_icons,
403                          "show-numbers", priv->show_numbers,
404                          "limit", priv->limit,
405                          "sort-type", priv->sort_type,
406                          "recent-manager", priv->manager,
407                          "filter", priv->current_filter,
408                          "local-only", priv->local_only,
409                          NULL);
410   
411   if (priv->sort_func)
412     {
413       gtk_recent_chooser_set_sort_func (GTK_RECENT_CHOOSER (widget),
414                                         priv->sort_func,
415                                         priv->sort_data,
416                                         priv->data_destroy);
417     }
418
419   g_signal_connect_swapped (widget, "selection_changed",
420                             G_CALLBACK (delegate_selection_changed),
421                             recent_action);
422   g_signal_connect_swapped (widget, "item-activated",
423                             G_CALLBACK (delegate_item_activated),
424                             recent_action);
425
426   /* keep track of the choosers we create */
427   priv->choosers = g_slist_prepend (priv->choosers, widget);
428
429   return widget;
430 }
431
432 static GtkWidget *
433 gtk_recent_action_create_menu_item (GtkAction *action)
434 {
435   GtkWidget *menu;
436   GtkWidget *menuitem;
437
438   menu = gtk_recent_action_create_menu (action);
439   menuitem = g_object_new (GTK_TYPE_IMAGE_MENU_ITEM, NULL);
440   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
441   gtk_widget_show (menu);
442
443   return menuitem;
444 }
445
446 static GtkWidget *
447 gtk_recent_action_create_tool_item (GtkAction *action)
448 {
449   GtkWidget *menu;
450   GtkWidget *toolitem;
451
452   menu = gtk_recent_action_create_menu (action);
453   toolitem = g_object_new (GTK_TYPE_MENU_TOOL_BUTTON, NULL);
454   gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (toolitem), menu);
455   gtk_widget_show (menu);
456
457   return toolitem;
458 }
459
460 static void
461 set_recent_manager (GtkRecentAction  *action,
462                     GtkRecentManager *manager)
463 {
464   GtkRecentActionPrivate *priv = action->priv;
465
466   if (manager)
467     priv->manager = NULL;
468   else
469     priv->manager = gtk_recent_manager_get_default ();
470 }
471
472 static void
473 gtk_recent_action_finalize (GObject *gobject)
474 {
475   GtkRecentAction *action = GTK_RECENT_ACTION (gobject);
476   GtkRecentActionPrivate *priv = action->priv;
477
478   priv->manager = NULL;
479   
480   if (priv->data_destroy)
481     {
482       priv->data_destroy (priv->sort_data);
483       priv->data_destroy = NULL;
484     }
485
486   priv->sort_data = NULL;
487   priv->sort_func = NULL;
488
489   g_slist_free (priv->choosers);
490
491   G_OBJECT_CLASS (gtk_recent_action_parent_class)->finalize (gobject);
492 }
493
494 static void
495 gtk_recent_action_dispose (GObject *gobject)
496 {
497   GtkRecentAction *action = GTK_RECENT_ACTION (gobject);
498   GtkRecentActionPrivate *priv = action->priv;
499
500   if (priv->current_filter)
501     {
502       g_object_unref (priv->current_filter);
503       priv->current_filter = NULL;
504     }
505
506   G_OBJECT_CLASS (gtk_recent_action_parent_class)->dispose (gobject);
507 }
508
509 static void
510 gtk_recent_action_set_property (GObject      *gobject,
511                                 guint         prop_id,
512                                 const GValue *value,
513                                 GParamSpec   *pspec)
514 {
515   GtkRecentAction *action = GTK_RECENT_ACTION (gobject);
516   GtkRecentActionPrivate *priv = action->priv;
517
518   switch (prop_id)
519     {
520     case PROP_SHOW_NUMBERS:
521       priv->show_numbers = g_value_get_boolean (value);
522       break;
523     case GTK_RECENT_CHOOSER_PROP_SHOW_PRIVATE:
524       priv->show_private = g_value_get_boolean (value);
525       break;
526     case GTK_RECENT_CHOOSER_PROP_SHOW_NOT_FOUND:
527       priv->show_not_found = g_value_get_boolean (value);
528       break;
529     case GTK_RECENT_CHOOSER_PROP_SHOW_TIPS:
530       priv->show_tips = g_value_get_boolean (value);
531       break;
532     case GTK_RECENT_CHOOSER_PROP_SHOW_ICONS:
533       priv->show_icons = g_value_get_boolean (value);
534       break;
535     case GTK_RECENT_CHOOSER_PROP_LIMIT:
536       priv->limit = g_value_get_int (value);
537       break;
538     case GTK_RECENT_CHOOSER_PROP_LOCAL_ONLY:
539       priv->local_only = g_value_get_boolean (value);
540       break;
541     case GTK_RECENT_CHOOSER_PROP_SORT_TYPE:
542       priv->sort_type = g_value_get_enum (value);
543       break;
544     case GTK_RECENT_CHOOSER_PROP_FILTER:
545       set_current_filter (action, g_value_get_object (value));
546       break;
547     case GTK_RECENT_CHOOSER_PROP_SELECT_MULTIPLE:
548       g_warning ("%s: Choosers of type `%s' do not support selecting multiple items.",
549                  G_STRFUNC,
550                  G_OBJECT_TYPE_NAME (gobject));
551       return;
552     case GTK_RECENT_CHOOSER_PROP_RECENT_MANAGER:
553       set_recent_manager (action, g_value_get_object (value));
554       break;
555     default:
556       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
557       return;
558     }
559 }
560
561 static void
562 gtk_recent_action_get_property (GObject    *gobject,
563                                 guint       prop_id,
564                                 GValue     *value,
565                                 GParamSpec *pspec)
566 {
567   GtkRecentAction *action = GTK_RECENT_ACTION (gobject);
568   GtkRecentActionPrivate *priv = action->priv;
569
570   switch (prop_id)
571     {
572     case PROP_SHOW_NUMBERS:
573       g_value_set_boolean (value, priv->show_numbers);
574       break;
575     case GTK_RECENT_CHOOSER_PROP_SHOW_PRIVATE:
576       g_value_set_boolean (value, priv->show_private);
577       break;
578     case GTK_RECENT_CHOOSER_PROP_SHOW_NOT_FOUND:
579       g_value_set_boolean (value, priv->show_not_found);
580       break;
581     case GTK_RECENT_CHOOSER_PROP_SHOW_TIPS:
582       g_value_set_boolean (value, priv->show_tips);
583       break;
584     case GTK_RECENT_CHOOSER_PROP_SHOW_ICONS:
585       g_value_set_boolean (value, priv->show_icons);
586       break;
587     case GTK_RECENT_CHOOSER_PROP_LIMIT:
588       g_value_set_int (value, priv->limit);
589       break;
590     case GTK_RECENT_CHOOSER_PROP_LOCAL_ONLY:
591       g_value_set_boolean (value, priv->local_only);
592       break;
593     case GTK_RECENT_CHOOSER_PROP_SORT_TYPE:
594       g_value_set_enum (value, priv->sort_type);
595       break;
596     case GTK_RECENT_CHOOSER_PROP_FILTER:
597       g_value_set_object (value, priv->current_filter);
598       break;
599     case GTK_RECENT_CHOOSER_PROP_SELECT_MULTIPLE:
600       g_value_set_boolean (value, FALSE);
601       break;
602     default:
603       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
604       break;
605     }
606 }
607
608 static void
609 gtk_recent_action_class_init (GtkRecentActionClass *klass)
610 {
611   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
612   GtkActionClass *action_class = GTK_ACTION_CLASS (klass);
613
614   g_type_class_add_private (klass, sizeof (GtkRecentActionPrivate));
615
616   gobject_class->finalize = gtk_recent_action_finalize;
617   gobject_class->dispose = gtk_recent_action_dispose;
618   gobject_class->set_property = gtk_recent_action_set_property;
619   gobject_class->get_property = gtk_recent_action_get_property;
620
621   action_class->activate = gtk_recent_action_activate;
622   action_class->connect_proxy = gtk_recent_action_connect_proxy;
623   action_class->disconnect_proxy = gtk_recent_action_disconnect_proxy;
624   action_class->create_menu_item = gtk_recent_action_create_menu_item;
625   action_class->create_tool_item = gtk_recent_action_create_tool_item;
626   action_class->create_menu = gtk_recent_action_create_menu;
627   action_class->menu_item_type = GTK_TYPE_IMAGE_MENU_ITEM;
628   action_class->toolbar_item_type = GTK_TYPE_MENU_TOOL_BUTTON;
629
630   _gtk_recent_chooser_install_properties (gobject_class);
631
632   g_object_class_install_property (gobject_class,
633                                    PROP_SHOW_NUMBERS,
634                                    g_param_spec_boolean ("show-numbers",
635                                                          P_("Show Numbers"),
636                                                          P_("Whether the items should be displayed with a number"),
637                                                          FALSE,
638                                                          G_PARAM_READWRITE));
639
640 }
641
642 static void
643 gtk_recent_action_init (GtkRecentAction *action)
644 {
645   GtkRecentActionPrivate *priv;
646
647   action->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (action,
648                                                      GTK_TYPE_RECENT_ACTION,
649                                                      GtkRecentActionPrivate);
650
651   priv->show_numbers = FALSE;
652   priv->show_icons = TRUE;
653   priv->show_tips = FALSE;
654   priv->show_not_found = TRUE;
655   priv->show_private = FALSE;
656   priv->local_only = TRUE;
657
658   priv->limit = FALLBACK_ITEM_LIMIT;
659
660   priv->sort_type = GTK_RECENT_SORT_NONE;
661   priv->sort_func = NULL;
662   priv->sort_data = NULL;
663   priv->data_destroy = NULL;
664
665   priv->current_filter = NULL;
666
667   priv->manager = NULL;
668 }
669
670 /**
671  * gtk_recent_action_new:
672  * @name: a unique name for the action
673  * @label: (allow-none): the label displayed in menu items and on buttons,
674  *   or %NULL
675  * @tooltip: (allow-none): a tooltip for the action, or %NULL
676  * @stock_id: (allow-none): the stock icon to display in widgets representing
677  *   the action, or %NULL
678  *
679  * Creates a new #GtkRecentAction object. To add the action to
680  * a #GtkActionGroup and set the accelerator for the action,
681  * call gtk_action_group_add_action_with_accel().
682  *
683  * Return value: the newly created #GtkRecentAction.
684  *
685  * Since: 2.12
686  */
687 GtkAction *
688 gtk_recent_action_new (const gchar *name,
689                        const gchar *label,
690                        const gchar *tooltip,
691                        const gchar *stock_id)
692 {
693   g_return_val_if_fail (name != NULL, NULL);
694
695   return g_object_new (GTK_TYPE_RECENT_ACTION,
696                        "name", name,
697                        "label", label,
698                        "tooltip", tooltip,
699                        "stock-id", stock_id,
700                        NULL);
701 }
702
703 /**
704  * gtk_recent_action_new_for_manager:
705  * @name: a unique name for the action
706  * @label: (allow-none): the label displayed in menu items and on buttons,
707  *   or %NULL
708  * @tooltip: (allow-none): a tooltip for the action, or %NULL
709  * @stock_id: (allow-none): the stock icon to display in widgets representing
710  *   the action, or %NULL
711  * @manager: (allow-none): a #GtkRecentManager, or %NULL for using the default
712  *   #GtkRecentManager
713  *
714  * Creates a new #GtkRecentAction object. To add the action to
715  * a #GtkActionGroup and set the accelerator for the action,
716  * call gtk_action_group_add_action_with_accel().
717  *
718  * Return value: the newly created #GtkRecentAction
719  * 
720  * Since: 2.12
721  */
722 GtkAction *
723 gtk_recent_action_new_for_manager (const gchar      *name,
724                                    const gchar      *label,
725                                    const gchar      *tooltip,
726                                    const gchar      *stock_id,
727                                    GtkRecentManager *manager)
728 {
729   g_return_val_if_fail (name != NULL, NULL);
730   g_return_val_if_fail (manager == NULL || GTK_IS_RECENT_MANAGER (manager), NULL);
731
732   return g_object_new (GTK_TYPE_RECENT_ACTION,
733                        "name", name,
734                        "label", label,
735                        "tooltip", tooltip,
736                        "stock-id", stock_id,
737                        "recent-manager", manager,
738                        NULL);
739 }
740
741 /**
742  * gtk_recent_action_get_show_numbers:
743  * @action: a #GtkRecentAction
744  *
745  * Returns the value set by gtk_recent_chooser_menu_set_show_numbers().
746  *
747  * Return value: %TRUE if numbers should be shown.
748  *
749  * Since: 2.12
750  */
751 gboolean
752 gtk_recent_action_get_show_numbers (GtkRecentAction *action)
753 {
754   g_return_val_if_fail (GTK_IS_RECENT_ACTION (action), FALSE);
755
756   return action->priv->show_numbers;
757 }
758
759 /**
760  * gtk_recent_action_set_show_numbers:
761  * @action: a #GtkRecentAction
762  * @show_numbers: %TRUE if the shown items should be numbered
763  *
764  * Sets whether a number should be added to the items shown by the
765  * widgets representing @action. The numbers are shown to provide
766  * a unique character for a mnemonic to be used inside the menu item's
767  * label. Only the first ten items get a number to avoid clashes.
768  *
769  * Since: 2.12
770  */
771 void
772 gtk_recent_action_set_show_numbers (GtkRecentAction *action,
773                                     gboolean         show_numbers)
774 {
775   GtkRecentActionPrivate *priv;
776
777   g_return_if_fail (GTK_IS_RECENT_ACTION (action));
778
779   priv = action->priv;
780
781   if (priv->show_numbers != show_numbers)
782     {
783       g_object_ref (action);
784
785       priv->show_numbers = show_numbers;
786
787       g_object_notify (G_OBJECT (action), "show-numbers");
788       g_object_unref (action);
789     }
790 }