1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpactiongroup.c
5  * Copyright (C) 2004 Michael Natterer <mitch@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <gegl.h>
24 #include <gtk/gtk.h>
25 
26 #include "libgimpbase/gimpbase.h"
27 #include "libgimpwidgets/gimpwidgets.h"
28 
29 #include "widgets-types.h"
30 
31 #include "core/gimp.h"
32 #include "core/gimpcontext.h"
33 #include "core/gimpmarshal.h"
34 #include "core/gimpviewable.h"
35 
36 #include "gimpaction.h"
37 #include "gimpactiongroup.h"
38 #include "gimpactionimpl.h"
39 #include "gimpenumaction.h"
40 #include "gimpprocedureaction.h"
41 #include "gimpradioaction.h"
42 #include "gimpstringaction.h"
43 #include "gimptoggleaction.h"
44 
45 #include "gimp-intl.h"
46 
47 enum
48 {
49   ACTION_ADDED,
50   LAST_SIGNAL
51 };
52 
53 enum
54 {
55   PROP_0,
56   PROP_GIMP,
57   PROP_LABEL,
58   PROP_ICON_NAME
59 };
60 
61 
62 static void   gimp_action_group_constructed   (GObject      *object);
63 static void   gimp_action_group_dispose       (GObject      *object);
64 static void   gimp_action_group_finalize      (GObject      *object);
65 static void   gimp_action_group_set_property  (GObject      *object,
66                                                guint         prop_id,
67                                                const GValue *value,
68                                                GParamSpec   *pspec);
69 static void   gimp_action_group_get_property  (GObject      *object,
70                                                guint         prop_id,
71                                                GValue       *value,
72                                                GParamSpec   *pspec);
73 
74 
75 G_DEFINE_TYPE (GimpActionGroup, gimp_action_group, GTK_TYPE_ACTION_GROUP)
76 
77 static guint signals[LAST_SIGNAL] = { 0, };
78 
79 #define parent_class gimp_action_group_parent_class
80 
81 
82 static void
gimp_action_group_class_init(GimpActionGroupClass * klass)83 gimp_action_group_class_init (GimpActionGroupClass *klass)
84 {
85   GObjectClass *object_class = G_OBJECT_CLASS (klass);
86 
87   object_class->constructed  = gimp_action_group_constructed;
88   object_class->dispose      = gimp_action_group_dispose;
89   object_class->finalize     = gimp_action_group_finalize;
90   object_class->set_property = gimp_action_group_set_property;
91   object_class->get_property = gimp_action_group_get_property;
92 
93   g_object_class_install_property (object_class, PROP_GIMP,
94                                    g_param_spec_object ("gimp",
95                                                         NULL, NULL,
96                                                         GIMP_TYPE_GIMP,
97                                                         GIMP_PARAM_READWRITE |
98                                                         G_PARAM_CONSTRUCT_ONLY));
99 
100   g_object_class_install_property (object_class, PROP_LABEL,
101                                    g_param_spec_string ("label",
102                                                         NULL, NULL,
103                                                         NULL,
104                                                         GIMP_PARAM_READWRITE |
105                                                         G_PARAM_CONSTRUCT_ONLY));
106 
107   g_object_class_install_property (object_class, PROP_ICON_NAME,
108                                    g_param_spec_string ("icon-name",
109                                                         NULL, NULL,
110                                                         NULL,
111                                                         GIMP_PARAM_READWRITE |
112                                                         G_PARAM_CONSTRUCT_ONLY));
113 
114   klass->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
115 
116   signals[ACTION_ADDED] =
117     g_signal_new ("action-added",
118                   G_OBJECT_CLASS_TYPE (klass),
119                   G_SIGNAL_RUN_LAST,
120                   G_STRUCT_OFFSET (GimpActionGroupClass, action_added),
121                   NULL, NULL,
122                   gimp_marshal_VOID__OBJECT,
123                   G_TYPE_NONE, 1,
124                   GIMP_TYPE_ACTION);
125 }
126 
127 static void
gimp_action_group_init(GimpActionGroup * group)128 gimp_action_group_init (GimpActionGroup *group)
129 {
130 }
131 
132 static void
gimp_action_group_constructed(GObject * object)133 gimp_action_group_constructed (GObject *object)
134 {
135   GimpActionGroup *group = GIMP_ACTION_GROUP (object);
136   const gchar     *name;
137 
138   G_OBJECT_CLASS (parent_class)->constructed (object);
139 
140   gimp_assert (GIMP_IS_GIMP (group->gimp));
141 
142   name = gimp_action_group_get_name (group);
143 
144   if (name)
145     {
146       GimpActionGroupClass *group_class;
147       GList                *list;
148 
149       group_class = GIMP_ACTION_GROUP_GET_CLASS (object);
150 
151       list = g_hash_table_lookup (group_class->groups, name);
152 
153       list = g_list_append (list, object);
154 
155       g_hash_table_replace (group_class->groups,
156                             g_strdup (name), list);
157     }
158 }
159 
160 static void
gimp_action_group_dispose(GObject * object)161 gimp_action_group_dispose (GObject *object)
162 {
163   const gchar *name = gimp_action_group_get_name (GIMP_ACTION_GROUP (object));
164 
165   if (name)
166     {
167       GimpActionGroupClass *group_class;
168       GList                *list;
169 
170       group_class = GIMP_ACTION_GROUP_GET_CLASS (object);
171 
172       list = g_hash_table_lookup (group_class->groups, name);
173 
174       if (list)
175         {
176           list = g_list_remove (list, object);
177 
178           if (list)
179             g_hash_table_replace (group_class->groups,
180                                   g_strdup (name), list);
181           else
182             g_hash_table_remove (group_class->groups, name);
183         }
184     }
185 
186   G_OBJECT_CLASS (parent_class)->dispose (object);
187 }
188 
189 static void
gimp_action_group_finalize(GObject * object)190 gimp_action_group_finalize (GObject *object)
191 {
192   GimpActionGroup *group = GIMP_ACTION_GROUP (object);
193 
194   g_clear_pointer (&group->label,     g_free);
195   g_clear_pointer (&group->icon_name, g_free);
196 
197   G_OBJECT_CLASS (parent_class)->finalize (object);
198 }
199 
200 static void
gimp_action_group_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)201 gimp_action_group_set_property (GObject      *object,
202                                 guint         prop_id,
203                                 const GValue *value,
204                                 GParamSpec   *pspec)
205 {
206   GimpActionGroup *group = GIMP_ACTION_GROUP (object);
207 
208   switch (prop_id)
209     {
210     case PROP_GIMP:
211       group->gimp = g_value_get_object (value);
212       break;
213     case PROP_LABEL:
214       group->label = g_value_dup_string (value);
215       break;
216     case PROP_ICON_NAME:
217       group->icon_name = g_value_dup_string (value);
218       break;
219 
220     default:
221       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
222       break;
223     }
224 }
225 
226 static void
gimp_action_group_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)227 gimp_action_group_get_property (GObject    *object,
228                                 guint       prop_id,
229                                 GValue     *value,
230                                 GParamSpec *pspec)
231 {
232   GimpActionGroup *group = GIMP_ACTION_GROUP (object);
233 
234   switch (prop_id)
235     {
236     case PROP_GIMP:
237       g_value_set_object (value, group->gimp);
238       break;
239     case PROP_LABEL:
240       g_value_set_string (value, group->label);
241       break;
242     case PROP_ICON_NAME:
243       g_value_set_string (value, group->icon_name);
244       break;
245 
246     default:
247       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
248       break;
249     }
250 }
251 
252 static gboolean
gimp_action_group_check_unique_action(GimpActionGroup * group,const gchar * action_name)253 gimp_action_group_check_unique_action (GimpActionGroup *group,
254                                        const gchar     *action_name)
255 {
256   if (G_UNLIKELY (gimp_action_group_get_action (group, action_name)))
257     {
258       g_warning ("Refusing to add non-unique action '%s' to action group '%s'",
259                  action_name,
260                  gimp_action_group_get_name (group));
261       return FALSE;
262     }
263 
264   return TRUE;
265 
266 }
267 
268 /**
269  * gimp_action_group_new:
270  * @gimp:        the @Gimp instance this action group belongs to
271  * @name:        the name of the action group.
272  * @label:       the user visible label of the action group.
273  * @icon_name:   the icon of the action group.
274  * @user_data:   the user_data for #GtkAction callbacks.
275  * @update_func: the function that will be called on
276  *               gimp_action_group_update().
277  *
278  * Creates a new #GimpActionGroup object. The name of the action group
279  * is used when associating <link linkend="Action-Accel">keybindings</link>
280  * with the actions.
281  *
282  * Returns: the new #GimpActionGroup
283  */
284 GimpActionGroup *
gimp_action_group_new(Gimp * gimp,const gchar * name,const gchar * label,const gchar * icon_name,gpointer user_data,GimpActionGroupUpdateFunc update_func)285 gimp_action_group_new (Gimp                      *gimp,
286                        const gchar               *name,
287                        const gchar               *label,
288                        const gchar               *icon_name,
289                        gpointer                   user_data,
290                        GimpActionGroupUpdateFunc  update_func)
291 {
292   GimpActionGroup *group;
293 
294   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
295   g_return_val_if_fail (name != NULL, NULL);
296 
297   group = g_object_new (GIMP_TYPE_ACTION_GROUP,
298                         "gimp",      gimp,
299                         "name",      name,
300                         "label",     label,
301                         "icon-name", icon_name,
302                         NULL);
303 
304   group->user_data   = user_data;
305   group->update_func = update_func;
306 
307   return group;
308 }
309 
310 const gchar *
gimp_action_group_get_name(GimpActionGroup * group)311 gimp_action_group_get_name (GimpActionGroup *group)
312 {
313   return gtk_action_group_get_name ((GtkActionGroup *) group);
314 }
315 
316 void
gimp_action_group_add_action(GimpActionGroup * action_group,GimpAction * action)317 gimp_action_group_add_action (GimpActionGroup *action_group,
318                               GimpAction      *action)
319 {
320   gtk_action_group_add_action ((GtkActionGroup *) action_group,
321                                (GtkAction *) action);
322 }
323 
324 void
gimp_action_group_add_action_with_accel(GimpActionGroup * action_group,GimpAction * action,const gchar * accelerator)325 gimp_action_group_add_action_with_accel (GimpActionGroup *action_group,
326                                          GimpAction      *action,
327                                          const gchar     *accelerator)
328 {
329   gtk_action_group_add_action_with_accel ((GtkActionGroup *) action_group,
330                                           (GtkAction *) action,
331                                           accelerator);
332 }
333 
334 void
gimp_action_group_remove_action(GimpActionGroup * action_group,GimpAction * action)335 gimp_action_group_remove_action (GimpActionGroup *action_group,
336                                  GimpAction      *action)
337 {
338   gtk_action_group_remove_action ((GtkActionGroup *) action_group,
339                                   (GtkAction *) action);
340 }
341 
342 GimpAction *
gimp_action_group_get_action(GimpActionGroup * group,const gchar * action_name)343 gimp_action_group_get_action (GimpActionGroup *group,
344                               const gchar     *action_name)
345 {
346   return (GimpAction *) gtk_action_group_get_action ((GtkActionGroup *) group,
347                                                      action_name);
348 }
349 
350 GList *
gimp_action_group_list_actions(GimpActionGroup * group)351 gimp_action_group_list_actions (GimpActionGroup *group)
352 {
353   return gtk_action_group_list_actions ((GtkActionGroup *) group);
354 }
355 
356 GList *
gimp_action_groups_from_name(const gchar * name)357 gimp_action_groups_from_name (const gchar *name)
358 {
359   GimpActionGroupClass *group_class;
360   GList                *list;
361 
362   g_return_val_if_fail (name != NULL, NULL);
363 
364   group_class = g_type_class_ref (GIMP_TYPE_ACTION_GROUP);
365 
366   list = g_hash_table_lookup (group_class->groups, name);
367 
368   g_type_class_unref (group_class);
369 
370   return list;
371 }
372 
373 void
gimp_action_group_update(GimpActionGroup * group,gpointer update_data)374 gimp_action_group_update (GimpActionGroup *group,
375                           gpointer         update_data)
376 {
377   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
378 
379   if (group->update_func)
380     group->update_func (group, update_data);
381 }
382 
383 void
gimp_action_group_add_actions(GimpActionGroup * group,const gchar * msg_context,const GimpActionEntry * entries,guint n_entries)384 gimp_action_group_add_actions (GimpActionGroup       *group,
385                                const gchar           *msg_context,
386                                const GimpActionEntry *entries,
387                                guint                  n_entries)
388 {
389   gint i;
390 
391   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
392 
393   for (i = 0; i < n_entries; i++)
394     {
395       GimpAction  *action;
396       const gchar *label;
397       const gchar *tooltip = NULL;
398 
399       if (! gimp_action_group_check_unique_action (group, entries[i].name))
400         continue;
401 
402       if (msg_context)
403         {
404           label = g_dpgettext2 (NULL, msg_context, entries[i].label);
405 
406           if (entries[i].tooltip)
407             tooltip = g_dpgettext2 (NULL, msg_context, entries[i].tooltip);
408         }
409       else
410         {
411           label   = gettext (entries[i].label);
412           tooltip = gettext (entries[i].tooltip);
413         }
414 
415       action = gimp_action_impl_new (entries[i].name, label, tooltip,
416                                      entries[i].icon_name,
417                                      entries[i].help_id);
418 
419       if (entries[i].callback)
420         g_signal_connect (action, "gimp-activate",
421                           G_CALLBACK (entries[i].callback),
422                           group->user_data);
423 
424       gimp_action_group_add_action_with_accel (group, GIMP_ACTION (action),
425                                                entries[i].accelerator);
426       g_signal_emit (group, signals[ACTION_ADDED], 0, action);
427 
428       g_object_unref (action);
429     }
430 }
431 
432 void
gimp_action_group_add_toggle_actions(GimpActionGroup * group,const gchar * msg_context,const GimpToggleActionEntry * entries,guint n_entries)433 gimp_action_group_add_toggle_actions (GimpActionGroup             *group,
434                                       const gchar                 *msg_context,
435                                       const GimpToggleActionEntry *entries,
436                                       guint                        n_entries)
437 {
438   gint i;
439 
440   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
441 
442   for (i = 0; i < n_entries; i++)
443     {
444       GtkToggleAction *action;
445       const gchar     *label;
446       const gchar     *tooltip = NULL;
447 
448       if (! gimp_action_group_check_unique_action (group, entries[i].name))
449         continue;
450 
451       if (msg_context)
452         {
453           label = g_dpgettext2 (NULL, msg_context, entries[i].label);
454 
455           if (entries[i].tooltip)
456             tooltip = g_dpgettext2 (NULL, msg_context, entries[i].tooltip);
457         }
458       else
459         {
460           label   = gettext (entries[i].label);
461           tooltip = gettext (entries[i].tooltip);
462         }
463 
464       action = gimp_toggle_action_new (entries[i].name, label, tooltip,
465                                        entries[i].icon_name,
466                                        entries[i].help_id);
467 
468       gimp_toggle_action_set_active (GIMP_TOGGLE_ACTION (action),
469                                      entries[i].is_active);
470 
471       if (entries[i].callback)
472         g_signal_connect (action, "gimp-change-state",
473                           G_CALLBACK (entries[i].callback),
474                           group->user_data);
475 
476       gimp_action_group_add_action_with_accel (group, GIMP_ACTION (action),
477                                                entries[i].accelerator);
478       g_signal_emit (group, signals[ACTION_ADDED], 0, action);
479 
480       g_object_unref (action);
481     }
482 }
483 
484 GSList *
gimp_action_group_add_radio_actions(GimpActionGroup * group,const gchar * msg_context,const GimpRadioActionEntry * entries,guint n_entries,GSList * radio_group,gint value,GimpActionCallback callback)485 gimp_action_group_add_radio_actions (GimpActionGroup            *group,
486                                      const gchar                *msg_context,
487                                      const GimpRadioActionEntry *entries,
488                                      guint                       n_entries,
489                                      GSList                     *radio_group,
490                                      gint                        value,
491                                      GimpActionCallback          callback)
492 {
493   GtkRadioAction *first_action = NULL;
494   gint            i;
495 
496   g_return_val_if_fail (GIMP_IS_ACTION_GROUP (group), NULL);
497 
498   for (i = 0; i < n_entries; i++)
499     {
500       GtkRadioAction *action;
501       const gchar    *label;
502       const gchar    *tooltip = NULL;
503 
504       if (! gimp_action_group_check_unique_action (group, entries[i].name))
505         continue;
506 
507       if (msg_context)
508         {
509           label = g_dpgettext2 (NULL, msg_context, entries[i].label);
510 
511           if (entries[i].tooltip)
512             tooltip = g_dpgettext2 (NULL, msg_context, entries[i].tooltip);
513         }
514       else
515         {
516           label   = gettext (entries[i].label);
517           tooltip = gettext (entries[i].tooltip);
518         }
519 
520       action = gimp_radio_action_new (entries[i].name, label, tooltip,
521                                       entries[i].icon_name,
522                                       entries[i].help_id,
523                                       entries[i].value);
524 
525       if (i == 0)
526         first_action = action;
527 
528       gtk_radio_action_set_group (action, radio_group);
529       radio_group = gtk_radio_action_get_group (action);
530 
531       if (value == entries[i].value)
532         gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
533 
534       gimp_action_group_add_action_with_accel (group, GIMP_ACTION (action),
535                                                entries[i].accelerator);
536       g_signal_emit (group, signals[ACTION_ADDED], 0, action);
537 
538       g_object_unref (action);
539     }
540 
541   if (callback && first_action)
542     g_signal_connect (first_action, "gimp-change-state",
543                       G_CALLBACK (callback),
544                       group->user_data);
545 
546   return radio_group;
547 }
548 
549 void
gimp_action_group_add_enum_actions(GimpActionGroup * group,const gchar * msg_context,const GimpEnumActionEntry * entries,guint n_entries,GimpActionCallback callback)550 gimp_action_group_add_enum_actions (GimpActionGroup           *group,
551                                     const gchar               *msg_context,
552                                     const GimpEnumActionEntry *entries,
553                                     guint                      n_entries,
554                                     GimpActionCallback         callback)
555 {
556   gint i;
557 
558   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
559 
560   for (i = 0; i < n_entries; i++)
561     {
562       GimpEnumAction *action;
563       const gchar    *label;
564       const gchar    *tooltip = NULL;
565 
566       if (! gimp_action_group_check_unique_action (group, entries[i].name))
567         continue;
568 
569       if (msg_context)
570         {
571           label = g_dpgettext2 (NULL, msg_context, entries[i].label);
572 
573           if (entries[i].tooltip)
574             tooltip = g_dpgettext2 (NULL, msg_context, entries[i].tooltip);
575         }
576       else
577         {
578           label   = gettext (entries[i].label);
579           tooltip = gettext (entries[i].tooltip);
580         }
581 
582       action = gimp_enum_action_new (entries[i].name, label, tooltip,
583                                      entries[i].icon_name,
584                                      entries[i].help_id,
585                                      entries[i].value,
586                                      entries[i].value_variable);
587 
588       if (callback)
589         g_signal_connect (action, "gimp-activate",
590                           G_CALLBACK (callback),
591                           group->user_data);
592 
593       gimp_action_group_add_action_with_accel (group, GIMP_ACTION (action),
594                                                entries[i].accelerator);
595       g_signal_emit (group, signals[ACTION_ADDED], 0, action);
596 
597       g_object_unref (action);
598     }
599 }
600 
601 void
gimp_action_group_add_string_actions(GimpActionGroup * group,const gchar * msg_context,const GimpStringActionEntry * entries,guint n_entries,GimpActionCallback callback)602 gimp_action_group_add_string_actions (GimpActionGroup             *group,
603                                       const gchar                 *msg_context,
604                                       const GimpStringActionEntry *entries,
605                                       guint                        n_entries,
606                                       GimpActionCallback           callback)
607 {
608   gint i;
609 
610   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
611 
612   for (i = 0; i < n_entries; i++)
613     {
614       GimpStringAction *action;
615       const gchar      *label;
616       const gchar      *tooltip = NULL;
617 
618       if (! gimp_action_group_check_unique_action (group, entries[i].name))
619         continue;
620 
621       if (msg_context)
622         {
623           label = g_dpgettext2 (NULL, msg_context, entries[i].label);
624 
625           if (entries[i].tooltip)
626             tooltip = g_dpgettext2 (NULL, msg_context, entries[i].tooltip);
627         }
628       else
629         {
630           label   = gettext (entries[i].label);
631           tooltip = gettext (entries[i].tooltip);
632         }
633 
634       action = gimp_string_action_new (entries[i].name, label, tooltip,
635                                        entries[i].icon_name,
636                                        entries[i].help_id,
637                                        entries[i].value);
638 
639       if (callback)
640         g_signal_connect (action, "gimp-activate",
641                           G_CALLBACK (callback),
642                           group->user_data);
643 
644       gimp_action_group_add_action_with_accel (group, GIMP_ACTION (action),
645                                                entries[i].accelerator);
646       g_signal_emit (group, signals[ACTION_ADDED], 0, action);
647 
648       g_object_unref (action);
649     }
650 }
651 
652 void
gimp_action_group_add_procedure_actions(GimpActionGroup * group,const GimpProcedureActionEntry * entries,guint n_entries,GimpActionCallback callback)653 gimp_action_group_add_procedure_actions (GimpActionGroup                *group,
654                                          const GimpProcedureActionEntry *entries,
655                                          guint                           n_entries,
656                                          GimpActionCallback              callback)
657 {
658   gint i;
659 
660   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
661 
662   for (i = 0; i < n_entries; i++)
663     {
664       GimpProcedureAction *action;
665 
666       if (! gimp_action_group_check_unique_action (group, entries[i].name))
667         continue;
668 
669       action = gimp_procedure_action_new (entries[i].name,
670                                           entries[i].label,
671                                           entries[i].tooltip,
672                                           entries[i].icon_name,
673                                           entries[i].help_id,
674                                           entries[i].procedure);
675 
676       if (callback)
677         g_signal_connect (action, "gimp-activate",
678                           G_CALLBACK (callback),
679                           group->user_data);
680 
681       gimp_action_group_add_action_with_accel (group, GIMP_ACTION (action),
682                                                entries[i].accelerator);
683       g_signal_emit (group, signals[ACTION_ADDED], 0, action);
684 
685       g_object_unref (action);
686     }
687 }
688 
689 /**
690  * gimp_action_group_remove_action_and_accel:
691  * @group:  the #GimpActionGroup to which @action belongs.
692  * @action: the #GimpAction.
693  *
694  * This function removes @action from @group and clean any
695  * accelerator this action may have set.
696  * If you wish to only remove the action from the group, use
697  * gimp_action_group_remove_action() instead.
698  */
699 void
gimp_action_group_remove_action_and_accel(GimpActionGroup * group,GimpAction * action)700 gimp_action_group_remove_action_and_accel (GimpActionGroup *group,
701                                            GimpAction      *action)
702 {
703   const gchar *action_name;
704   const gchar *group_name;
705   gchar       *accel_path;
706 
707   action_name = gimp_action_get_name (action);
708   group_name  = gimp_action_group_get_name (group);
709   accel_path = g_strconcat ("<Actions>/", group_name, "/",
710                             action_name, NULL);
711 
712   gtk_accel_map_change_entry (accel_path, 0, 0, FALSE);
713 
714   gimp_action_group_remove_action (group, action);
715   g_free (accel_path);
716 }
717 
718 void
gimp_action_group_activate_action(GimpActionGroup * group,const gchar * action_name)719 gimp_action_group_activate_action (GimpActionGroup *group,
720                                    const gchar     *action_name)
721 {
722   GimpAction *action;
723 
724   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
725   g_return_if_fail (action_name != NULL);
726 
727   action = gimp_action_group_get_action (group, action_name);
728 
729   if (! action)
730     {
731       g_warning ("%s: Unable to activate action which doesn't exist: %s",
732                  G_STRFUNC, action_name);
733       return;
734     }
735 
736   gimp_action_activate (action);
737 }
738 
739 void
gimp_action_group_set_action_visible(GimpActionGroup * group,const gchar * action_name,gboolean visible)740 gimp_action_group_set_action_visible (GimpActionGroup *group,
741                                       const gchar     *action_name,
742                                       gboolean         visible)
743 {
744   GimpAction *action;
745 
746   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
747   g_return_if_fail (action_name != NULL);
748 
749   action = gimp_action_group_get_action (group, action_name);
750 
751   if (! action)
752     {
753       g_warning ("%s: Unable to set visibility of action "
754                  "which doesn't exist: %s",
755                  G_STRFUNC, action_name);
756       return;
757     }
758 
759   gimp_action_set_visible (action, visible);
760 }
761 
762 void
gimp_action_group_set_action_sensitive(GimpActionGroup * group,const gchar * action_name,gboolean sensitive)763 gimp_action_group_set_action_sensitive (GimpActionGroup *group,
764                                         const gchar     *action_name,
765                                         gboolean         sensitive)
766 {
767   GimpAction *action;
768 
769   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
770   g_return_if_fail (action_name != NULL);
771 
772   action = gimp_action_group_get_action (group, action_name);
773 
774   if (! action)
775     {
776       g_warning ("%s: Unable to set sensitivity of action "
777                  "which doesn't exist: %s",
778                  G_STRFUNC, action_name);
779       return;
780     }
781 
782   gimp_action_set_sensitive (action, sensitive);
783 }
784 
785 void
gimp_action_group_set_action_active(GimpActionGroup * group,const gchar * action_name,gboolean active)786 gimp_action_group_set_action_active (GimpActionGroup *group,
787                                      const gchar     *action_name,
788                                      gboolean         active)
789 {
790   GimpAction *action;
791 
792   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
793   g_return_if_fail (action_name != NULL);
794 
795   action = gimp_action_group_get_action (group, action_name);
796 
797   if (! action)
798     {
799       g_warning ("%s: Unable to set \"active\" of action "
800                  "which doesn't exist: %s",
801                  G_STRFUNC, action_name);
802       return;
803     }
804 
805   if (! GTK_IS_TOGGLE_ACTION (action))
806     {
807       g_warning ("%s: Unable to set \"active\" of action "
808                  "which is not a GtkToggleAction: %s",
809                  G_STRFUNC, action_name);
810       return;
811     }
812 
813   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action),
814                                 active ? TRUE : FALSE);
815 }
816 
817 void
gimp_action_group_set_action_label(GimpActionGroup * group,const gchar * action_name,const gchar * label)818 gimp_action_group_set_action_label (GimpActionGroup *group,
819                                     const gchar     *action_name,
820                                     const gchar     *label)
821 {
822   GimpAction *action;
823 
824   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
825   g_return_if_fail (action_name != NULL);
826 
827   action = gimp_action_group_get_action (group, action_name);
828 
829   if (! action)
830     {
831       g_warning ("%s: Unable to set label of action "
832                  "which doesn't exist: %s",
833                  G_STRFUNC, action_name);
834       return;
835     }
836 
837   gimp_action_set_label (action, label);
838 }
839 
840 void
gimp_action_group_set_action_pixbuf(GimpActionGroup * group,const gchar * action_name,GdkPixbuf * pixbuf)841 gimp_action_group_set_action_pixbuf (GimpActionGroup *group,
842                                      const gchar     *action_name,
843                                      GdkPixbuf       *pixbuf)
844 {
845   GimpAction *action;
846 
847   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
848   g_return_if_fail (action_name != NULL);
849 
850   action = gimp_action_group_get_action (group, action_name);
851 
852   if (! action)
853     {
854       g_warning ("%s: Unable to set pixbuf of action "
855                  "which doesn't exist: %s",
856                  G_STRFUNC, action_name);
857       return;
858     }
859 
860   gimp_action_set_gicon (action, G_ICON (pixbuf));
861 }
862 
863 
864 void
gimp_action_group_set_action_tooltip(GimpActionGroup * group,const gchar * action_name,const gchar * tooltip)865 gimp_action_group_set_action_tooltip (GimpActionGroup     *group,
866                                       const gchar         *action_name,
867                                       const gchar         *tooltip)
868 {
869   GimpAction *action;
870 
871   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
872   g_return_if_fail (action_name != NULL);
873 
874   action = gimp_action_group_get_action (group, action_name);
875 
876   if (! action)
877     {
878       g_warning ("%s: Unable to set tooltip of action "
879                  "which doesn't exist: %s",
880                  G_STRFUNC, action_name);
881       return;
882     }
883 
884   gimp_action_set_tooltip (action, tooltip);
885 }
886 
887 const gchar *
gimp_action_group_get_action_tooltip(GimpActionGroup * group,const gchar * action_name)888 gimp_action_group_get_action_tooltip (GimpActionGroup     *group,
889                                       const gchar         *action_name)
890 {
891   GimpAction *action;
892 
893   g_return_val_if_fail (GIMP_IS_ACTION_GROUP (group), NULL);
894   g_return_val_if_fail (action_name != NULL, NULL);
895 
896   action = gimp_action_group_get_action (group, action_name);
897 
898   if (! action)
899     {
900       g_warning ("%s: Unable to get tooltip of action "
901                  "which doesn't exist: %s",
902                  G_STRFUNC, action_name);
903       return NULL;
904     }
905 
906   return gimp_action_get_tooltip (action);
907 }
908 
909 void
gimp_action_group_set_action_context(GimpActionGroup * group,const gchar * action_name,GimpContext * context)910 gimp_action_group_set_action_context (GimpActionGroup *group,
911                                       const gchar     *action_name,
912                                       GimpContext     *context)
913 {
914   GimpAction *action;
915 
916   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
917   g_return_if_fail (action_name != NULL);
918   g_return_if_fail (context == NULL || GIMP_IS_CONTEXT (context));
919 
920   action = gimp_action_group_get_action (group, action_name);
921 
922   if (! action)
923     {
924       g_warning ("%s: Unable to set context of action "
925                  "which doesn't exist: %s",
926                  G_STRFUNC, action_name);
927       return;
928     }
929 
930   if (! GIMP_IS_ACTION (action))
931     {
932       g_warning ("%s: Unable to set \"context\" of action "
933                  "which is not a GimpAction: %s",
934                  G_STRFUNC, action_name);
935       return;
936     }
937 
938   g_object_set (action, "context", context, NULL);
939 }
940 
941 void
gimp_action_group_set_action_color(GimpActionGroup * group,const gchar * action_name,const GimpRGB * color,gboolean set_label)942 gimp_action_group_set_action_color (GimpActionGroup *group,
943                                     const gchar     *action_name,
944                                     const GimpRGB   *color,
945                                     gboolean         set_label)
946 {
947   GimpAction *action;
948 
949   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
950   g_return_if_fail (action_name != NULL);
951 
952   action = gimp_action_group_get_action (group, action_name);
953 
954   if (! action)
955     {
956       g_warning ("%s: Unable to set color of action "
957                  "which doesn't exist: %s",
958                  G_STRFUNC, action_name);
959       return;
960     }
961 
962   if (! GIMP_IS_ACTION (action))
963     {
964       g_warning ("%s: Unable to set \"color\" of action "
965                  "which is not a GimpAction: %s",
966                  G_STRFUNC, action_name);
967       return;
968     }
969 
970   if (set_label)
971     {
972       gchar *label;
973 
974       if (color)
975         label = g_strdup_printf (_("RGBA (%0.3f, %0.3f, %0.3f, %0.3f)"),
976                                  color->r, color->g, color->b, color->a);
977       else
978         label = g_strdup (_("(none)"));
979 
980       g_object_set (action,
981                     "color", color,
982                     "label", label,
983                     NULL);
984       g_free (label);
985     }
986   else
987     {
988       g_object_set (action, "color", color, NULL);
989     }
990 }
991 
992 void
gimp_action_group_set_action_viewable(GimpActionGroup * group,const gchar * action_name,GimpViewable * viewable)993 gimp_action_group_set_action_viewable (GimpActionGroup *group,
994                                        const gchar     *action_name,
995                                        GimpViewable    *viewable)
996 {
997   GimpAction *action;
998 
999   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
1000   g_return_if_fail (action_name != NULL);
1001   g_return_if_fail (viewable == NULL || GIMP_IS_VIEWABLE (viewable));
1002 
1003   action = gimp_action_group_get_action (group, action_name);
1004 
1005   if (! action)
1006     {
1007       g_warning ("%s: Unable to set viewable of action "
1008                  "which doesn't exist: %s",
1009                  G_STRFUNC, action_name);
1010       return;
1011     }
1012 
1013   if (! GIMP_IS_ACTION (action))
1014     {
1015       g_warning ("%s: Unable to set \"viewable\" of action "
1016                  "which is not a GimpAction: %s",
1017                  G_STRFUNC, action_name);
1018       return;
1019     }
1020 
1021   g_object_set (action, "viewable", viewable, NULL);
1022 }
1023 
1024 void
gimp_action_group_set_action_hide_empty(GimpActionGroup * group,const gchar * action_name,gboolean hide_empty)1025 gimp_action_group_set_action_hide_empty (GimpActionGroup *group,
1026                                          const gchar     *action_name,
1027                                          gboolean         hide_empty)
1028 {
1029   GimpAction *action;
1030 
1031   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
1032   g_return_if_fail (action_name != NULL);
1033 
1034   action = gimp_action_group_get_action (group, action_name);
1035 
1036   if (! action)
1037     {
1038       g_warning ("%s: Unable to set \"hide-if-empty\" of action "
1039                  "which doesn't exist: %s",
1040                  G_STRFUNC, action_name);
1041       return;
1042     }
1043 
1044   g_object_set (action, "hide-if-empty", hide_empty ? TRUE : FALSE, NULL);
1045 }
1046 
1047 void
gimp_action_group_set_action_always_show_image(GimpActionGroup * group,const gchar * action_name,gboolean always_show_image)1048 gimp_action_group_set_action_always_show_image (GimpActionGroup *group,
1049                                                 const gchar     *action_name,
1050                                                 gboolean         always_show_image)
1051 {
1052   GimpAction *action;
1053 
1054   g_return_if_fail (GIMP_IS_ACTION_GROUP (group));
1055   g_return_if_fail (action_name != NULL);
1056 
1057   action = gimp_action_group_get_action (group, action_name);
1058 
1059   if (! action)
1060     {
1061       g_warning ("%s: Unable to set \"always-show-image\" of action "
1062                  "which doesn't exist: %s",
1063                  G_STRFUNC, action_name);
1064       return;
1065     }
1066 
1067   gtk_action_set_always_show_image ((GtkAction *) action, always_show_image);
1068 }
1069