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