file-commands.c 14.5 KB
Newer Older
Michael Natterer's avatar
Michael Natterer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include "config.h"

21 22
#include <string.h>

Michael Natterer's avatar
Michael Natterer committed
23 24
#include <gtk/gtk.h>

25 26
#include "libgimpwidgets/gimpwidgets.h"

Michael Natterer's avatar
Michael Natterer committed
27
#include "actions-types.h"
Michael Natterer's avatar
Michael Natterer committed
28

29 30
#include "config/gimpguiconfig.h"

31
#include "core/gimp.h"
32
#include "core/gimpcontainer.h"
33
#include "core/gimpimage.h"
34
#include "core/gimpprogress.h"
35
#include "core/gimptemplate.h"
36

Michael Natterer's avatar
Michael Natterer committed
37 38
#include "file/file-open.h"
#include "file/file-save.h"
39
#include "file/file-utils.h"
Michael Natterer's avatar
Michael Natterer committed
40

41
#include "widgets/gimpdialogfactory.h"
42
#include "widgets/gimpfiledialog.h"
43
#include "widgets/gimphelp-ids.h"
44 45
#include "widgets/gimpmessagebox.h"
#include "widgets/gimpmessagedialog.h"
46

47
#include "display/gimpdisplay.h"
48
#include "display/gimpdisplay-foreach.h"
49

50
#include "dialogs/dialogs.h"
Michael Natterer's avatar
Michael Natterer committed
51

52
#include "actions.h"
Michael Natterer's avatar
Michael Natterer committed
53 54
#include "file-commands.h"

55
#include "gimp-intl.h"
Michael Natterer's avatar
Michael Natterer committed
56 57


58 59
#define REVERT_DATA_KEY "revert-confirm-dialog"

60

61 62
/*  local function prototypes  */

63 64
static void   file_open_dialog_show        (GtkWidget   *parent,
                                            GimpImage   *gimage,
65 66
                                            const gchar *uri,
                                            gboolean     open_as_layer);
67 68 69 70 71 72 73
static void   file_save_dialog_show        (GimpImage   *gimage,
                                            GtkWidget   *parent,
                                            const gchar *title,
                                            gboolean     set_uri_and_proc,
                                            gboolean     set_image_clean);
static void   file_save_dialog_destroyed   (GtkWidget   *dialog,
                                            GimpImage   *gimage);
74 75 76
static void   file_new_template_callback   (GtkWidget   *widget,
                                            const gchar *name,
                                            gpointer     data);
77 78 79
static void   file_revert_confirm_response (GtkWidget   *dialog,
                                            gint         response_id,
                                            GimpDisplay *gdisp);
80 81 82 83


/*  public functions  */

Michael Natterer's avatar
Michael Natterer committed
84
void
85
file_open_cmd_callback (GtkAction *action,
86
                        gpointer   data)
Michael Natterer's avatar
Michael Natterer committed
87
{
88 89
  GtkWidget *widget;
  return_if_no_widget (widget, data);
Michael Natterer's avatar
Michael Natterer committed
90

91
  file_open_dialog_show (widget, NULL, NULL, FALSE);
Michael Natterer's avatar
Michael Natterer committed
92 93 94
}

void
95 96
file_open_from_image_cmd_callback (GtkAction *action,
                                   gpointer   data)
Michael Natterer's avatar
Michael Natterer committed
97
{
98 99
  GtkWidget *widget;
  return_if_no_widget (widget, data);
100

101 102 103 104 105 106 107 108 109 110 111 112 113
  file_open_dialog_show (widget, action_data_get_image (data), NULL, FALSE);
}

void
file_open_as_layer_cmd_callback (GtkAction *action,
                                 gpointer   data)
{
  GimpDisplay *gdisp;
  GtkWidget   *widget;
  return_if_no_display (gdisp, data);
  return_if_no_widget (widget, data);

  file_open_dialog_show (widget, gdisp->gimage, NULL, TRUE);
Michael Natterer's avatar
Michael Natterer committed
114 115
}

116 117 118 119 120 121 122
void
file_open_location_cmd_callback (GtkAction *action,
                                 gpointer   data)
{
  GtkWidget *widget;
  return_if_no_widget (widget, data);

123 124 125
  gimp_dialog_factory_dialog_new (global_dialog_factory,
                                  gtk_widget_get_screen (widget),
                                  "gimp-file-open-location-dialog", -1, TRUE);
126 127
}

Michael Natterer's avatar
Michael Natterer committed
128
void
129 130
file_last_opened_cmd_callback (GtkAction *action,
                               gint       value,
131
                               gpointer   data)
Michael Natterer's avatar
Michael Natterer committed
132
{
Michael Natterer's avatar
Michael Natterer committed
133
  Gimp          *gimp;
134
  GimpImagefile *imagefile;
135
  gint           num_entries;
136
  return_if_no_gimp (gimp, data);
Michael Natterer's avatar
Michael Natterer committed
137 138

  num_entries = gimp_container_num_children (gimp->documents);
Michael Natterer's avatar
Michael Natterer committed
139

140
  if (value >= num_entries)
Michael Natterer's avatar
Michael Natterer committed
141 142
    return;

143
  imagefile = (GimpImagefile *)
144
    gimp_container_get_child_by_index (gimp->documents, value);
Michael Natterer's avatar
Michael Natterer committed
145

146
  if (imagefile)
Michael Natterer's avatar
Michael Natterer committed
147
    {
148 149 150 151
      GimpImage         *gimage;
      GimpPDBStatusType  status;
      GError            *error = NULL;

152
      gimage = file_open_with_display (gimp, action_data_get_context (data),
153
                                       NULL,
154
                                       GIMP_OBJECT (imagefile)->name,
155 156 157 158 159
                                       &status, &error);

      if (! gimage && status != GIMP_PDB_CANCEL)
        {
          gchar *filename;
160

161 162 163 164 165 166 167 168 169
          filename =
            file_utils_uri_to_utf8_filename (GIMP_OBJECT (imagefile)->name);

          g_message (_("Opening '%s' failed:\n\n%s"),
                     filename, error->message);
          g_clear_error (&error);

          g_free (filename);
        }
Michael Natterer's avatar
Michael Natterer committed
170 171 172
    }
}

Michael Natterer's avatar
Michael Natterer committed
173
void
174
file_save_cmd_callback (GtkAction *action,
175
                        gpointer   data)
Michael Natterer's avatar
Michael Natterer committed
176
{
177
  GimpDisplay *gdisp;
Michael Natterer's avatar
Michael Natterer committed
178
  return_if_no_display (gdisp, data);
179

180 181
  if (! gimp_image_active_drawable (gdisp->gimage))
    return;
182 183

  /*  Only save if the gimage has been modified  */
184 185
  if (gdisp->gimage->dirty ||
      ! GIMP_GUI_CONFIG (gdisp->gimage->gimp->config)->trust_dirty_flag)
186
    {
187
      const gchar *uri = gimp_object_get_name (GIMP_OBJECT (gdisp->gimage));
188

189
      if (! uri)
190 191 192
        {
          file_save_as_cmd_callback (action, data);
        }
193
      else
194 195
        {
          GimpPDBStatusType  status;
196
          GError            *error = NULL;
197

198
          status = file_save (gdisp->gimage, action_data_get_context (data),
199
                              GIMP_PROGRESS (gdisp),
200
                              GIMP_RUN_WITH_LAST_VALS, &error);
201

202 203 204
          if (status != GIMP_PDB_SUCCESS &&
              status != GIMP_PDB_CANCEL)
            {
205 206
              gchar *filename;

207
              filename = file_utils_uri_to_utf8_filename (uri);
208

209
              g_message (_("Saving '%s' failed:\n\n%s"),
210 211
                         filename, error->message);
              g_clear_error (&error);
212 213

              g_free (filename);
214 215
            }
        }
216
    }
Michael Natterer's avatar
Michael Natterer committed
217 218 219
}

void
220
file_save_as_cmd_callback (GtkAction *action,
221
                           gpointer   data)
Michael Natterer's avatar
Michael Natterer committed
222
{
223
  GimpDisplay *gdisp;
224
  GtkWidget   *widget;
Michael Natterer's avatar
Michael Natterer committed
225
  return_if_no_display (gdisp, data);
226 227 228 229 230
  return_if_no_widget (widget, data);

  if (! gimp_image_active_drawable (gdisp->gimage))
    return;

231 232
  file_save_dialog_show (gdisp->gimage, widget, _("Save Image"),
                         TRUE, TRUE);
Michael Natterer's avatar
Michael Natterer committed
233 234 235
}

void
236
file_save_a_copy_cmd_callback (GtkAction *action,
237
                               gpointer   data)
Michael Natterer's avatar
Michael Natterer committed
238
{
239
  GimpDisplay *gdisp;
240
  GtkWidget   *widget;
Michael Natterer's avatar
Michael Natterer committed
241
  return_if_no_display (gdisp, data);
242 243 244 245 246
  return_if_no_widget (widget, data);

  if (! gimp_image_active_drawable (gdisp->gimage))
    return;

247 248
  file_save_dialog_show (gdisp->gimage, widget, _("Save a Copy of the Image"),
                         FALSE, FALSE);
Michael Natterer's avatar
Michael Natterer committed
249 250
}

251
void
252
file_save_template_cmd_callback (GtkAction *action,
253
                                 gpointer   data)
254 255
{
  GimpDisplay *gdisp;
256
  GtkWidget   *dialog;
257 258
  return_if_no_display (gdisp, data);

259 260 261 262 263 264 265 266 267
  dialog = gimp_query_string_box (_("Create New Template"),
                                  gdisp->shell,
                                  gimp_standard_help_func,
                                  GIMP_HELP_FILE_SAVE_AS_TEMPLATE,
                                  _("Enter a name for this template"),
                                  NULL,
                                  G_OBJECT (gdisp->gimage), "disconnect",
                                  file_new_template_callback, gdisp->gimage);
  gtk_widget_show (dialog);
268 269
}

Michael Natterer's avatar
Michael Natterer committed
270
void
271
file_revert_cmd_callback (GtkAction *action,
272
                          gpointer   data)
Michael Natterer's avatar
Michael Natterer committed
273
{
274
  GimpDisplay *gdisp;
275
  GtkWidget   *dialog;
276
  const gchar *uri;
Michael Natterer's avatar
Michael Natterer committed
277
  return_if_no_display (gdisp, data);
278

279
  uri = gimp_object_get_name (GIMP_OBJECT (gdisp->gimage));
280

281
  dialog = g_object_get_data (G_OBJECT (gdisp->gimage), REVERT_DATA_KEY);
282

283
  if (! uri)
284
    {
285
      g_message (_("Revert failed. No file name associated with this image."));
286
    }
287
  else if (dialog)
288
    {
289
      gtk_window_present (GTK_WINDOW (dialog));
290 291 292
    }
  else
    {
293
      gchar *basename;
294
      gchar *filename;
295

296 297 298 299
      dialog =
        gimp_message_dialog_new (_("Revert Image"), GIMP_STOCK_QUESTION,
                                 gdisp->shell, 0,
                                 gimp_standard_help_func, GIMP_HELP_FILE_REVERT,
300

301 302
                                 GTK_STOCK_CANCEL,          GTK_RESPONSE_CANCEL,
                                 GTK_STOCK_REVERT_TO_SAVED, GTK_RESPONSE_OK,
303

304
                                 NULL);
305

306 307 308
      g_signal_connect_object (gdisp, "disconnect",
                               G_CALLBACK (gtk_widget_destroy),
                               dialog, G_CONNECT_SWAPPED);
309

310 311 312
      g_signal_connect (dialog, "response",
                        G_CALLBACK (file_revert_confirm_response),
                        gdisp);
313

314
      basename = g_path_get_basename (uri);
315 316
      filename = file_utils_uri_to_utf8_filename (uri);

317 318
      gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
                                         _("Revert '%s' to '%s'?"),
319 320
                                         basename, filename);
      g_free (filename);
321 322 323 324 325 326
      g_free (basename);

      gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
                                 _("By reverting the image to the state saved "
                                   "on disk, you will lose all changes, "
                                   "including all undo information."));
327

328
      g_object_set_data (G_OBJECT (gdisp->gimage), REVERT_DATA_KEY, dialog);
329

330
      gtk_widget_show (dialog);
331
    }
Michael Natterer's avatar
Michael Natterer committed
332 333 334
}

void
335
file_quit_cmd_callback (GtkAction *action,
336
                        gpointer   data)
Michael Natterer's avatar
Michael Natterer committed
337
{
338 339 340 341
  Gimp *gimp;
  return_if_no_gimp (gimp, data);

  gimp_exit (gimp, FALSE);
Michael Natterer's avatar
Michael Natterer committed
342
}
343

344 345
void
file_file_open_dialog (Gimp        *gimp,
346 347
                       const gchar *uri,
                       GtkWidget   *parent)
348
{
349
  file_open_dialog_show (parent, NULL, uri, FALSE);
350 351 352 353 354 355 356 357
}


/*  private functions  */

static void
file_open_dialog_show (GtkWidget   *parent,
                       GimpImage   *gimage,
358 359
                       const gchar *uri,
                       gboolean     open_as_layer)
360
{
361 362 363 364 365 366 367 368
  GtkWidget *dialog;

  dialog = gimp_dialog_factory_dialog_new (global_dialog_factory,
                                           gtk_widget_get_screen (parent),
                                           "gimp-file-open-dialog", -1, FALSE);

  if (dialog)
    {
369
      gimp_file_dialog_set_uri (GIMP_FILE_DIALOG (dialog), gimage, uri);
370

371 372 373 374 375 376 377 378 379 380 381
      if (open_as_layer)
        {
          gtk_window_set_title (GTK_WINDOW (dialog), _("Open Image as Layer"));
          GIMP_FILE_DIALOG (dialog)->gimage = gimage;
        }
      else
        {
          gtk_window_set_title (GTK_WINDOW (dialog), _("Open Image"));
          GIMP_FILE_DIALOG (dialog)->gimage = NULL;
        }

382 383
      gtk_window_present (GTK_WINDOW (dialog));
    }
384
}
385

386 387 388 389 390 391 392 393
static void
file_save_dialog_show (GimpImage   *gimage,
                       GtkWidget   *parent,
                       const gchar *title,
                       gboolean     set_uri_and_proc,
                       gboolean     set_image_clean)
{
  GtkWidget *dialog;
394

395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
  dialog = g_object_get_data (G_OBJECT (gimage), "gimp-file-save-dialog");

  if (! dialog)
    {
      dialog = gimp_dialog_factory_dialog_new (global_dialog_factory,
                                               gtk_widget_get_screen (parent),
                                               "gimp-file-save-dialog",
                                               -1, FALSE);

      if (dialog)
        {
          g_object_set_data_full (G_OBJECT (gimage),
                                  "gimp-file-save-dialog", dialog,
                                  (GDestroyNotify) gtk_widget_destroy);
          g_signal_connect (dialog, "destroy",
                            G_CALLBACK (file_save_dialog_destroyed),
                            gimage);
        }
    }


  if (dialog)
    {
      gtk_window_set_title (GTK_WINDOW (dialog), title);

      gimp_file_dialog_set_image (GIMP_FILE_DIALOG (dialog), gimage,
                                  set_uri_and_proc, set_image_clean);

      gtk_window_present (GTK_WINDOW (dialog));
    }
}

static void
file_save_dialog_destroyed (GtkWidget *dialog,
                            GimpImage *gimage)
{
  if (GIMP_FILE_DIALOG (dialog)->gimage == gimage)
    g_object_set_data (G_OBJECT (gimage), "gimp-file-save-dialog", NULL);
}
434

435
static void
436 437 438
file_new_template_callback (GtkWidget   *widget,
                            const gchar *name,
                            gpointer     data)
439 440 441 442 443 444 445 446 447 448 449
{
  GimpTemplate *template;
  GimpImage    *gimage;

  gimage = (GimpImage *) data;

  if (! (name && strlen (name)))
    name = _("(Unnamed Template)");

  template = gimp_template_new (name);
  gimp_template_set_from_image (template, gimage);
450
  gimp_container_add (gimage->gimp->templates, GIMP_OBJECT (template));
451 452 453
  g_object_unref (template);
}

454
static void
455 456 457
file_revert_confirm_response (GtkWidget   *dialog,
                              gint         response_id,
                              GimpDisplay *gdisp)
458
{
459 460 461
  GimpImage *old_gimage = gdisp->gimage;

  gtk_widget_destroy (dialog);
462

463
  g_object_set_data (G_OBJECT (old_gimage), REVERT_DATA_KEY, NULL);
464

465
  if (response_id == GTK_RESPONSE_OK)
466
    {
467
      Gimp              *gimp = old_gimage->gimp;
Michael Natterer's avatar
Michael Natterer committed
468
      GimpImage         *new_gimage;
469
      const gchar       *uri;
Michael Natterer's avatar
Michael Natterer committed
470
      GimpPDBStatusType  status;
471
      GError            *error = NULL;
472

473
      uri = gimp_object_get_name (GIMP_OBJECT (old_gimage));
474

475
      new_gimage = file_open_image (gimp, gimp_get_user_context (gimp),
476
                                    GIMP_PROGRESS (gdisp),
477
                                    uri, uri, NULL,
478 479
                                    GIMP_RUN_INTERACTIVE,
                                    &status, NULL, &error);
480

481
      if (new_gimage)
482 483
        {
          gimp_displays_reconnect (gimp, old_gimage, new_gimage);
484
          gimp_image_flush (new_gimage);
485 486 487

          /*  the displays own the image now  */
          g_object_unref (new_gimage);
488
        }
489
      else if (status != GIMP_PDB_CANCEL)
490
        {
491 492 493 494
          gchar *filename;

          filename = file_utils_uri_to_utf8_filename (uri);

495
          g_message (_("Reverting to '%s' failed:\n\n%s"),
496
                     filename, error->message);
497
          g_clear_error (&error);
498 499

          g_free (filename);
500
        }
501 502
    }
}