summaryrefslogtreecommitdiffstats
path: root/app/actions/file-commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/actions/file-commands.c')
-rw-r--r--app/actions/file-commands.c837
1 files changed, 837 insertions, 0 deletions
diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c
new file mode 100644
index 0000000..9e72f3e
--- /dev/null
+++ b/app/actions/file-commands.c
@@ -0,0 +1,837 @@
+/* GIMP - The GNU 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 3 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, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "actions-types.h"
+
+#include "config/gimpguiconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpimage.h"
+#include "core/gimpimagefile.h"
+#include "core/gimpprogress.h"
+#include "core/gimptemplate.h"
+
+#include "plug-in/gimppluginmanager-file.h"
+
+#include "file/file-open.h"
+#include "file/file-save.h"
+#include "file/gimp-file.h"
+
+#include "widgets/gimpactiongroup.h"
+#include "widgets/gimpclipboard.h"
+#include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpexportdialog.h"
+#include "widgets/gimpfiledialog.h"
+#include "widgets/gimphelp-ids.h"
+#include "widgets/gimpmessagebox.h"
+#include "widgets/gimpmessagedialog.h"
+#include "widgets/gimpopendialog.h"
+#include "widgets/gimpsavedialog.h"
+#include "widgets/gimpwidgets-utils.h"
+
+#include "display/gimpdisplay.h"
+#include "display/gimpdisplay-foreach.h"
+
+#include "dialogs/dialogs.h"
+#include "dialogs/file-save-dialog.h"
+
+#include "actions.h"
+#include "file-commands.h"
+
+#include "gimp-intl.h"
+
+
+/* local function prototypes */
+
+static void file_open_dialog_show (Gimp *gimp,
+ GtkWidget *parent,
+ const gchar *title,
+ GimpImage *image,
+ GFile *file,
+ gboolean open_as_layers);
+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);
+static GtkWidget * file_export_dialog_show (Gimp *gimp,
+ GimpImage *image,
+ GtkWidget *parent);
+static void file_save_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ gpointer data);
+static void file_export_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ gpointer data);
+static void file_new_template_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data);
+static void file_revert_confirm_response (GtkWidget *dialog,
+ gint response_id,
+ GimpDisplay *display);
+
+
+
+/* public functions */
+
+
+void
+file_open_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GtkWidget *widget;
+ GimpImage *image;
+ return_if_no_gimp (gimp, data);
+ return_if_no_widget (widget, data);
+
+ image = action_data_get_image (data);
+
+ file_open_dialog_show (gimp, widget,
+ _("Open Image"),
+ image, NULL, FALSE);
+}
+
+void
+file_open_as_layers_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GtkWidget *widget;
+ GimpDisplay *display;
+ GimpImage *image = NULL;
+ return_if_no_gimp (gimp, data);
+ return_if_no_widget (widget, data);
+
+ display = action_data_get_display (data);
+
+ if (display)
+ image = gimp_display_get_image (display);
+
+ file_open_dialog_show (gimp, widget,
+ _("Open Image as Layers"),
+ image, NULL, TRUE);
+}
+
+void
+file_open_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GtkWidget *widget;
+ return_if_no_widget (widget, data);
+
+ gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ NULL /*ui_manager*/,
+ "gimp-file-open-location-dialog", -1, TRUE);
+}
+
+void
+file_open_recent_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpImagefile *imagefile;
+ gint index;
+ gint num_entries;
+ return_if_no_gimp (gimp, data);
+
+ index = g_variant_get_int32 (value);
+
+ num_entries = gimp_container_get_n_children (gimp->documents);
+
+ if (index >= num_entries)
+ return;
+
+ imagefile = (GimpImagefile *)
+ gimp_container_get_child_by_index (gimp->documents, index);
+
+ if (imagefile)
+ {
+ GFile *file;
+ GimpDisplay *display;
+ GtkWidget *widget;
+ GimpProgress *progress;
+ GimpImage *image;
+ GimpPDBStatusType status;
+ GError *error = NULL;
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ g_object_ref (display);
+ g_object_ref (imagefile);
+
+ file = gimp_imagefile_get_file (imagefile);
+
+ progress = gimp_display_get_image (display) ?
+ NULL : GIMP_PROGRESS (display);
+
+ image = file_open_with_display (gimp, action_data_get_context (data),
+ progress,
+ file, FALSE,
+ G_OBJECT (gtk_widget_get_screen (widget)),
+ gimp_widget_get_monitor (widget),
+ &status, &error);
+
+ if (! image && status != GIMP_PDB_CANCEL)
+ {
+ gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
+ _("Opening '%s' failed:\n\n%s"),
+ gimp_file_get_utf8_name (file), error->message);
+ g_clear_error (&error);
+ }
+
+ g_object_unref (imagefile);
+ g_object_unref (display);
+ }
+}
+
+void
+file_save_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *widget;
+ GimpSaveMode save_mode;
+ GFile *file = NULL;
+ gboolean saved = FALSE;
+ return_if_no_gimp (gimp, data);
+ return_if_no_display (display, data);
+ return_if_no_widget (widget, data);
+
+ image = gimp_display_get_image (display);
+
+ save_mode = (GimpSaveMode) g_variant_get_int32 (value);
+
+ if (! gimp_image_get_active_drawable (image))
+ return;
+
+ file = gimp_image_get_file (image);
+
+ switch (save_mode)
+ {
+ case GIMP_SAVE_MODE_SAVE:
+ case GIMP_SAVE_MODE_SAVE_AND_CLOSE:
+ /* Only save if the image has been modified, or if it is new. */
+ if ((gimp_image_is_dirty (image) ||
+ ! GIMP_GUI_CONFIG (image->gimp->config)->trust_dirty_flag) ||
+ file == NULL)
+ {
+ GimpPlugInProcedure *save_proc = gimp_image_get_save_proc (image);
+
+ if (file && ! save_proc)
+ {
+ save_proc =
+ gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager,
+ GIMP_FILE_PROCEDURE_GROUP_SAVE,
+ file, NULL);
+ }
+
+ if (file && save_proc)
+ {
+ saved = file_save_dialog_save_image (GIMP_PROGRESS (display),
+ gimp, image, file,
+ save_proc,
+ GIMP_RUN_WITH_LAST_VALS,
+ TRUE, FALSE, FALSE,
+ gimp_image_get_xcf_compression (image),
+ TRUE);
+ break;
+ }
+
+ /* fall thru */
+ }
+ else
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (display), GIMP_MESSAGE_INFO,
+ _("No changes need to be saved"));
+ saved = TRUE;
+ break;
+ }
+
+ case GIMP_SAVE_MODE_SAVE_AS:
+ file_save_dialog_show (gimp, image, widget,
+ _("Save Image"), FALSE,
+ save_mode == GIMP_SAVE_MODE_SAVE_AND_CLOSE, display);
+ break;
+
+ case GIMP_SAVE_MODE_SAVE_A_COPY:
+ file_save_dialog_show (gimp, image, widget,
+ _("Save a Copy of the Image"), TRUE,
+ FALSE, display);
+ break;
+
+ case GIMP_SAVE_MODE_EXPORT_AS:
+ file_export_dialog_show (gimp, image, widget);
+ break;
+
+ case GIMP_SAVE_MODE_EXPORT:
+ case GIMP_SAVE_MODE_OVERWRITE:
+ {
+ GFile *file = NULL;
+ GimpPlugInProcedure *export_proc = NULL;
+ gboolean overwrite = FALSE;
+
+ if (save_mode == GIMP_SAVE_MODE_EXPORT)
+ {
+ file = gimp_image_get_exported_file (image);
+ export_proc = gimp_image_get_export_proc (image);
+
+ if (! file)
+ {
+ /* Behave as if Export As... was invoked */
+ file_export_dialog_show (gimp, image, widget);
+ break;
+ }
+
+ overwrite = FALSE;
+ }
+ else if (save_mode == GIMP_SAVE_MODE_OVERWRITE)
+ {
+ file = gimp_image_get_imported_file (image);
+
+ overwrite = TRUE;
+ }
+
+ if (file && ! export_proc)
+ {
+ export_proc =
+ gimp_plug_in_manager_file_procedure_find (image->gimp->plug_in_manager,
+ GIMP_FILE_PROCEDURE_GROUP_EXPORT,
+ file, NULL);
+ }
+
+ if (file && export_proc)
+ {
+ saved = file_save_dialog_save_image (GIMP_PROGRESS (display),
+ gimp, image, file,
+ export_proc,
+ GIMP_RUN_WITH_LAST_VALS,
+ FALSE,
+ overwrite, ! overwrite,
+ FALSE, TRUE);
+ }
+ }
+ break;
+ }
+
+ if (save_mode == GIMP_SAVE_MODE_SAVE_AND_CLOSE &&
+ saved &&
+ ! gimp_image_is_dirty (image))
+ {
+ gimp_display_close (display);
+ }
+}
+
+void
+file_create_template_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ dialog = gimp_query_string_box (_("Create New Template"),
+ GTK_WIDGET (gimp_display_get_shell (display)),
+ gimp_standard_help_func,
+ GIMP_HELP_FILE_CREATE_TEMPLATE,
+ _("Enter a name for this template"),
+ NULL,
+ G_OBJECT (image), "disconnect",
+ file_new_template_callback, image);
+ gtk_widget_show (dialog);
+}
+
+void
+file_revert_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ GimpDisplay *display;
+ GimpImage *image;
+ GtkWidget *dialog;
+ GFile *file;
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ file = gimp_image_get_file (image);
+
+ if (! file)
+ file = gimp_image_get_imported_file (image);
+
+ if (! file)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (display), GIMP_MESSAGE_ERROR,
+ _("Revert failed. "
+ "No file name associated with this image."));
+ return;
+ }
+
+#define REVERT_DIALOG_KEY "gimp-revert-confirm-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), REVERT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog =
+ gimp_message_dialog_new (_("Revert Image"), GIMP_ICON_DOCUMENT_REVERT,
+ GTK_WIDGET (gimp_display_get_shell (display)),
+ 0,
+ gimp_standard_help_func, GIMP_HELP_FILE_REVERT,
+
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Revert"), GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ g_signal_connect_object (display, "disconnect",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (file_revert_confirm_response),
+ display);
+
+ gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
+ _("Revert '%s' to '%s'?"),
+ gimp_image_get_display_name (image),
+ gimp_file_get_utf8_name (file));
+
+ 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."));
+
+ dialogs_attach_dialog (G_OBJECT (image), REVERT_DIALOG_KEY, dialog);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+}
+
+void
+file_close_all_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ return_if_no_gimp (gimp, data);
+
+ if (! gimp_displays_dirty (gimp))
+ {
+ gimp_displays_close (gimp);
+ }
+ else
+ {
+ GtkWidget *widget;
+ return_if_no_widget (widget, data);
+
+ gimp_dialog_factory_dialog_raise (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (widget),
+ gimp_widget_get_monitor (widget),
+ "gimp-close-all-dialog", -1);
+ }
+}
+
+void
+file_copy_location_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplay *display;
+ GimpImage *image;
+ GFile *file;
+ return_if_no_gimp (gimp, data);
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ file = gimp_image_get_any_file (image);
+
+ if (file)
+ {
+ gchar *uri = g_file_get_uri (file);
+
+ gimp_clipboard_set_text (gimp, uri);
+ g_free (uri);
+ }
+}
+
+void
+file_show_in_file_manager_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ GimpDisplay *display;
+ GimpImage *image;
+ GFile *file;
+ return_if_no_gimp (gimp, data);
+ return_if_no_display (display, data);
+
+ image = gimp_display_get_image (display);
+
+ file = gimp_image_get_any_file (image);
+
+ if (file)
+ {
+ GError *error = NULL;
+
+ if (! gimp_file_show_in_file_manager (file, &error))
+ {
+ gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
+ _("Can't show file in file manager: %s"),
+ error->message);
+ g_clear_error (&error);
+ }
+ }
+}
+
+void
+file_quit_cmd_callback (GimpAction *action,
+ GVariant *value,
+ gpointer data)
+{
+ Gimp *gimp;
+ return_if_no_gimp (gimp, data);
+
+ gimp_exit (gimp, FALSE);
+}
+
+void
+file_file_open_dialog (Gimp *gimp,
+ GFile *file,
+ GtkWidget *parent)
+{
+ file_open_dialog_show (gimp, parent,
+ _("Open Image"),
+ NULL, file, FALSE);
+}
+
+
+/* private functions */
+
+static void
+file_open_dialog_show (Gimp *gimp,
+ GtkWidget *parent,
+ const gchar *title,
+ GimpImage *image,
+ GFile *file,
+ gboolean open_as_layers)
+{
+ GtkWidget *dialog;
+
+ dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (parent),
+ gimp_widget_get_monitor (parent),
+ NULL /*ui_manager*/,
+ "gimp-file-open-dialog", -1, FALSE);
+
+ if (dialog)
+ {
+ if (! file && image)
+ file = gimp_image_get_file (image);
+
+ if (! file)
+ file = g_object_get_data (G_OBJECT (gimp),
+ GIMP_FILE_OPEN_LAST_FILE_KEY);
+
+ if (file)
+ {
+ gtk_file_chooser_set_file (GTK_FILE_CHOOSER (dialog), file, NULL);
+ }
+ else if (gimp->default_folder)
+ {
+ gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
+ gimp->default_folder, NULL);
+ }
+
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ gimp_open_dialog_set_image (GIMP_OPEN_DIALOG (dialog),
+ image, open_as_layers);
+
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_toplevel (parent)));
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+}
+
+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)
+{
+ GtkWidget *dialog;
+
+#define SAVE_DIALOG_KEY "gimp-file-save-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), SAVE_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (parent),
+ gimp_widget_get_monitor (parent),
+ NULL /*ui_manager*/,
+ "gimp-file-save-dialog",
+ -1, FALSE);
+
+ if (dialog)
+ {
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_toplevel (parent)));
+
+ dialogs_attach_dialog (G_OBJECT (image), SAVE_DIALOG_KEY, dialog);
+ g_signal_connect_object (image, "disconnect",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (file_save_dialog_response),
+ image);
+ }
+ }
+
+ if (dialog)
+ {
+ gtk_window_set_title (GTK_WINDOW (dialog), title);
+
+ gimp_save_dialog_set_image (GIMP_SAVE_DIALOG (dialog),
+ image, save_a_copy,
+ close_after_saving, GIMP_OBJECT (display));
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+
+ return dialog;
+}
+
+static void
+file_save_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ gpointer data)
+{
+ if (response_id == FILE_SAVE_RESPONSE_OTHER_DIALOG)
+ {
+ GimpFileDialog *file_dialog = GIMP_FILE_DIALOG (dialog);
+ GtkWindow *parent;
+ GtkWidget *other;
+ GFile *file;
+ gchar *folder;
+ gchar *basename;
+
+ parent = gtk_window_get_transient_for (GTK_WINDOW (dialog));
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ folder = g_path_get_dirname (gimp_file_get_utf8_name (file));
+ basename = g_path_get_basename (gimp_file_get_utf8_name (file));
+ g_object_unref (file);
+
+ other = file_export_dialog_show (GIMP_FILE_DIALOG (file_dialog)->image->gimp,
+ GIMP_FILE_DIALOG (file_dialog)->image,
+ GTK_WIDGET (parent));
+
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (other), folder);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (other), basename);
+
+ g_free (folder);
+ g_free (basename);
+ }
+}
+
+static GtkWidget *
+file_export_dialog_show (Gimp *gimp,
+ GimpImage *image,
+ GtkWidget *parent)
+{
+ GtkWidget *dialog;
+
+#define EXPORT_DIALOG_KEY "gimp-file-export-dialog"
+
+ dialog = dialogs_get_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY);
+
+ if (! dialog)
+ {
+ dialog = gimp_dialog_factory_dialog_new (gimp_dialog_factory_get_singleton (),
+ gtk_widget_get_screen (parent),
+ gimp_widget_get_monitor (parent),
+ NULL /*ui_manager*/,
+ "gimp-file-export-dialog",
+ -1, FALSE);
+
+ if (dialog)
+ {
+ gtk_window_set_transient_for (GTK_WINDOW (dialog),
+ GTK_WINDOW (gtk_widget_get_toplevel (parent)));
+
+ dialogs_attach_dialog (G_OBJECT (image), EXPORT_DIALOG_KEY, dialog);
+ g_signal_connect_object (image, "disconnect",
+ G_CALLBACK (gtk_widget_destroy),
+ dialog, G_CONNECT_SWAPPED);
+
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (file_export_dialog_response),
+ image);
+ }
+ }
+
+ if (dialog)
+ {
+ gimp_export_dialog_set_image (GIMP_EXPORT_DIALOG (dialog), image);
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ }
+
+ return dialog;
+}
+
+static void
+file_export_dialog_response (GtkWidget *dialog,
+ gint response_id,
+ gpointer data)
+{
+ if (response_id == FILE_SAVE_RESPONSE_OTHER_DIALOG)
+ {
+ GimpFileDialog *file_dialog = GIMP_FILE_DIALOG (dialog);
+ GtkWindow *parent;
+ GtkWidget *other;
+ GFile *file;
+ gchar *folder;
+ gchar *basename;
+
+ parent = gtk_window_get_transient_for (GTK_WINDOW (dialog));
+ file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+ folder = g_path_get_dirname (gimp_file_get_utf8_name (file));
+ basename = g_path_get_basename (gimp_file_get_utf8_name (file));
+ g_object_unref (file);
+
+ other = file_save_dialog_show (GIMP_FILE_DIALOG (file_dialog)->image->gimp,
+ GIMP_FILE_DIALOG (file_dialog)->image,
+ GTK_WIDGET (parent),
+ _("Save Image"),
+ FALSE, FALSE, NULL);
+
+ gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (other), folder);
+ gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (other), basename);
+
+ g_free (folder);
+ g_free (basename);
+ }
+}
+
+static void
+file_new_template_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data)
+{
+ GimpTemplate *template;
+ GimpImage *image;
+
+ image = (GimpImage *) data;
+
+ if (! (name && strlen (name)))
+ name = _("(Unnamed Template)");
+
+ template = gimp_template_new (name);
+ gimp_template_set_from_image (template, image);
+ gimp_container_add (image->gimp->templates, GIMP_OBJECT (template));
+ g_object_unref (template);
+}
+
+static void
+file_revert_confirm_response (GtkWidget *dialog,
+ gint response_id,
+ GimpDisplay *display)
+{
+ GimpImage *old_image = gimp_display_get_image (display);
+
+ gtk_widget_destroy (dialog);
+
+ if (response_id == GTK_RESPONSE_OK)
+ {
+ Gimp *gimp = old_image->gimp;
+ GimpImage *new_image;
+ GFile *file;
+ GimpPDBStatusType status;
+ GError *error = NULL;
+
+ file = gimp_image_get_file (old_image);
+
+ if (! file)
+ file = gimp_image_get_imported_file (old_image);
+
+ new_image = file_open_image (gimp, gimp_get_user_context (gimp),
+ GIMP_PROGRESS (display),
+ file, file, FALSE, NULL,
+ GIMP_RUN_INTERACTIVE,
+ &status, NULL, &error);
+
+ if (new_image)
+ {
+ gimp_displays_reconnect (gimp, old_image, new_image);
+ gimp_image_flush (new_image);
+
+ /* the displays own the image now */
+ g_object_unref (new_image);
+ }
+ else if (status != GIMP_PDB_CANCEL)
+ {
+ gimp_message (gimp, G_OBJECT (display), GIMP_MESSAGE_ERROR,
+ _("Reverting to '%s' failed:\n\n%s"),
+ gimp_file_get_utf8_name (file), error->message);
+ g_clear_error (&error);
+ }
+ }
+}