1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <string.h>
21 
22 #include <gegl.h>
23 #include <gtk/gtk.h>
24 
25 #include "libgimpbase/gimpbase.h"
26 #include "libgimpwidgets/gimpwidgets.h"
27 
28 #include "actions-types.h"
29 
30 #include "config/gimpguiconfig.h"
31 
32 #include "core/gimp.h"
33 #include "core/gimpcontainer.h"
34 #include "core/gimpimage.h"
35 #include "core/gimpimagefile.h"
36 #include "core/gimpprogress.h"
37 #include "core/gimptemplate.h"
38 
39 #include "plug-in/gimppluginmanager-file.h"
40 
41 #include "file/file-open.h"
42 #include "file/file-save.h"
43 #include "file/gimp-file.h"
44 
45 #include "widgets/gimpactiongroup.h"
46 #include "widgets/gimpclipboard.h"
47 #include "widgets/gimpdialogfactory.h"
48 #include "widgets/gimpexportdialog.h"
49 #include "widgets/gimpfiledialog.h"
50 #include "widgets/gimphelp-ids.h"
51 #include "widgets/gimpmessagebox.h"
52 #include "widgets/gimpmessagedialog.h"
53 #include "widgets/gimpopendialog.h"
54 #include "widgets/gimpsavedialog.h"
55 #include "widgets/gimpwidgets-utils.h"
56 
57 #include "display/gimpdisplay.h"
58 #include "display/gimpdisplay-foreach.h"
59 
60 #include "dialogs/dialogs.h"
61 #include "dialogs/file-save-dialog.h"
62 
63 #include "actions.h"
64 #include "file-commands.h"
65 
66 #include "gimp-intl.h"
67 
68 
69 /*  local function prototypes  */
70 
71 static void        file_open_dialog_show        (Gimp         *gimp,
72                                                  GtkWidget    *parent,
73                                                  const gchar  *title,
74                                                  GimpImage    *image,
75                                                  GFile        *file,
76                                                  gboolean      open_as_layers);
77 static GtkWidget * file_save_dialog_show        (Gimp         *gimp,
78                                                  GimpImage    *image,
79                                                  GtkWidget    *parent,
80                                                  const gchar  *title,
81                                                  gboolean      save_a_copy,
82                                                  gboolean      close_after_saving,
83                                                  GimpDisplay  *display);
84 static GtkWidget * file_export_dialog_show      (Gimp         *gimp,
85                                                  GimpImage    *image,
86                                                  GtkWidget    *parent);
87 static void        file_save_dialog_response    (GtkWidget    *dialog,
88                                                  gint          response_id,
89                                                  gpointer      data);
90 static void        file_export_dialog_response  (GtkWidget    *dialog,
91                                                  gint          response_id,
92                                                  gpointer      data);
93 static void        file_new_template_callback   (GtkWidget    *widget,
94                                                  const gchar  *name,
95                                                  gpointer      data);
96 static void        file_revert_confirm_response (GtkWidget    *dialog,
97                                                  gint          response_id,
98                                                  GimpDisplay  *display);
99 
100 
101 
102 /*  public functions  */
103 
104 
105 void
file_open_cmd_callback(GimpAction * action,GVariant * value,gpointer data)106 file_open_cmd_callback (GimpAction *action,
107                         GVariant   *value,
108                         gpointer    data)
109 {
110   Gimp        *gimp;
111   GtkWidget   *widget;
112   GimpImage   *image;
113   return_if_no_gimp (gimp, data);
114   return_if_no_widget (widget, data);
115 
116   image = action_data_get_image (data);
117 
118   file_open_dialog_show (gimp, widget,
119                          _("Open Image"),
120                          image, NULL, FALSE);
121 }
122 
123 void
file_open_as_layers_cmd_callback(GimpAction * action,GVariant * value,gpointer data)124 file_open_as_layers_cmd_callback (GimpAction *action,
125                                   GVariant   *value,
126                                   gpointer    data)
127 {
128   Gimp        *gimp;
129   GtkWidget   *widget;
130   GimpDisplay *display;
131   GimpImage   *image = NULL;
132   return_if_no_gimp (gimp, data);
133   return_if_no_widget (widget, data);
134 
135   display = action_data_get_display (data);
136 
137   if (display)
138     image = gimp_display_get_image (display);
139 
140   file_open_dialog_show (gimp, widget,
141                          _("Open Image as Layers"),
142                          image, NULL, TRUE);
143 }
144 
145 void
file_open_location_cmd_callback(GimpAction * action,GVariant * value,gpointer data)146 file_open_location_cmd_callback (GimpAction *action,
147                                  GVariant   *value,
148                                  gpointer    data)
149 {
150   GtkWidget *widget;
151   return_if_no_widget (widget, data);
152 
153   gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
154                                   gtk_widget_get_screen (widget),
155                                   gimp_widget_get_monitor (widget),
156                                   NULL /*ui_manager*/,
157                                   "gimp-file-open-location-dialog", -1, TRUE);
158 }
159 
160 void
file_open_recent_cmd_callback(GimpAction * action,GVariant * value,gpointer data)161 file_open_recent_cmd_callback (GimpAction *action,
162                                GVariant   *value,
163                                gpointer    data)
164 {
165   Gimp          *gimp;
166   GimpImagefile *imagefile;
167   gint           index;
168   gint           num_entries;
169   return_if_no_gimp (gimp, data);
170 
171   index = g_variant_get_int32 (value);
172 
173   num_entries = gimp_container_get_n_children (gimp->documents);
174 
175   if (index >= num_entries)
176     return;
177 
178   imagefile = (GimpImagefile *)
179     gimp_container_get_child_by_index (gimp->documents, index);
180 
181   if (imagefile)
182     {
183       GFile             *file;
184       GimpDisplay       *display;
185       GtkWidget         *widget;
186       GimpProgress      *progress;
187       GimpImage         *image;
188       GimpPDBStatusType  status;
189       GError            *error = NULL;
190       return_if_no_display (display, data);
191       return_if_no_widget (widget, data);
192 
193       g_object_ref (display);
194       g_object_ref (imagefile);
195 
196       file = gimp_imagefile_get_file (imagefile);
197 
198       progress = gimp_display_get_image (display) ?
199                  NULL : GIMP_PROGRESS (display);
200 
201       image = file_open_with_display (gimp, action_data_get_context (data),
202                                       progress,
203                                       file, FALSE,
204                                       G_OBJECT (gtk_widget_get_screen (widget)),
205                                       gimp_widget_get_monitor (widget),
206                                       &status, &error);
207 
208       if (! image && status != GIMP_PDB_CANCEL)
209         {
210           gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
211                         _("Opening '%s' failed:\n\n%s"),
212                         gimp_file_get_utf8_name (file), error->message);
213           g_clear_error (&error);
214         }
215 
216       g_object_unref (imagefile);
217       g_object_unref (display);
218     }
219 }
220 
221 void
file_save_cmd_callback(GimpAction * action,GVariant * value,gpointer data)222 file_save_cmd_callback (GimpAction *action,
223                         GVariant   *value,
224                         gpointer    data)
225 {
226   Gimp         *gimp;
227   GimpDisplay  *display;
228   GimpImage    *image;
229   GtkWidget    *widget;
230   GimpSaveMode  save_mode;
231   GFile        *file  = NULL;
232   gboolean      saved = FALSE;
233   return_if_no_gimp (gimp, data);
234   return_if_no_display (display, data);
235   return_if_no_widget (widget, data);
236 
237   image = gimp_display_get_image (display);
238 
239   save_mode = (GimpSaveMode) g_variant_get_int32 (value);
240 
241   if (! gimp_image_get_active_drawable (image))
242     return;
243 
244   file = gimp_image_get_file (image);
245 
246   switch (save_mode)
247     {
248     case GIMP_SAVE_MODE_SAVE:
249     case GIMP_SAVE_MODE_SAVE_AND_CLOSE:
250       /*  Only save if the image has been modified, or if it is new.  */
251       if ((gimp_image_is_dirty (image) ||
252            ! GIMP_GUI_CONFIG (image->gimp->config)->trust_dirty_flag) ||
253           file == NULL)
254         {
255           GimpPlugInProcedure *save_proc = gimp_image_get_save_proc (image);
256 
257           if (file && ! save_proc)
258             {
259               save_proc =
260                 gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager,
261                                                           GIMP_FILE_PROCEDURE_GROUP_SAVE,
262                                                           file, NULL);
263             }
264 
265           if (file && save_proc)
266             {
267               saved = file_save_dialog_save_image (GIMP_PROGRESS (display),
268                                                    gimp, image, file,
269                                                    save_proc,
270                                                    GIMP_RUN_WITH_LAST_VALS,
271                                                    TRUE, FALSE, FALSE,
272                                                    gimp_image_get_xcf_compression (image),
273                                                    TRUE);
274               break;
275             }
276 
277           /* fall thru */
278         }
279       else
280         {
281           gimp_message_literal (image->gimp,
282                                 G_OBJECT (display), GIMP_MESSAGE_INFO,
283                                 _("No changes need to be saved"));
284           saved = TRUE;
285           break;
286         }
287 
288     case GIMP_SAVE_MODE_SAVE_AS:
289       file_save_dialog_show (gimp, image, widget,
290                              _("Save Image"), FALSE,
291                              save_mode == GIMP_SAVE_MODE_SAVE_AND_CLOSE, display);
292       break;
293 
294     case GIMP_SAVE_MODE_SAVE_A_COPY:
295       file_save_dialog_show (gimp, image, widget,
296                              _("Save a Copy of the Image"), TRUE,
297                              FALSE, display);
298       break;
299 
300     case GIMP_SAVE_MODE_EXPORT_AS:
301       file_export_dialog_show (gimp, image, widget);
302       break;
303 
304     case GIMP_SAVE_MODE_EXPORT:
305     case GIMP_SAVE_MODE_OVERWRITE:
306       {
307         GFile               *file        = NULL;
308         GimpPlugInProcedure *export_proc = NULL;
309         gboolean             overwrite   = FALSE;
310 
311         if (save_mode == GIMP_SAVE_MODE_EXPORT)
312           {
313             file        = gimp_image_get_exported_file (image);
314             export_proc = gimp_image_get_export_proc (image);
315 
316             if (! file)
317               {
318                 /* Behave as if Export As... was invoked */
319                 file_export_dialog_show (gimp, image, widget);
320                 break;
321               }
322 
323             overwrite = FALSE;
324           }
325         else if (save_mode == GIMP_SAVE_MODE_OVERWRITE)
326           {
327             file = gimp_image_get_imported_file (image);
328 
329             overwrite = TRUE;
330           }
331 
332         if (file && ! export_proc)
333           {
334             export_proc =
335               gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager,
336                                                         GIMP_FILE_PROCEDURE_GROUP_EXPORT,
337                                                         file, NULL);
338           }
339 
340         if (file && export_proc)
341           {
342             saved = file_save_dialog_save_image (GIMP_PROGRESS (display),
343                                                  gimp, image, file,
344                                                  export_proc,
345                                                  GIMP_RUN_WITH_LAST_VALS,
346                                                  FALSE,
347                                                  overwrite, ! overwrite,
348                                                  FALSE, TRUE);
349           }
350       }
351       break;
352     }
353 
354   if (save_mode == GIMP_SAVE_MODE_SAVE_AND_CLOSE &&
355       saved &&
356       ! gimp_image_is_dirty (image))
357     {
358       gimp_display_close (display);
359     }
360 }
361 
362 void
file_create_template_cmd_callback(GimpAction * action,GVariant * value,gpointer data)363 file_create_template_cmd_callback (GimpAction *action,
364                                    GVariant   *value,
365                                    gpointer    data)
366 {
367   GimpDisplay *display;
368   GimpImage   *image;
369   GtkWidget   *dialog;
370   return_if_no_display (display, data);
371 
372   image = gimp_display_get_image (display);
373 
374   dialog = gimp_query_string_box (_("Create New Template"),
375                                   GTK_WIDGET (gimp_display_get_shell (display)),
376                                   gimp_standard_help_func,
377                                   GIMP_HELP_FILE_CREATE_TEMPLATE,
378                                   _("Enter a name for this template"),
379                                   NULL,
380                                   G_OBJECT (image), "disconnect",
381                                   file_new_template_callback, image);
382   gtk_widget_show (dialog);
383 }
384 
385 void
file_revert_cmd_callback(GimpAction * action,GVariant * value,gpointer data)386 file_revert_cmd_callback (GimpAction *action,
387                           GVariant   *value,
388                           gpointer    data)
389 {
390   GimpDisplay *display;
391   GimpImage   *image;
392   GtkWidget   *dialog;
393   GFile       *file;
394   return_if_no_display (display, data);
395 
396   image = gimp_display_get_image (display);
397 
398   file = gimp_image_get_file (image);
399 
400   if (! file)
401     file = gimp_image_get_imported_file (image);
402 
403   if (! file)
404     {
405       gimp_message_literal (image->gimp,
406                             G_OBJECT (display), GIMP_MESSAGE_ERROR,
407                             _("Revert failed. "
408                               "No file name associated with this image."));
409       return;
410     }
411 
412 #define REVERT_DIALOG_KEY "gimp-revert-confirm-dialog"
413 
414   dialog = dialogs_get_dialog (G_OBJECT (image), REVERT_DIALOG_KEY);
415 
416   if (! dialog)
417     {
418       dialog =
419         gimp_message_dialog_new (_("Revert Image"), GIMP_ICON_DOCUMENT_REVERT,
420                                  GTK_WIDGET (gimp_display_get_shell (display)),
421                                  0,
422                                  gimp_standard_help_func, GIMP_HELP_FILE_REVERT,
423 
424                                  _("_Cancel"), GTK_RESPONSE_CANCEL,
425                                  _("_Revert"), GTK_RESPONSE_OK,
426 
427                                  NULL);
428 
429       gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
430                                                GTK_RESPONSE_OK,
431                                                GTK_RESPONSE_CANCEL,
432                                                -1);
433 
434       g_signal_connect_object (display, "disconnect",
435                                G_CALLBACK (gtk_widget_destroy),
436                                dialog, G_CONNECT_SWAPPED);
437 
438       g_signal_connect (dialog, "response",
439                         G_CALLBACK (file_revert_confirm_response),
440                         display);
441 
442       gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
443                                          _("Revert '%s' to '%s'?"),
444                                          gimp_image_get_display_name (image),
445                                          gimp_file_get_utf8_name (file));
446 
447       gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
448                                  _("By reverting the image to the state saved "
449                                    "on disk, you will lose all changes, "
450                                    "including all undo information."));
451 
452       dialogs_attach_dialog (G_OBJECT (image), REVERT_DIALOG_KEY, dialog);
453     }
454 
455   gtk_window_present (GTK_WINDOW (dialog));
456 }
457 
458 void
file_close_all_cmd_callback(GimpAction * action,GVariant * value,gpointer data)459 file_close_all_cmd_callback (GimpAction *action,
460                              GVariant   *value,
461                              gpointer    data)
462 {
463   Gimp *gimp;
464   return_if_no_gimp (gimp, data);
465 
466   if (! gimp_displays_dirty (gimp))
467     {
468       gimp_displays_close (gimp);
469     }
470   else
471     {
472       GtkWidget *widget;
473       return_if_no_widget (widget, data);
474 
475       gimp_dialog_factory_dialog_raise (gimp_dialog_factory_get_singleton (),
476                                         gtk_widget_get_screen (widget),
477                                         gimp_widget_get_monitor (widget),
478                                         "gimp-close-all-dialog", -1);
479     }
480 }
481 
482 void
file_copy_location_cmd_callback(GimpAction * action,GVariant * value,gpointer data)483 file_copy_location_cmd_callback (GimpAction *action,
484                                  GVariant   *value,
485                                  gpointer    data)
486 {
487   Gimp         *gimp;
488   GimpDisplay  *display;
489   GimpImage    *image;
490   GFile        *file;
491   return_if_no_gimp (gimp, data);
492   return_if_no_display (display, data);
493 
494   image = gimp_display_get_image (display);
495 
496   file = gimp_image_get_any_file (image);
497 
498   if (file)
499     {
500       gchar *uri = g_file_get_uri (file);
501 
502       gimp_clipboard_set_text (gimp, uri);
503       g_free (uri);
504     }
505 }
506 
507 void
file_show_in_file_manager_cmd_callback(GimpAction * action,GVariant * value,gpointer data)508 file_show_in_file_manager_cmd_callback (GimpAction *action,
509                                         GVariant   *value,
510                                         gpointer    data)
511 {
512   Gimp         *gimp;
513   GimpDisplay  *display;
514   GimpImage    *image;
515   GFile        *file;
516   return_if_no_gimp (gimp, data);
517   return_if_no_display (display, data);
518 
519   image = gimp_display_get_image (display);
520 
521   file = gimp_image_get_any_file (image);
522 
523   if (file)
524     {
525       GError *error = NULL;
526 
527       if (! gimp_file_show_in_file_manager (file, &error))
528         {
529           gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
530                         _("Can't show file in file manager: %s"),
531                         error->message);
532           g_clear_error (&error);
533         }
534     }
535 }
536 
537 void
file_quit_cmd_callback(GimpAction * action,GVariant * value,gpointer data)538 file_quit_cmd_callback (GimpAction *action,
539                         GVariant   *value,
540                         gpointer    data)
541 {
542   Gimp *gimp;
543   return_if_no_gimp (gimp, data);
544 
545   gimp_exit (gimp, FALSE);
546 }
547 
548 void
file_file_open_dialog(Gimp * gimp,GFile * file,GtkWidget * parent)549 file_file_open_dialog (Gimp      *gimp,
550                        GFile     *file,
551                        GtkWidget *parent)
552 {
553   file_open_dialog_show (gimp, parent,
554                          _("Open Image"),
555                          NULL, file, FALSE);
556 }
557 
558 
559 /*  private functions  */
560 
561 static void
file_open_dialog_show(Gimp * gimp,GtkWidget * parent,const gchar * title,GimpImage * image,GFile * file,gboolean open_as_layers)562 file_open_dialog_show (Gimp        *gimp,
563                        GtkWidget   *parent,
564                        const gchar *title,
565                        GimpImage   *image,
566                        GFile       *file,
567                        gboolean     open_as_layers)
568 {
569   GtkWidget *dialog;
570 
571   dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
572                                            gtk_widget_get_screen (parent),
573                                            gimp_widget_get_monitor (parent),
574                                            NULL /*ui_manager*/,
575                                            "gimp-file-open-dialog", -1, FALSE);
576 
577   if (dialog)
578     {
579       if (! file && image)
580         file = gimp_image_get_file (image);
581 
582       if (! file)
583         file = g_object_get_data (G_OBJECT (gimp),
584                                   GIMP_FILE_OPEN_LAST_FILE_KEY);
585 
586       if (file)
587         {
588           gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog), file, NULL);
589         }
590       else if (gimp->default_folder)
591         {
592           gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
593                                                     gimp->default_folder, NULL);
594         }
595 
596       gtk_window_set_title (GTK_WINDOW (dialog), title);
597 
598       gimp_open_dialog_set_image (GIMP_OPEN_DIALOG (dialog),
599                                   image, open_as_layers);
600 
601       gtk_window_set_transient_for (GTK_WINDOW (dialog),
602                                     GTK_WINDOW (gtk_widget_get_toplevel (parent)));
603 
604       gtk_window_present (GTK_WINDOW (dialog));
605     }
606 }
607 
608 static GtkWidget *
file_save_dialog_show(Gimp * gimp,GimpImage * image,GtkWidget * parent,const gchar * title,gboolean save_a_copy,gboolean close_after_saving,GimpDisplay * display)609 file_save_dialog_show (Gimp        *gimp,
610                        GimpImage   *image,
611                        GtkWidget   *parent,
612                        const gchar *title,
613                        gboolean     save_a_copy,
614                        gboolean     close_after_saving,
615                        GimpDisplay *display)
616 {
617   GtkWidget *dialog;
618 
619 #define SAVE_DIALOG_KEY "gimp-file-save-dialog"
620 
621   dialog = dialogs_get_dialog (G_OBJECT (image), SAVE_DIALOG_KEY);
622 
623   if (! dialog)
624     {
625       dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
626                                                gtk_widget_get_screen (parent),
627                                                gimp_widget_get_monitor (parent),
628                                                NULL /*ui_manager*/,
629                                                "gimp-file-save-dialog",
630                                                -1, FALSE);
631 
632       if (dialog)
633         {
634           gtk_window_set_transient_for (GTK_WINDOW (dialog),
635                                         GTK_WINDOW (gtk_widget_get_toplevel (parent)));
636 
637           dialogs_attach_dialog (G_OBJECT (image), SAVE_DIALOG_KEY, dialog);
638           g_signal_connect_object (image, "disconnect",
639                                    G_CALLBACK (gtk_widget_destroy),
640                                    dialog, G_CONNECT_SWAPPED);
641 
642           g_signal_connect (dialog, "response",
643                             G_CALLBACK (file_save_dialog_response),
644                             image);
645         }
646     }
647 
648   if (dialog)
649     {
650       gtk_window_set_title (GTK_WINDOW (dialog), title);
651 
652       gimp_save_dialog_set_image (GIMP_SAVE_DIALOG (dialog),
653                                   image, save_a_copy,
654                                   close_after_saving, GIMP_OBJECT (display));
655 
656       gtk_window_present (GTK_WINDOW (dialog));
657     }
658 
659   return dialog;
660 }
661 
662 static void
file_save_dialog_response(GtkWidget * dialog,gint response_id,gpointer data)663 file_save_dialog_response (GtkWidget *dialog,
664                            gint       response_id,
665                            gpointer   data)
666 {
667   if (response_id == FILE_SAVE_RESPONSE_OTHER_DIALOG)
668     {
669       GimpFileDialog *file_dialog = GIMP_FILE_DIALOG (dialog);
670       GtkWindow      *parent;
671       GtkWidget      *other;
672       GFile          *file;
673       gchar          *folder;
674       gchar          *basename;
675 
676       parent   = gtk_window_get_transient_for (GTK_WINDOW (dialog));
677       file     = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
678       folder   = g_path_get_dirname (gimp_file_get_utf8_name (file));
679       basename = g_path_get_basename (gimp_file_get_utf8_name (file));
680       g_object_unref (file);
681 
682       other = file_export_dialog_show (GIMP_FILE_DIALOG (file_dialog)->image->gimp,
683                                        GIMP_FILE_DIALOG (file_dialog)->image,
684                                        GTK_WIDGET (parent));
685 
686       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (other), folder);
687       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (other), basename);
688 
689       g_free (folder);
690       g_free (basename);
691     }
692 }
693 
694 static GtkWidget *
file_export_dialog_show(Gimp * gimp,GimpImage * image,GtkWidget * parent)695 file_export_dialog_show (Gimp      *gimp,
696                          GimpImage *image,
697                          GtkWidget *parent)
698 {
699   GtkWidget *dialog;
700 
701 #define EXPORT_DIALOG_KEY "gimp-file-export-dialog"
702 
703   dialog = dialogs_get_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY);
704 
705   if (! dialog)
706     {
707       dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
708                                                gtk_widget_get_screen (parent),
709                                                gimp_widget_get_monitor (parent),
710                                                NULL /*ui_manager*/,
711                                                "gimp-file-export-dialog",
712                                                -1, FALSE);
713 
714       if (dialog)
715         {
716           gtk_window_set_transient_for (GTK_WINDOW (dialog),
717                                         GTK_WINDOW (gtk_widget_get_toplevel (parent)));
718 
719           dialogs_attach_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY, dialog);
720           g_signal_connect_object (image, "disconnect",
721                                    G_CALLBACK (gtk_widget_destroy),
722                                    dialog, G_CONNECT_SWAPPED);
723 
724           g_signal_connect (dialog, "response",
725                             G_CALLBACK (file_export_dialog_response),
726                             image);
727         }
728     }
729 
730   if (dialog)
731     {
732       gimp_export_dialog_set_image (GIMP_EXPORT_DIALOG (dialog), image);
733 
734       gtk_window_present (GTK_WINDOW (dialog));
735     }
736 
737   return dialog;
738 }
739 
740 static void
file_export_dialog_response(GtkWidget * dialog,gint response_id,gpointer data)741 file_export_dialog_response (GtkWidget *dialog,
742                              gint       response_id,
743                              gpointer   data)
744 {
745   if (response_id == FILE_SAVE_RESPONSE_OTHER_DIALOG)
746     {
747       GimpFileDialog *file_dialog = GIMP_FILE_DIALOG (dialog);
748       GtkWindow      *parent;
749       GtkWidget      *other;
750       GFile          *file;
751       gchar          *folder;
752       gchar          *basename;
753 
754       parent   = gtk_window_get_transient_for (GTK_WINDOW (dialog));
755       file     = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
756       folder   = g_path_get_dirname (gimp_file_get_utf8_name (file));
757       basename = g_path_get_basename (gimp_file_get_utf8_name (file));
758       g_object_unref (file);
759 
760       other = file_save_dialog_show (GIMP_FILE_DIALOG (file_dialog)->image->gimp,
761                                      GIMP_FILE_DIALOG (file_dialog)->image,
762                                      GTK_WIDGET (parent),
763                                      _("Save Image"),
764                                      FALSE, FALSE, NULL);
765 
766       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (other), folder);
767       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (other), basename);
768 
769       g_free (folder);
770       g_free (basename);
771     }
772 }
773 
774 static void
file_new_template_callback(GtkWidget * widget,const gchar * name,gpointer data)775 file_new_template_callback (GtkWidget   *widget,
776                             const gchar *name,
777                             gpointer     data)
778 {
779   GimpTemplate *template;
780   GimpImage    *image;
781 
782   image = (GimpImage *) data;
783 
784   if (! (name && strlen (name)))
785     name = _("(Unnamed Template)");
786 
787   template = gimp_template_new (name);
788   gimp_template_set_from_image (template, image);
789   gimp_container_add (image->gimp->templates, GIMP_OBJECT (template));
790   g_object_unref (template);
791 }
792 
793 static void
file_revert_confirm_response(GtkWidget * dialog,gint response_id,GimpDisplay * display)794 file_revert_confirm_response (GtkWidget   *dialog,
795                               gint         response_id,
796                               GimpDisplay *display)
797 {
798   GimpImage *old_image = gimp_display_get_image (display);
799 
800   gtk_widget_destroy (dialog);
801 
802   if (response_id == GTK_RESPONSE_OK)
803     {
804       Gimp              *gimp = old_image->gimp;
805       GimpImage         *new_image;
806       GFile             *file;
807       GimpPDBStatusType  status;
808       GError            *error = NULL;
809 
810       file = gimp_image_get_file (old_image);
811 
812       if (! file)
813         file = gimp_image_get_imported_file (old_image);
814 
815       new_image = file_open_image (gimp, gimp_get_user_context (gimp),
816                                    GIMP_PROGRESS (display),
817                                    file, file, FALSE, NULL,
818                                    GIMP_RUN_INTERACTIVE,
819                                    &status, NULL, &error);
820 
821       if (new_image)
822         {
823           gimp_displays_reconnect (gimp, old_image, new_image);
824           gimp_image_flush (new_image);
825 
826           /*  the displays own the image now  */
827           g_object_unref (new_image);
828         }
829       else if (status != GIMP_PDB_CANCEL)
830         {
831           gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
832                         _("Reverting to '%s' failed:\n\n%s"),
833                         gimp_file_get_utf8_name (file), error->message);
834           g_clear_error (&error);
835         }
836     }
837 }
838