]> Pileus Git - ~andy/gtk/blob - gtk/gtkactiongroup.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkactiongroup.c
1 /*
2  * GTK - The GIMP Toolkit
3  * Copyright (C) 1998, 1999 Red Hat, Inc.
4  * All rights reserved.
5  *
6  * This Library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * 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  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /*
21  * Author: James Henstridge <james@daa.com.au>
22  *
23  * Modified by the GTK+ Team and others 2003.  See the AUTHORS
24  * file for a list of people on the GTK+ Team.  See the ChangeLog
25  * files for a list of changes.  These files are distributed with
26  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
27  */
28
29 /**
30  * SECTION:gtkactiongroup
31  * @Short_description: A group of actions
32  * @Title: GtkActionGroup
33  *
34  * Actions are organised into groups. An action group is essentially a
35  * map from names to #GtkAction objects.
36  *
37  * All actions that would make sense to use in a particular context
38  * should be in a single group. Multiple action groups may be used for a
39  * particular user interface. In fact, it is expected that most nontrivial
40  * applications will make use of multiple groups. For example, in an
41  * application that can edit multiple documents, one group holding global
42  * actions (e.g. quit, about, new), and one group per document holding
43  * actions that act on that document (eg. save, cut/copy/paste, etc). Each
44  * window's menus would be constructed from a combination of two action
45  * groups.
46  * </para>
47  * <para id="Action-Accel">
48  * Accelerators are handled by the GTK+ accelerator map. All actions are
49  * assigned an accelerator path (which normally has the form
50  * <literal>&lt;Actions&gt;/group-name/action-name</literal>)
51  * and a shortcut is associated with this accelerator path. All menuitems
52  * and toolitems take on this accelerator path. The GTK+ accelerator map
53  * code makes sure that the correct shortcut is displayed next to the menu
54  * item.
55  *
56  * <refsect2 id="GtkActionGroup-BUILDER-UI">
57  * <title>GtkActionGroup as GtkBuildable</title>
58  * <para>
59  * The #GtkActionGroup implementation of the #GtkBuildable interface accepts
60  * #GtkAction objects as &lt;child&gt; elements in UI definitions.
61  *
62  * Note that it is probably more common to define actions and action groups
63  * in the code, since they are directly related to what the code can do.
64  *
65  * The GtkActionGroup implementation of the GtkBuildable interface supports
66  * a custom &lt;accelerator&gt; element, which has attributes named key and
67  * modifiers and allows to specify accelerators. This is similar to the
68  * &lt;accelerator&gt; element of #GtkWidget, the main difference is that
69  * it doesn't allow you to specify a signal.
70  * </para>
71  * <example>
72  * <title>A #GtkDialog UI definition fragment.</title>
73  * <programlisting><![CDATA[
74  * <object class="GtkActionGroup" id="actiongroup">
75  *   <child>
76  *       <object class="GtkAction" id="About">
77  *           <property name="name">About</property>
78  *           <property name="stock_id">gtk-about</property>
79  *           <signal handler="about_activate" name="activate"/>
80  *       </object>
81  *       <accelerator key="F1" modifiers="GDK_CONTROL_MASK | GDK_SHIFT_MASK"/>
82  *   </child>
83  * </object>
84  * ]]></programlisting>
85  * </example>
86  * </refsect2>
87  */
88
89 #include "config.h"
90 #include <string.h>
91
92 #include "gtkactiongroup.h"
93 #include "gtkbuildable.h"
94 #include "gtkiconfactory.h"
95 #include "gtkicontheme.h"
96 #include "gtkstock.h"
97 #include "gtktoggleaction.h"
98 #include "gtkradioaction.h"
99 #include "gtkaccelmap.h"
100 #include "gtkmarshalers.h"
101 #include "gtkbuilderprivate.h"
102 #include "gtkprivate.h"
103 #include "gtkintl.h"
104
105
106 struct _GtkActionGroupPrivate 
107 {
108   gchar           *name;
109   gboolean         sensitive;
110   gboolean         visible;
111   GHashTable      *actions;
112   GtkAccelGroup   *accel_group;
113
114   GtkTranslateFunc translate_func;
115   gpointer         translate_data;
116   GDestroyNotify   translate_notify;
117 };
118
119 enum 
120 {
121   CONNECT_PROXY,
122   DISCONNECT_PROXY,
123   PRE_ACTIVATE,
124   POST_ACTIVATE,
125   LAST_SIGNAL
126 };
127
128 enum 
129 {
130   PROP_0,
131   PROP_NAME,
132   PROP_SENSITIVE,
133   PROP_VISIBLE,
134   PROP_ACCEL_GROUP
135 };
136
137 static void       gtk_action_group_init            (GtkActionGroup      *self);
138 static void       gtk_action_group_class_init      (GtkActionGroupClass *class);
139 static void       gtk_action_group_finalize        (GObject             *object);
140 static void       gtk_action_group_set_property    (GObject             *object,
141                                                     guint                prop_id,
142                                                     const GValue        *value,
143                                                     GParamSpec          *pspec);
144 static void       gtk_action_group_get_property    (GObject             *object,
145                                                     guint                prop_id,
146                                                     GValue              *value,
147                                                     GParamSpec          *pspec);
148 static GtkAction *gtk_action_group_real_get_action (GtkActionGroup      *self,
149                                                     const gchar         *name);
150
151 /* GtkBuildable */
152 static void gtk_action_group_buildable_init (GtkBuildableIface *iface);
153 static void gtk_action_group_buildable_add_child (GtkBuildable  *buildable,
154                                                   GtkBuilder    *builder,
155                                                   GObject       *child,
156                                                   const gchar   *type);
157 static void gtk_action_group_buildable_set_name (GtkBuildable *buildable,
158                                                  const gchar  *name);
159 static const gchar* gtk_action_group_buildable_get_name (GtkBuildable *buildable);
160 static gboolean gtk_action_group_buildable_custom_tag_start (GtkBuildable     *buildable,
161                                                              GtkBuilder       *builder,
162                                                              GObject          *child,
163                                                              const gchar      *tagname,
164                                                              GMarkupParser    *parser,
165                                                              gpointer         *data);
166 static void gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable,
167                                                        GtkBuilder   *builder,
168                                                        GObject      *child,
169                                                        const gchar  *tagname,
170                                                        gpointer     *user_data);
171
172 GType
173 gtk_action_group_get_type (void)
174 {
175   static GType type = 0;
176
177   if (!type)
178     {
179       const GTypeInfo type_info =
180       {
181         sizeof (GtkActionGroupClass),
182         NULL,           /* base_init */
183         NULL,           /* base_finalize */
184         (GClassInitFunc) gtk_action_group_class_init,
185         NULL,           /* class_finalize */
186         NULL,           /* class_data */
187         sizeof (GtkActionGroup),
188         0, /* n_preallocs */
189         (GInstanceInitFunc) gtk_action_group_init,
190       };
191
192       const GInterfaceInfo buildable_info =
193       {
194         (GInterfaceInitFunc) gtk_action_group_buildable_init,
195         NULL,
196         NULL
197       };
198
199       type = g_type_register_static (G_TYPE_OBJECT, I_("GtkActionGroup"),
200                                      &type_info, 0);
201
202       g_type_add_interface_static (type,
203                                    GTK_TYPE_BUILDABLE,
204                                    &buildable_info);
205     }
206   return type;
207 }
208
209 static GObjectClass *parent_class = NULL;
210 static guint         action_group_signals[LAST_SIGNAL] = { 0 };
211
212 static void
213 gtk_action_group_class_init (GtkActionGroupClass *klass)
214 {
215   GObjectClass *gobject_class;
216
217   gobject_class = G_OBJECT_CLASS (klass);
218   parent_class = g_type_class_peek_parent (klass);
219
220   gobject_class->finalize = gtk_action_group_finalize;
221   gobject_class->set_property = gtk_action_group_set_property;
222   gobject_class->get_property = gtk_action_group_get_property;
223   klass->get_action = gtk_action_group_real_get_action;
224
225   g_object_class_install_property (gobject_class,
226                                    PROP_NAME,
227                                    g_param_spec_string ("name",
228                                                         P_("Name"),
229                                                         P_("A name for the action group."),
230                                                         NULL,
231                                                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
232   g_object_class_install_property (gobject_class,
233                                    PROP_SENSITIVE,
234                                    g_param_spec_boolean ("sensitive",
235                                                          P_("Sensitive"),
236                                                          P_("Whether the action group is enabled."),
237                                                          TRUE,
238                                                          GTK_PARAM_READWRITE));
239   g_object_class_install_property (gobject_class,
240                                    PROP_VISIBLE,
241                                    g_param_spec_boolean ("visible",
242                                                          P_("Visible"),
243                                                          P_("Whether the action group is visible."),
244                                                          TRUE,
245                                                          GTK_PARAM_READWRITE));
246   g_object_class_install_property (gobject_class,
247                                    PROP_ACCEL_GROUP,
248                                    g_param_spec_object ("accel-group",
249                                                         P_("Accelerator Group"),
250                                                         P_("The accelerator group the actions of this group should use."),
251                                                         GTK_TYPE_ACCEL_GROUP,
252                                                         GTK_PARAM_READWRITE));
253
254   /**
255    * GtkActionGroup::connect-proxy:
256    * @action_group: the group
257    * @action: the action
258    * @proxy: the proxy
259    *
260    * The ::connect-proxy signal is emitted after connecting a proxy to 
261    * an action in the group. Note that the proxy may have been connected 
262    * to a different action before.
263    *
264    * This is intended for simple customizations for which a custom action
265    * class would be too clumsy, e.g. showing tooltips for menuitems in the
266    * statusbar.
267    *
268    * #GtkUIManager proxies the signal and provides global notification 
269    * just before any action is connected to a proxy, which is probably more
270    * convenient to use.
271    *
272    * Since: 2.4
273    */
274   action_group_signals[CONNECT_PROXY] =
275     g_signal_new (I_("connect-proxy"),
276                   G_OBJECT_CLASS_TYPE (klass),
277                   0, 0, NULL, NULL,
278                   _gtk_marshal_VOID__OBJECT_OBJECT,
279                   G_TYPE_NONE, 2,
280                   GTK_TYPE_ACTION, GTK_TYPE_WIDGET);
281
282   /**
283    * GtkActionGroup::disconnect-proxy:
284    * @action_group: the group
285    * @action: the action
286    * @proxy: the proxy
287    *
288    * The ::disconnect-proxy signal is emitted after disconnecting a proxy 
289    * from an action in the group. 
290    *
291    * #GtkUIManager proxies the signal and provides global notification 
292    * just before any action is connected to a proxy, which is probably more
293    * convenient to use.
294    *
295    * Since: 2.4
296    */
297   action_group_signals[DISCONNECT_PROXY] =
298     g_signal_new (I_("disconnect-proxy"),
299                   G_OBJECT_CLASS_TYPE (klass),
300                   0, 0, NULL, NULL,
301                   _gtk_marshal_VOID__OBJECT_OBJECT,
302                   G_TYPE_NONE, 2, 
303                   GTK_TYPE_ACTION, GTK_TYPE_WIDGET);
304
305   /**
306    * GtkActionGroup::pre-activate:
307    * @action_group: the group
308    * @action: the action
309    *
310    * The ::pre-activate signal is emitted just before the @action in the
311    * @action_group is activated
312    *
313    * This is intended for #GtkUIManager to proxy the signal and provide global
314    * notification just before any action is activated.
315    *
316    * Since: 2.4
317    */
318   action_group_signals[PRE_ACTIVATE] =
319     g_signal_new (I_("pre-activate"),
320                   G_OBJECT_CLASS_TYPE (klass),
321                   0, 0, NULL, NULL,
322                   _gtk_marshal_VOID__OBJECT,
323                   G_TYPE_NONE, 1, 
324                   GTK_TYPE_ACTION);
325
326   /**
327    * GtkActionGroup::post-activate:
328    * @action_group: the group
329    * @action: the action
330    *
331    * The ::post-activate signal is emitted just after the @action in the
332    * @action_group is activated
333    *
334    * This is intended for #GtkUIManager to proxy the signal and provide global
335    * notification just after any action is activated.
336    *
337    * Since: 2.4
338    */
339   action_group_signals[POST_ACTIVATE] =
340     g_signal_new (I_("post-activate"),
341                   G_OBJECT_CLASS_TYPE (klass),
342                   0, 0, NULL, NULL,
343                   _gtk_marshal_VOID__OBJECT,
344                   G_TYPE_NONE, 1, 
345                   GTK_TYPE_ACTION);
346
347   g_type_class_add_private (gobject_class, sizeof (GtkActionGroupPrivate));
348 }
349
350
351 static void 
352 remove_action (GtkAction *action) 
353 {
354   g_object_set (action, I_("action-group"), NULL, NULL);
355   g_object_unref (action);
356 }
357
358 static void
359 gtk_action_group_init (GtkActionGroup *action_group)
360 {
361   GtkActionGroupPrivate *private;
362
363   action_group->priv = G_TYPE_INSTANCE_GET_PRIVATE (action_group,
364                                                     GTK_TYPE_ACTION_GROUP,
365                                                     GtkActionGroupPrivate);
366   private = action_group->priv;
367
368   private->name = NULL;
369   private->sensitive = TRUE;
370   private->visible = TRUE;
371   private->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
372                                             NULL,
373                                             (GDestroyNotify) remove_action);
374   private->translate_func = NULL;
375   private->translate_data = NULL;
376   private->translate_notify = NULL;
377 }
378
379 static void
380 gtk_action_group_buildable_init (GtkBuildableIface *iface)
381 {
382   iface->add_child = gtk_action_group_buildable_add_child;
383   iface->set_name = gtk_action_group_buildable_set_name;
384   iface->get_name = gtk_action_group_buildable_get_name;
385   iface->custom_tag_start = gtk_action_group_buildable_custom_tag_start;
386   iface->custom_tag_end = gtk_action_group_buildable_custom_tag_end;
387 }
388
389 static void
390 gtk_action_group_buildable_add_child (GtkBuildable  *buildable,
391                                       GtkBuilder    *builder,
392                                       GObject       *child,
393                                       const gchar   *type)
394 {
395   gtk_action_group_add_action_with_accel (GTK_ACTION_GROUP (buildable),
396                                           GTK_ACTION (child), NULL);
397 }
398
399 static void
400 gtk_action_group_buildable_set_name (GtkBuildable *buildable,
401                                      const gchar  *name)
402 {
403   GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
404   GtkActionGroupPrivate *private = self->priv;
405
406   private->name = g_strdup (name);
407 }
408
409 static const gchar *
410 gtk_action_group_buildable_get_name (GtkBuildable *buildable)
411 {
412   GtkActionGroup *self = GTK_ACTION_GROUP (buildable);
413   GtkActionGroupPrivate *private = self->priv;
414
415   return private->name;
416 }
417
418 typedef struct {
419   GObject         *child;
420   guint            key;
421   GdkModifierType  modifiers;
422 } AcceleratorParserData;
423
424 static void
425 accelerator_start_element (GMarkupParseContext *context,
426                            const gchar         *element_name,
427                            const gchar        **names,
428                            const gchar        **values,
429                            gpointer             user_data,
430                            GError             **error)
431 {
432   gint i;
433   guint key = 0;
434   GdkModifierType modifiers = 0;
435   AcceleratorParserData *parser_data = (AcceleratorParserData*)user_data;
436
437   if (strcmp (element_name, "accelerator") != 0)
438     g_warning ("Unknown <accelerator> tag: %s", element_name);
439
440   for (i = 0; names[i]; i++)
441     {
442       if (strcmp (names[i], "key") == 0)
443         key = gdk_keyval_from_name (values[i]);
444       else if (strcmp (names[i], "modifiers") == 0)
445         {
446           if (!_gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE,
447                                                values[i],
448                                                &modifiers,
449                                                error))
450               return;
451         }
452     }
453
454   if (key == 0)
455     {
456       g_warning ("<accelerator> requires a key attribute");
457       return;
458     }
459   parser_data->key = key;
460   parser_data->modifiers = modifiers;
461 }
462
463 static const GMarkupParser accelerator_parser =
464   {
465     accelerator_start_element
466   };
467
468 static gboolean
469 gtk_action_group_buildable_custom_tag_start (GtkBuildable     *buildable,
470                                              GtkBuilder       *builder,
471                                              GObject          *child,
472                                              const gchar      *tagname,
473                                              GMarkupParser    *parser,
474                                              gpointer         *user_data)
475 {
476   AcceleratorParserData *parser_data;
477
478   if (child && strcmp (tagname, "accelerator") == 0)
479     {
480       parser_data = g_slice_new0 (AcceleratorParserData);
481       parser_data->child = child;
482       *user_data = parser_data;
483       *parser = accelerator_parser;
484
485       return TRUE;
486     }
487   return FALSE;
488 }
489
490 static void
491 gtk_action_group_buildable_custom_tag_end (GtkBuildable *buildable,
492                                            GtkBuilder   *builder,
493                                            GObject      *child,
494                                            const gchar  *tagname,
495                                            gpointer     *user_data)
496 {
497   AcceleratorParserData *data;
498   
499   if (strcmp (tagname, "accelerator") == 0)
500     {
501       GtkActionGroup *action_group;
502       GtkActionGroupPrivate *private;
503       GtkAction *action;
504       gchar *accel_path;
505       
506       data = (AcceleratorParserData*)user_data;
507       action_group = GTK_ACTION_GROUP (buildable);
508       private = action_group->priv;
509       action = GTK_ACTION (child);
510         
511       accel_path = g_strconcat ("<Actions>/",
512                                 private->name, "/",
513                                 gtk_action_get_name (action), NULL);
514
515       if (gtk_accel_map_lookup_entry (accel_path, NULL))
516         gtk_accel_map_change_entry (accel_path, data->key, data->modifiers, TRUE);
517       else
518         gtk_accel_map_add_entry (accel_path, data->key, data->modifiers);
519
520       gtk_action_set_accel_path (action, accel_path);
521       
522       g_free (accel_path);
523       g_slice_free (AcceleratorParserData, data);
524     }
525 }
526
527 /**
528  * gtk_action_group_new:
529  * @name: the name of the action group.
530  *
531  * Creates a new #GtkActionGroup object. The name of the action group
532  * is used when associating <link linkend="Action-Accel">keybindings</link> 
533  * with the actions.
534  *
535  * Returns: the new #GtkActionGroup
536  *
537  * Since: 2.4
538  */
539 GtkActionGroup *
540 gtk_action_group_new (const gchar *name)
541 {
542   GtkActionGroup *self;
543   GtkActionGroupPrivate *private;
544
545   self = g_object_new (GTK_TYPE_ACTION_GROUP, NULL);
546   private = self->priv;
547   private->name = g_strdup (name);
548
549   return self;
550 }
551
552 static void
553 gtk_action_group_finalize (GObject *object)
554 {
555   GtkActionGroup *self;
556   GtkActionGroupPrivate *private;
557
558   self = GTK_ACTION_GROUP (object);
559   private = self->priv;
560
561   g_free (private->name);
562   private->name = NULL;
563
564   g_hash_table_destroy (private->actions);
565   private->actions = NULL;
566
567   g_clear_object (&private->accel_group);
568
569   if (private->translate_notify)
570     private->translate_notify (private->translate_data);
571
572   parent_class->finalize (object);
573 }
574
575 static void
576 gtk_action_group_set_property (GObject         *object,
577                                guint            prop_id,
578                                const GValue    *value,
579                                GParamSpec      *pspec)
580 {
581   GtkActionGroup *self;
582   GtkActionGroupPrivate *private;
583   gchar *tmp;
584   
585   self = GTK_ACTION_GROUP (object);
586   private = self->priv;
587
588   switch (prop_id)
589     {
590     case PROP_NAME:
591       tmp = private->name;
592       private->name = g_value_dup_string (value);
593       g_free (tmp);
594       break;
595     case PROP_SENSITIVE:
596       gtk_action_group_set_sensitive (self, g_value_get_boolean (value));
597       break;
598     case PROP_VISIBLE:
599       gtk_action_group_set_visible (self, g_value_get_boolean (value));
600       break;
601     case PROP_ACCEL_GROUP:
602       gtk_action_group_set_accel_group (self, g_value_get_object (value));
603       break;
604     default:
605       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
606       break;
607     }
608 }
609
610 static void
611 gtk_action_group_get_property (GObject    *object,
612                                guint       prop_id,
613                                GValue     *value,
614                                GParamSpec *pspec)
615 {
616   GtkActionGroup *self;
617   GtkActionGroupPrivate *private;
618   
619   self = GTK_ACTION_GROUP (object);
620   private = self->priv;
621
622   switch (prop_id)
623     {
624     case PROP_NAME:
625       g_value_set_string (value, private->name);
626       break;
627     case PROP_SENSITIVE:
628       g_value_set_boolean (value, private->sensitive);
629       break;
630     case PROP_VISIBLE:
631       g_value_set_boolean (value, private->visible);
632       break;
633     case PROP_ACCEL_GROUP:
634       g_value_set_object (value, private->accel_group);
635       break;
636     default:
637       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
638       break;
639     }
640 }
641
642 static GtkAction *
643 gtk_action_group_real_get_action (GtkActionGroup *self,
644                                   const gchar    *action_name)
645 {
646   GtkActionGroupPrivate *private;
647
648   private = self->priv;
649
650   return g_hash_table_lookup (private->actions, action_name);
651 }
652
653 /**
654  * gtk_action_group_get_name:
655  * @action_group: the action group
656  *
657  * Gets the name of the action group.
658  *
659  * Returns: the name of the action group.
660  * 
661  * Since: 2.4
662  */
663 const gchar *
664 gtk_action_group_get_name (GtkActionGroup *action_group)
665 {
666   GtkActionGroupPrivate *private;
667
668   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
669
670   private = action_group->priv;
671
672   return private->name;
673 }
674
675 /**
676  * gtk_action_group_get_sensitive:
677  * @action_group: the action group
678  *
679  * Returns %TRUE if the group is sensitive.  The constituent actions
680  * can only be logically sensitive (see gtk_action_is_sensitive()) if
681  * they are sensitive (see gtk_action_get_sensitive()) and their group
682  * is sensitive.
683  * 
684  * Return value: %TRUE if the group is sensitive.
685  *
686  * Since: 2.4
687  */
688 gboolean
689 gtk_action_group_get_sensitive (GtkActionGroup *action_group)
690 {
691   GtkActionGroupPrivate *private;
692
693   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), FALSE);
694
695   private = action_group->priv;
696
697   return private->sensitive;
698 }
699
700 static void
701 cb_set_action_sensitivity (const gchar *name, 
702                            GtkAction   *action)
703 {
704   /* Minor optimization, the action_groups state only affects actions 
705    * that are themselves sensitive */
706   g_object_notify (G_OBJECT (action), "sensitive");
707
708 }
709
710 /**
711  * gtk_action_group_set_sensitive:
712  * @action_group: the action group
713  * @sensitive: new sensitivity
714  *
715  * Changes the sensitivity of @action_group
716  * 
717  * Since: 2.4
718  */
719 void
720 gtk_action_group_set_sensitive (GtkActionGroup *action_group, 
721                                 gboolean        sensitive)
722 {
723   GtkActionGroupPrivate *private;
724
725   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
726
727   private = action_group->priv;
728   sensitive = sensitive != FALSE;
729
730   if (private->sensitive != sensitive)
731     {
732       private->sensitive = sensitive;
733       g_hash_table_foreach (private->actions, 
734                             (GHFunc) cb_set_action_sensitivity, NULL);
735
736       g_object_notify (G_OBJECT (action_group), "sensitive");
737     }
738 }
739
740 /**
741  * gtk_action_group_get_visible:
742  * @action_group: the action group
743  *
744  * Returns %TRUE if the group is visible.  The constituent actions
745  * can only be logically visible (see gtk_action_is_visible()) if
746  * they are visible (see gtk_action_get_visible()) and their group
747  * is visible.
748  * 
749  * Return value: %TRUE if the group is visible.
750  * 
751  * Since: 2.4
752  */
753 gboolean
754 gtk_action_group_get_visible (GtkActionGroup *action_group)
755 {
756   GtkActionGroupPrivate *private;
757
758   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), FALSE);
759
760   private = action_group->priv;
761
762   return private->visible;
763 }
764
765 /**
766  * gtk_action_group_get_accel_group:
767  * @action_group: a #GtkActionGroup
768  *
769  * Gets the accelerator group.
770  * 
771  * Returns: (transfer none): the accelerator group associated with this action
772  * group or %NULL if there is none.
773  *
774  * Since: 3.6
775  */
776 GtkAccelGroup *
777 gtk_action_group_get_accel_group (GtkActionGroup *action_group)
778 {
779   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), FALSE);
780
781   return action_group->priv->accel_group;
782 }
783
784 static void
785 cb_set_action_visiblity (const gchar *name, 
786                          GtkAction   *action)
787 {
788   /* Minor optimization, the action_groups state only affects actions 
789    * that are themselves visible */
790   g_object_notify (G_OBJECT (action), "visible");
791 }
792
793 /**
794  * gtk_action_group_set_visible:
795  * @action_group: the action group
796  * @visible: new visiblity
797  *
798  * Changes the visible of @action_group.
799  * 
800  * Since: 2.4
801  */
802 void
803 gtk_action_group_set_visible (GtkActionGroup *action_group, 
804                               gboolean        visible)
805 {
806   GtkActionGroupPrivate *private;
807
808   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
809
810   private = action_group->priv;
811   visible = visible != FALSE;
812
813   if (private->visible != visible)
814     {
815       private->visible = visible;
816       g_hash_table_foreach (private->actions, 
817                             (GHFunc) cb_set_action_visiblity, NULL);
818
819       g_object_notify (G_OBJECT (action_group), "visible");
820     }
821 }
822
823 static void 
824 gtk_action_group_accel_group_foreach (gpointer key, gpointer val, gpointer data)
825 {
826   gtk_action_set_accel_group (val, data);
827 }
828
829 /**
830  * gtk_action_group_set_accel_group:
831  * @action_group: a #GtkActionGroup
832  * @accel_group: (allow-none): a #GtkAccelGroup to set or %NULL
833  *
834  * Sets the accelerator group to be used by every action in this group.
835  * 
836  * Since: 3.6
837  */
838 void
839 gtk_action_group_set_accel_group (GtkActionGroup *action_group,
840                                   GtkAccelGroup  *accel_group)
841 {
842   GtkActionGroupPrivate *private;
843
844   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
845
846   private = action_group->priv;
847
848   if (private->accel_group == accel_group)
849     return;
850
851   g_clear_object (&private->accel_group);
852
853   if (accel_group)
854     private->accel_group = g_object_ref (accel_group);
855
856   /* Set the new accel group on every action */
857   g_hash_table_foreach (private->actions,
858                         gtk_action_group_accel_group_foreach,
859                         accel_group);
860
861   g_object_notify (G_OBJECT (action_group), "accel-group");
862 }
863
864 /**
865  * gtk_action_group_get_action:
866  * @action_group: the action group
867  * @action_name: the name of the action
868  *
869  * Looks up an action in the action group by name.
870  *
871  * Returns: (transfer none): the action, or %NULL if no action by that name exists
872  *
873  * Since: 2.4
874  */
875 GtkAction *
876 gtk_action_group_get_action (GtkActionGroup *action_group,
877                              const gchar    *action_name)
878 {
879   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
880   g_return_val_if_fail (GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action != NULL, NULL);
881
882   return GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action (action_group,
883                                                                 action_name);
884 }
885
886 static gboolean
887 check_unique_action (GtkActionGroup *action_group,
888                      const gchar    *action_name)
889 {
890   if (gtk_action_group_get_action (action_group, action_name) != NULL)
891     {
892       GtkActionGroupPrivate *private;
893
894       private = action_group->priv;
895
896       g_warning ("Refusing to add non-unique action '%s' to action group '%s'",
897                  action_name,
898                  private->name);
899       return FALSE;
900     }
901
902   return TRUE;
903 }
904
905 /**
906  * gtk_action_group_add_action:
907  * @action_group: the action group
908  * @action: an action
909  *
910  * Adds an action object to the action group. Note that this function
911  * does not set up the accel path of the action, which can lead to problems
912  * if a user tries to modify the accelerator of a menuitem associated with
913  * the action. Therefore you must either set the accel path yourself with
914  * gtk_action_set_accel_path(), or use 
915  * <literal>gtk_action_group_add_action_with_accel (..., NULL)</literal>.
916  *
917  * Since: 2.4
918  */
919 void
920 gtk_action_group_add_action (GtkActionGroup *action_group,
921                              GtkAction      *action)
922 {
923   GtkActionGroupPrivate *private;
924   const gchar *name;
925
926   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
927   g_return_if_fail (GTK_IS_ACTION (action));
928
929   name = gtk_action_get_name (action);
930   g_return_if_fail (name != NULL);
931   
932   if (!check_unique_action (action_group, name))
933     return;
934
935   private = action_group->priv;
936
937   g_hash_table_insert (private->actions, 
938                        (gpointer) name,
939                        g_object_ref (action));
940   g_object_set (action, I_("action-group"), action_group, NULL);
941   
942   if (private->accel_group)
943     gtk_action_set_accel_group (action, private->accel_group);
944 }
945
946 /**
947  * gtk_action_group_add_action_with_accel:
948  * @action_group: the action group
949  * @action: the action to add
950  * @accelerator: (allow-none): the accelerator for the action, in
951  *   the format understood by gtk_accelerator_parse(), or "" for no accelerator, or
952  *   %NULL to use the stock accelerator
953  *
954  * Adds an action object to the action group and sets up the accelerator.
955  *
956  * If @accelerator is %NULL, attempts to use the accelerator associated 
957  * with the stock_id of the action. 
958  *
959  * Accel paths are set to
960  * <literal>&lt;Actions&gt;/<replaceable>group-name</replaceable>/<replaceable>action-name</replaceable></literal>.
961  *
962  * Since: 2.4
963  */
964 void
965 gtk_action_group_add_action_with_accel (GtkActionGroup *action_group,
966                                         GtkAction      *action,
967                                         const gchar    *accelerator)
968 {
969   GtkActionGroupPrivate *private;
970   gchar *accel_path;
971   guint  accel_key = 0;
972   GdkModifierType accel_mods;
973   const gchar *name;
974
975   name = gtk_action_get_name (action);
976   if (!check_unique_action (action_group, name))
977     return;
978
979   private = action_group->priv;
980   accel_path = g_strconcat ("<Actions>/",
981                             private->name, "/", name, NULL);
982
983   if (accelerator)
984     {
985       if (accelerator[0] == 0) 
986         accel_key = 0;
987       else
988         {
989           gtk_accelerator_parse (accelerator, &accel_key, &accel_mods);
990           if (accel_key == 0)
991             g_warning ("Unable to parse accelerator '%s' for action '%s'",
992                        accelerator, name);
993         }
994     }
995   else 
996     {
997       gchar *stock_id;
998       GtkStockItem stock_item;
999
1000       g_object_get (action, "stock-id", &stock_id, NULL);
1001
1002       if (stock_id && gtk_stock_lookup (stock_id, &stock_item))
1003         {
1004           accel_key = stock_item.keyval;
1005           accel_mods = stock_item.modifier;
1006         }
1007
1008       g_free (stock_id);
1009     }
1010
1011   if (accel_key)
1012     gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
1013
1014   gtk_action_set_accel_path (action, accel_path);
1015   gtk_action_group_add_action (action_group, action);
1016
1017   g_free (accel_path);
1018 }
1019
1020 /**
1021  * gtk_action_group_remove_action:
1022  * @action_group: the action group
1023  * @action: an action
1024  *
1025  * Removes an action object from the action group.
1026  *
1027  * Since: 2.4
1028  */
1029 void
1030 gtk_action_group_remove_action (GtkActionGroup *action_group,
1031                                 GtkAction      *action)
1032 {
1033   GtkActionGroupPrivate *private;
1034   const gchar *name;
1035
1036   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1037   g_return_if_fail (GTK_IS_ACTION (action));
1038
1039   name = gtk_action_get_name (action);
1040   g_return_if_fail (name != NULL);
1041
1042   private = action_group->priv;
1043
1044   g_hash_table_remove (private->actions, name);
1045 }
1046
1047 static void
1048 add_single_action (gpointer key, 
1049                    gpointer value, 
1050                    gpointer user_data)
1051 {
1052   GList **list = user_data;
1053
1054   *list = g_list_prepend (*list, value);
1055 }
1056
1057 /**
1058  * gtk_action_group_list_actions:
1059  * @action_group: the action group
1060  *
1061  * Lists the actions in the action group.
1062  *
1063  * Returns: (element-type GtkAction) (transfer container): an allocated list of the action objects in the action group
1064  *
1065  * Since: 2.4
1066  */
1067 GList *
1068 gtk_action_group_list_actions (GtkActionGroup *action_group)
1069 {
1070   GtkActionGroupPrivate *private;
1071   GList *actions = NULL;
1072
1073   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
1074
1075   private = action_group->priv;
1076   
1077   g_hash_table_foreach (private->actions, add_single_action, &actions);
1078
1079   return g_list_reverse (actions);
1080 }
1081
1082
1083 /**
1084  * gtk_action_group_add_actions: (skip)
1085  * @action_group: the action group
1086  * @entries: (array length=n_entries): an array of action descriptions
1087  * @n_entries: the number of entries
1088  * @user_data: data to pass to the action callbacks
1089  *
1090  * This is a convenience function to create a number of actions and add them 
1091  * to the action group.
1092  *
1093  * The "activate" signals of the actions are connected to the callbacks and 
1094  * their accel paths are set to 
1095  * <literal>&lt;Actions&gt;/<replaceable>group-name</replaceable>/<replaceable>action-name</replaceable></literal>.  
1096  * 
1097  * Since: 2.4
1098  */
1099 void
1100 gtk_action_group_add_actions (GtkActionGroup       *action_group,
1101                               const GtkActionEntry *entries,
1102                               guint                 n_entries,
1103                               gpointer              user_data)
1104 {
1105   gtk_action_group_add_actions_full (action_group, 
1106                                      entries, n_entries, 
1107                                      user_data, NULL);
1108 }
1109
1110 typedef struct _SharedData  SharedData;
1111
1112 struct _SharedData {
1113   guint          ref_count;
1114   gpointer       data;
1115   GDestroyNotify destroy;
1116 };
1117
1118 static void
1119 shared_data_unref (gpointer data)
1120 {
1121   SharedData *shared_data = (SharedData *)data;
1122
1123   shared_data->ref_count--;
1124   if (shared_data->ref_count == 0)
1125     {
1126       if (shared_data->destroy)
1127         shared_data->destroy (shared_data->data);
1128
1129       g_slice_free (SharedData, shared_data);
1130     }
1131 }
1132
1133
1134 /**
1135  * gtk_action_group_add_actions_full: (skip)
1136  * @action_group: the action group
1137  * @entries: (array length=n_entries): an array of action descriptions
1138  * @n_entries: the number of entries
1139  * @user_data: data to pass to the action callbacks
1140  * @destroy: destroy notification callback for @user_data
1141  *
1142  * This variant of gtk_action_group_add_actions() adds a #GDestroyNotify
1143  * callback for @user_data. 
1144  * 
1145  * Since: 2.4
1146  */
1147 void
1148 gtk_action_group_add_actions_full (GtkActionGroup       *action_group,
1149                                    const GtkActionEntry *entries,
1150                                    guint                 n_entries,
1151                                    gpointer              user_data,
1152                                    GDestroyNotify        destroy)
1153 {
1154
1155   /* Keep this in sync with the other 
1156    * gtk_action_group_add_..._actions_full() functions.
1157    */
1158   guint i;
1159   SharedData *shared_data;
1160
1161   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1162
1163   shared_data = g_slice_new0 (SharedData);
1164   shared_data->ref_count = 1;
1165   shared_data->data = user_data;
1166   shared_data->destroy = destroy;
1167
1168   for (i = 0; i < n_entries; i++)
1169     {
1170       GtkAction *action;
1171       const gchar *label;
1172       const gchar *tooltip;
1173
1174       if (!check_unique_action (action_group, entries[i].name))
1175         continue;
1176
1177       label = gtk_action_group_translate_string (action_group, entries[i].label);
1178       tooltip = gtk_action_group_translate_string (action_group, entries[i].tooltip);
1179
1180       action = gtk_action_new (entries[i].name,
1181                                label,
1182                                tooltip,
1183                                NULL);
1184
1185       if (entries[i].stock_id) 
1186         {
1187           g_object_set (action, "stock-id", entries[i].stock_id, NULL);
1188           if (gtk_icon_theme_has_icon (gtk_icon_theme_get_default (), 
1189                                        entries[i].stock_id))
1190             g_object_set (action, "icon-name", entries[i].stock_id, NULL);
1191         }
1192           
1193       if (entries[i].callback)
1194         {
1195           GClosure *closure;
1196
1197           closure = g_cclosure_new (entries[i].callback, user_data, NULL);
1198           g_closure_add_finalize_notifier (closure, shared_data, 
1199                                            (GClosureNotify)shared_data_unref);
1200           shared_data->ref_count++;
1201
1202           g_signal_connect_closure (action, "activate", closure, FALSE);
1203         }
1204           
1205       gtk_action_group_add_action_with_accel (action_group, 
1206                                               action,
1207                                               entries[i].accelerator);
1208       g_object_unref (action);
1209     }
1210
1211   shared_data_unref (shared_data);
1212 }
1213
1214 /**
1215  * gtk_action_group_add_toggle_actions: (skip)
1216  * @action_group: the action group
1217  * @entries: (array length=n_entries): an array of toggle action descriptions
1218  * @n_entries: the number of entries
1219  * @user_data: data to pass to the action callbacks
1220  *
1221  * This is a convenience function to create a number of toggle actions and add them 
1222  * to the action group.
1223  *
1224  * The "activate" signals of the actions are connected to the callbacks and 
1225  * their accel paths are set to 
1226  * <literal>&lt;Actions&gt;/<replaceable>group-name</replaceable>/<replaceable>action-name</replaceable></literal>.  
1227  * 
1228  * Since: 2.4
1229  */
1230 void
1231 gtk_action_group_add_toggle_actions (GtkActionGroup             *action_group,
1232                                      const GtkToggleActionEntry *entries,
1233                                      guint                       n_entries,
1234                                      gpointer                    user_data)
1235 {
1236   gtk_action_group_add_toggle_actions_full (action_group, 
1237                                             entries, n_entries, 
1238                                             user_data, NULL);
1239 }
1240
1241
1242 /**
1243  * gtk_action_group_add_toggle_actions_full: (skip)
1244  * @action_group: the action group
1245  * @entries: (array length=n_entries): an array of toggle action descriptions
1246  * @n_entries: the number of entries
1247  * @user_data: data to pass to the action callbacks
1248  * @destroy: destroy notification callback for @user_data
1249  *
1250  * This variant of gtk_action_group_add_toggle_actions() adds a 
1251  * #GDestroyNotify callback for @user_data. 
1252  * 
1253  * Since: 2.4
1254  */
1255 void
1256 gtk_action_group_add_toggle_actions_full (GtkActionGroup             *action_group,
1257                                           const GtkToggleActionEntry *entries,
1258                                           guint                       n_entries,
1259                                           gpointer                    user_data,
1260                                           GDestroyNotify              destroy)
1261 {
1262   /* Keep this in sync with the other 
1263    * gtk_action_group_add_..._actions_full() functions.
1264    */
1265   guint i;
1266   SharedData *shared_data;
1267
1268   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1269
1270   shared_data = g_slice_new0 (SharedData);
1271   shared_data->ref_count = 1;
1272   shared_data->data = user_data;
1273   shared_data->destroy = destroy;
1274
1275   for (i = 0; i < n_entries; i++)
1276     {
1277       GtkToggleAction *action;
1278       const gchar *label;
1279       const gchar *tooltip;
1280
1281       if (!check_unique_action (action_group, entries[i].name))
1282         continue;
1283
1284       label = gtk_action_group_translate_string (action_group, entries[i].label);
1285       tooltip = gtk_action_group_translate_string (action_group, entries[i].tooltip);
1286
1287       action = gtk_toggle_action_new (entries[i].name,
1288                                       label,
1289                                       tooltip,
1290                                       NULL);
1291
1292       if (entries[i].stock_id) 
1293         {
1294           if (gtk_icon_factory_lookup_default (entries[i].stock_id))
1295             g_object_set (action, "stock-id", entries[i].stock_id, NULL);
1296           else
1297             g_object_set (action, "icon-name", entries[i].stock_id, NULL);
1298         }
1299
1300       gtk_toggle_action_set_active (action, entries[i].is_active);
1301
1302       if (entries[i].callback)
1303         {
1304           GClosure *closure;
1305
1306           closure = g_cclosure_new (entries[i].callback, user_data, NULL);
1307           g_closure_add_finalize_notifier (closure, shared_data, 
1308                                            (GClosureNotify)shared_data_unref);
1309           shared_data->ref_count++;
1310
1311           g_signal_connect_closure (action, "activate", closure, FALSE);
1312         }
1313           
1314       gtk_action_group_add_action_with_accel (action_group, 
1315                                               GTK_ACTION (action),
1316                                               entries[i].accelerator);
1317       g_object_unref (action);
1318     }
1319
1320   shared_data_unref (shared_data);
1321 }
1322
1323 /**
1324  * gtk_action_group_add_radio_actions: (skip)
1325  * @action_group: the action group
1326  * @entries: (array length=n_entries): an array of radio action descriptions
1327  * @n_entries: the number of entries
1328  * @value: the value of the action to activate initially, or -1 if
1329  *   no action should be activated
1330  * @on_change: the callback to connect to the changed signal
1331  * @user_data: data to pass to the action callbacks
1332  * 
1333  * This is a convenience routine to create a group of radio actions and
1334  * add them to the action group. 
1335  *
1336  * The "changed" signal of the first radio action is connected to the 
1337  * @on_change callback and the accel paths of the actions are set to 
1338  * <literal>&lt;Actions&gt;/<replaceable>group-name</replaceable>/<replaceable>action-name</replaceable></literal>.  
1339  * 
1340  * Since: 2.4
1341  **/
1342 void            
1343 gtk_action_group_add_radio_actions (GtkActionGroup            *action_group,
1344                                     const GtkRadioActionEntry *entries,
1345                                     guint                      n_entries,
1346                                     gint                       value,
1347                                     GCallback                  on_change,
1348                                     gpointer                   user_data)
1349 {
1350   gtk_action_group_add_radio_actions_full (action_group, 
1351                                            entries, n_entries, 
1352                                            value,
1353                                            on_change, user_data, NULL);
1354 }
1355
1356 /**
1357  * gtk_action_group_add_radio_actions_full: (skip)
1358  * @action_group: the action group
1359  * @entries: (array length=n_entries): an array of radio action descriptions
1360  * @n_entries: the number of entries
1361  * @value: the value of the action to activate initially, or -1 if
1362  *   no action should be activated
1363  * @on_change: the callback to connect to the changed signal
1364  * @user_data: data to pass to the action callbacks
1365  * @destroy: destroy notification callback for @user_data
1366  *
1367  * This variant of gtk_action_group_add_radio_actions() adds a 
1368  * #GDestroyNotify callback for @user_data. 
1369  * 
1370  * Since: 2.4
1371  **/
1372 void            
1373 gtk_action_group_add_radio_actions_full (GtkActionGroup            *action_group,
1374                                          const GtkRadioActionEntry *entries,
1375                                          guint                      n_entries,
1376                                          gint                       value,
1377                                          GCallback                  on_change,
1378                                          gpointer                   user_data,
1379                                          GDestroyNotify             destroy)
1380 {
1381   /* Keep this in sync with the other 
1382    * gtk_action_group_add_..._actions_full() functions.
1383    */
1384   guint i;
1385   GSList *group = NULL;
1386   GtkRadioAction *first_action = NULL;
1387
1388   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1389
1390   for (i = 0; i < n_entries; i++)
1391     {
1392       GtkRadioAction *action;
1393       const gchar *label;
1394       const gchar *tooltip; 
1395
1396       if (!check_unique_action (action_group, entries[i].name))
1397         continue;
1398
1399       label = gtk_action_group_translate_string (action_group, entries[i].label);
1400       tooltip = gtk_action_group_translate_string (action_group, entries[i].tooltip);
1401
1402       action = gtk_radio_action_new (entries[i].name,
1403                                      label,
1404                                      tooltip,
1405                                      NULL,
1406                                      entries[i].value);
1407
1408       if (entries[i].stock_id) 
1409         {
1410           if (gtk_icon_factory_lookup_default (entries[i].stock_id))
1411             g_object_set (action, "stock-id", entries[i].stock_id, NULL);
1412           else
1413             g_object_set (action, "icon-name", entries[i].stock_id, NULL);
1414         }
1415
1416       if (i == 0) 
1417         first_action = action;
1418
1419       gtk_radio_action_set_group (action, group);
1420       group = gtk_radio_action_get_group (action);
1421
1422       if (value == entries[i].value)
1423         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
1424
1425       gtk_action_group_add_action_with_accel (action_group, 
1426                                               GTK_ACTION (action),
1427                                               entries[i].accelerator);
1428       g_object_unref (action);
1429     }
1430
1431   if (on_change && first_action)
1432     g_signal_connect_data (first_action, "changed",
1433                            on_change, user_data, 
1434                            (GClosureNotify)destroy, 0);
1435 }
1436
1437 /**
1438  * gtk_action_group_set_translate_func:
1439  * @action_group: a #GtkActionGroup
1440  * @func: a #GtkTranslateFunc
1441  * @data: data to be passed to @func and @notify
1442  * @notify: a #GDestroyNotify function to be called when @action_group is
1443  *   destroyed and when the translation function is changed again
1444  *
1445  * Sets a function to be used for translating the @label and @tooltip of 
1446  * #GtkActionEntry<!-- -->s added by gtk_action_group_add_actions().
1447  *
1448  * If you're using gettext(), it is enough to set the translation domain
1449  * with gtk_action_group_set_translation_domain().
1450  *
1451  * Since: 2.4 
1452  **/
1453 void
1454 gtk_action_group_set_translate_func (GtkActionGroup   *action_group,
1455                                      GtkTranslateFunc  func,
1456                                      gpointer          data,
1457                                      GDestroyNotify    notify)
1458 {
1459   GtkActionGroupPrivate *private;
1460
1461   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1462   
1463   private = action_group->priv;
1464
1465   if (private->translate_notify)
1466     private->translate_notify (private->translate_data);
1467       
1468   private->translate_func = func;
1469   private->translate_data = data;
1470   private->translate_notify = notify;
1471 }
1472
1473 static gchar *
1474 dgettext_swapped (const gchar *msgid, 
1475                   const gchar *domainname)
1476 {
1477   /* Pass through g_dgettext if and only if msgid is nonempty. */
1478   if (msgid && *msgid) 
1479     return (gchar*) g_dgettext (domainname, msgid); 
1480   else
1481     return (gchar*) msgid;
1482 }
1483
1484 /**
1485  * gtk_action_group_set_translation_domain:
1486  * @action_group: a #GtkActionGroup
1487  * @domain: (allow-none): the translation domain to use for g_dgettext()
1488  * calls, or %NULL to use the domain set with textdomain()
1489  * 
1490  * Sets the translation domain and uses g_dgettext() for translating the 
1491  * @label and @tooltip of #GtkActionEntry<!-- -->s added by 
1492  * gtk_action_group_add_actions().
1493  *
1494  * If you're not using gettext() for localization, see 
1495  * gtk_action_group_set_translate_func().
1496  *
1497  * Since: 2.4
1498  **/
1499 void 
1500 gtk_action_group_set_translation_domain (GtkActionGroup *action_group,
1501                                          const gchar    *domain)
1502 {
1503   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
1504
1505   gtk_action_group_set_translate_func (action_group, 
1506                                        (GtkTranslateFunc)dgettext_swapped,
1507                                        g_strdup (domain),
1508                                        g_free);
1509
1510
1511
1512 /**
1513  * gtk_action_group_translate_string:
1514  * @action_group: a #GtkActionGroup
1515  * @string: a string
1516  *
1517  * Translates a string using the function set with 
1518  * gtk_action_group_set_translate_func(). This
1519  * is mainly intended for language bindings.
1520  *
1521  * Returns: the translation of @string
1522  *
1523  * Since: 2.6
1524  **/
1525 const gchar *
1526 gtk_action_group_translate_string (GtkActionGroup *action_group,
1527                                    const gchar    *string)
1528 {
1529   GtkActionGroupPrivate *private;
1530   GtkTranslateFunc translate_func;
1531   gpointer translate_data;
1532   
1533   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), string);
1534   
1535   if (string == NULL)
1536     return NULL;
1537
1538   private = action_group->priv;
1539
1540   translate_func = private->translate_func;
1541   translate_data = private->translate_data;
1542   
1543   if (translate_func)
1544     return translate_func (string, translate_data);
1545   else
1546     return string;
1547 }
1548
1549 /* Protected for use by GtkAction */
1550 void
1551 _gtk_action_group_emit_connect_proxy  (GtkActionGroup *action_group,
1552                                        GtkAction      *action,
1553                                        GtkWidget      *proxy)
1554 {
1555   g_signal_emit (action_group, action_group_signals[CONNECT_PROXY], 0, 
1556                  action, proxy);
1557 }
1558
1559 void
1560 _gtk_action_group_emit_disconnect_proxy  (GtkActionGroup *action_group,
1561                                           GtkAction      *action,
1562                                           GtkWidget      *proxy)
1563 {
1564   g_signal_emit (action_group, action_group_signals[DISCONNECT_PROXY], 0, 
1565                  action, proxy);
1566 }
1567
1568 void
1569 _gtk_action_group_emit_pre_activate  (GtkActionGroup *action_group,
1570                                       GtkAction      *action)
1571 {
1572   g_signal_emit (action_group, action_group_signals[PRE_ACTIVATE], 0, action);
1573 }
1574
1575 void
1576 _gtk_action_group_emit_post_activate (GtkActionGroup *action_group,
1577                                       GtkAction      *action)
1578 {
1579   g_signal_emit (action_group, action_group_signals[POST_ACTIVATE], 0, action);
1580 }