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