/* 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" #include #include #include "libgimpwidgets/gimpwidgets.h" #include "display-types.h" #include "config/gimpdisplayconfig.h" #include "core/gimp.h" #include "core/gimpimage.h" #include "file/file-utils.h" #include "widgets/gimphelp-ids.h" #include "widgets/gimpmessagebox.h" #include "widgets/gimpmessagedialog.h" #include "widgets/gimpuimanager.h" #include "gimpdisplay.h" #include "gimpdisplayshell.h" #include "gimpdisplayshell-close.h" #include "gimp-intl.h" /* local function prototypes */ static void gimp_display_shell_close_dialog (GimpDisplayShell *shell, GimpImage *gimage); static void gimp_display_shell_close_name_changed (GimpImage *image, GimpMessageBox *box); static gboolean gimp_display_shell_close_time_changed (GimpMessageBox *box); static void gimp_display_shell_close_response (GtkWidget *widget, gboolean close, GimpDisplayShell *shell); static gchar * gimp_time_since (guint then); /* public functions */ void gimp_display_shell_close (GimpDisplayShell *shell, gboolean kill_it) { GimpImage *gimage; g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell)); gimage = shell->gdisp->gimage; /* FIXME: gimp_busy HACK not really appropriate here because we only * want to prevent the busy image and display to be closed. --Mitch */ if (gimage->gimp->busy) return; /* If the image has been modified, give the user a chance to save * it before nuking it--this only applies if its the last view * to an image canvas. (a gimage with disp_count = 1) */ if (! kill_it && gimage->disp_count == 1 && gimage->dirty && GIMP_DISPLAY_CONFIG (gimage->gimp->config)->confirm_on_close) { gimp_display_shell_close_dialog (shell, gimage); } else { gimp_display_delete (shell->gdisp); } } /* private functions */ #define RESPONSE_SAVE 1 static void gimp_display_shell_close_dialog (GimpDisplayShell *shell, GimpImage *gimage) { GtkWidget *dialog; GimpMessageBox *box; GClosure *closure; GSource *source; gchar *name; gchar *title; if (shell->close_dialog) { gtk_window_present (GTK_WINDOW (shell->close_dialog)); return; } name = file_utils_uri_to_utf8_basename (gimp_image_get_uri (gimage)); title = g_strdup_printf (_("Close %s"), name); g_free (name); shell->close_dialog = dialog = gimp_message_dialog_new (title, GIMP_STOCK_WARNING, GTK_WIDGET (shell), GTK_DIALOG_DESTROY_WITH_PARENT, gimp_standard_help_func, NULL, _("Do_n't save"), GTK_RESPONSE_CLOSE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, RESPONSE_SAVE, NULL); g_free (title); gtk_dialog_set_default_response (GTK_DIALOG (dialog), RESPONSE_SAVE); g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_widget_destroyed), &shell->close_dialog); g_signal_connect (dialog, "response", G_CALLBACK (gimp_display_shell_close_response), shell); box = GIMP_MESSAGE_DIALOG (dialog)->box; g_signal_connect_object (gimage, "name_changed", G_CALLBACK (gimp_display_shell_close_name_changed), box, 0); gimp_display_shell_close_name_changed (gimage, box); closure = g_cclosure_new_object (G_CALLBACK (gimp_display_shell_close_time_changed), G_OBJECT (box)); source = g_timeout_source_new (1000); g_source_set_closure (source, closure); g_source_attach (source, NULL); /* The dialog is destroyed with the shell, so it should be safe * to hold an image pointer for the lifetime of the dialog. */ g_object_set_data (G_OBJECT (box), "gimp-image", gimage); gimp_display_shell_close_time_changed (box); gtk_widget_show (dialog); } static void gimp_display_shell_close_name_changed (GimpImage *image, GimpMessageBox *box) { GtkWidget *window = gtk_widget_get_toplevel (GTK_WIDGET (box)); gchar *name; name = file_utils_uri_to_utf8_basename (gimp_image_get_uri (image)); if (window) { gchar *title = g_strdup_printf (_("Close %s"), name); gtk_window_set_title (GTK_WINDOW (window), title); g_free (title); } gimp_message_box_set_primary_text (box, _("Save the changes to image '%s' " "before closing?"), name); g_free (name); } static gboolean gimp_display_shell_close_time_changed (GimpMessageBox *box) { GimpImage *image = g_object_get_data (G_OBJECT (box), "gimp-image"); if (image->dirty_time) { gchar *period = gimp_time_since (image->dirty_time); gimp_message_box_set_text (box, _("If you don't save the image, " "changes from the last %s will be lost."), period); g_free (period); } else { gimp_message_box_set_text (box, NULL); } return TRUE; } static void gimp_display_shell_close_response (GtkWidget *widget, gint response_id, GimpDisplayShell *shell) { gtk_widget_destroy (widget); switch (response_id) { case GTK_RESPONSE_CLOSE: gimp_display_delete (shell->gdisp); break; case RESPONSE_SAVE: { GtkAction *action; action = gimp_ui_manager_get_action (shell->menubar_manager, "file", "file-save"); g_return_if_fail (action != NULL); gtk_action_activate (action); if (! shell->gdisp->gimage->dirty) gimp_display_delete (shell->gdisp); } break; default: break; } } static gchar * gimp_time_since (guint then) { guint now = time (NULL); guint diff = 1 + now - then; g_return_val_if_fail (now >= then, NULL); if (diff == 1) /* one second, the time period */ return g_strdup (_("second")); if (diff < 60) return g_strdup_printf (_("%d seconds"), diff); /* round to the nearest minute */ diff = (diff + 30) / 60; if (diff == 1) return g_strdup (_("minute")); return g_strdup_printf (_("%d minutes"), diff); }