[gimp] Bug 736907 - Compat mode for XCF



commit 950f753ede1348fce9f5629b02c8b55a619eb10b
Author: Michael Natterer <mitch gimp org>
Date:   Sat Oct 4 02:26:36 2014 +0200

    Bug 736907 - Compat mode for XCF
    
    - add gimp_image_get,get_xcf_compat_mode()
    - add a compat toggle to GimpFileDialog which is shown and sensitive
      only for a save (not export), and if the image structure allows
      to save an old version at all. The button also has a tooltip
      which explains why it is sensitive and what it does
    - add "gboolean xcf_compat" to file_save_dialog_save_image()
    - in file_save_dialog_save_image(), call image_set_xcf_compat_mode(TRUE)
      only around the call to file_save() and set it to FALSE after saving
    - in xcf_save_invoker(), honor the image's XCF compat flag and save an
      RLE-compressed XCF if possible
    
    The above is very convoluted and doesn't pass the "xcf_compat" boolean
    directly because we can't change the parameters of gimp-xcf-save, and
    because the gimp-xcf-save might be called indirectly.

 app/actions/file-commands.c    |    5 ++-
 app/core/gimpimage-private.h   |    2 +
 app/core/gimpimage.c           |   17 ++++++++++
 app/core/gimpimage.h           |    4 ++
 app/dialogs/file-save-dialog.c |    8 +++++
 app/dialogs/file-save-dialog.h |    1 +
 app/widgets/gimpfiledialog.c   |   68 ++++++++++++++++++++++++++++++++++++++-
 app/widgets/gimpfiledialog.h   |    3 ++
 app/xcf/xcf.c                  |    9 +++++-
 9 files changed, 112 insertions(+), 5 deletions(-)
---
diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c
index fead957..598e3f7 100644
--- a/app/actions/file-commands.c
+++ b/app/actions/file-commands.c
@@ -264,7 +264,8 @@ file_save_cmd_callback (GtkAction *action,
                                                    gimp, image, file,
                                                    save_proc,
                                                    GIMP_RUN_WITH_LAST_VALS,
-                                                   TRUE, FALSE, FALSE, TRUE);
+                                                   TRUE, FALSE, FALSE,
+                                                   FALSE, TRUE);
               break;
             }
 
@@ -338,7 +339,7 @@ file_save_cmd_callback (GtkAction *action,
                                                  GIMP_RUN_WITH_LAST_VALS,
                                                  FALSE,
                                                  overwrite, ! overwrite,
-                                                 TRUE);
+                                                 FALSE, TRUE);
           }
       }
       break;
diff --git a/app/core/gimpimage-private.h b/app/core/gimpimage-private.h
index e7a87ad..6cec1c1 100644
--- a/app/core/gimpimage-private.h
+++ b/app/core/gimpimage-private.h
@@ -64,6 +64,8 @@ struct _GimpImagePrivate
   GFile             *save_a_copy_file;      /*  the image's save-a-copy file */
   GFile             *untitled_file;         /*  a file saying "Untitled"     */
 
+  gboolean           xcf_compat_mode;       /*  if possible, save compat XCF */
+
   gint               dirty;                 /*  dirty flag -- # of ops       */
   gint64             dirty_time;            /*  time when image became dirty */
   gint               export_dirty;          /*  'dirty' but for export       */
diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c
index 45ae8f9..809c989 100644
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -2364,6 +2364,23 @@ gimp_image_get_xcf_version (GimpImage    *image,
 }
 
 void
+gimp_image_set_xcf_compat_mode (GimpImage *image,
+                                gboolean   compat_mode)
+{
+  g_return_if_fail (GIMP_IS_IMAGE (image));
+
+  GIMP_IMAGE_GET_PRIVATE (image)->xcf_compat_mode = compat_mode;
+}
+
+gboolean
+gimp_image_get_xcf_compat_mode (const GimpImage *image)
+{
+  g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
+
+  return GIMP_IMAGE_GET_PRIVATE (image)->xcf_compat_mode;
+}
+
+void
 gimp_image_set_resolution (GimpImage *image,
                            gdouble    xresolution,
                            gdouble    yresolution)
diff --git a/app/core/gimpimage.h b/app/core/gimpimage.h
index 9b9716c..2562456 100644
--- a/app/core/gimpimage.h
+++ b/app/core/gimpimage.h
@@ -175,6 +175,10 @@ gint            gimp_image_get_xcf_version       (GimpImage          *image,
                                                   gint               *gimp_version,
                                                   const gchar       **version_string);
 
+void            gimp_image_set_xcf_compat_mode   (GimpImage          *image,
+                                                  gboolean            compat_mode);
+gboolean        gimp_image_get_xcf_compat_mode   (const GimpImage    *image);
+
 void            gimp_image_set_resolution        (GimpImage          *image,
                                                   gdouble             xres,
                                                   gdouble             yres);
diff --git a/app/dialogs/file-save-dialog.c b/app/dialogs/file-save-dialog.c
index d740b96..dc23396 100644
--- a/app/dialogs/file-save-dialog.c
+++ b/app/dialogs/file-save-dialog.c
@@ -204,6 +204,7 @@ file_save_dialog_response (GtkWidget *save_dialog,
                                        ! dialog->save_a_copy && ! dialog->export,
                                        FALSE,
                                        dialog->export,
+                                       ! dialog->export && dialog->compat,
                                        FALSE))
         {
           /* Save was successful, now store the URI in a couple of
@@ -742,6 +743,7 @@ file_save_dialog_save_image (GimpProgress        *progress,
                              gboolean             change_saved_state,
                              gboolean             export_backward,
                              gboolean             export_forward,
+                             gboolean             xcf_compat,
                              gboolean             verbose_cancel)
 {
   GimpPDBStatusType  status;
@@ -756,11 +758,17 @@ file_save_dialog_save_image (GimpProgress        *progress,
       gimp_action_group_set_action_sensitive (list->data, "file-quit", FALSE);
     }
 
+  if (xcf_compat)
+    gimp_image_set_xcf_compat_mode (image, TRUE);
+
   status = file_save (gimp, image, progress, file,
                       save_proc, run_mode,
                       change_saved_state, export_backward, export_forward,
                       &error);
 
+  if (xcf_compat)
+    gimp_image_set_xcf_compat_mode (image, FALSE);
+
   switch (status)
     {
     case GIMP_PDB_SUCCESS:
diff --git a/app/dialogs/file-save-dialog.h b/app/dialogs/file-save-dialog.h
index 92649eb..d3539c9 100644
--- a/app/dialogs/file-save-dialog.h
+++ b/app/dialogs/file-save-dialog.h
@@ -34,6 +34,7 @@ gboolean    file_save_dialog_save_image (GimpProgress        *progress_and_handl
                                          gboolean             save_a_copy,
                                          gboolean             export_backward,
                                          gboolean             export_forward,
+                                         gboolean             xcf_compat,
                                          gboolean             verbose_cancel);
 
 
diff --git a/app/widgets/gimpfiledialog.c b/app/widgets/gimpfiledialog.c
index 6631351..3718f45 100644
--- a/app/widgets/gimpfiledialog.c
+++ b/app/widgets/gimpfiledialog.c
@@ -98,6 +98,7 @@ static void     gimp_file_dialog_add_filters            (GimpFileDialog   *dialo
                                                                            action,
                                                          GSList           *file_procs,
                                                          GSList           *file_procs_all_images);
+static void     gimp_file_dialog_add_compat_toggle      (GimpFileDialog   *dialog);
 static void     gimp_file_dialog_process_procedure      (GimpPlugInProcedure
                                                                           *file_proc,
                                                          GtkFileFilter   **filter_out,
@@ -114,6 +115,8 @@ static void     gimp_file_dialog_selection_changed      (GtkFileChooser   *choos
 static void     gimp_file_dialog_update_preview         (GtkFileChooser   *chooser,
                                                          GimpFileDialog   *dialog);
 
+static void     gimp_file_dialog_compat_toggled         (GtkToggleButton  *button,
+                                                         GimpFileDialog   *dialog);
 static void     gimp_file_dialog_proc_changed           (GimpFileProcView *view,
                                                          GimpFileDialog   *dialog);
 
@@ -398,6 +401,13 @@ gimp_file_dialog_new (Gimp                  *gimp,
                                 file_procs,
                                 file_procs_all_images);
 
+  dialog->extra_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 4);
+  gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog),
+                                     dialog->extra_vbox);
+  gtk_widget_show (dialog->extra_vbox);
+
+  gimp_file_dialog_add_compat_toggle (dialog);
+
   gimp_file_dialog_add_proc_selection (dialog, gimp, file_procs, automatic,
                                        automatic_help_id);
 
@@ -496,6 +506,11 @@ gimp_file_dialog_set_save_image (GimpFileDialog *dialog,
 
   if (! export)
     {
+      gint         rle_version;
+      gint         zlib_version;
+      const gchar *version_string;
+      gchar       *tooltip;
+
       /*
        * Priority of default paths for Save:
        *
@@ -564,6 +579,32 @@ gimp_file_dialog_set_save_image (GimpFileDialog *dialog,
         g_object_ref (ext_file);
       else
         ext_file = g_file_new_for_uri ("file:///we/only/care/about/extension.xcf");
+
+      gimp_image_get_xcf_version (image, FALSE, &rle_version,  &version_string);
+      gimp_image_get_xcf_version (image, TRUE,  &zlib_version, NULL);
+
+      if (rle_version == zlib_version)
+        {
+          gtk_widget_set_sensitive (dialog->compat_toggle, FALSE);
+
+          tooltip = g_strdup_printf (_("The image uses features from %s and "
+                                       "cannot be saved for older GIMP "
+                                       "versions."),
+                                     version_string);
+        }
+      else
+        {
+          gtk_widget_set_sensitive (dialog->compat_toggle, TRUE);
+
+          tooltip = g_strdup_printf (_("Disables compression to make the XCF "
+                                       "file readable by %s and later."),
+                                     version_string);
+        }
+
+      gimp_help_set_help_data (dialog->compat_toggle, tooltip, NULL);
+      g_free (tooltip);
+
+      gtk_widget_show (dialog->compat_toggle);
     }
   else /* if (export) */
     {
@@ -642,8 +683,13 @@ gimp_file_dialog_set_save_image (GimpFileDialog *dialog,
         g_object_ref (ext_file);
       else
         ext_file = g_file_new_for_uri ("file:///we/only/care/about/extension.png");
+
+      gtk_widget_hide (dialog->compat_toggle);
     }
 
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->compat_toggle),
+                                FALSE);
+
   if (ext_file)
     {
       GFile *tmp_file = file_utils_file_with_new_ext (name_file, ext_file);
@@ -847,6 +893,17 @@ gimp_file_dialog_add_filters (GimpFileDialog        *dialog,
     gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), all);
 }
 
+static void
+gimp_file_dialog_add_compat_toggle (GimpFileDialog *dialog)
+{
+  dialog->compat_toggle = gtk_check_button_new_with_label (_("Save this XCF file with maximum 
compatibility"));
+  gtk_box_pack_start (GTK_BOX (dialog->extra_vbox), dialog->compat_toggle,
+                      FALSE, FALSE, 0);
+
+  g_signal_connect (dialog->compat_toggle, "toggled",
+                    G_CALLBACK (gimp_file_dialog_compat_toggled),
+                    dialog);
+}
 
 /**
  * gimp_file_dialog_process_procedure:
@@ -939,8 +996,8 @@ gimp_file_dialog_add_proc_selection (GimpFileDialog *dialog,
   GtkWidget *scrolled_window;
 
   dialog->proc_expander = gtk_expander_new_with_mnemonic (NULL);
-  gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog),
-                                     dialog->proc_expander);
+  gtk_box_pack_start (GTK_BOX (dialog->extra_vbox), dialog->proc_expander,
+                      TRUE, TRUE, 0);
   gtk_widget_show (dialog->proc_expander);
 
   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
@@ -982,6 +1039,13 @@ gimp_file_dialog_update_preview (GtkFileChooser *chooser,
 }
 
 static void
+gimp_file_dialog_compat_toggled (GtkToggleButton *button,
+                                 GimpFileDialog  *dialog)
+{
+  dialog->compat = gtk_toggle_button_get_active (button);
+}
+
+static void
 gimp_file_dialog_proc_changed (GimpFileProcView *view,
                                GimpFileDialog   *dialog)
 {
diff --git a/app/widgets/gimpfiledialog.h b/app/widgets/gimpfiledialog.h
index 90a82c4..723dd4c 100644
--- a/app/widgets/gimpfiledialog.h
+++ b/app/widgets/gimpfiledialog.h
@@ -44,10 +44,13 @@ struct _GimpFileDialog
   gboolean              open_as_layers;
   gboolean              save_a_copy;
   gboolean              export;
+  gboolean              compat;
   gboolean              close_after_saving;
   GimpObject           *display_to_close;
 
   GtkWidget            *thumb_box;
+  GtkWidget            *extra_vbox;
+  GtkWidget            *compat_toggle;
   GtkWidget            *proc_expander;
   GtkWidget            *proc_view;
   GtkWidget            *progress;
diff --git a/app/xcf/xcf.c b/app/xcf/xcf.c
index ff55a53..15c34ad 100644
--- a/app/xcf/xcf.c
+++ b/app/xcf/xcf.c
@@ -376,11 +376,18 @@ xcf_save_invoker (GimpProcedure         *procedure,
 
   if (info.output)
     {
+      gboolean compat_mode = gimp_image_get_xcf_compat_mode (image);
+
       info.gimp         = gimp;
       info.seekable     = G_SEEKABLE (info.output);
       info.progress     = progress;
       info.filename     = filename;
-      info.compression  = COMPRESS_ZLIB;
+
+      if (compat_mode)
+        info.compression = COMPRESS_RLE;
+      else
+        info.compression = COMPRESS_ZLIB;
+
       info.file_version = gimp_image_get_xcf_version (image,
                                                       info.compression ==
                                                       COMPRESS_ZLIB,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]