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