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