1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
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 <gdk-pixbuf/gdk-pixbuf.h>
21 #include <gegl.h>
22 
23 #include "libgimpbase/gimpbase.h"
24 #include "libgimpconfig/gimpconfig.h"
25 
26 #include "core-types.h"
27 
28 #include "gimp.h"
29 #include "gimperror.h"
30 #include "gimptoolinfo.h"
31 #include "gimptooloptions.h"
32 
33 #include "gimp-intl.h"
34 
35 
36 enum
37 {
38   PROP_0,
39   PROP_TOOL,
40   PROP_TOOL_INFO
41 };
42 
43 
44 static void   gimp_tool_options_config_iface_init (GimpConfigInterface *iface);
45 
46 static void   gimp_tool_options_dispose           (GObject         *object);
47 static void   gimp_tool_options_set_property      (GObject         *object,
48                                                    guint            property_id,
49                                                    const GValue    *value,
50                                                    GParamSpec      *pspec);
51 static void   gimp_tool_options_get_property      (GObject         *object,
52                                                    guint            property_id,
53                                                    GValue          *value,
54                                                    GParamSpec      *pspec);
55 
56 static void   gimp_tool_options_config_reset      (GimpConfig      *config);
57 
58 static void   gimp_tool_options_tool_notify       (GimpToolOptions *options,
59                                                    GParamSpec      *pspec);
60 
61 
G_DEFINE_TYPE_WITH_CODE(GimpToolOptions,gimp_tool_options,GIMP_TYPE_CONTEXT,G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,gimp_tool_options_config_iface_init))62 G_DEFINE_TYPE_WITH_CODE (GimpToolOptions, gimp_tool_options, GIMP_TYPE_CONTEXT,
63                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
64                                                 gimp_tool_options_config_iface_init))
65 
66 #define parent_class gimp_tool_options_parent_class
67 
68 
69 static void
70 gimp_tool_options_class_init (GimpToolOptionsClass *klass)
71 {
72   GObjectClass *object_class = G_OBJECT_CLASS (klass);
73 
74   object_class->dispose      = gimp_tool_options_dispose;
75   object_class->set_property = gimp_tool_options_set_property;
76   object_class->get_property = gimp_tool_options_get_property;
77 
78   g_object_class_override_property (object_class, PROP_TOOL, "tool");
79 
80   g_object_class_install_property (object_class, PROP_TOOL_INFO,
81                                    g_param_spec_object ("tool-info",
82                                                         NULL, NULL,
83                                                         GIMP_TYPE_TOOL_INFO,
84                                                         GIMP_PARAM_READWRITE));
85 
86 }
87 
88 static void
gimp_tool_options_init(GimpToolOptions * options)89 gimp_tool_options_init (GimpToolOptions *options)
90 {
91   options->tool_info = NULL;
92 
93   g_signal_connect (options, "notify::tool",
94                     G_CALLBACK (gimp_tool_options_tool_notify),
95                     NULL);
96 }
97 
98 static void
gimp_tool_options_config_iface_init(GimpConfigInterface * iface)99 gimp_tool_options_config_iface_init (GimpConfigInterface *iface)
100 {
101   iface->reset = gimp_tool_options_config_reset;
102 }
103 
104 static void
gimp_tool_options_dispose(GObject * object)105 gimp_tool_options_dispose (GObject *object)
106 {
107   GimpToolOptions *options = GIMP_TOOL_OPTIONS (object);
108 
109   g_clear_object (&options->tool_info);
110 
111   G_OBJECT_CLASS (parent_class)->dispose (object);
112 }
113 
114 /*  This is such a horrible hack, but necessary because we
115  *  a) load an option's tool-info from disk in many cases
116  *  b) screwed up in the past and saved the wrong tool-info in some cases
117  */
118 static GimpToolInfo *
gimp_tool_options_check_tool_info(GimpToolOptions * options,GimpToolInfo * tool_info,gboolean warn)119 gimp_tool_options_check_tool_info (GimpToolOptions *options,
120                                    GimpToolInfo    *tool_info,
121                                    gboolean         warn)
122 {
123   if (tool_info && G_OBJECT_TYPE (options) == tool_info->tool_options_type)
124     {
125       return tool_info;
126     }
127   else
128     {
129       GList *list;
130 
131       for (list = gimp_get_tool_info_iter (GIMP_CONTEXT (options)->gimp);
132            list;
133            list = g_list_next (list))
134         {
135           GimpToolInfo *new_info = list->data;
136 
137           if (G_OBJECT_TYPE (options) == new_info->tool_options_type)
138             {
139               if (warn)
140                 g_printerr ("%s: correcting bogus deserialized tool "
141                             "type '%s' with right type '%s'\n",
142                             g_type_name (G_OBJECT_TYPE (options)),
143                             tool_info ? gimp_object_get_name (tool_info) : "NULL",
144                             gimp_object_get_name (new_info));
145 
146               return new_info;
147             }
148         }
149 
150       g_return_val_if_reached (NULL);
151     }
152 }
153 
154 static void
gimp_tool_options_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)155 gimp_tool_options_set_property (GObject      *object,
156                                 guint         property_id,
157                                 const GValue *value,
158                                 GParamSpec   *pspec)
159 {
160   GimpToolOptions *options = GIMP_TOOL_OPTIONS (object);
161 
162   switch (property_id)
163     {
164     case PROP_TOOL:
165       {
166         GimpToolInfo *tool_info = g_value_get_object (value);
167         GimpToolInfo *context_tool;
168 
169         context_tool = gimp_context_get_tool (GIMP_CONTEXT (options));
170 
171         g_return_if_fail (context_tool == NULL ||
172                           context_tool == tool_info);
173 
174         tool_info = gimp_tool_options_check_tool_info (options, tool_info, TRUE);
175 
176         if (! context_tool)
177           gimp_context_set_tool (GIMP_CONTEXT (options), tool_info);
178       }
179       break;
180 
181     case PROP_TOOL_INFO:
182       {
183         GimpToolInfo *tool_info = g_value_get_object (value);
184 
185         g_return_if_fail (options->tool_info == NULL ||
186                           options->tool_info == tool_info);
187 
188         tool_info = gimp_tool_options_check_tool_info (options, tool_info, TRUE);
189 
190         if (! options->tool_info)
191           {
192             options->tool_info = g_object_ref (tool_info);
193 
194             gimp_context_set_serialize_properties (GIMP_CONTEXT (options),
195                                                    tool_info->context_props);
196           }
197       }
198       break;
199 
200     default:
201       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
202       break;
203     }
204 }
205 
206 static void
gimp_tool_options_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)207 gimp_tool_options_get_property (GObject    *object,
208                                 guint       property_id,
209                                 GValue     *value,
210                                 GParamSpec *pspec)
211 {
212   GimpToolOptions *options = GIMP_TOOL_OPTIONS (object);
213 
214   switch (property_id)
215     {
216     case PROP_TOOL:
217       g_value_set_object (value, gimp_context_get_tool (GIMP_CONTEXT (options)));
218       break;
219 
220     case PROP_TOOL_INFO:
221       g_value_set_object (value, options->tool_info);
222       break;
223 
224     default:
225       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
226       break;
227     }
228 }
229 
230 static void
gimp_tool_options_config_reset(GimpConfig * config)231 gimp_tool_options_config_reset (GimpConfig *config)
232 {
233   gchar *name = g_strdup (gimp_object_get_name (config));
234 
235   gimp_config_reset_properties (G_OBJECT (config));
236 
237   gimp_object_take_name (GIMP_OBJECT (config), name);
238 }
239 
240 static void
gimp_tool_options_tool_notify(GimpToolOptions * options,GParamSpec * pspec)241 gimp_tool_options_tool_notify (GimpToolOptions *options,
242                                GParamSpec      *pspec)
243 {
244   GimpToolInfo *tool_info = gimp_context_get_tool (GIMP_CONTEXT (options));
245   GimpToolInfo *new_info;
246 
247   new_info = gimp_tool_options_check_tool_info (options, tool_info, FALSE);
248 
249   if (tool_info && new_info != tool_info)
250     g_warning ("%s: 'tool' property on %s was set to bogus value "
251                "'%s', it MUST be '%s'.",
252                G_STRFUNC,
253                g_type_name (G_OBJECT_TYPE (options)),
254                gimp_object_get_name (tool_info),
255                gimp_object_get_name (new_info));
256 }
257 
258 
259 /*  public functions  */
260 
261 void
gimp_tool_options_set_gui_mode(GimpToolOptions * tool_options,gboolean gui_mode)262 gimp_tool_options_set_gui_mode (GimpToolOptions *tool_options,
263                                 gboolean         gui_mode)
264 {
265   g_return_if_fail (GIMP_IS_TOOL_OPTIONS (tool_options));
266 
267   tool_options->gui_mode = gui_mode ? TRUE : FALSE;
268 }
269 
270 gboolean
gimp_tool_options_get_gui_mode(GimpToolOptions * tool_options)271 gimp_tool_options_get_gui_mode (GimpToolOptions *tool_options)
272 {
273   g_return_val_if_fail (GIMP_IS_TOOL_OPTIONS (tool_options), FALSE);
274 
275   return tool_options->gui_mode;
276 }
277 
278 gboolean
gimp_tool_options_serialize(GimpToolOptions * tool_options,GError ** error)279 gimp_tool_options_serialize (GimpToolOptions  *tool_options,
280                              GError          **error)
281 {
282   GFile    *file;
283   gchar    *header;
284   gchar    *footer;
285   gboolean  retval;
286 
287   g_return_val_if_fail (GIMP_IS_TOOL_OPTIONS (tool_options), FALSE);
288   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
289 
290   file = gimp_tool_info_get_options_file (tool_options->tool_info, NULL);
291 
292   if (tool_options->tool_info->gimp->be_verbose)
293     g_print ("Writing '%s'\n", gimp_file_get_utf8_name (file));
294 
295   header = g_strdup_printf ("GIMP %s options",
296                             gimp_object_get_name (tool_options->tool_info));
297   footer = g_strdup_printf ("end of %s options",
298                             gimp_object_get_name (tool_options->tool_info));
299 
300   retval = gimp_config_serialize_to_gfile (GIMP_CONFIG (tool_options),
301                                            file,
302                                            header, footer,
303                                            NULL,
304                                            error);
305 
306   g_free (header);
307   g_free (footer);
308 
309   g_object_unref (file);
310 
311   return retval;
312 }
313 
314 gboolean
gimp_tool_options_deserialize(GimpToolOptions * tool_options,GError ** error)315 gimp_tool_options_deserialize (GimpToolOptions  *tool_options,
316                                GError          **error)
317 {
318   GFile    *file;
319   gboolean  retval;
320 
321   g_return_val_if_fail (GIMP_IS_TOOL_OPTIONS (tool_options), FALSE);
322   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
323 
324   file = gimp_tool_info_get_options_file (tool_options->tool_info, NULL);
325 
326   if (tool_options->tool_info->gimp->be_verbose)
327     g_print ("Parsing '%s'\n", gimp_file_get_utf8_name (file));
328 
329   retval = gimp_config_deserialize_gfile (GIMP_CONFIG (tool_options),
330                                           file,
331                                           NULL,
332                                           error);
333 
334   g_object_unref (file);
335 
336   return retval;
337 }
338 
339 gboolean
gimp_tool_options_delete(GimpToolOptions * tool_options,GError ** error)340 gimp_tool_options_delete (GimpToolOptions  *tool_options,
341                           GError          **error)
342 {
343   GFile    *file;
344   GError   *my_error = NULL;
345   gboolean  success  = TRUE;
346 
347   g_return_val_if_fail (GIMP_IS_TOOL_OPTIONS (tool_options), FALSE);
348   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
349 
350   file = gimp_tool_info_get_options_file (tool_options->tool_info, NULL);
351 
352   if (tool_options->tool_info->gimp->be_verbose)
353     g_print ("Deleting '%s'\n", gimp_file_get_utf8_name (file));
354 
355   if (! g_file_delete (file, NULL, &my_error) &&
356       my_error->code != G_IO_ERROR_NOT_FOUND)
357     {
358       success = FALSE;
359 
360       g_set_error (error, GIMP_ERROR, GIMP_FAILED,
361                    _("Deleting \"%s\" failed: %s"),
362                    gimp_file_get_utf8_name (file), my_error->message);
363     }
364 
365   g_clear_error (&my_error);
366   g_object_unref (file);
367 
368   return success;
369 }
370 
371 void
gimp_tool_options_create_folder(void)372 gimp_tool_options_create_folder (void)
373 {
374   GFile *file = gimp_directory_file ("tool-options", NULL);
375 
376   g_file_make_directory (file, NULL, NULL);
377   g_object_unref (file);
378 }
379