1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis and others
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22 
23 #include "libgimpbase/gimpbase.h"
24 #include "libgimpconfig/gimpconfig.h"
25 #include "libgimpwidgets/gimpwidgets.h"
26 
27 #include "tools-types.h"
28 
29 #include "widgets/gimpwidgets-utils.h"
30 
31 #include "core/gimp.h"
32 #include "core/gimp-contexts.h"
33 #include "core/gimp-internal-data.h"
34 #include "core/gimpcontext.h"
35 #include "core/gimplist.h"
36 #include "core/gimptoolgroup.h"
37 #include "core/gimptoolinfo.h"
38 #include "core/gimptooloptions.h"
39 
40 #include "gimp-tool-options-manager.h"
41 #include "gimp-tools.h"
42 #include "gimptooloptions-gui.h"
43 #include "tool_manager.h"
44 
45 #include "gimpairbrushtool.h"
46 #include "gimpaligntool.h"
47 #include "gimpbrightnesscontrasttool.h"
48 #include "gimpbucketfilltool.h"
49 #include "gimpbycolorselecttool.h"
50 #include "gimpcagetool.h"
51 #include "gimpclonetool.h"
52 #include "gimpcolorpickertool.h"
53 #include "gimpconvolvetool.h"
54 #include "gimpcroptool.h"
55 #include "gimpcurvestool.h"
56 #include "gimpdodgeburntool.h"
57 #include "gimpellipseselecttool.h"
58 #include "gimperasertool.h"
59 #include "gimpfliptool.h"
60 #include "gimpfreeselecttool.h"
61 #include "gimpforegroundselecttool.h"
62 #include "gimpfuzzyselecttool.h"
63 #include "gimpgegltool.h"
64 #include "gimpgradienttool.h"
65 #include "gimphandletransformtool.h"
66 #include "gimphealtool.h"
67 #include "gimpinktool.h"
68 #include "gimpiscissorstool.h"
69 #include "gimplevelstool.h"
70 #include "gimpoperationtool.h"
71 #include "gimpmagnifytool.h"
72 #include "gimpmeasuretool.h"
73 #include "gimpmovetool.h"
74 #include "gimpmybrushtool.h"
75 #include "gimpnpointdeformationtool.h"
76 #include "gimpoffsettool.h"
77 #include "gimppaintbrushtool.h"
78 #include "gimppenciltool.h"
79 #include "gimpperspectiveclonetool.h"
80 #include "gimpperspectivetool.h"
81 #include "gimpthresholdtool.h"
82 #include "gimprectangleselecttool.h"
83 #include "gimprotatetool.h"
84 #include "gimpseamlessclonetool.h"
85 #include "gimpscaletool.h"
86 #include "gimpsheartool.h"
87 #include "gimpsmudgetool.h"
88 #include "gimptexttool.h"
89 #include "gimptransform3dtool.h"
90 #include "gimpunifiedtransformtool.h"
91 #include "gimpvectortool.h"
92 #include "gimpwarptool.h"
93 
94 #include "gimp-intl.h"
95 
96 
97 #define TOOL_RC_FILE_VERSION 1
98 
99 
100 /*  local function prototypes  */
101 
102 static void   gimp_tools_register       (GType                   tool_type,
103                                          GType                   tool_options_type,
104                                          GimpToolOptionsGUIFunc  options_gui_func,
105                                          GimpContextPropMask     context_props,
106                                          const gchar            *identifier,
107                                          const gchar            *label,
108                                          const gchar            *tooltip,
109                                          const gchar            *menu_label,
110                                          const gchar            *menu_accel,
111                                          const gchar            *help_domain,
112                                          const gchar            *help_data,
113                                          const gchar            *icon_name,
114                                          gpointer                data);
115 
116 static void   gimp_tools_copy_structure (Gimp                   *gimp,
117                                          GimpContainer          *src_container,
118                                          GimpContainer          *dest_container,
119                                          GHashTable             *tools);
120 
121 /*  private variables  */
122 
123 static GBinding *toolbox_groups_binding = NULL;
124 static gboolean  tool_options_deleted   = FALSE;
125 
126 
127 /*  public functions  */
128 
129 void
gimp_tools_init(Gimp * gimp)130 gimp_tools_init (Gimp *gimp)
131 {
132   GimpToolRegisterFunc register_funcs[] =
133   {
134     /*  selection tools */
135 
136     gimp_rectangle_select_tool_register,
137     gimp_ellipse_select_tool_register,
138     gimp_free_select_tool_register,
139     gimp_fuzzy_select_tool_register,
140     gimp_by_color_select_tool_register,
141     gimp_iscissors_tool_register,
142     gimp_foreground_select_tool_register,
143 
144     /*  path tool */
145 
146     gimp_vector_tool_register,
147 
148     /*  non-modifying tools  */
149 
150     gimp_color_picker_tool_register,
151     gimp_magnify_tool_register,
152     gimp_measure_tool_register,
153 
154     /*  transform tools  */
155 
156     gimp_move_tool_register,
157     gimp_align_tool_register,
158     gimp_crop_tool_register,
159     gimp_unified_transform_tool_register,
160     gimp_rotate_tool_register,
161     gimp_scale_tool_register,
162     gimp_shear_tool_register,
163     gimp_handle_transform_tool_register,
164     gimp_perspective_tool_register,
165     gimp_transform_3d_tool_register,
166     gimp_flip_tool_register,
167     gimp_cage_tool_register,
168     gimp_warp_tool_register,
169     gimp_n_point_deformation_tool_register,
170 
171     /*  paint tools  */
172 
173     gimp_seamless_clone_tool_register,
174     gimp_text_tool_register,
175     gimp_bucket_fill_tool_register,
176     gimp_gradient_tool_register,
177     gimp_pencil_tool_register,
178     gimp_paintbrush_tool_register,
179     gimp_eraser_tool_register,
180     gimp_airbrush_tool_register,
181     gimp_ink_tool_register,
182     gimp_mybrush_tool_register,
183     gimp_clone_tool_register,
184     gimp_heal_tool_register,
185     gimp_perspective_clone_tool_register,
186     gimp_convolve_tool_register,
187     gimp_smudge_tool_register,
188     gimp_dodge_burn_tool_register,
189 
190     /*  filter tools  */
191 
192     gimp_brightness_contrast_tool_register,
193     gimp_threshold_tool_register,
194     gimp_levels_tool_register,
195     gimp_curves_tool_register,
196     gimp_offset_tool_register,
197     gimp_gegl_tool_register,
198     gimp_operation_tool_register
199   };
200 
201   gint i;
202 
203   g_return_if_fail (GIMP_IS_GIMP (gimp));
204 
205   gimp_tool_options_create_folder ();
206 
207   gimp_container_freeze (gimp->tool_info_list);
208 
209   for (i = 0; i < G_N_ELEMENTS (register_funcs); i++)
210     {
211       register_funcs[i] (gimp_tools_register, gimp);
212     }
213 
214   gimp_container_thaw (gimp->tool_info_list);
215 
216   gimp_tool_options_manager_init (gimp);
217 
218   tool_manager_init (gimp);
219 
220   toolbox_groups_binding = g_object_bind_property (
221     gimp->config,            "toolbox-groups",
222     gimp->tool_item_ui_list, "flat",
223     G_BINDING_INVERT_BOOLEAN |
224     G_BINDING_SYNC_CREATE);
225 }
226 
227 void
gimp_tools_exit(Gimp * gimp)228 gimp_tools_exit (Gimp *gimp)
229 {
230   GList *list;
231 
232   g_return_if_fail (GIMP_IS_GIMP (gimp));
233 
234   g_clear_object (&toolbox_groups_binding);
235 
236   tool_manager_exit (gimp);
237 
238   gimp_tool_options_manager_exit (gimp);
239 
240   for (list = gimp_get_tool_info_iter (gimp);
241        list;
242        list = g_list_next (list))
243     {
244       GimpToolInfo *tool_info = list->data;
245 
246       gimp_tools_set_tool_options_gui (tool_info->tool_options, NULL);
247     }
248 }
249 
250 void
gimp_tools_restore(Gimp * gimp)251 gimp_tools_restore (Gimp *gimp)
252 {
253   GimpObject *object;
254   GList      *list;
255   GError     *error = NULL;
256 
257   g_return_if_fail (GIMP_IS_GIMP (gimp));
258 
259   /* restore tool order */
260   gimp_tools_reset (gimp, gimp->tool_item_list, TRUE);
261 
262   /* make the generic operation tool invisible by default */
263   object = gimp_container_get_child_by_name (gimp->tool_info_list,
264                                              "gimp-operation-tool");
265   if (object)
266     g_object_set (object, "visible", FALSE, NULL);
267 
268   for (list = gimp_get_tool_info_iter (gimp);
269        list;
270        list = g_list_next (list))
271     {
272       GimpToolInfo *tool_info = GIMP_TOOL_INFO (list->data);
273 
274       /*  get default values from prefs (see bug #120832)  */
275       gimp_config_reset (GIMP_CONFIG (tool_info->tool_options));
276     }
277 
278   if (! gimp_contexts_load (gimp, &error))
279     {
280       gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING, error->message);
281       g_clear_error (&error);
282     }
283 
284   if (! gimp_internal_data_load (gimp, &error))
285     {
286       gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING, error->message);
287       g_clear_error (&error);
288     }
289 
290   /*  make sure there is always a tool active, so broken config files
291    *  can't leave us with no initial tool
292    */
293   if (! gimp_context_get_tool (gimp_get_user_context (gimp)))
294     {
295       gimp_context_set_tool (gimp_get_user_context (gimp),
296                              gimp_get_tool_info_iter (gimp)->data);
297     }
298 
299   for (list = gimp_get_tool_info_iter (gimp);
300        list;
301        list = g_list_next (list))
302     {
303       GimpToolInfo           *tool_info = GIMP_TOOL_INFO (list->data);
304       GimpToolOptionsGUIFunc  options_gui_func;
305 
306       /*  copy all context properties except those the tool actually
307        *  uses, because the subsequent deserialize() on the tool
308        *  options will only set the properties that were set to
309        *  non-default values at the time of saving, and we want to
310        *  keep these default values as if they have been saved.
311        * (see bug #541586).
312        */
313       gimp_context_copy_properties (gimp_get_user_context (gimp),
314                                     GIMP_CONTEXT (tool_info->tool_options),
315                                     GIMP_CONTEXT_PROP_MASK_ALL &~
316                                     (tool_info->context_props    |
317                                      GIMP_CONTEXT_PROP_MASK_TOOL |
318                                      GIMP_CONTEXT_PROP_MASK_PAINT_INFO));
319 
320       gimp_tool_options_deserialize (tool_info->tool_options, NULL);
321 
322       options_gui_func = g_object_get_data (G_OBJECT (tool_info),
323                                             "gimp-tool-options-gui-func");
324 
325       if (! options_gui_func)
326         options_gui_func = gimp_tool_options_empty_gui;
327 
328       gimp_tools_set_tool_options_gui_func (tool_info->tool_options,
329                                             options_gui_func);
330     }
331 }
332 
333 void
gimp_tools_save(Gimp * gimp,gboolean save_tool_options,gboolean always_save)334 gimp_tools_save (Gimp     *gimp,
335                  gboolean  save_tool_options,
336                  gboolean  always_save)
337 {
338   GimpConfigWriter *writer;
339   GFile            *file;
340 
341   g_return_if_fail (GIMP_IS_GIMP (gimp));
342 
343   if (save_tool_options && (! tool_options_deleted || always_save))
344     {
345       GList  *list;
346       GError *error = NULL;
347 
348       if (! gimp_contexts_save (gimp, &error))
349         {
350           gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING,
351                                 error->message);
352           g_clear_error (&error);
353         }
354 
355       if (! gimp_internal_data_save (gimp, &error))
356         {
357           gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING,
358                                 error->message);
359           g_clear_error (&error);
360         }
361 
362       gimp_tool_options_create_folder ();
363 
364       for (list = gimp_get_tool_info_iter (gimp);
365            list;
366            list = g_list_next (list))
367         {
368           GimpToolInfo *tool_info = GIMP_TOOL_INFO (list->data);
369 
370           gimp_tool_options_serialize (tool_info->tool_options, NULL);
371         }
372     }
373 
374   file = gimp_directory_file ("toolrc", NULL);
375 
376   if (gimp->be_verbose)
377     g_print ("Writing '%s'\n", gimp_file_get_utf8_name (file));
378 
379   writer = gimp_config_writer_new_gfile (file, TRUE, "GIMP toolrc", NULL);
380 
381   if (writer)
382     {
383       gimp_tools_serialize (gimp, gimp->tool_item_list, writer);
384 
385       gimp_config_writer_finish (writer, "end of toolrc", NULL);
386     }
387 
388   g_object_unref (file);
389 }
390 
391 gboolean
gimp_tools_clear(Gimp * gimp,GError ** error)392 gimp_tools_clear (Gimp    *gimp,
393                   GError **error)
394 {
395   GList    *list;
396   gboolean  success = TRUE;
397 
398   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
399 
400   for (list = gimp_get_tool_info_iter (gimp);
401        list && success;
402        list = g_list_next (list))
403     {
404       GimpToolInfo *tool_info = GIMP_TOOL_INFO (list->data);
405 
406       success = gimp_tool_options_delete (tool_info->tool_options, NULL);
407     }
408 
409   if (success)
410     success = gimp_contexts_clear (gimp, error);
411 
412   if (success)
413     success = gimp_internal_data_clear (gimp, error);
414 
415   if (success)
416     tool_options_deleted = TRUE;
417 
418   return success;
419 }
420 
421 gboolean
gimp_tools_serialize(Gimp * gimp,GimpContainer * container,GimpConfigWriter * writer)422 gimp_tools_serialize (Gimp             *gimp,
423                       GimpContainer    *container,
424                       GimpConfigWriter *writer)
425 {
426   g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
427   g_return_val_if_fail (GIMP_IS_CONTAINER (container), FALSE);
428 
429   gimp_config_writer_open (writer, "file-version");
430   gimp_config_writer_printf (writer, "%d", TOOL_RC_FILE_VERSION);
431   gimp_config_writer_close (writer);
432 
433   gimp_config_writer_linefeed (writer);
434 
435   return gimp_config_serialize (GIMP_CONFIG (container), writer, NULL);
436 }
437 
438 gboolean
gimp_tools_deserialize(Gimp * gimp,GimpContainer * container,GScanner * scanner)439 gimp_tools_deserialize (Gimp          *gimp,
440                         GimpContainer *container,
441                         GScanner      *scanner)
442 {
443   enum
444   {
445     FILE_VERSION = 1
446   };
447 
448   GimpContainer *src_container;
449   GTokenType     token;
450   guint          scope_id;
451   guint          old_scope_id;
452   gint           file_version = 0;
453   gboolean       result       = FALSE;
454 
455   scope_id     = g_type_qname (GIMP_TYPE_TOOL_GROUP);
456   old_scope_id = g_scanner_set_scope (scanner, scope_id);
457 
458   g_scanner_scope_add_symbol (scanner, scope_id,
459                               "file-version",
460                               GINT_TO_POINTER (FILE_VERSION));
461 
462   token = G_TOKEN_LEFT_PAREN;
463 
464   while (g_scanner_peek_next_token (scanner) == token &&
465          (token != G_TOKEN_LEFT_PAREN                 ||
466           ! file_version))
467     {
468       token = g_scanner_get_next_token (scanner);
469 
470       switch (token)
471         {
472         case G_TOKEN_LEFT_PAREN:
473           token = G_TOKEN_SYMBOL;
474           break;
475 
476         case G_TOKEN_SYMBOL:
477           switch (GPOINTER_TO_INT (scanner->value.v_symbol))
478             {
479             case FILE_VERSION:
480               token = G_TOKEN_INT;
481               if (gimp_scanner_parse_int (scanner, &file_version))
482                 token = G_TOKEN_RIGHT_PAREN;
483               break;
484             }
485           break;
486 
487         case G_TOKEN_RIGHT_PAREN:
488           token = G_TOKEN_LEFT_PAREN;
489           break;
490 
491         default:
492           break;
493         }
494     }
495 
496   g_scanner_set_scope (scanner, old_scope_id);
497 
498   if (token != G_TOKEN_LEFT_PAREN)
499     {
500       g_scanner_get_next_token (scanner);
501       g_scanner_unexp_token (scanner, token, NULL, NULL, NULL,
502                              _("fatal parse error"), TRUE);
503 
504       return FALSE;
505     }
506   else if (file_version != TOOL_RC_FILE_VERSION)
507     {
508       g_scanner_error (scanner, "wrong toolrc file format version");
509 
510       return FALSE;
511     }
512 
513   gimp_container_freeze (container);
514 
515   /* make sure the various GimpToolItem types are registered */
516   g_type_class_unref (g_type_class_ref (GIMP_TYPE_TOOL_GROUP));
517   g_type_class_unref (g_type_class_ref (GIMP_TYPE_TOOL_INFO));
518 
519   gimp_container_clear (container);
520 
521   src_container = g_object_new (GIMP_TYPE_LIST,
522                                 "children-type", GIMP_TYPE_TOOL_ITEM,
523                                 "append",        TRUE,
524                                 NULL);
525 
526   if (gimp_config_deserialize (GIMP_CONFIG (src_container),
527                                scanner, 0, NULL))
528     {
529       GHashTable *tools;
530       GList      *list;
531 
532       result = TRUE;
533 
534       tools = g_hash_table_new (g_direct_hash, g_direct_equal);
535 
536       gimp_tools_copy_structure (gimp, src_container, container, tools);
537 
538       for (list = gimp_get_tool_info_iter (gimp);
539            list;
540            list = g_list_next (list))
541         {
542           GimpToolInfo *tool_info = list->data;
543 
544           if (! tool_info->hidden && ! g_hash_table_contains (tools, tool_info))
545             {
546               if (tool_info->experimental)
547                 {
548                   /* if an experimental tool is not in the file, just add it to
549                    * the tool-item list.
550                    */
551                   gimp_container_add (container, GIMP_OBJECT (tool_info));
552                 }
553               else
554                 {
555                   /* otherwise, it means we added a new stable tool.  this must
556                    * be the user toolrc file; rejct it, so that we fall back to
557                    * the default toolrc file, which should contain the missing
558                    * tool.
559                    */
560                   g_scanner_error (scanner, "missing tools in toolrc file");
561 
562                   result = FALSE;
563 
564                   break;
565                 }
566             }
567         }
568 
569       g_hash_table_unref (tools);
570     }
571 
572   g_object_unref (src_container);
573 
574   gimp_container_thaw (container);
575 
576   return result;
577 }
578 
579 void
gimp_tools_reset(Gimp * gimp,GimpContainer * container,gboolean user_toolrc)580 gimp_tools_reset (Gimp          *gimp,
581                   GimpContainer *container,
582                   gboolean       user_toolrc)
583 {
584   GList *files = NULL;
585   GList *list;
586 
587   g_return_if_fail (GIMP_IS_GIMP (gimp));
588   g_return_if_fail (GIMP_IS_CONTAINER (container));
589 
590   if (user_toolrc)
591     files = g_list_prepend (files, gimp_directory_file       ("toolrc", NULL));
592   files = g_list_prepend (files, gimp_sysconf_directory_file ("toolrc", NULL));
593 
594   files = g_list_reverse (files);
595 
596   gimp_container_freeze (container);
597 
598   gimp_container_clear (container);
599 
600   for (list = files; list; list = g_list_next (list))
601     {
602       GScanner *scanner;
603       GFile    *file  = list->data;
604       GError   *error = NULL;
605 
606       if (gimp->be_verbose)
607         g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
608 
609       scanner = gimp_scanner_new_gfile (file, &error);
610 
611       if (scanner && gimp_tools_deserialize (gimp, container, scanner))
612         {
613           gimp_scanner_destroy (scanner);
614 
615           break;
616         }
617       else
618         {
619           if (error->code != G_IO_ERROR_NOT_FOUND)
620             {
621               gimp_message_literal (gimp, NULL,
622                                     GIMP_MESSAGE_WARNING, error->message);
623             }
624 
625           g_clear_error (&error);
626 
627           gimp_container_clear (container);
628         }
629 
630       g_clear_pointer (&scanner, gimp_scanner_destroy);
631     }
632 
633   g_list_free_full (files, g_object_unref);
634 
635   if (gimp_container_is_empty (container))
636     {
637       if (gimp->be_verbose)
638         g_print ("Using default tool order\n");
639 
640       gimp_tools_copy_structure (gimp, gimp->tool_info_list, container, NULL);
641     }
642 
643   gimp_container_thaw (container);
644 }
645 
646 
647 /*  private functions  */
648 
649 static void
gimp_tools_register(GType tool_type,GType tool_options_type,GimpToolOptionsGUIFunc options_gui_func,GimpContextPropMask context_props,const gchar * identifier,const gchar * label,const gchar * tooltip,const gchar * menu_label,const gchar * menu_accel,const gchar * help_domain,const gchar * help_data,const gchar * icon_name,gpointer data)650 gimp_tools_register (GType                   tool_type,
651                      GType                   tool_options_type,
652                      GimpToolOptionsGUIFunc  options_gui_func,
653                      GimpContextPropMask     context_props,
654                      const gchar            *identifier,
655                      const gchar            *label,
656                      const gchar            *tooltip,
657                      const gchar            *menu_label,
658                      const gchar            *menu_accel,
659                      const gchar            *help_domain,
660                      const gchar            *help_data,
661                      const gchar            *icon_name,
662                      gpointer                data)
663 {
664   Gimp         *gimp = (Gimp *) data;
665   GimpToolInfo *tool_info;
666   const gchar  *paint_core_name;
667   gboolean      visible;
668 
669   g_return_if_fail (GIMP_IS_GIMP (gimp));
670   g_return_if_fail (g_type_is_a (tool_type, GIMP_TYPE_TOOL));
671   g_return_if_fail (tool_options_type == G_TYPE_NONE ||
672                     g_type_is_a (tool_options_type, GIMP_TYPE_TOOL_OPTIONS));
673 
674   if (tool_options_type == G_TYPE_NONE)
675     tool_options_type = GIMP_TYPE_TOOL_OPTIONS;
676 
677   if (tool_type == GIMP_TYPE_PENCIL_TOOL)
678     {
679       paint_core_name = "gimp-pencil";
680     }
681   else if (tool_type == GIMP_TYPE_PAINTBRUSH_TOOL)
682     {
683       paint_core_name = "gimp-paintbrush";
684     }
685   else if (tool_type == GIMP_TYPE_ERASER_TOOL)
686     {
687       paint_core_name = "gimp-eraser";
688     }
689   else if (tool_type == GIMP_TYPE_AIRBRUSH_TOOL)
690     {
691       paint_core_name = "gimp-airbrush";
692     }
693   else if (tool_type == GIMP_TYPE_CLONE_TOOL)
694     {
695       paint_core_name = "gimp-clone";
696     }
697   else if (tool_type == GIMP_TYPE_HEAL_TOOL)
698     {
699       paint_core_name = "gimp-heal";
700     }
701   else if (tool_type == GIMP_TYPE_PERSPECTIVE_CLONE_TOOL)
702     {
703       paint_core_name = "gimp-perspective-clone";
704     }
705   else if (tool_type == GIMP_TYPE_CONVOLVE_TOOL)
706     {
707       paint_core_name = "gimp-convolve";
708     }
709   else if (tool_type == GIMP_TYPE_SMUDGE_TOOL)
710     {
711       paint_core_name = "gimp-smudge";
712     }
713   else if (tool_type == GIMP_TYPE_DODGE_BURN_TOOL)
714     {
715       paint_core_name = "gimp-dodge-burn";
716     }
717   else if (tool_type == GIMP_TYPE_INK_TOOL)
718     {
719       paint_core_name = "gimp-ink";
720     }
721   else if (tool_type == GIMP_TYPE_MYBRUSH_TOOL)
722     {
723       paint_core_name = "gimp-mybrush";
724     }
725   else
726     {
727       paint_core_name = "gimp-paintbrush";
728     }
729 
730   tool_info = gimp_tool_info_new (gimp,
731                                   tool_type,
732                                   tool_options_type,
733                                   context_props,
734                                   identifier,
735                                   label,
736                                   tooltip,
737                                   menu_label,
738                                   menu_accel,
739                                   help_domain,
740                                   help_data,
741                                   paint_core_name,
742                                   icon_name);
743 
744   visible = (! g_type_is_a (tool_type, GIMP_TYPE_FILTER_TOOL));
745 
746   gimp_tool_item_set_visible (GIMP_TOOL_ITEM (tool_info), visible);
747 
748   /* hack to hide the operation tool entirely */
749   if (tool_type == GIMP_TYPE_OPERATION_TOOL)
750     tool_info->hidden = TRUE;
751 
752   /* hack to not require experimental tools to be present in toolrc */
753   if (tool_type == GIMP_TYPE_N_POINT_DEFORMATION_TOOL ||
754       tool_type == GIMP_TYPE_SEAMLESS_CLONE_TOOL)
755     {
756       tool_info->experimental = TRUE;
757     }
758 
759   g_object_set_data (G_OBJECT (tool_info), "gimp-tool-options-gui-func",
760                      options_gui_func);
761 
762   gimp_container_add (gimp->tool_info_list, GIMP_OBJECT (tool_info));
763   g_object_unref (tool_info);
764 
765   if (tool_type == GIMP_TYPE_PAINTBRUSH_TOOL)
766     gimp_tool_info_set_standard (gimp, tool_info);
767 }
768 
769 static void
gimp_tools_copy_structure(Gimp * gimp,GimpContainer * src_container,GimpContainer * dest_container,GHashTable * tools)770 gimp_tools_copy_structure (Gimp          *gimp,
771                            GimpContainer *src_container,
772                            GimpContainer *dest_container,
773                            GHashTable    *tools)
774 {
775   GList *list;
776 
777   for (list = GIMP_LIST (src_container)->queue->head;
778        list;
779        list = g_list_next (list))
780     {
781       GimpToolItem *src_tool_item  = list->data;
782       GimpToolItem *dest_tool_item = NULL;
783 
784       if (GIMP_IS_TOOL_GROUP (src_tool_item))
785         {
786           dest_tool_item = GIMP_TOOL_ITEM (gimp_tool_group_new ());
787 
788           gimp_tools_copy_structure (
789             gimp,
790             gimp_viewable_get_children (GIMP_VIEWABLE (src_tool_item)),
791             gimp_viewable_get_children (GIMP_VIEWABLE (dest_tool_item)),
792             tools);
793 
794           gimp_tool_group_set_active_tool (
795             GIMP_TOOL_GROUP (dest_tool_item),
796             gimp_tool_group_get_active_tool (GIMP_TOOL_GROUP (src_tool_item)));
797         }
798       else
799         {
800           dest_tool_item = GIMP_TOOL_ITEM (
801             gimp_get_tool_info (gimp, gimp_object_get_name (src_tool_item)));
802 
803           if (dest_tool_item)
804             {
805               if (! GIMP_TOOL_INFO (dest_tool_item)->hidden)
806                 {
807                   g_object_ref (dest_tool_item);
808 
809                   if (tools)
810                     g_hash_table_add (tools, dest_tool_item);
811                 }
812               else
813                 {
814                   dest_tool_item = NULL;
815                 }
816             }
817         }
818 
819       if (dest_tool_item)
820         {
821           gimp_tool_item_set_visible (
822             dest_tool_item,
823             gimp_tool_item_get_visible (src_tool_item));
824 
825           gimp_container_add (dest_container,
826                               GIMP_OBJECT (dest_tool_item));
827 
828           g_object_unref (dest_tool_item);
829         }
830     }
831 }
832