1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * gimpdata.c
5 * Copyright (C) 2001 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 <gdk-pixbuf/gdk-pixbuf.h>
24 #include <gegl.h>
25
26 #include "libgimpbase/gimpbase.h"
27
28 #include "core-types.h"
29
30 #include "gimp-memsize.h"
31 #include "gimpdata.h"
32 #include "gimpmarshal.h"
33 #include "gimptag.h"
34 #include "gimptagged.h"
35
36 #include "gimp-intl.h"
37
38
39 enum
40 {
41 DIRTY,
42 LAST_SIGNAL
43 };
44
45 enum
46 {
47 PROP_0,
48 PROP_FILE,
49 PROP_WRITABLE,
50 PROP_DELETABLE,
51 PROP_MIME_TYPE
52 };
53
54
55 struct _GimpDataPrivate
56 {
57 GFile *file;
58 GQuark mime_type;
59 guint writable : 1;
60 guint deletable : 1;
61 guint dirty : 1;
62 guint internal : 1;
63 gint freeze_count;
64 gint64 mtime;
65
66 /* Identifies the GimpData object across sessions. Used when there
67 * is not a filename associated with the object.
68 */
69 gchar *identifier;
70
71 GList *tags;
72 };
73
74 #define GIMP_DATA_GET_PRIVATE(obj) (((GimpData *) (obj))->priv)
75
76
77 static void gimp_data_tagged_iface_init (GimpTaggedInterface *iface);
78
79 static void gimp_data_constructed (GObject *object);
80 static void gimp_data_finalize (GObject *object);
81 static void gimp_data_set_property (GObject *object,
82 guint property_id,
83 const GValue *value,
84 GParamSpec *pspec);
85 static void gimp_data_get_property (GObject *object,
86 guint property_id,
87 GValue *value,
88 GParamSpec *pspec);
89
90 static void gimp_data_name_changed (GimpObject *object);
91 static gint64 gimp_data_get_memsize (GimpObject *object,
92 gint64 *gui_size);
93
94 static gboolean gimp_data_is_name_editable (GimpViewable *viewable);
95
96 static void gimp_data_real_dirty (GimpData *data);
97 static GimpData * gimp_data_real_duplicate (GimpData *data);
98 static gint gimp_data_real_compare (GimpData *data1,
99 GimpData *data2);
100
101 static gboolean gimp_data_add_tag (GimpTagged *tagged,
102 GimpTag *tag);
103 static gboolean gimp_data_remove_tag (GimpTagged *tagged,
104 GimpTag *tag);
105 static GList * gimp_data_get_tags (GimpTagged *tagged);
106 static gchar * gimp_data_get_identifier (GimpTagged *tagged);
107 static gchar * gimp_data_get_checksum (GimpTagged *tagged);
108
109
110 G_DEFINE_TYPE_WITH_CODE (GimpData, gimp_data, GIMP_TYPE_VIEWABLE,
111 G_ADD_PRIVATE (GimpData)
112 G_IMPLEMENT_INTERFACE (GIMP_TYPE_TAGGED,
113 gimp_data_tagged_iface_init))
114
115 #define parent_class gimp_data_parent_class
116
117 static guint data_signals[LAST_SIGNAL] = { 0 };
118
119
120 static void
gimp_data_class_init(GimpDataClass * klass)121 gimp_data_class_init (GimpDataClass *klass)
122 {
123 GObjectClass *object_class = G_OBJECT_CLASS (klass);
124 GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
125 GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
126
127 parent_class = g_type_class_peek_parent (klass);
128
129 data_signals[DIRTY] =
130 g_signal_new ("dirty",
131 G_TYPE_FROM_CLASS (klass),
132 G_SIGNAL_RUN_FIRST,
133 G_STRUCT_OFFSET (GimpDataClass, dirty),
134 NULL, NULL,
135 gimp_marshal_VOID__VOID,
136 G_TYPE_NONE, 0);
137
138 object_class->constructed = gimp_data_constructed;
139 object_class->finalize = gimp_data_finalize;
140 object_class->set_property = gimp_data_set_property;
141 object_class->get_property = gimp_data_get_property;
142
143 gimp_object_class->name_changed = gimp_data_name_changed;
144 gimp_object_class->get_memsize = gimp_data_get_memsize;
145
146 viewable_class->name_editable = TRUE;
147 viewable_class->is_name_editable = gimp_data_is_name_editable;
148
149 klass->dirty = gimp_data_real_dirty;
150 klass->save = NULL;
151 klass->get_extension = NULL;
152 klass->copy = NULL;
153 klass->duplicate = gimp_data_real_duplicate;
154 klass->compare = gimp_data_real_compare;
155
156 g_object_class_install_property (object_class, PROP_FILE,
157 g_param_spec_object ("file", NULL, NULL,
158 G_TYPE_FILE,
159 GIMP_PARAM_READWRITE));
160
161 g_object_class_install_property (object_class, PROP_WRITABLE,
162 g_param_spec_boolean ("writable", NULL, NULL,
163 FALSE,
164 GIMP_PARAM_READWRITE));
165
166 g_object_class_install_property (object_class, PROP_DELETABLE,
167 g_param_spec_boolean ("deletable", NULL, NULL,
168 FALSE,
169 GIMP_PARAM_READWRITE));
170
171 g_object_class_install_property (object_class, PROP_MIME_TYPE,
172 g_param_spec_string ("mime-type", NULL, NULL,
173 NULL,
174 GIMP_PARAM_READWRITE |
175 G_PARAM_CONSTRUCT_ONLY));
176 }
177
178 static void
gimp_data_tagged_iface_init(GimpTaggedInterface * iface)179 gimp_data_tagged_iface_init (GimpTaggedInterface *iface)
180 {
181 iface->add_tag = gimp_data_add_tag;
182 iface->remove_tag = gimp_data_remove_tag;
183 iface->get_tags = gimp_data_get_tags;
184 iface->get_identifier = gimp_data_get_identifier;
185 iface->get_checksum = gimp_data_get_checksum;
186 }
187
188 static void
gimp_data_init(GimpData * data)189 gimp_data_init (GimpData *data)
190 {
191 GimpDataPrivate *private = gimp_data_get_instance_private (data);
192
193 data->priv = private;
194
195 private->writable = TRUE;
196 private->deletable = TRUE;
197 private->dirty = TRUE;
198
199 /* freeze the data object during construction */
200 gimp_data_freeze (data);
201 }
202
203 static void
gimp_data_constructed(GObject * object)204 gimp_data_constructed (GObject *object)
205 {
206 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (object);
207
208 G_OBJECT_CLASS (parent_class)->constructed (object);
209
210 if (! GIMP_DATA_GET_CLASS (object)->save)
211 private->writable = FALSE;
212
213 gimp_data_thaw (GIMP_DATA (object));
214 }
215
216 static void
gimp_data_finalize(GObject * object)217 gimp_data_finalize (GObject *object)
218 {
219 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (object);
220
221 g_clear_object (&private->file);
222
223 if (private->tags)
224 {
225 g_list_free_full (private->tags, (GDestroyNotify) g_object_unref);
226 private->tags = NULL;
227 }
228
229 g_clear_pointer (&private->identifier, g_free);
230
231 G_OBJECT_CLASS (parent_class)->finalize (object);
232 }
233
234 static void
gimp_data_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)235 gimp_data_set_property (GObject *object,
236 guint property_id,
237 const GValue *value,
238 GParamSpec *pspec)
239 {
240 GimpData *data = GIMP_DATA (object);
241 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (data);
242
243 switch (property_id)
244 {
245 case PROP_FILE:
246 gimp_data_set_file (data,
247 g_value_get_object (value),
248 private->writable,
249 private->deletable);
250 break;
251
252 case PROP_WRITABLE:
253 private->writable = g_value_get_boolean (value);
254 break;
255
256 case PROP_DELETABLE:
257 private->deletable = g_value_get_boolean (value);
258 break;
259
260 case PROP_MIME_TYPE:
261 if (g_value_get_string (value))
262 private->mime_type = g_quark_from_string (g_value_get_string (value));
263 else
264 private->mime_type = 0;
265 break;
266
267 default:
268 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
269 break;
270 }
271 }
272
273 static void
gimp_data_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)274 gimp_data_get_property (GObject *object,
275 guint property_id,
276 GValue *value,
277 GParamSpec *pspec)
278 {
279 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (object);
280
281 switch (property_id)
282 {
283 case PROP_FILE:
284 g_value_set_object (value, private->file);
285 break;
286
287 case PROP_WRITABLE:
288 g_value_set_boolean (value, private->writable);
289 break;
290
291 case PROP_DELETABLE:
292 g_value_set_boolean (value, private->deletable);
293 break;
294
295 case PROP_MIME_TYPE:
296 g_value_set_string (value, g_quark_to_string (private->mime_type));
297 break;
298
299 default:
300 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
301 break;
302 }
303 }
304
305 static void
gimp_data_name_changed(GimpObject * object)306 gimp_data_name_changed (GimpObject *object)
307 {
308 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (object);
309
310 private->dirty = TRUE;
311
312 if (GIMP_OBJECT_CLASS (parent_class)->name_changed)
313 GIMP_OBJECT_CLASS (parent_class)->name_changed (object);
314 }
315
316 static gint64
gimp_data_get_memsize(GimpObject * object,gint64 * gui_size)317 gimp_data_get_memsize (GimpObject *object,
318 gint64 *gui_size)
319 {
320 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (object);
321 gint64 memsize = 0;
322
323 memsize += gimp_g_object_get_memsize (G_OBJECT (private->file));
324
325 return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
326 gui_size);
327 }
328
329 static gboolean
gimp_data_is_name_editable(GimpViewable * viewable)330 gimp_data_is_name_editable (GimpViewable *viewable)
331 {
332 return gimp_data_is_writable (GIMP_DATA (viewable)) &&
333 ! gimp_data_is_internal (GIMP_DATA (viewable));
334 }
335
336 static void
gimp_data_real_dirty(GimpData * data)337 gimp_data_real_dirty (GimpData *data)
338 {
339 gimp_viewable_invalidate_preview (GIMP_VIEWABLE (data));
340
341 /* Emit the "name-changed" to signal general dirtiness, our name
342 * changed implementation will also set the "dirty" flag to TRUE.
343 */
344 gimp_object_name_changed (GIMP_OBJECT (data));
345 }
346
347 static GimpData *
gimp_data_real_duplicate(GimpData * data)348 gimp_data_real_duplicate (GimpData *data)
349 {
350 if (GIMP_DATA_GET_CLASS (data)->copy)
351 {
352 GimpData *new = g_object_new (G_OBJECT_TYPE (data), NULL);
353
354 gimp_data_copy (new, data);
355
356 return new;
357 }
358
359 return NULL;
360 }
361
362 static gint
gimp_data_real_compare(GimpData * data1,GimpData * data2)363 gimp_data_real_compare (GimpData *data1,
364 GimpData *data2)
365 {
366 GimpDataPrivate *private1 = GIMP_DATA_GET_PRIVATE (data1);
367 GimpDataPrivate *private2 = GIMP_DATA_GET_PRIVATE (data2);
368
369 /* move the internal objects (like the FG -> BG) gradient) to the top */
370 if (private1->internal != private2->internal)
371 return private1->internal ? -1 : 1;
372
373 /* keep user-deletable objects above system resource files */
374 if (private1->deletable != private2->deletable)
375 return private1->deletable ? -1 : 1;
376
377 return gimp_object_name_collate ((GimpObject *) data1,
378 (GimpObject *) data2);
379 }
380
381 static gboolean
gimp_data_add_tag(GimpTagged * tagged,GimpTag * tag)382 gimp_data_add_tag (GimpTagged *tagged,
383 GimpTag *tag)
384 {
385 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (tagged);
386 GList *list;
387
388 for (list = private->tags; list; list = g_list_next (list))
389 {
390 GimpTag *this = GIMP_TAG (list->data);
391
392 if (gimp_tag_equals (tag, this))
393 return FALSE;
394 }
395
396 private->tags = g_list_prepend (private->tags, g_object_ref (tag));
397
398 return TRUE;
399 }
400
401 static gboolean
gimp_data_remove_tag(GimpTagged * tagged,GimpTag * tag)402 gimp_data_remove_tag (GimpTagged *tagged,
403 GimpTag *tag)
404 {
405 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (tagged);
406 GList *list;
407
408 for (list = private->tags; list; list = g_list_next (list))
409 {
410 GimpTag *this = GIMP_TAG (list->data);
411
412 if (gimp_tag_equals (tag, this))
413 {
414 private->tags = g_list_delete_link (private->tags, list);
415 g_object_unref (this);
416 return TRUE;
417 }
418 }
419
420 return FALSE;
421 }
422
423 static GList *
gimp_data_get_tags(GimpTagged * tagged)424 gimp_data_get_tags (GimpTagged *tagged)
425 {
426 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (tagged);
427
428 return private->tags;
429 }
430
431 static gchar *
gimp_data_get_identifier(GimpTagged * tagged)432 gimp_data_get_identifier (GimpTagged *tagged)
433 {
434 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (tagged);
435 gchar *identifier = NULL;
436
437 if (private->file)
438 {
439 const gchar *data_dir = gimp_data_directory ();
440 const gchar *gimp_dir = gimp_directory ();
441 gchar *path = g_file_get_path (private->file);
442 gchar *tmp;
443
444 if (g_str_has_prefix (path, data_dir))
445 {
446 tmp = g_strconcat ("${gimp_data_dir}",
447 path + strlen (data_dir),
448 NULL);
449 identifier = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
450 g_free (tmp);
451 }
452 else if (g_str_has_prefix (path, gimp_dir))
453 {
454 tmp = g_strconcat ("${gimp_dir}",
455 path + strlen (gimp_dir),
456 NULL);
457 identifier = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
458 g_free (tmp);
459 }
460 else if (g_str_has_prefix (path, MYPAINT_BRUSHES_DIR))
461 {
462 tmp = g_strconcat ("${mypaint_brushes_dir}",
463 path + strlen (MYPAINT_BRUSHES_DIR),
464 NULL);
465 identifier = g_filename_to_utf8 (tmp, -1, NULL, NULL, NULL);
466 g_free (tmp);
467 }
468 else
469 {
470 identifier = g_filename_to_utf8 (path, -1,
471 NULL, NULL, NULL);
472 }
473
474 if (! identifier)
475 {
476 g_printerr ("%s: failed to convert '%s' to utf8.\n",
477 G_STRFUNC, path);
478 identifier = g_strdup (path);
479 }
480
481 g_free (path);
482 }
483 else if (private->internal)
484 {
485 identifier = g_strdup (private->identifier);
486 }
487
488 return identifier;
489 }
490
491 static gchar *
gimp_data_get_checksum(GimpTagged * tagged)492 gimp_data_get_checksum (GimpTagged *tagged)
493 {
494 return NULL;
495 }
496
497 /**
498 * gimp_data_save:
499 * @data: object whose contents are to be saved.
500 * @error: return location for errors or %NULL
501 *
502 * Save the object. If the object is marked as "internal", nothing
503 * happens. Otherwise, it is saved to disk, using the file name set
504 * by gimp_data_set_file(). If the save is successful, the object is
505 * marked as not dirty. If not, an error message is returned using
506 * the @error argument.
507 *
508 * Returns: %TRUE if the object is internal or the save is successful.
509 **/
510 gboolean
gimp_data_save(GimpData * data,GError ** error)511 gimp_data_save (GimpData *data,
512 GError **error)
513 {
514 GimpDataPrivate *private;
515 gboolean success = FALSE;
516
517 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
518 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
519
520 private = GIMP_DATA_GET_PRIVATE (data);
521
522 g_return_val_if_fail (private->writable == TRUE, FALSE);
523
524 if (private->internal)
525 {
526 private->dirty = FALSE;
527 return TRUE;
528 }
529
530 g_return_val_if_fail (G_IS_FILE (private->file), FALSE);
531
532 if (GIMP_DATA_GET_CLASS (data)->save)
533 {
534 GOutputStream *output;
535
536 output = G_OUTPUT_STREAM (g_file_replace (private->file,
537 NULL, FALSE, G_FILE_CREATE_NONE,
538 NULL, error));
539
540 if (output)
541 {
542 success = GIMP_DATA_GET_CLASS (data)->save (data, output, error);
543
544 if (success)
545 {
546 if (! g_output_stream_close (output, NULL, error))
547 {
548 g_prefix_error (error,
549 _("Error saving '%s': "),
550 gimp_file_get_utf8_name (private->file));
551 success = FALSE;
552 }
553 }
554 else
555 {
556 GCancellable *cancellable = g_cancellable_new ();
557
558 g_cancellable_cancel (cancellable);
559 if (error && *error)
560 {
561 g_prefix_error (error,
562 _("Error saving '%s': "),
563 gimp_file_get_utf8_name (private->file));
564 }
565 else
566 {
567 g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_WRITE,
568 _("Error saving '%s'"),
569 gimp_file_get_utf8_name (private->file));
570 }
571 g_output_stream_close (output, cancellable, NULL);
572 g_object_unref (cancellable);
573 }
574
575 g_object_unref (output);
576 }
577 }
578
579 if (success)
580 {
581 GFileInfo *info = g_file_query_info (private->file,
582 G_FILE_ATTRIBUTE_TIME_MODIFIED,
583 G_FILE_QUERY_INFO_NONE,
584 NULL, NULL);
585 if (info)
586 {
587 private->mtime =
588 g_file_info_get_attribute_uint64 (info,
589 G_FILE_ATTRIBUTE_TIME_MODIFIED);
590 g_object_unref (info);
591 }
592
593 private->dirty = FALSE;
594 }
595
596 return success;
597 }
598
599 /**
600 * gimp_data_dirty:
601 * @data: a #GimpData object.
602 *
603 * Marks @data as dirty. Unless the object is frozen, this causes
604 * its preview to be invalidated, and emits a "dirty" signal. If the
605 * object is frozen, the function has no effect.
606 **/
607 void
gimp_data_dirty(GimpData * data)608 gimp_data_dirty (GimpData *data)
609 {
610 GimpDataPrivate *private;
611
612 g_return_if_fail (GIMP_IS_DATA (data));
613
614 private = GIMP_DATA_GET_PRIVATE (data);
615
616 if (private->freeze_count == 0)
617 g_signal_emit (data, data_signals[DIRTY], 0);
618 }
619
620 void
gimp_data_clean(GimpData * data)621 gimp_data_clean (GimpData *data)
622 {
623 GimpDataPrivate *private;
624
625 g_return_if_fail (GIMP_IS_DATA (data));
626
627 private = GIMP_DATA_GET_PRIVATE (data);
628
629 private->dirty = FALSE;
630 }
631
632 gboolean
gimp_data_is_dirty(GimpData * data)633 gimp_data_is_dirty (GimpData *data)
634 {
635 GimpDataPrivate *private;
636
637 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
638
639 private = GIMP_DATA_GET_PRIVATE (data);
640
641 return private->dirty;
642 }
643
644 /**
645 * gimp_data_freeze:
646 * @data: a #GimpData object.
647 *
648 * Increments the freeze count for the object. A positive freeze count
649 * prevents the object from being treated as dirty. Any call to this
650 * function must be followed eventually by a call to gimp_data_thaw().
651 **/
652 void
gimp_data_freeze(GimpData * data)653 gimp_data_freeze (GimpData *data)
654 {
655 GimpDataPrivate *private;
656
657 g_return_if_fail (GIMP_IS_DATA (data));
658
659 private = GIMP_DATA_GET_PRIVATE (data);
660
661 private->freeze_count++;
662 }
663
664 /**
665 * gimp_data_thaw:
666 * @data: a #GimpData object.
667 *
668 * Decrements the freeze count for the object. If the freeze count
669 * drops to zero, the object is marked as dirty, and the "dirty"
670 * signal is emitted. It is an error to call this function without
671 * having previously called gimp_data_freeze().
672 **/
673 void
gimp_data_thaw(GimpData * data)674 gimp_data_thaw (GimpData *data)
675 {
676 GimpDataPrivate *private;
677
678 g_return_if_fail (GIMP_IS_DATA (data));
679
680 private = GIMP_DATA_GET_PRIVATE (data);
681
682 g_return_if_fail (private->freeze_count > 0);
683
684 private->freeze_count--;
685
686 if (private->freeze_count == 0)
687 gimp_data_dirty (data);
688 }
689
690 gboolean
gimp_data_is_frozen(GimpData * data)691 gimp_data_is_frozen (GimpData *data)
692 {
693 GimpDataPrivate *private;
694
695 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
696
697 private = GIMP_DATA_GET_PRIVATE (data);
698
699 return private->freeze_count > 0;
700 }
701
702 /**
703 * gimp_data_delete_from_disk:
704 * @data: a #GimpData object.
705 * @error: return location for errors or %NULL
706 *
707 * Deletes the object from disk. If the object is marked as "internal",
708 * nothing happens. Otherwise, if the file exists whose name has been
709 * set by gimp_data_set_file(), it is deleted. Obviously this is
710 * a potentially dangerous function, which should be used with care.
711 *
712 * Returns: %TRUE if the object is internal to Gimp, or the deletion is
713 * successful.
714 **/
715 gboolean
gimp_data_delete_from_disk(GimpData * data,GError ** error)716 gimp_data_delete_from_disk (GimpData *data,
717 GError **error)
718 {
719 GimpDataPrivate *private;
720
721 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
722 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
723
724 private = GIMP_DATA_GET_PRIVATE (data);
725
726 g_return_val_if_fail (private->file != NULL, FALSE);
727 g_return_val_if_fail (private->deletable == TRUE, FALSE);
728
729 if (private->internal)
730 return TRUE;
731
732 return g_file_delete (private->file, NULL, error);
733 }
734
735 const gchar *
gimp_data_get_extension(GimpData * data)736 gimp_data_get_extension (GimpData *data)
737 {
738 g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
739
740 if (GIMP_DATA_GET_CLASS (data)->get_extension)
741 return GIMP_DATA_GET_CLASS (data)->get_extension (data);
742
743 return NULL;
744 }
745
746 /**
747 * gimp_data_set_file:
748 * @data: A #GimpData object
749 * @file: File to assign to @data.
750 * @writable: %TRUE if we want to be able to write to this file.
751 * @deletable: %TRUE if we want to be able to delete this file.
752 *
753 * This function assigns a file to @data, and sets some flags
754 * according to the properties of the file. If @writable is %TRUE,
755 * and the user has permission to write or overwrite the requested
756 * file name, and a "save" method exists for @data's object type, then
757 * @data is marked as writable.
758 **/
759 void
gimp_data_set_file(GimpData * data,GFile * file,gboolean writable,gboolean deletable)760 gimp_data_set_file (GimpData *data,
761 GFile *file,
762 gboolean writable,
763 gboolean deletable)
764 {
765 GimpDataPrivate *private;
766 gchar *path;
767
768 g_return_if_fail (GIMP_IS_DATA (data));
769 g_return_if_fail (G_IS_FILE (file));
770
771 path = g_file_get_path (file);
772
773 g_return_if_fail (path != NULL);
774 g_return_if_fail (g_path_is_absolute (path));
775
776 g_free (path);
777
778 private = GIMP_DATA_GET_PRIVATE (data);
779
780 if (private->internal)
781 return;
782
783 g_set_object (&private->file, file);
784
785 private->writable = FALSE;
786 private->deletable = FALSE;
787
788 /* if the data is supposed to be writable or deletable,
789 * still check if it really is
790 */
791 if (writable || deletable)
792 {
793 GFileInfo *info;
794
795 if (g_file_query_exists (private->file, NULL)) /* check if it exists */
796 {
797 info = g_file_query_info (private->file,
798 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
799 G_FILE_QUERY_INFO_NONE,
800 NULL, NULL);
801
802 /* and we can write it */
803 if (info)
804 {
805 if (g_file_info_get_attribute_boolean (info,
806 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
807 {
808 private->writable = writable ? TRUE : FALSE;
809 private->deletable = deletable ? TRUE : FALSE;
810 }
811
812 g_object_unref (info);
813 }
814 }
815 else /* OR it doesn't exist */
816 {
817 GFile *parent = g_file_get_parent (private->file);
818
819 info = g_file_query_info (parent,
820 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE,
821 G_FILE_QUERY_INFO_NONE,
822 NULL, NULL);
823
824 /* and we can write to its parent directory */
825 if (info)
826 {
827 if (g_file_info_get_attribute_boolean (info,
828 G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE))
829 {
830 private->writable = writable ? TRUE : FALSE;
831 private->deletable = deletable ? TRUE : FALSE;
832 }
833
834 g_object_unref (info);
835 }
836
837 g_object_unref (parent);
838 }
839
840 /* if we can't save, we are not writable */
841 if (! GIMP_DATA_GET_CLASS (data)->save)
842 private->writable = FALSE;
843 }
844 }
845
846 GFile *
gimp_data_get_file(GimpData * data)847 gimp_data_get_file (GimpData *data)
848 {
849 GimpDataPrivate *private;
850
851 g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
852
853 private = GIMP_DATA_GET_PRIVATE (data);
854
855 return private->file;
856 }
857
858 /**
859 * gimp_data_create_filename:
860 * @data: a #Gimpdata object.
861 * @dest_dir: directory in which to create a file name.
862 *
863 * This function creates a unique file name to be used for saving
864 * a representation of @data in the directory @dest_dir. If the
865 * user does not have write permission in @dest_dir, then @data
866 * is marked as "not writable", so you should check on this before
867 * assuming that @data can be saved.
868 **/
869 void
gimp_data_create_filename(GimpData * data,GFile * dest_dir)870 gimp_data_create_filename (GimpData *data,
871 GFile *dest_dir)
872 {
873 GimpDataPrivate *private;
874 gchar *safename;
875 gchar *basename;
876 GFile *file;
877 gint i;
878 gint unum = 1;
879 GError *error = NULL;
880
881 g_return_if_fail (GIMP_IS_DATA (data));
882 g_return_if_fail (G_IS_FILE (dest_dir));
883
884 private = GIMP_DATA_GET_PRIVATE (data);
885
886 if (private->internal)
887 return;
888
889 safename = g_strstrip (g_strdup (gimp_object_get_name (data)));
890
891 if (safename[0] == '.')
892 safename[0] = '-';
893
894 for (i = 0; safename[i]; i++)
895 if (strchr ("\\/*?\"`'<>{}|\n\t ;:$^&", safename[i]))
896 safename[i] = '-';
897
898 basename = g_strconcat (safename, gimp_data_get_extension (data), NULL);
899
900 file = g_file_get_child_for_display_name (dest_dir, basename, &error);
901 g_free (basename);
902
903 if (! file)
904 {
905 g_warning ("gimp_data_create_filename:\n"
906 "g_file_get_child_for_display_name() failed for '%s': %s",
907 gimp_object_get_name (data), error->message);
908 g_clear_error (&error);
909 g_free (safename);
910 return;
911 }
912
913 while (g_file_query_exists (file, NULL))
914 {
915 g_object_unref (file);
916
917 basename = g_strdup_printf ("%s-%d%s",
918 safename,
919 unum++,
920 gimp_data_get_extension (data));
921
922 file = g_file_get_child_for_display_name (dest_dir, basename, NULL);
923 g_free (basename);
924 }
925
926 g_free (safename);
927
928 gimp_data_set_file (data, file, TRUE, TRUE);
929
930 g_object_unref (file);
931 }
932
933 static const gchar *tag_blacklist[] = { "brushes",
934 "dynamics",
935 "patterns",
936 "palettes",
937 "gradients",
938 "tool-presets" };
939
940 /**
941 * gimp_data_set_folder_tags:
942 * @data: a #Gimpdata object.
943 * @top_directory: the top directory of the currently processed data
944 * hierarchy.
945 *
946 * Sets tags based on all folder names below top_directory. So if the
947 * data's filename is e.g.
948 * /home/foo/.config/GIMP/X.Y/brushes/Flowers/Roses/rose.gbr, it will
949 * add "Flowers" and "Roses" tags.
950 *
951 * if the top directory (as passed, or as derived from the data's
952 * filename) does not end with one of the default data directory names
953 * (brushes, patterns etc), its name will be added as tag too.
954 **/
955 void
gimp_data_set_folder_tags(GimpData * data,GFile * top_directory)956 gimp_data_set_folder_tags (GimpData *data,
957 GFile *top_directory)
958 {
959 GimpDataPrivate *private;
960 gchar *tmp;
961 gchar *dirname;
962 gchar *top_path;
963
964 g_return_if_fail (GIMP_IS_DATA (data));
965 g_return_if_fail (G_IS_FILE (top_directory));
966
967 private = GIMP_DATA_GET_PRIVATE (data);
968
969 if (private->internal)
970 return;
971
972 g_return_if_fail (private->file != NULL);
973
974 tmp = g_file_get_path (private->file);
975 dirname = g_path_get_dirname (tmp);
976 g_free (tmp);
977
978 top_path = g_file_get_path (top_directory);
979
980 g_return_if_fail (g_str_has_prefix (dirname, top_path));
981
982 /* walk up the hierarchy and set each folder on the way as tag,
983 * except the top_directory
984 */
985 while (strcmp (dirname, top_path))
986 {
987 gchar *basename = g_path_get_basename (dirname);
988 GimpTag *tag = gimp_tag_new (basename);
989
990 gimp_tag_set_internal (tag, TRUE);
991 gimp_tagged_add_tag (GIMP_TAGGED (data), tag);
992 g_object_unref (tag);
993 g_free (basename);
994
995 tmp = g_path_get_dirname (dirname);
996 g_free (dirname);
997 dirname = tmp;
998 }
999
1000 g_free (top_path);
1001
1002 if (dirname)
1003 {
1004 gchar *basename = g_path_get_basename (dirname);
1005 gint i;
1006
1007 for (i = 0; i < G_N_ELEMENTS (tag_blacklist); i++)
1008 {
1009 if (! strcmp (basename, tag_blacklist[i]))
1010 break;
1011 }
1012
1013 if (i == G_N_ELEMENTS (tag_blacklist))
1014 {
1015 GimpTag *tag = gimp_tag_new (basename);
1016
1017 gimp_tag_set_internal (tag, TRUE);
1018 gimp_tagged_add_tag (GIMP_TAGGED (data), tag);
1019 g_object_unref (tag);
1020 }
1021
1022 g_free (basename);
1023 g_free (dirname);
1024 }
1025 }
1026
1027 const gchar *
gimp_data_get_mime_type(GimpData * data)1028 gimp_data_get_mime_type (GimpData *data)
1029 {
1030 GimpDataPrivate *private;
1031
1032 g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
1033
1034 private = GIMP_DATA_GET_PRIVATE (data);
1035
1036 return g_quark_to_string (private->mime_type);
1037 }
1038
1039 gboolean
gimp_data_is_writable(GimpData * data)1040 gimp_data_is_writable (GimpData *data)
1041 {
1042 GimpDataPrivate *private;
1043
1044 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
1045
1046 private = GIMP_DATA_GET_PRIVATE (data);
1047
1048 return private->writable;
1049 }
1050
1051 gboolean
gimp_data_is_deletable(GimpData * data)1052 gimp_data_is_deletable (GimpData *data)
1053 {
1054 GimpDataPrivate *private;
1055
1056 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
1057
1058 private = GIMP_DATA_GET_PRIVATE (data);
1059
1060 return private->deletable;
1061 }
1062
1063 void
gimp_data_set_mtime(GimpData * data,gint64 mtime)1064 gimp_data_set_mtime (GimpData *data,
1065 gint64 mtime)
1066 {
1067 GimpDataPrivate *private;
1068
1069 g_return_if_fail (GIMP_IS_DATA (data));
1070
1071 private = GIMP_DATA_GET_PRIVATE (data);
1072
1073 private->mtime = mtime;
1074 }
1075
1076 gint64
gimp_data_get_mtime(GimpData * data)1077 gimp_data_get_mtime (GimpData *data)
1078 {
1079 GimpDataPrivate *private;
1080
1081 g_return_val_if_fail (GIMP_IS_DATA (data), 0);
1082
1083 private = GIMP_DATA_GET_PRIVATE (data);
1084
1085 return private->mtime;
1086 }
1087
1088 gboolean
gimp_data_is_copyable(GimpData * data)1089 gimp_data_is_copyable (GimpData *data)
1090 {
1091 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
1092
1093 return GIMP_DATA_GET_CLASS (data)->copy != NULL;
1094 }
1095
1096 /**
1097 * gimp_data_copy:
1098 * @data: a #GimpData object
1099 * @src_data: the #GimpData object to copy from
1100 *
1101 * Copies @src_data to @data. Only the object data is copied: the
1102 * name, file name, preview, etc. are not copied.
1103 **/
1104 void
gimp_data_copy(GimpData * data,GimpData * src_data)1105 gimp_data_copy (GimpData *data,
1106 GimpData *src_data)
1107 {
1108 g_return_if_fail (GIMP_IS_DATA (data));
1109 g_return_if_fail (GIMP_IS_DATA (src_data));
1110 g_return_if_fail (GIMP_DATA_GET_CLASS (data)->copy != NULL);
1111 g_return_if_fail (GIMP_DATA_GET_CLASS (data)->copy ==
1112 GIMP_DATA_GET_CLASS (src_data)->copy);
1113
1114 if (data != src_data)
1115 GIMP_DATA_GET_CLASS (data)->copy (data, src_data);
1116 }
1117
1118 gboolean
gimp_data_is_duplicatable(GimpData * data)1119 gimp_data_is_duplicatable (GimpData *data)
1120 {
1121 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
1122
1123 if (GIMP_DATA_GET_CLASS (data)->duplicate == gimp_data_real_duplicate)
1124 return gimp_data_is_copyable (data);
1125 else
1126 return GIMP_DATA_GET_CLASS (data)->duplicate != NULL;
1127 }
1128
1129 /**
1130 * gimp_data_duplicate:
1131 * @data: a #GimpData object
1132 *
1133 * Creates a copy of @data, if possible. Only the object data is
1134 * copied: the newly created object is not automatically given an
1135 * object name, file name, preview, etc.
1136 *
1137 * Returns: the newly created copy, or %NULL if @data cannot be copied.
1138 **/
1139 GimpData *
gimp_data_duplicate(GimpData * data)1140 gimp_data_duplicate (GimpData *data)
1141 {
1142 g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
1143
1144 if (gimp_data_is_duplicatable (data))
1145 {
1146 GimpData *new = GIMP_DATA_GET_CLASS (data)->duplicate (data);
1147 GimpDataPrivate *private = GIMP_DATA_GET_PRIVATE (new);
1148
1149 g_object_set (new,
1150 "name", NULL,
1151 "writable", GIMP_DATA_GET_CLASS (new)->save != NULL,
1152 "deletable", TRUE,
1153 NULL);
1154
1155 g_clear_object (&private->file);
1156
1157 return new;
1158 }
1159
1160 return NULL;
1161 }
1162
1163 /**
1164 * gimp_data_make_internal:
1165 * @data: a #GimpData object.
1166 *
1167 * Mark @data as "internal" to Gimp, which means that it will not be
1168 * saved to disk. Note that if you do this, later calls to
1169 * gimp_data_save() and gimp_data_delete_from_disk() will
1170 * automatically return successfully without giving any warning.
1171 *
1172 * The identifier name shall be an untranslated globally unique string
1173 * that identifies the internal object across sessions.
1174 **/
1175 void
gimp_data_make_internal(GimpData * data,const gchar * identifier)1176 gimp_data_make_internal (GimpData *data,
1177 const gchar *identifier)
1178 {
1179 GimpDataPrivate *private;
1180
1181 g_return_if_fail (GIMP_IS_DATA (data));
1182
1183 private = GIMP_DATA_GET_PRIVATE (data);
1184
1185 g_clear_object (&private->file);
1186
1187 g_free (private->identifier);
1188 private->identifier = g_strdup (identifier);
1189
1190 private->writable = FALSE;
1191 private->deletable = FALSE;
1192 private->internal = TRUE;
1193 }
1194
1195 gboolean
gimp_data_is_internal(GimpData * data)1196 gimp_data_is_internal (GimpData *data)
1197 {
1198 GimpDataPrivate *private;
1199
1200 g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
1201
1202 private = GIMP_DATA_GET_PRIVATE (data);
1203
1204 return private->internal;
1205 }
1206
1207 /**
1208 * gimp_data_compare:
1209 * @data1: a #GimpData object.
1210 * @data2: another #GimpData object.
1211 *
1212 * Compares two data objects for use in sorting. Objects marked as
1213 * "internal" come first, then user-writable objects, then system data
1214 * files. In these three groups, the objects are sorted alphabetically
1215 * by name, using gimp_object_name_collate().
1216 *
1217 * Return value: -1 if @data1 compares before @data2,
1218 * 0 if they compare equal,
1219 * 1 if @data1 compares after @data2.
1220 **/
1221 gint
gimp_data_compare(GimpData * data1,GimpData * data2)1222 gimp_data_compare (GimpData *data1,
1223 GimpData *data2)
1224 {
1225 g_return_val_if_fail (GIMP_IS_DATA (data1), 0);
1226 g_return_val_if_fail (GIMP_IS_DATA (data2), 0);
1227 g_return_val_if_fail (GIMP_DATA_GET_CLASS (data1)->compare ==
1228 GIMP_DATA_GET_CLASS (data2)->compare, 0);
1229
1230 return GIMP_DATA_GET_CLASS (data1)->compare (data1, data2);
1231 }
1232
1233 /**
1234 * gimp_data_error_quark:
1235 *
1236 * This function is used to implement the GIMP_DATA_ERROR macro. It
1237 * shouldn't be called directly.
1238 *
1239 * Return value: the #GQuark to identify error in the GimpData error domain.
1240 **/
1241 GQuark
gimp_data_error_quark(void)1242 gimp_data_error_quark (void)
1243 {
1244 return g_quark_from_static_string ("gimp-data-error-quark");
1245 }
1246