~ubuntu-branches/ubuntu/maverick/gimp/maverick-updates

« back to all changes in this revision

Viewing changes to app/core/gimpdata.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-12-09 19:44:52 UTC
  • Revision ID: james.westby@ubuntu.com-20051209194452-yggpemjlofpjqyf4
Tags: upstream-2.2.9
ImportĀ upstreamĀ versionĀ 2.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* The GIMP -- an 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 2 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, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <errno.h>
 
25
#include <stdio.h>
 
26
#include <string.h>
 
27
 
 
28
#ifdef HAVE_UNISTD_H
 
29
#include <unistd.h>
 
30
#endif
 
31
 
 
32
#include <glib-object.h>
 
33
 
 
34
#include "libgimpbase/gimpbase.h"
 
35
 
 
36
#ifdef G_OS_WIN32
 
37
#include "libgimpbase/gimpwin32-io.h"
 
38
#endif
 
39
 
 
40
#include "core-types.h"
 
41
 
 
42
#include "gimpdata.h"
 
43
#include "gimpmarshal.h"
 
44
 
 
45
#include "gimp-intl.h"
 
46
 
 
47
/* Need this test somewhere, might as well do it here */
 
48
#ifdef G_OS_WIN32
 
49
#if GLIB_CHECK_VERSION (2,6,0)
 
50
#error GIMP 2.2 for Win32 must be compiled against GLib 2.4 
 
51
#endif
 
52
#endif
 
53
 
 
54
enum
 
55
{
 
56
  DIRTY,
 
57
  LAST_SIGNAL
 
58
};
 
59
 
 
60
 
 
61
static void    gimp_data_class_init   (GimpDataClass *klass);
 
62
static void    gimp_data_init         (GimpData      *data,
 
63
                                       GimpDataClass *data_class);
 
64
 
 
65
static void    gimp_data_finalize     (GObject       *object);
 
66
 
 
67
static void    gimp_data_name_changed (GimpObject    *object);
 
68
static gint64  gimp_data_get_memsize  (GimpObject    *object,
 
69
                                       gint64        *gui_size);
 
70
 
 
71
static void    gimp_data_real_dirty   (GimpData      *data);
 
72
 
 
73
 
 
74
static guint data_signals[LAST_SIGNAL] = { 0 };
 
75
 
 
76
static GimpViewableClass *parent_class = NULL;
 
77
 
 
78
 
 
79
GType
 
80
gimp_data_get_type (void)
 
81
{
 
82
  static GType data_type = 0;
 
83
 
 
84
  if (! data_type)
 
85
    {
 
86
      static const GTypeInfo data_info =
 
87
      {
 
88
        sizeof (GimpDataClass),
 
89
        (GBaseInitFunc) NULL,
 
90
        (GBaseFinalizeFunc) NULL,
 
91
        (GClassInitFunc) gimp_data_class_init,
 
92
        NULL,           /* class_finalize */
 
93
        NULL,           /* class_data     */
 
94
        sizeof (GimpData),
 
95
        0,              /* n_preallocs    */
 
96
        (GInstanceInitFunc) gimp_data_init,
 
97
      };
 
98
 
 
99
      data_type = g_type_register_static (GIMP_TYPE_VIEWABLE,
 
100
                                          "GimpData",
 
101
                                          &data_info, 0);
 
102
  }
 
103
 
 
104
  return data_type;
 
105
}
 
106
 
 
107
static void
 
108
gimp_data_class_init (GimpDataClass *klass)
 
109
{
 
110
  GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
 
111
  GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
 
112
 
 
113
  parent_class = g_type_class_peek_parent (klass);
 
114
 
 
115
  data_signals[DIRTY] =
 
116
    g_signal_new ("dirty",
 
117
                  G_TYPE_FROM_CLASS (klass),
 
118
                  G_SIGNAL_RUN_FIRST,
 
119
                  G_STRUCT_OFFSET (GimpDataClass, dirty),
 
120
                  NULL, NULL,
 
121
                  gimp_marshal_VOID__VOID,
 
122
                  G_TYPE_NONE, 0);
 
123
 
 
124
  object_class->finalize          = gimp_data_finalize;
 
125
 
 
126
  gimp_object_class->name_changed = gimp_data_name_changed;
 
127
  gimp_object_class->get_memsize  = gimp_data_get_memsize;
 
128
 
 
129
  klass->dirty                    = gimp_data_real_dirty;
 
130
  klass->save                     = NULL;
 
131
  klass->get_extension            = NULL;
 
132
  klass->duplicate                = NULL;
 
133
}
 
134
 
 
135
static void
 
136
gimp_data_init (GimpData      *data,
 
137
                GimpDataClass *data_class)
 
138
{
 
139
  data->filename     = NULL;
 
140
  data->writable     = TRUE;
 
141
  data->deletable    = TRUE;
 
142
  data->dirty        = TRUE;
 
143
  data->internal     = FALSE;
 
144
  data->freeze_count = 0;
 
145
 
 
146
  /*  look at the passed class pointer, not at GIMP_DATA_GET_CLASS(data)
 
147
   *  here, because the latter is always GimpDataClass itself
 
148
   */
 
149
  if (! data_class->save)
 
150
    data->writable = FALSE;
 
151
}
 
152
 
 
153
static void
 
154
gimp_data_finalize (GObject *object)
 
155
{
 
156
  GimpData *data = GIMP_DATA (object);
 
157
 
 
158
  if (data->filename)
 
159
    {
 
160
      g_free (data->filename);
 
161
      data->filename = NULL;
 
162
    }
 
163
 
 
164
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
165
}
 
166
 
 
167
static void
 
168
gimp_data_name_changed (GimpObject *object)
 
169
{
 
170
  if (GIMP_OBJECT_CLASS (parent_class)->name_changed)
 
171
    GIMP_OBJECT_CLASS (parent_class)->name_changed (object);
 
172
 
 
173
  gimp_data_dirty (GIMP_DATA (object));
 
174
}
 
175
 
 
176
static gint64
 
177
gimp_data_get_memsize (GimpObject *object,
 
178
                       gint64     *gui_size)
 
179
{
 
180
  GimpData *data    = GIMP_DATA (object);
 
181
  gint64    memsize = 0;
 
182
 
 
183
  if (data->filename)
 
184
    memsize += strlen (data->filename) + 1;
 
185
 
 
186
  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
 
187
                                                                  gui_size);
 
188
}
 
189
 
 
190
static void
 
191
gimp_data_real_dirty (GimpData *data)
 
192
{
 
193
  data->dirty = TRUE;
 
194
 
 
195
  gimp_viewable_invalidate_preview (GIMP_VIEWABLE (data));
 
196
}
 
197
 
 
198
/**
 
199
 * gimp_data_save:
 
200
 * @data:  object whose contents are to be saved.
 
201
 * @error: return location for errors or %NULL
 
202
 *
 
203
 * Save the object.  If the object is marked as "internal", nothing happens.
 
204
 * Otherwise, it is saved to disk, using the file name set by
 
205
 * gimp_data_set_filename().  If the save is successful, the
 
206
 * object is marked as not dirty.  If not, an error message is returned
 
207
 * using the @error argument.
 
208
 *
 
209
 * Returns: %TRUE if the object is internal or the save is successful.
 
210
 **/
 
211
gboolean
 
212
gimp_data_save (GimpData  *data,
 
213
                GError   **error)
 
214
{
 
215
  gboolean success = FALSE;
 
216
 
 
217
  g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
 
218
  g_return_val_if_fail (data->writable == TRUE, FALSE);
 
219
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
220
 
 
221
  if (data->internal)
 
222
    {
 
223
      data->dirty = FALSE;
 
224
      return TRUE;
 
225
    }
 
226
 
 
227
  g_return_val_if_fail (data->filename != NULL, FALSE);
 
228
 
 
229
  if (GIMP_DATA_GET_CLASS (data)->save)
 
230
    success = GIMP_DATA_GET_CLASS (data)->save (data, error);
 
231
 
 
232
  if (success)
 
233
    data->dirty = FALSE;
 
234
 
 
235
  return success;
 
236
}
 
237
 
 
238
/**
 
239
 * gimp_data_dirty:
 
240
 * @data: a #GimpData object.
 
241
 *
 
242
 * Marks @data as dirty.  Unless the object is frozen, this causes
 
243
 * its preview to be invalidated, and emits a "dirty" signal.  If the
 
244
 * object is frozen, the function has no effect.
 
245
 **/
 
246
void
 
247
gimp_data_dirty (GimpData *data)
 
248
{
 
249
  g_return_if_fail (GIMP_IS_DATA (data));
 
250
 
 
251
  if (data->freeze_count == 0)
 
252
    g_signal_emit (data, data_signals[DIRTY], 0);
 
253
}
 
254
 
 
255
/**
 
256
 * gimp_data_freeze:
 
257
 * @data: a #GimpData object.
 
258
 *
 
259
 * Increments the freeze count for the object.  A positive freeze count
 
260
 * prevents the object from being treated as dirty.  Any call to this
 
261
 * function must be followed eventually by a call to gimp_data_thaw().
 
262
 **/
 
263
void
 
264
gimp_data_freeze (GimpData *data)
 
265
{
 
266
  g_return_if_fail (GIMP_IS_DATA (data));
 
267
 
 
268
  data->freeze_count++;
 
269
}
 
270
 
 
271
/**
 
272
 * gimp_data_thaw:
 
273
 * @data: a #GimpData object.
 
274
 *
 
275
 * Decrements the freeze count for the object.  If the freeze count
 
276
 * drops to zero, the object is marked as dirty, and the "dirty"
 
277
 * signal is emitted.  It is an error to call this function without
 
278
 * having previously called gimp_data_freeze().
 
279
 **/
 
280
void
 
281
gimp_data_thaw (GimpData *data)
 
282
{
 
283
  g_return_if_fail (GIMP_IS_DATA (data));
 
284
  g_return_if_fail (data->freeze_count > 0);
 
285
 
 
286
  data->freeze_count--;
 
287
 
 
288
  if (data->freeze_count == 0)
 
289
    gimp_data_dirty (data);
 
290
}
 
291
 
 
292
/**
 
293
 * gimp_data_delete_from_disk:
 
294
 * @data:  a #GimpData object.
 
295
 * @error: return location for errors or %NULL
 
296
 *
 
297
 * Deletes the object from disk.  If the object is marked as "internal",
 
298
 * nothing happens.  Otherwise, if the file exists whose name has been
 
299
 * set by gimp_data_set_filename(), it is deleted.  Obviously this is
 
300
 * a potentially dangerous function, which should be used with care.
 
301
 *
 
302
 * Returns: %TRUE if the object is internal to Gimp, or the deletion is
 
303
 *          successful.
 
304
 **/
 
305
gboolean
 
306
gimp_data_delete_from_disk (GimpData  *data,
 
307
                            GError   **error)
 
308
{
 
309
  g_return_val_if_fail (GIMP_IS_DATA (data), FALSE);
 
310
  g_return_val_if_fail (data->filename != NULL, FALSE);
 
311
  g_return_val_if_fail (data->deletable == TRUE, FALSE);
 
312
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
313
 
 
314
  if (data->internal)
 
315
    return TRUE;
 
316
 
 
317
  if (unlink (data->filename) == -1)
 
318
    {
 
319
      g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_DELETE,
 
320
                   _("Could not delete '%s': %s"),
 
321
                   gimp_filename_to_utf8 (data->filename), g_strerror (errno));
 
322
      return FALSE;
 
323
    }
 
324
 
 
325
  return TRUE;
 
326
}
 
327
 
 
328
const gchar *
 
329
gimp_data_get_extension (GimpData *data)
 
330
{
 
331
  g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
 
332
 
 
333
  if (GIMP_DATA_GET_CLASS (data)->get_extension)
 
334
    return GIMP_DATA_GET_CLASS (data)->get_extension (data);
 
335
 
 
336
  return NULL;
 
337
}
 
338
 
 
339
/**
 
340
 * gimp_data_set_filename:
 
341
 * @data:     A #GimpData object
 
342
 * @filename: File name to assign to @data.
 
343
 * @writable: %TRUE if we want to be able to write to this file.
 
344
 * @deletable: %TRUE if we want to be able to delete this file.
 
345
 *
 
346
 * This function assigns a file name to @data, and sets some flags
 
347
 * according to the properties of the file.  If @writable is %TRUE,
 
348
 * and the user has permission to write or overwrite the requested file
 
349
 * name, and a "save" method exists for @data's object type, then
 
350
 * @data is marked as writable.
 
351
 **/
 
352
void
 
353
gimp_data_set_filename (GimpData    *data,
 
354
                        const gchar *filename,
 
355
                        gboolean     writable,
 
356
                        gboolean     deletable)
 
357
{
 
358
  g_return_if_fail (GIMP_IS_DATA (data));
 
359
  g_return_if_fail (filename != NULL);
 
360
  g_return_if_fail (g_path_is_absolute (filename));
 
361
 
 
362
  if (data->internal)
 
363
    return;
 
364
 
 
365
  if (data->filename)
 
366
    g_free (data->filename);
 
367
 
 
368
  data->filename  = g_strdup (filename);
 
369
  data->writable  = FALSE;
 
370
  data->deletable = FALSE;
 
371
 
 
372
  /*  if the data is supposed to be writable or deletable,
 
373
   *  still check if it really is
 
374
   */
 
375
  if (writable || deletable)
 
376
    {
 
377
      gchar *dirname = g_path_get_dirname (filename);
 
378
 
 
379
      if ((access (filename, F_OK) == 0 &&  /* check if the file exists    */
 
380
           access (filename, W_OK) == 0) || /* and is writable             */
 
381
          (access (filename, F_OK) != 0 &&  /* OR doesn't exist            */
 
382
           access (dirname,  W_OK) == 0))   /* and we can write to its dir */
 
383
        {
 
384
          data->writable  = writable  ? TRUE : FALSE;
 
385
          data->deletable = deletable ? TRUE : FALSE;
 
386
        }
 
387
 
 
388
      g_free (dirname);
 
389
 
 
390
      /*  if we can't save, we are not writable  */
 
391
      if (! GIMP_DATA_GET_CLASS (data)->save)
 
392
        data->writable = FALSE;
 
393
    }
 
394
}
 
395
 
 
396
/**
 
397
 * gimp_data_create_filename:
 
398
 * @data:     a #Gimpdata object.
 
399
 * @dest_dir: directory in which to create a file name.
 
400
 *
 
401
 * This function creates a unique file name to be used for saving
 
402
 * a representation of @data in the directory @dest_dir.  If the
 
403
 * user does not have write permission in @dest_dir, then @data
 
404
 * is marked as "not writable", so you should check on this before
 
405
 * assuming that @data can be saved.
 
406
 **/
 
407
void
 
408
gimp_data_create_filename (GimpData    *data,
 
409
                           const gchar *dest_dir)
 
410
{
 
411
  gchar  *safename;
 
412
  gchar  *filename;
 
413
  gchar  *fullpath;
 
414
  gint    i;
 
415
  gint    unum  = 1;
 
416
  GError *error = NULL;
 
417
 
 
418
  g_return_if_fail (GIMP_IS_DATA (data));
 
419
  g_return_if_fail (dest_dir != NULL);
 
420
  g_return_if_fail (g_path_is_absolute (dest_dir));
 
421
 
 
422
  if (data->internal)
 
423
    return;
 
424
 
 
425
#ifdef G_OS_WIN32
 
426
  {
 
427
    const gchar *charset;
 
428
 
 
429
    filename = g_strdup (gimp_object_get_name (GIMP_OBJECT (data)));
 
430
 
 
431
    /* Map illegal characters to '-' while the name is still in UTF-8 */
 
432
    for (i = 0; filename[i]; i++)
 
433
      if (strchr ("<>:\"/\\|", filename[i]) ||
 
434
          g_ascii_iscntrl (filename[i]) ||
 
435
          g_ascii_isspace (filename[i]))
 
436
        filename[i] = '-';
 
437
 
 
438
    /* Map also trailing periods to '-' */
 
439
    for (i = strlen (filename) - 1; i >= 0; i--)
 
440
      if (filename[i] == '.')
 
441
        filename[i] = '-';
 
442
      else
 
443
        break;
 
444
 
 
445
    /* Next convert to the filename charset. Note that this branch of
 
446
     * GIMP must be compiled against GLib 2.4 and we thus use system
 
447
     * codepage for file names in the GLib API.
 
448
     */
 
449
    g_get_charset (&charset);
 
450
    safename = g_convert_with_fallback (filename,
 
451
                                        -1, charset, "UTF-8",
 
452
                                        "-", NULL, NULL, &error);
 
453
    if (! safename)
 
454
      {
 
455
        g_warning ("gimp_data_create_filename:\n"
 
456
                   "g_convert_with_fallback() failed for '%s': %s",
 
457
                   filename, error->message);
 
458
        g_free (filename);
 
459
        g_error_free (error);
 
460
        return;
 
461
      }
 
462
    g_free (filename);
 
463
  }
 
464
#else
 
465
  safename = g_filename_from_utf8 (gimp_object_get_name (GIMP_OBJECT (data)),
 
466
                                   -1, NULL, NULL, &error);
 
467
  if (! safename)
 
468
    {
 
469
      g_warning ("gimp_data_create_filename:\n"
 
470
                 "g_filename_from_utf8() failed for '%s': %s",
 
471
                 gimp_object_get_name (GIMP_OBJECT (data)), error->message);
 
472
      g_error_free (error);
 
473
      return;
 
474
    }
 
475
 
 
476
  if (safename[0] == '.')
 
477
    safename[0] = '-';
 
478
 
 
479
  for (i = 0; safename[i]; i++)
 
480
    if (safename[i] == G_DIR_SEPARATOR || g_ascii_isspace (safename[i]))
 
481
      safename[i] = '-';
 
482
#endif
 
483
 
 
484
  filename = g_strconcat (safename, gimp_data_get_extension (data), NULL);
 
485
 
 
486
  fullpath = g_build_filename (dest_dir, filename, NULL);
 
487
 
 
488
  g_free (filename);
 
489
 
 
490
  while (g_file_test (fullpath, G_FILE_TEST_EXISTS))
 
491
    {
 
492
      g_free (fullpath);
 
493
 
 
494
      filename = g_strdup_printf ("%s-%d%s",
 
495
                                  safename,
 
496
                                  unum++,
 
497
                                  gimp_data_get_extension (data));
 
498
 
 
499
      fullpath = g_build_filename (dest_dir, filename, NULL);
 
500
 
 
501
      g_free (filename);
 
502
    }
 
503
 
 
504
  g_free (safename);
 
505
 
 
506
  gimp_data_set_filename (data, fullpath, TRUE, TRUE);
 
507
 
 
508
  g_free (fullpath);
 
509
}
 
510
 
 
511
/**
 
512
 * gimp_data_duplicate:
 
513
 * @data:              a #GimpData object
 
514
 * @stingy_memory_use: if %TRUE, use the disk rather than RAM
 
515
 *                     where possible.
 
516
 *
 
517
 * Creates a copy of @data, if possible.  Only the object data is
 
518
 * copied:  the newly created object is not automatically given an
 
519
 * object name, file name, preview, etc.
 
520
 *
 
521
 * Returns: the newly created copy, or %NULL if @data cannot be copied.
 
522
 **/
 
523
GimpData *
 
524
gimp_data_duplicate (GimpData *data,
 
525
                     gboolean  stingy_memory_use)
 
526
{
 
527
  g_return_val_if_fail (GIMP_IS_DATA (data), NULL);
 
528
 
 
529
  if (GIMP_DATA_GET_CLASS (data)->duplicate)
 
530
    return GIMP_DATA_GET_CLASS (data)->duplicate (data, stingy_memory_use);
 
531
 
 
532
  return NULL;
 
533
}
 
534
 
 
535
/**
 
536
 * gimp_data_make_internal:
 
537
 * @data: a #GimpData object.
 
538
 *
 
539
 * Mark @data as "internal" to Gimp, which means that it will not be
 
540
 * saved to disk.  Note that if you do this, later calls to
 
541
 * gimp_data_save() and gimp_data_delete_from_disk() will
 
542
 * automatically return successfully without giving any warning.
 
543
 **/
 
544
void
 
545
gimp_data_make_internal (GimpData *data)
 
546
{
 
547
  g_return_if_fail (GIMP_IS_DATA (data));
 
548
 
 
549
  if (data->filename)
 
550
    {
 
551
      g_free (data->filename);
 
552
      data->filename = NULL;
 
553
    }
 
554
 
 
555
  data->internal  = TRUE;
 
556
  data->writable  = FALSE;
 
557
  data->deletable = FALSE;
 
558
}
 
559
 
 
560
/**
 
561
 * gimp_data_name_compare:
 
562
 * @data1: a #GimpData object.
 
563
 * @data2: another #GimpData object.
 
564
 *
 
565
 * Compares the names of the two objects for use in sorting; see
 
566
 * gimp_object_name_collate() for the method.  Objects marked as
 
567
 * "internal" are considered to come before any objects that are not.
 
568
 *
 
569
 * Return value: -1 if @data1 compares before @data2,
 
570
 *                0 if they compare equal,
 
571
 *                1 if @data1 compares after @data2.
 
572
 **/
 
573
gint
 
574
gimp_data_name_compare (GimpData *data1,
 
575
                        GimpData *data2)
 
576
{
 
577
  /*  move the internal objects (like the FG -> BG) gradient) to the top  */
 
578
  if (data1->internal != data2->internal)
 
579
    return data1->internal ? -1 : 1;
 
580
 
 
581
  return gimp_object_name_collate ((GimpObject *) data1,
 
582
                                   (GimpObject *) data2);
 
583
}
 
584
 
 
585
/**
 
586
 * gimp_data_error_quark:
 
587
 *
 
588
 * This function is used to implement the GIMP_DATA_ERROR macro. It
 
589
 * shouldn't be called directly.
 
590
 *
 
591
 * Return value: the #GQuark to identify error in the GimpData error domain.
 
592
 **/
 
593
GQuark
 
594
gimp_data_error_quark (void)
 
595
{
 
596
  static GQuark quark = 0;
 
597
 
 
598
  if (! quark)
 
599
    quark = g_quark_from_static_string ("gimp-data-error-quark");
 
600
 
 
601
  return quark;
 
602
}