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