]> Pileus Git - ~andy/gtk/blob - gtk/gtkactiongroup.c
Don't use first_action without initializing it if n_entries is 0.
[~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 #include <config.h>
32
33 #include "gtkactiongroup.h"
34 #include "gtktoggleaction.h"
35 #include "gtkradioaction.h"
36 #include "gtkaccelmap.h"
37 #include "gtkintl.h"
38
39 #define GTK_ACTION_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ACTION_GROUP, GtkActionGroupPrivate))
40
41 struct _GtkActionGroupPrivate 
42 {
43   gchar           *name;
44   GHashTable      *actions;
45
46   GtkTranslateFunc translate_func;
47   gpointer         translate_data;
48   GtkDestroyNotify translate_notify;   
49 };
50
51 enum 
52 {
53   PROP_0,
54   PROP_NAME
55 };
56
57 static void       gtk_action_group_init            (GtkActionGroup      *self);
58 static void       gtk_action_group_class_init      (GtkActionGroupClass *class);
59 static void       gtk_action_group_finalize        (GObject             *object);
60 static void       gtk_action_group_set_property    (GObject             *object,
61                                                     guint                prop_id,
62                                                     const GValue        *value,
63                                                     GParamSpec          *pspec);
64 static void       gtk_action_group_get_property    (GObject             *object,
65                                                     guint                prop_id,
66                                                     GValue              *value,
67                                                     GParamSpec          *pspec);
68 static GtkAction *gtk_action_group_real_get_action (GtkActionGroup      *self,
69                                                     const gchar         *name);
70
71
72 GType
73 gtk_action_group_get_type (void)
74 {
75   static GType type = 0;
76
77   if (!type)
78     {
79       static const GTypeInfo type_info =
80       {
81         sizeof (GtkActionGroupClass),
82         NULL,           /* base_init */
83         NULL,           /* base_finalize */
84         (GClassInitFunc) gtk_action_group_class_init,
85         NULL,           /* class_finalize */
86         NULL,           /* class_data */
87         sizeof (GtkActionGroup),
88         0, /* n_preallocs */
89         (GInstanceInitFunc) gtk_action_group_init,
90       };
91
92       type = g_type_register_static (G_TYPE_OBJECT, "GtkActionGroup",
93                                      &type_info, 0);
94     }
95
96   return type;
97 }
98
99 static GObjectClass *parent_class = NULL;
100
101 static void
102 gtk_action_group_class_init (GtkActionGroupClass *klass)
103 {
104   GObjectClass *gobject_class;
105
106   gobject_class = G_OBJECT_CLASS (klass);
107   parent_class = g_type_class_peek_parent (klass);
108
109   gobject_class->finalize = gtk_action_group_finalize;
110   gobject_class->set_property = gtk_action_group_set_property;
111   gobject_class->get_property = gtk_action_group_get_property;
112   klass->get_action = gtk_action_group_real_get_action;
113
114   g_object_class_install_property (gobject_class,
115                                    PROP_NAME,
116                                    g_param_spec_string ("name",
117                                                         _("Name"),
118                                                         _("A name for the action group."),
119                                                         NULL,
120                                                         G_PARAM_READWRITE |
121                                                         G_PARAM_CONSTRUCT_ONLY));
122   g_type_class_add_private (gobject_class, sizeof (GtkActionGroupPrivate));
123 }
124
125 static void
126 gtk_action_group_init (GtkActionGroup *self)
127 {
128   self->private_data = GTK_ACTION_GROUP_GET_PRIVATE (self);
129   self->private_data->name = NULL;
130   self->private_data->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
131                                                        (GDestroyNotify) g_free,
132                                                        (GDestroyNotify) g_object_unref);
133   self->private_data->translate_func = NULL;
134   self->private_data->translate_data = NULL;
135   self->private_data->translate_notify = NULL;
136 }
137
138 /**
139  * gtk_action_group_new:
140  * @name: the name of the action group.
141  *
142  * Creates a new #GtkActionGroup object. The name of the action group
143  * is used when associating <link linkend="Action-Accel">keybindings</link> 
144  * with the actions.
145  *
146  * Returns: the new #GtkActionGroup
147  *
148  * Since: 2.4
149  */
150 GtkActionGroup *
151 gtk_action_group_new (const gchar *name)
152 {
153   GtkActionGroup *self;
154
155   self = g_object_new (GTK_TYPE_ACTION_GROUP, NULL);
156   self->private_data->name = g_strdup (name);
157
158   return self;
159 }
160
161 static void
162 gtk_action_group_finalize (GObject *object)
163 {
164   GtkActionGroup *self;
165
166   self = GTK_ACTION_GROUP (object);
167
168   g_free (self->private_data->name);
169   self->private_data->name = NULL;
170
171   g_hash_table_destroy (self->private_data->actions);
172   self->private_data->actions = NULL;
173
174   if (self->private_data->translate_notify)
175     self->private_data->translate_notify (self->private_data->translate_data);
176
177   if (parent_class->finalize)
178     (* parent_class->finalize) (object);
179 }
180
181 static void
182 gtk_action_group_set_property (GObject         *object,
183                                guint            prop_id,
184                                const GValue    *value,
185                                GParamSpec      *pspec)
186 {
187   GtkActionGroup *self;
188   gchar *tmp;
189   
190   self = GTK_ACTION_GROUP (object);
191
192   switch (prop_id)
193     {
194     case PROP_NAME:
195       tmp = self->private_data->name;
196       self->private_data->name = g_value_dup_string (value);
197       g_free (tmp);
198       break;
199     default:
200       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
201       break;
202     }
203 }
204
205 static void
206 gtk_action_group_get_property (GObject    *object,
207                                guint       prop_id,
208                                GValue     *value,
209                                GParamSpec *pspec)
210 {
211   GtkActionGroup *self;
212   
213   self = GTK_ACTION_GROUP (object);
214
215   switch (prop_id)
216     {
217     case PROP_NAME:
218       g_value_set_string (value, self->private_data->name);
219       break;
220     default:
221       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
222       break;
223     }
224 }
225
226 static GtkAction *
227 gtk_action_group_real_get_action (GtkActionGroup *self,
228                                   const gchar    *action_name)
229 {
230   return g_hash_table_lookup (self->private_data->actions, action_name);
231 }
232
233 /**
234  * gtk_action_group_get_name:
235  * @action_group: the action group
236  *
237  * Gets the name of the action group.
238  *
239  * Returns: the name of the action group.
240  * 
241  * Since: 2.4
242  */
243 const gchar *
244 gtk_action_group_get_name (GtkActionGroup *action_group)
245 {
246   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
247
248   return action_group->private_data->name;
249 }
250
251 /**
252  * gtk_action_group_get_action:
253  * @action_group: the action group
254  * @action_name: the name of the action
255  *
256  * Looks up an action in the action group by name.
257  *
258  * Returns: the action, or %NULL if no action by that name exists
259  *
260  * Since: 2.4
261  */
262 GtkAction *
263 gtk_action_group_get_action (GtkActionGroup *action_group,
264                              const gchar    *action_name)
265 {
266   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
267   g_return_val_if_fail (GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action != NULL, NULL);
268
269   return (* GTK_ACTION_GROUP_GET_CLASS (action_group)->get_action)
270     (action_group, action_name);
271 }
272
273 /**
274  * gtk_action_group_add_action:
275  * @action_group: the action group
276  * @action: an action
277  *
278  * Adds an action object to the action group. 
279  *
280  * Since: 2.4
281  */
282 void
283 gtk_action_group_add_action (GtkActionGroup *action_group,
284                              GtkAction      *action)
285 {
286   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
287   g_return_if_fail (GTK_IS_ACTION (action));
288   g_return_if_fail (gtk_action_get_name (action) != NULL);
289
290   g_hash_table_insert (action_group->private_data->actions, 
291                        g_strdup (gtk_action_get_name (action)),
292                        g_object_ref (action));
293 }
294
295 /**
296  * gtk_action_group_remove_action:
297  * @action_group: the action group
298  * @action: an action
299  *
300  * Removes an action object from the action group.
301  *
302  * Since: 2.4
303  */
304 void
305 gtk_action_group_remove_action (GtkActionGroup *action_group,
306                                 GtkAction      *action)
307 {
308   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
309   g_return_if_fail (GTK_IS_ACTION (action));
310   g_return_if_fail (gtk_action_get_name (action) != NULL);
311
312   /* extra protection to make sure action->name is valid */
313   g_object_ref (action);
314   g_hash_table_remove (action_group->private_data->actions, gtk_action_get_name (action));
315   g_object_unref (action);
316 }
317
318 static void
319 add_single_action (gpointer key, 
320                    gpointer value, 
321                    gpointer user_data)
322 {
323   GList **list = user_data;
324
325   *list = g_list_prepend (*list, value);
326 }
327
328 /**
329  * gtk_action_group_list_actions:
330  * @action_group: the action group
331  *
332  * Lists the actions in the action group.
333  *
334  * Returns: an allocated list of the action objects in the action group
335  * 
336  * Since: 2.4
337  */
338 GList *
339 gtk_action_group_list_actions (GtkActionGroup *action_group)
340 {
341   GList *actions = NULL;
342   g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
343   
344   g_hash_table_foreach (action_group->private_data->actions, add_single_action, &actions);
345
346   return g_list_reverse (actions);
347 }
348
349
350 /**
351  * gtk_action_group_add_actions:
352  * @action_group: the action group
353  * @entries: an array of action descriptions
354  * @n_entries: the number of entries
355  * @user_data: data to pass to the action callbacks
356  *
357  * This is a convenience function to create a number of actions and add them 
358  * to the action group.
359  *
360  * The "activate" signals of the actions are connected to the callbacks and 
361  * their accel paths are set to 
362  * <literal>&lt;Actions&gt;/<replaceable>group-name</replaceable>/<replaceable>action-name</replaceable></literal>.  
363  * 
364  * Since: 2.4
365  */
366 void
367 gtk_action_group_add_actions (GtkActionGroup *action_group,
368                               GtkActionEntry *entries,
369                               guint           n_entries,
370                               gpointer        user_data)
371 {
372   gtk_action_group_add_actions_full (action_group, 
373                                      entries, n_entries, 
374                                      user_data, NULL);
375 }
376
377
378 /**
379  * gtk_action_group_add_actions_full:
380  * @action_group: the action group
381  * @entries: an array of action descriptions
382  * @n_entries: the number of entries
383  * @user_data: data to pass to the action callbacks
384  * @destroy: destroy notification callback for @user_data
385  *
386  * This variant of gtk_action_group_add_actions() adds a #GDestroyNotify
387  * callback for @user_data. 
388  * 
389  * Since: 2.4
390  */
391 void
392 gtk_action_group_add_actions_full (GtkActionGroup *action_group,
393                                    GtkActionEntry *entries,
394                                    guint           n_entries,
395                                    gpointer        user_data,
396                                    GDestroyNotify  destroy)
397 {
398   guint i;
399   GtkTranslateFunc translate_func;
400   gpointer translate_data;
401
402   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
403
404   translate_func = action_group->private_data->translate_func;
405   translate_data = action_group->private_data->translate_data;
406
407   for (i = 0; i < n_entries; i++)
408     {
409       GtkAction *action;
410       gchar *accel_path;
411       gchar *label;
412       gchar *tooltip;
413
414       if (translate_func)
415         {
416           label = translate_func (entries[i].label, translate_data);
417           tooltip = translate_func (entries[i].tooltip, translate_data);
418         }
419       else
420         {
421           label = entries[i].label;
422           tooltip = entries[i].tooltip;
423         }
424
425       action = g_object_new (GTK_TYPE_ACTION,
426                              "name", entries[i].name,
427                              "label", label,
428                              "tooltip", tooltip,
429                              "stock_id", entries[i].stock_id,
430                              NULL);
431
432       if (entries[i].callback)
433         g_signal_connect_data (action, "activate",
434                                entries[i].callback, 
435                                user_data, (GClosureNotify)destroy, 0);
436
437       /* set the accel path for the menu item */
438       accel_path = g_strconcat ("<Actions>/", action_group->private_data->name, "/",
439                                 entries[i].name, NULL);
440       if (entries[i].accelerator)
441         {
442           guint accel_key = 0;
443           GdkModifierType accel_mods;
444
445           gtk_accelerator_parse (entries[i].accelerator, &accel_key,
446                                  &accel_mods);
447           if (accel_key)
448             gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
449         }
450
451       gtk_action_set_accel_path (action, accel_path);
452       g_free (accel_path);
453
454       gtk_action_group_add_action (action_group, action);
455       g_object_unref (action);
456     }
457 }
458
459 /**
460  * gtk_action_group_add_toggle_actions:
461  * @action_group: the action group
462  * @entries: an array of toggle action descriptions
463  * @n_entries: the number of entries
464  * @user_data: data to pass to the action callbacks
465  *
466  * This is a convenience function to create a number of toggle actions and add them 
467  * to the action group.
468  *
469  * The "activate" signals of the actions are connected to the callbacks and 
470  * their accel paths are set to 
471  * <literal>&lt;Actions&gt;/<replaceable>group-name</replaceable>/<replaceable>action-name</replaceable></literal>.  
472  * 
473  * Since: 2.4
474  */
475 void
476 gtk_action_group_add_toggle_actions (GtkActionGroup       *action_group,
477                                      GtkToggleActionEntry *entries,
478                                      guint                 n_entries,
479                                      gpointer              user_data)
480 {
481   gtk_action_group_add_toggle_actions_full (action_group, 
482                                             entries, n_entries, 
483                                             user_data, NULL);
484 }
485
486
487 /**
488  * gtk_action_group_add_toggle_actions_full:
489  * @action_group: the action group
490  * @entries: an array of toggle action descriptions
491  * @n_entries: the number of entries
492  * @user_data: data to pass to the action callbacks
493  * @destroy: destroy notification callback for @user_data
494  *
495  * This variant of gtk_action_group_add_toggle_actions() adds a 
496  * #GDestroyNotify callback for @user_data. 
497  * 
498  * Since: 2.4
499  */
500 void
501 gtk_action_group_add_toggle_actions_full (GtkActionGroup       *action_group,
502                                           GtkToggleActionEntry *entries,
503                                           guint                 n_entries,
504                                           gpointer              user_data,
505                                           GDestroyNotify        destroy)
506 {
507   guint i;
508   GtkTranslateFunc translate_func;
509   gpointer translate_data;
510
511   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
512
513   translate_func = action_group->private_data->translate_func;
514   translate_data = action_group->private_data->translate_data;
515
516   for (i = 0; i < n_entries; i++)
517     {
518       GtkAction *action;
519       gchar *accel_path;
520       gchar *label;
521       gchar *tooltip;
522
523       if (translate_func)
524         {
525           label = translate_func (entries[i].label, translate_data);
526           tooltip = translate_func (entries[i].tooltip, translate_data);
527         }
528       else
529         {
530           label = entries[i].label;
531           tooltip = entries[i].tooltip;
532         }
533
534       action = g_object_new (GTK_TYPE_TOGGLE_ACTION,
535                              "name", entries[i].name,
536                              "label", label,
537                              "tooltip", tooltip,
538                              "stock_id", entries[i].stock_id,
539                              NULL);
540
541       gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), 
542                                     entries[i].is_active);
543
544       if (entries[i].callback)
545         g_signal_connect_data (action, "activate",
546                                entries[i].callback, 
547                                user_data, (GClosureNotify)destroy, 0);
548
549       /* set the accel path for the menu item */
550       accel_path = g_strconcat ("<Actions>/", action_group->private_data->name, "/",
551                                 entries[i].name, NULL);
552       if (entries[i].accelerator)
553         {
554           guint accel_key = 0;
555           GdkModifierType accel_mods;
556
557           gtk_accelerator_parse (entries[i].accelerator, &accel_key,
558                                  &accel_mods);
559           if (accel_key)
560             gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
561         }
562
563       gtk_action_set_accel_path (action, accel_path);
564       g_free (accel_path);
565
566       gtk_action_group_add_action (action_group, action);
567       g_object_unref (action);
568     }
569 }
570
571 /**
572  * gtk_action_group_add_radio_actions:
573  * @action_group: the action group
574  * @entries: an array of radio action descriptions
575  * @n_entries: the number of entries
576  * @value: the value of the action to activate initially, or -1 if
577  *   no action should be activated
578  * @on_change: the callback to connect to the changed signal
579  * @user_data: data to pass to the action callbacks
580  * 
581  * This is a convenience routine to create a group of radio actions and
582  * add them to the action group. 
583  *
584  * The "changed" signal of the first radio action is connected to the 
585  * @on_change callback and the accel paths of the actions are set to 
586  * <literal>&lt;Actions&gt;/<replaceable>group-name</replaceable>/<replaceable>action-name</replaceable></literal>.  
587  * 
588  * Since: 2.4
589  **/
590 void            
591 gtk_action_group_add_radio_actions (GtkActionGroup      *action_group,
592                                     GtkRadioActionEntry *entries,
593                                     guint                n_entries,
594                                     gint                 value,
595                                     GCallback            on_change,
596                                     gpointer             user_data)
597 {
598   gtk_action_group_add_radio_actions_full (action_group, 
599                                            entries, n_entries, 
600                                            value,
601                                            on_change, user_data, NULL);
602 }
603
604 /**
605  * gtk_action_group_add_radio_actions_full:
606  * @action_group: the action group
607  * @entries: an array of radio action descriptions
608  * @n_entries: the number of entries
609  * @value: the value of the action to activate initially, or -1 if
610  *   no action should be activated
611  * @on_change: the callback to connect to the changed signal
612  * @user_data: data to pass to the action callbacks
613  * @destroy: destroy notification callback for @user_data
614  *
615  * This variant of gtk_action_group_add_radio_actions() adds a 
616  * #GDestroyNotify callback for @user_data. 
617  * 
618  * Since: 2.4
619  **/
620 void            
621 gtk_action_group_add_radio_actions_full (GtkActionGroup      *action_group,
622                                          GtkRadioActionEntry *entries,
623                                          guint                n_entries,
624                                          gint                 value,
625                                          GCallback            on_change,
626                                          gpointer             user_data,
627                                          GDestroyNotify       destroy)
628 {
629   guint i;
630   GtkTranslateFunc translate_func;
631   gpointer translate_data;
632   GSList *group = NULL;
633   GtkAction *first_action = NULL;
634
635   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
636
637   translate_func = action_group->private_data->translate_func;
638   translate_data = action_group->private_data->translate_data;
639
640   for (i = 0; i < n_entries; i++)
641     {
642       GtkAction *action;
643       gchar *accel_path;
644       gchar *label;
645       gchar *tooltip; 
646
647       if (translate_func)
648         {
649           label = translate_func (entries[i].label, translate_data);
650           tooltip = translate_func (entries[i].tooltip, translate_data);
651         }
652       else
653         {
654           label = entries[i].label;
655           tooltip = entries[i].tooltip;
656         }
657
658       action = g_object_new (GTK_TYPE_RADIO_ACTION,
659                              "name", entries[i].name,
660                              "label", label,
661                              "tooltip", tooltip,
662                              "stock_id", entries[i].stock_id,
663                              "value", entries[i].value,
664                              NULL);
665
666       if (i == 0) 
667         first_action = action;
668
669       gtk_radio_action_set_group (GTK_RADIO_ACTION (action), group);
670       group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
671
672       if (value == entries[i].value)
673         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
674       
675       /* set the accel path for the menu item */
676       accel_path = g_strconcat ("<Actions>/", 
677                                 action_group->private_data->name, "/",
678                                 entries[i].name, NULL);
679       if (entries[i].accelerator)
680         {
681           guint accel_key = 0;
682           GdkModifierType accel_mods;
683
684           gtk_accelerator_parse (entries[i].accelerator, &accel_key,
685                                  &accel_mods);
686           if (accel_key)
687             gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
688         }
689
690       gtk_action_set_accel_path (action, accel_path);
691       g_free (accel_path);
692       
693       gtk_action_group_add_action (action_group, action);
694       g_object_unref (action);
695     }
696
697   if (on_change && first_action)
698     g_signal_connect_data (first_action, "changed",
699                            on_change, user_data, 
700                            (GClosureNotify)destroy, 0);
701 }
702
703 /**
704  * gtk_action_group_set_translate_func:
705  * @action_group: a #GtkActionGroup
706  * @func: a #GtkTranslateFunc
707  * @data: data to be passed to @func and @notify
708  * @notify: a #GtkDestroyNotify function to be called when @action_group is 
709  *   destroyed and when the translation function is changed again
710  * 
711  * Sets a function to be used for translating the @label and @tooltip of 
712  * #GtkActionGroupEntry<!-- -->s added by gtk_action_group_add_actions().
713  *
714  * If you're using gettext(), it is enough to set the translation domain
715  * with gtk_action_group_set_translation_domain().
716  *
717  * Since: 2.4 
718  **/
719 void
720 gtk_action_group_set_translate_func (GtkActionGroup      *action_group,
721                                      GtkTranslateFunc     func,
722                                      gpointer             data,
723                                      GtkDestroyNotify     notify)
724 {
725   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
726   
727   if (action_group->private_data->translate_notify)
728     action_group->private_data->translate_notify (action_group->private_data->translate_data);
729       
730   action_group->private_data->translate_func = func;
731   action_group->private_data->translate_data = data;
732   action_group->private_data->translate_notify = notify;
733 }
734
735 static gchar *
736 dgettext_swapped (const gchar *msgid, 
737                   const gchar *domainname)
738 {
739   return dgettext (domainname, msgid);
740 }
741
742 /**
743  * gtk_action_group_set_translation_domain:
744  * @action_group: a #GtkActionGroup
745  * @domain: the translation domain to use for dgettext() calls
746  * 
747  * Sets the translation domain and uses dgettext() for translating the 
748  * @label and @tooltip of #GtkActionEntry<!-- -->s added by 
749  * gtk_action_group_add_actions().
750  *
751  * If you're not using gettext() for localization, see 
752  * gtk_action_group_set_translate_func().
753  *
754  * Since: 2.4
755  **/
756 void 
757 gtk_action_group_set_translation_domain (GtkActionGroup *action_group,
758                                          const gchar    *domain)
759 {
760   g_return_if_fail (GTK_IS_ACTION_GROUP (action_group));
761
762   gtk_action_group_set_translate_func (action_group, 
763                                        (GtkTranslateFunc)dgettext_swapped,
764                                        g_strdup (domain),
765                                        g_free);
766