[gimp/GimpFileDialog-refactoring: 1/3] app: split GimpFileDialog into Gimp(Open|Save|Export)Dialog subclasses.



commit 6aafdeceff935f7e4c9de03e0554234a6504d643
Author: Jehan <jehan girinstud io>
Date:   Mon Aug 31 20:57:37 2015 +0200

    app: split GimpFileDialog into Gimp(Open|Save|Export)Dialog subclasses.
    
    The code refactoring allows better readability which will allow in turn
    to add more complex specific features making good use of the save/export
    split concept.

 app/actions/file-commands.c     |   26 +-
 app/dialogs/file-open-dialog.c  |   23 +-
 app/dialogs/file-save-dialog.c  |   78 ++--
 app/widgets/Makefile.am         |    6 +
 app/widgets/gimpexportdialog.c  |  258 +++++++++++++
 app/widgets/gimpexportdialog.h  |   59 +++
 app/widgets/gimpfiledialog.c    |  798 ++++++++++++++-------------------------
 app/widgets/gimpfiledialog.h    |   55 ++--
 app/widgets/gimpopendialog.c    |  104 +++++
 app/widgets/gimpopendialog.h    |   59 +++
 app/widgets/gimpsavedialog.c    |  333 ++++++++++++++++
 app/widgets/gimpsavedialog.h    |   69 ++++
 app/widgets/widgets-enums.h     |    7 -
 app/widgets/widgets-types.h     |    7 +-
 devel-docs/app/app-sections.txt |    1 -
 15 files changed, 1262 insertions(+), 621 deletions(-)
---
diff --git a/app/actions/file-commands.c b/app/actions/file-commands.c
index 2ed08b5..33ae8ee 100644
--- a/app/actions/file-commands.c
+++ b/app/actions/file-commands.c
@@ -46,10 +46,13 @@
 #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"
@@ -596,8 +599,8 @@ file_open_dialog_show (Gimp        *gimp,
         gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
                                                   gimp->default_folder, NULL);
 
-      gimp_file_dialog_set_open_image (GIMP_FILE_DIALOG (dialog),
-                                       image, open_as_layers);
+      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)));
@@ -649,9 +652,9 @@ file_save_dialog_show (Gimp        *gimp,
     {
       gtk_window_set_title (GTK_WINDOW (dialog), title);
 
-      gimp_file_dialog_set_save_image (GIMP_FILE_DIALOG (dialog),
-                                       gimp, image, save_a_copy, FALSE,
-                                       close_after_saving, GIMP_OBJECT (display));
+      gimp_save_dialog_set_image (GIMP_SAVE_DIALOG (dialog),
+                                  gimp, image, save_a_copy,
+                                  close_after_saving, GIMP_OBJECT (display));
 
       gtk_window_present (GTK_WINDOW (dialog));
     }
@@ -679,8 +682,8 @@ file_save_dialog_response (GtkWidget *dialog,
       basename = g_path_get_basename (gimp_file_get_utf8_name (file));
       g_object_unref (file);
 
-      other = file_export_dialog_show (file_dialog->image->gimp,
-                                       file_dialog->image,
+      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_file (GTK_FILE_CHOOSER (other),
@@ -737,9 +740,8 @@ file_export_dialog_show (Gimp      *gimp,
 
   if (dialog)
     {
-      gimp_file_dialog_set_save_image (GIMP_FILE_DIALOG (dialog),
-                                       gimp, image, FALSE, TRUE,
-                                       FALSE, NULL);
+      gimp_export_dialog_set_image (GIMP_EXPORT_DIALOG (dialog),
+                                    gimp, image);
 
       gtk_window_present (GTK_WINDOW (dialog));
     }
@@ -767,8 +769,8 @@ file_export_dialog_response (GtkWidget *dialog,
       basename = g_path_get_basename (gimp_file_get_utf8_name (file));
       g_object_unref (file);
 
-      other = file_save_dialog_show (file_dialog->image->gimp,
-                                     file_dialog->image,
+      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);
diff --git a/app/dialogs/file-open-dialog.c b/app/dialogs/file-open-dialog.c
index d250627..362025b 100644
--- a/app/dialogs/file-open-dialog.c
+++ b/app/dialogs/file-open-dialog.c
@@ -40,6 +40,7 @@
 
 #include "widgets/gimpfiledialog.h"
 #include "widgets/gimphelp-ids.h"
+#include "widgets/gimpopendialog.h"
 #include "widgets/gimpwidgets-utils.h"
 
 #include "file-open-dialog.h"
@@ -72,11 +73,7 @@ file_open_dialog_new (Gimp *gimp)
 
   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
 
-  dialog = gimp_file_dialog_new (gimp,
-                                 GIMP_FILE_CHOOSER_ACTION_OPEN,
-                                 _("Open Image"), "gimp-file-open",
-                                 GTK_STOCK_OPEN,
-                                 GIMP_HELP_FILE_OPEN);
+  dialog = gimp_open_dialog_new (gimp);
 
   gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dialog), TRUE);
 
@@ -132,27 +129,27 @@ file_open_dialog_response (GtkWidget *open_dialog,
    * will pull the image window it was invoked from on top of all the
    * new opened image windows, and we don't want that to happen.
    */
-  if (! dialog->open_as_layers)
+  if (! GIMP_OPEN_DIALOG (dialog)->open_as_layers)
     gtk_window_set_transient_for (GTK_WINDOW (open_dialog), NULL);
 
   for (list = files; list; list = g_slist_next (list))
     {
       GFile *file = list->data;
 
-      if (dialog->open_as_layers)
+      if (GIMP_OPEN_DIALOG (dialog)->open_as_layers)
         {
-          if (! dialog->image)
+          if (! GIMP_FILE_DIALOG (dialog)->image)
             {
-              dialog->image = file_open_dialog_open_image (open_dialog,
+              GIMP_FILE_DIALOG (dialog)->image = file_open_dialog_open_image (open_dialog,
                                                            gimp,
                                                            file,
                                                            dialog->file_proc);
 
-              if (dialog->image)
+              if (GIMP_FILE_DIALOG (dialog)->image)
                 success = TRUE;
             }
           else if (file_open_dialog_open_layers (open_dialog,
-                                                 dialog->image,
+                                                 GIMP_FILE_DIALOG (dialog)->image,
                                                  file,
                                                  dialog->file_proc))
             {
@@ -181,8 +178,8 @@ file_open_dialog_response (GtkWidget *open_dialog,
 
   if (success)
     {
-      if (dialog->open_as_layers && dialog->image)
-        gimp_image_flush (dialog->image);
+      if (GIMP_OPEN_DIALOG (dialog)->open_as_layers && GIMP_FILE_DIALOG (dialog)->image)
+        gimp_image_flush (GIMP_FILE_DIALOG (dialog)->image);
 
       gtk_widget_destroy (open_dialog);
     }
diff --git a/app/dialogs/file-save-dialog.c b/app/dialogs/file-save-dialog.c
index e922d44..aa48a66 100644
--- a/app/dialogs/file-save-dialog.c
+++ b/app/dialogs/file-save-dialog.c
@@ -40,10 +40,11 @@
 #include "file/gimp-file.h"
 
 #include "widgets/gimpactiongroup.h"
-#include "widgets/gimpfiledialog.h"
+#include "widgets/gimpexportdialog.h"
 #include "widgets/gimphelp-ids.h"
 #include "widgets/gimpmessagebox.h"
 #include "widgets/gimpmessagedialog.h"
+#include "widgets/gimpsavedialog.h"
 
 #include "display/gimpdisplay.h"
 #include "display/gimpdisplayshell.h"
@@ -97,21 +98,13 @@ file_save_dialog_new (Gimp     *gimp,
 
   if (! export)
     {
-      dialog = gimp_file_dialog_new (gimp,
-                                     GIMP_FILE_CHOOSER_ACTION_SAVE,
-                                     _("Save Image"), "gimp-file-save",
-                                     GTK_STOCK_SAVE,
-                                     GIMP_HELP_FILE_SAVE);
+      dialog = gimp_save_dialog_new (gimp);
 
       state = g_object_get_data (G_OBJECT (gimp), "gimp-file-save-dialog-state");
     }
   else
     {
-      dialog = gimp_file_dialog_new (gimp,
-                                     GIMP_FILE_CHOOSER_ACTION_EXPORT,
-                                     _("Export Image"), "gimp-file-export",
-                                     _("_Export"),
-                                     GIMP_HELP_FILE_EXPORT_AS);
+      dialog = gimp_export_dialog_new (gimp);
 
       state = g_object_get_data (G_OBJECT (gimp), "gimp-file-export-dialog-state");
     }
@@ -160,13 +153,13 @@ file_save_dialog_response (GtkWidget *save_dialog,
   gchar               *basename;
   GimpPlugInProcedure *save_proc;
 
-  if (! dialog->export)
+  if (GIMP_IS_SAVE_DIALOG (dialog))
     {
       g_object_set_data_full (G_OBJECT (gimp), "gimp-file-save-dialog-state",
                               gimp_file_dialog_get_state (dialog),
                               (GDestroyNotify) gimp_file_dialog_state_destroy);
     }
-  else
+  else /* GIMP_IS_EXPORT_DIALOG (dialog) */
     {
       g_object_set_data_full (G_OBJECT (gimp), "gimp-file-export-dialog-state",
                               gimp_file_dialog_get_state (dialog),
@@ -199,10 +192,12 @@ file_save_dialog_response (GtkWidget *save_dialog,
                                        file,
                                        save_proc,
                                        GIMP_RUN_INTERACTIVE,
-                                       ! dialog->save_a_copy && ! dialog->export,
+                                       GIMP_IS_SAVE_DIALOG (dialog) &&
+                                       ! GIMP_SAVE_DIALOG (dialog)->save_a_copy,
                                        FALSE,
-                                       dialog->export,
-                                       ! dialog->export && dialog->compat,
+                                       GIMP_IS_EXPORT_DIALOG (dialog),
+                                       GIMP_IS_SAVE_DIALOG (dialog) &&
+                                       GIMP_SAVE_DIALOG (dialog)->compat,
                                        FALSE))
         {
           /* Save was successful, now store the URI in a couple of
@@ -210,30 +205,37 @@ file_save_dialog_response (GtkWidget *save_dialog,
            * save. Lower-level URI management is handled in
            * file_save()
            */
-          if (dialog->save_a_copy)
-            gimp_image_set_save_a_copy_file (dialog->image, file);
-
-          if (! dialog->export)
-            g_object_set_data_full (G_OBJECT (dialog->image->gimp),
-                                    GIMP_FILE_SAVE_LAST_FILE_KEY,
-                                    g_object_ref (file),
-                                    (GDestroyNotify) g_object_unref);
+          if (GIMP_IS_SAVE_DIALOG (dialog))
+            {
+              GimpSaveDialog *save_dialog = GIMP_SAVE_DIALOG (dialog);
+
+              if (save_dialog->save_a_copy)
+                gimp_image_set_save_a_copy_file (dialog->image, file);
+
+              g_object_set_data_full (G_OBJECT (dialog->image->gimp),
+                                      GIMP_FILE_SAVE_LAST_FILE_KEY,
+                                      g_object_ref (file),
+                                      (GDestroyNotify) g_object_unref);
+            }
           else
-            g_object_set_data_full (G_OBJECT (dialog->image->gimp),
-                                    GIMP_FILE_EXPORT_LAST_FILE_KEY,
-                                    g_object_ref (file),
-                                    (GDestroyNotify) g_object_unref);
+            {
+              g_object_set_data_full (G_OBJECT (dialog->image->gimp),
+                                      GIMP_FILE_EXPORT_LAST_FILE_KEY,
+                                      g_object_ref (file),
+                                      (GDestroyNotify) g_object_unref);
+            }
 
           /*  make sure the menus are updated with the keys we've just set  */
           gimp_image_flush (dialog->image);
 
           /* Handle close-after-saving */
-          if (dialog->close_after_saving && dialog->display_to_close)
+          if (GIMP_IS_SAVE_DIALOG (dialog)                  &&
+              GIMP_SAVE_DIALOG (dialog)->close_after_saving &&
+              GIMP_SAVE_DIALOG (dialog)->display_to_close)
             {
-              GimpDisplay *display = GIMP_DISPLAY (dialog->display_to_close);
+              GimpDisplay *display = GIMP_DISPLAY (GIMP_SAVE_DIALOG (dialog)->display_to_close);
 
-              if (display &&
-                  ! gimp_image_is_dirty (gimp_display_get_image (display)))
+              if (! gimp_image_is_dirty (gimp_display_get_image (display)))
                 {
                   gimp_display_close (display);
                 }
@@ -324,7 +326,7 @@ file_save_dialog_check_file (GtkWidget            *save_dialog,
 
           GIMP_LOG (SAVE_DIALOG, "basename has no '.', trying to add extension");
 
-          if (! save_proc && ! dialog->export)
+          if (! save_proc && GIMP_IS_SAVE_DIALOG (dialog))
             {
               ext = "xcf";
             }
@@ -554,7 +556,7 @@ static GSList *
 file_save_dialog_get_procs (GimpFileDialog *dialog,
                             Gimp           *gimp)
 {
-  return (! dialog->export ?
+  return (GIMP_IS_SAVE_DIALOG (dialog) ?
           gimp->plug_in_manager->save_procs :
           gimp->plug_in_manager->export_procs);
 }
@@ -581,7 +583,7 @@ file_save_dialog_switch_dialogs (GimpFileDialog *file_dialog,
   file = g_file_new_for_uri (basename);
 
   proc_in_other_group =
-    file_procedure_find (file_dialog->export ?
+    file_procedure_find (GIMP_IS_EXPORT_DIALOG (file_dialog) ?
                          gimp->plug_in_manager->save_procs :
                          gimp->plug_in_manager->export_procs,
                          file, NULL);
@@ -595,7 +597,7 @@ file_save_dialog_switch_dialogs (GimpFileDialog *file_dialog,
       const gchar *message;
       const gchar *link;
 
-      if (file_dialog->export)
+      if (GIMP_IS_EXPORT_DIALOG (file_dialog))
         {
           primary = _("The given filename cannot be used for exporting");
           message = _("You can use this dialog to export to various file formats. "
@@ -627,7 +629,9 @@ file_save_dialog_switch_dialogs (GimpFileDialog *file_dialog,
       gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
                                  "%s", message);
 
-      if (! file_dialog->save_a_copy && ! file_dialog->close_after_saving)
+      if (GIMP_IS_EXPORT_DIALOG (file_dialog) ||
+          (! GIMP_SAVE_DIALOG (file_dialog)->save_a_copy &&
+          ! GIMP_SAVE_DIALOG (file_dialog)->close_after_saving))
         {
           GtkWidget *label;
           gchar     *markup;
diff --git a/app/widgets/Makefile.am b/app/widgets/Makefile.am
index cc85911..a352bba 100644
--- a/app/widgets/Makefile.am
+++ b/app/widgets/Makefile.am
@@ -175,6 +175,8 @@ libappwidgets_a_sources = \
        gimperrorconsole.h              \
        gimperrordialog.c               \
        gimperrordialog.h               \
+       gimpexportdialog.c              \
+       gimpexportdialog.h              \
        gimpfgbgeditor.c                \
        gimpfgbgeditor.h                \
        gimpfgbgview.c                  \
@@ -242,6 +244,8 @@ libappwidgets_a_sources = \
        gimpmessagedialog.h             \
        gimpnavigationview.c            \
        gimpnavigationview.h            \
+       gimpopendialog.c                \
+       gimpopendialog.h                \
        gimpoverlaybox.c                \
        gimpoverlaybox.h                \
        gimpoverlaychild.c              \
@@ -294,6 +298,8 @@ libappwidgets_a_sources = \
        gimprender.h                    \
        gimpsamplepointeditor.c         \
        gimpsamplepointeditor.h         \
+       gimpsavedialog.c                \
+       gimpsavedialog.h                \
        gimpscalebutton.c               \
        gimpscalebutton.h               \
        gimpselectiondata.c             \
diff --git a/app/widgets/gimpexportdialog.c b/app/widgets/gimpexportdialog.c
new file mode 100644
index 0000000..897c205
--- /dev/null
+++ b/app/widgets/gimpexportdialog.c
@@ -0,0 +1,258 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpexportdialog.c
+ * Copyright (C) 2015 Jehan <jehan girinstud io>
+ *
+ * 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 <http://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 "widgets-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+
+#include "file/file-utils.h"
+#include "file/gimp-file.h"
+
+#include "pdb/gimppdb.h"
+
+#include "plug-in/gimppluginmanager.h"
+
+#include "gimpexportdialog.h"
+#include "gimpfiledialog.h"
+#include "gimphelp-ids.h"
+
+#include "gimp-intl.h"
+
+
+static GFile  * gimp_export_dialog_get_default_folder (Gimp *gimp);
+
+G_DEFINE_TYPE (GimpExportDialog, gimp_export_dialog,
+               GIMP_TYPE_FILE_DIALOG)
+
+#define parent_class gimp_export_dialog_parent_class
+
+static void
+gimp_export_dialog_class_init (GimpExportDialogClass *klass)
+{
+}
+
+static void
+gimp_export_dialog_init (GimpExportDialog *dialog)
+{
+}
+
+/*  public functions  */
+
+GtkWidget *
+gimp_export_dialog_new (Gimp *gimp)
+{
+  GimpExportDialog *dialog;
+
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+
+  dialog = g_object_new (GIMP_TYPE_EXPORT_DIALOG,
+                         "gimp",                      gimp,
+                         "title",                     _("Export Image"),
+                         "role",                      "gimp-file-export",
+                         "help-id",                   GIMP_HELP_FILE_EXPORT_AS,
+                         "stock-id",                  _("_Export"),
+
+                         "automatic-label",           _("By Extension"),
+                         "automatic-help-id",         GIMP_HELP_FILE_SAVE_BY_EXTENSION,
+
+                         "action",                    GTK_FILE_CHOOSER_ACTION_SAVE,
+                         "file-procs",                gimp->plug_in_manager->export_procs,
+                         "file-procs-all-images",     gimp->plug_in_manager->save_procs,
+                         "file-filter-label",         _("All export images"),
+                         "local-only",                FALSE,
+                         "do-overwrite-confirmation", TRUE,
+                         NULL);
+
+  return GTK_WIDGET (dialog);
+}
+
+void
+gimp_export_dialog_set_image (GimpExportDialog *dialog,
+                              Gimp             *gimp,
+                              GimpImage        *image)
+{
+  GFile *dir_file  = NULL;
+  GFile *name_file = NULL;
+  GFile *ext_file  = NULL;
+  gchar *basename;
+
+  g_return_if_fail (GIMP_IS_EXPORT_DIALOG (dialog));
+  g_return_if_fail (GIMP_IS_IMAGE (image));
+
+  GIMP_FILE_DIALOG (dialog)->image = image;
+
+  gimp_file_dialog_set_file_proc (GIMP_FILE_DIALOG (dialog), NULL);
+
+  /*
+   * Priority of default paths for Export:
+   *
+   *   1. Last Export path
+   *   2. Path of import source
+   *   3. Path of XCF source
+   *   4. Last path of any save to XCF
+   *   5. Last Export path of any document
+   *   6. The default path (usually the OS 'Documents' path)
+   */
+
+  dir_file = gimp_image_get_exported_file (image);
+
+  if (! dir_file)
+    dir_file = g_object_get_data (G_OBJECT (image),
+                                  "gimp-image-source-file");
+
+  if (! dir_file)
+    dir_file = gimp_image_get_imported_file (image);
+
+  if (! dir_file)
+    dir_file = gimp_image_get_file (image);
+
+  if (! dir_file)
+    dir_file = g_object_get_data (G_OBJECT (gimp),
+                                  GIMP_FILE_SAVE_LAST_FILE_KEY);
+
+  if (! dir_file)
+    dir_file = g_object_get_data (G_OBJECT (gimp),
+                                  GIMP_FILE_EXPORT_LAST_FILE_KEY);
+
+  if (! dir_file)
+    dir_file = gimp_export_dialog_get_default_folder (gimp);
+
+  /* Priority of default basenames for Export:
+   *
+   *   1. Last Export name
+   *   3. Save URI
+   *   2. Source file name
+   *   3. 'Untitled'
+   */
+
+  name_file = gimp_image_get_exported_file (image);
+
+  if (! name_file)
+    name_file = gimp_image_get_file (image);
+
+  if (! name_file)
+    name_file = gimp_image_get_imported_file (image);
+
+  if (! name_file)
+    name_file = gimp_image_get_untitled_file (image);
+
+
+  /* Priority of default type/extension for Export:
+   *
+   *   1. Type of last Export
+   *   2. Type of the image Import
+   *   3. Type of latest Export of any document
+   *   4. .png
+   */
+  ext_file = gimp_image_get_exported_file (image);
+
+  if (! ext_file)
+    ext_file = gimp_image_get_imported_file (image);
+
+  if (! ext_file)
+    ext_file = g_object_get_data (G_OBJECT (gimp),
+                                  GIMP_FILE_EXPORT_LAST_FILE_KEY);
+
+  if (ext_file)
+    g_object_ref (ext_file);
+  else
+    ext_file = g_file_new_for_uri ("file:///we/only/care/about/extension.png");
+
+  if (ext_file)
+    {
+      GFile *tmp_file = file_utils_file_with_new_ext (name_file, ext_file);
+      basename = g_path_get_basename (gimp_file_get_utf8_name (tmp_file));
+      g_object_unref (tmp_file);
+      g_object_unref (ext_file);
+    }
+  else
+    {
+      basename = g_path_get_basename (gimp_file_get_utf8_name (name_file));
+    }
+
+  if (g_file_query_file_type (dir_file, G_FILE_QUERY_INFO_NONE, NULL) ==
+      G_FILE_TYPE_DIRECTORY)
+    {
+      gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
+                                                dir_file, NULL);
+    }
+  else
+    {
+      GFile *parent_file = g_file_get_parent (dir_file);
+      gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
+                                                parent_file, NULL);
+      g_object_unref (parent_file);
+    }
+
+  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
+}
+
+/*  private functions  */
+
+static GFile *
+gimp_export_dialog_get_default_folder (Gimp *gimp)
+{
+  if (gimp->default_folder)
+    {
+      return gimp->default_folder;
+    }
+  else
+    {
+      GFile *file = g_object_get_data (G_OBJECT (gimp),
+                                       "gimp-documents-folder");
+
+      if (! file)
+        {
+          gchar *path;
+
+          /* Make sure it ends in '/' */
+          path = g_build_path (G_DIR_SEPARATOR_S,
+                               g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS),
+                               G_DIR_SEPARATOR_S,
+                               NULL);
+
+          /* Paranoia fallback, see bug #722400 */
+          if (! path)
+            path = g_build_path (G_DIR_SEPARATOR_S,
+                                 g_get_home_dir (),
+                                 G_DIR_SEPARATOR_S,
+                                 NULL);
+
+          file = g_file_new_for_path (path);
+          g_free (path);
+
+          g_object_set_data_full (G_OBJECT (gimp), "gimp-documents-folder",
+                                  file, (GDestroyNotify) g_object_unref);
+        }
+
+      return file;
+    }
+}
diff --git a/app/widgets/gimpexportdialog.h b/app/widgets/gimpexportdialog.h
new file mode 100644
index 0000000..1280c74
--- /dev/null
+++ b/app/widgets/gimpexportdialog.h
@@ -0,0 +1,59 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpexportdialog.h
+ * Copyright (C) 2015 Jehan <jehan girinstud io>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_EXPORT_DIALOG_H__
+#define __GIMP_EXPORT_DIALOG_H__
+
+#include "gimpfiledialog.h"
+
+G_BEGIN_DECLS
+
+#define GIMP_TYPE_EXPORT_DIALOG            (gimp_export_dialog_get_type ())
+#define GIMP_EXPORT_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_EXPORT_DIALOG, 
GimpExportDialog))
+#define GIMP_EXPORT_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_EXPORT_DIALOG, 
GimpExportDialogClass))
+#define GIMP_IS_EXPORT_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_EXPORT_DIALOG))
+#define GIMP_IS_EXPORT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_EXPORT_DIALOG))
+#define GIMP_EXPORT_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_EXPORT_DIALOG, 
GimpExportDialogClass))
+
+
+typedef struct _GimpExportDialogClass  GimpExportDialogClass;
+
+struct _GimpExportDialog
+{
+  GimpFileDialog       parent_instance;
+};
+
+struct _GimpExportDialogClass
+{
+  GimpFileDialogClass  parent_class;
+};
+
+
+GType       gimp_export_dialog_get_type         (void) G_GNUC_CONST;
+
+GtkWidget * gimp_export_dialog_new              (Gimp                 *gimp);
+
+void        gimp_export_dialog_set_image        (GimpExportDialog      *dialog,
+                                                 Gimp                  *gimp,
+                                                 GimpImage             *image);
+
+G_END_DECLS
+
+#endif /* __GIMP_EXPORT_DIALOG_H__ */
diff --git a/app/widgets/gimpfiledialog.c b/app/widgets/gimpfiledialog.c
index a1e8c5f..fc61abd 100644
--- a/app/widgets/gimpfiledialog.c
+++ b/app/widgets/gimpfiledialog.c
@@ -26,6 +26,7 @@
 #include <gtk/gtk.h>
 
 #include "libgimpbase/gimpbase.h"
+#include "libgimpconfig/gimpconfig.h"
 #include "libgimpwidgets/gimpwidgets.h"
 
 #include "widgets-types.h"
@@ -36,97 +37,95 @@
 
 #include "config/gimpguiconfig.h"
 
-#include "file/file-utils.h"
-#include "file/gimp-file.h"
-
 #include "pdb/gimppdb.h"
 
-#include "plug-in/gimppluginmanager.h"
 #include "plug-in/gimppluginprocedure.h"
 
 #include "gimpfiledialog.h"
 #include "gimpfileprocview.h"
-#include "gimphelp-ids.h"
 #include "gimpprogressbox.h"
-#include "gimpview.h"
-#include "gimpviewrendererimagefile.h"
 #include "gimpthumbbox.h"
 #include "gimpwidgets-utils.h"
 
 #include "gimp-intl.h"
 
-
 /*  an arbitrary limit to keep the file dialog from becoming too wide  */
 #define MAX_EXTENSIONS  4
 
-
 struct _GimpFileDialogState
 {
   gchar *filter_name;
 };
 
+enum
+{
+  PROP_0,
+  PROP_GIMP,
+  PROP_HELP_ID,
+  PROP_STOCK_ID,
+  PROP_AUTOMATIC_HELP_ID,
+  PROP_AUTOMATIC_LABEL,
+  PROP_FILE_FILTER_LABEL,
+  PROP_FILE_PROCS,
+  PROP_FILE_PROCS_ALL_IMAGES
+};
 
 static void     gimp_file_dialog_progress_iface_init    (GimpProgressInterface *iface);
 
-static void     gimp_file_dialog_dispose                (GObject          *object);
 
-static gboolean gimp_file_dialog_delete_event           (GtkWidget        *widget,
-                                                         GdkEventAny      *event);
-static void     gimp_file_dialog_response               (GtkDialog        *dialog,
-                                                         gint              response_id);
+static void     gimp_file_dialog_set_property           (GObject             *object,
+                                                         guint                property_id,
+                                                         const GValue        *value,
+                                                         GParamSpec          *pspec);
+static void     gimp_file_dialog_get_property           (GObject             *object,
+                                                         guint                property_id,
+                                                         GValue              *value,
+                                                         GParamSpec          *pspec);
+static void     gimp_file_dialog_constructed            (GObject             *object);
+static void     gimp_file_dialog_dispose                (GObject             *object);
+
+static gboolean gimp_file_dialog_delete_event           (GtkWidget           *widget,
+                                                         GdkEventAny         *event);
+static void     gimp_file_dialog_response               (GtkDialog           *dialog,
+                                                         gint                 response_id);
 static GimpProgress *
-                gimp_file_dialog_progress_start         (GimpProgress     *progress,
-                                                         gboolean          cancellable,
-                                                         const gchar      *message);
-static void     gimp_file_dialog_progress_end           (GimpProgress     *progress);
-static gboolean gimp_file_dialog_progress_is_active     (GimpProgress     *progress);
-static void     gimp_file_dialog_progress_set_text      (GimpProgress     *progress,
-                                                         const gchar      *message);
-static void     gimp_file_dialog_progress_set_value     (GimpProgress     *progress,
-                                                         gdouble           percentage);
-static gdouble  gimp_file_dialog_progress_get_value     (GimpProgress     *progress);
-static void     gimp_file_dialog_progress_pulse         (GimpProgress     *progress);
-static guint32  gimp_file_dialog_progress_get_window_id (GimpProgress     *progress);
-
-static void     gimp_file_dialog_add_user_dir           (GimpFileDialog   *dialog,
-                                                         GUserDirectory    directory);
-static void     gimp_file_dialog_add_preview            (GimpFileDialog   *dialog,
-                                                         Gimp             *gimp);
-static void     gimp_file_dialog_add_filters            (GimpFileDialog   *dialog,
-                                                         Gimp             *gimp,
-                                                         GimpFileChooserAction
-                                                                           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,
-                                                         GtkFileFilter    *all,
-                                                         GtkFileFilter    *all_savable);
-static void     gimp_file_dialog_add_proc_selection     (GimpFileDialog   *dialog,
-                                                         Gimp             *gimp,
-                                                         GSList           *file_procs,
-                                                         const gchar      *automatic,
-                                                         const gchar      *automatic_help_id);
-
-static void     gimp_file_dialog_selection_changed      (GtkFileChooser   *chooser,
-                                                         GimpFileDialog   *dialog);
-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);
-
-static void     gimp_file_dialog_help_func              (const gchar      *help_id,
-                                                         gpointer          help_data);
-static void     gimp_file_dialog_help_clicked           (GtkWidget        *widget,
-                                                         gpointer          dialog);
-
-static gchar  * gimp_file_dialog_pattern_from_extension (const gchar      *extension);
-static GFile  * gimp_file_dialog_get_default_folder     (Gimp             *gimp);
+                gimp_file_dialog_progress_start         (GimpProgress        *progress,
+                                                         gboolean             cancellable,
+                                                         const gchar         *message);
+static void     gimp_file_dialog_progress_end           (GimpProgress        *progress);
+static gboolean gimp_file_dialog_progress_is_active     (GimpProgress        *progress);
+static void     gimp_file_dialog_progress_set_text      (GimpProgress        *progress,
+                                                         const gchar         *message);
+static void     gimp_file_dialog_progress_set_value     (GimpProgress        *progress,
+                                                         gdouble              percentage);
+static gdouble  gimp_file_dialog_progress_get_value     (GimpProgress        *progress);
+static void     gimp_file_dialog_progress_pulse         (GimpProgress        *progress);
+static guint32  gimp_file_dialog_progress_get_window_id (GimpProgress        *progress);
+
+static void     gimp_file_dialog_add_user_dir           (GimpFileDialog      *dialog,
+                                                         GUserDirectory       directory);
+static void     gimp_file_dialog_add_preview            (GimpFileDialog      *dialog);
+static void     gimp_file_dialog_add_filters            (GimpFileDialog      *dialog);
+static void     gimp_file_dialog_process_procedure      (GimpPlugInProcedure *file_proc,
+                                                         GtkFileFilter      **filter_out,
+                                                         GtkFileFilter       *all,
+                                                         GtkFileFilter       *all_savable);
+static void     gimp_file_dialog_add_proc_selection     (GimpFileDialog      *dialog);
+
+static void     gimp_file_dialog_selection_changed      (GtkFileChooser      *chooser,
+                                                         GimpFileDialog      *dialog);
+static void     gimp_file_dialog_update_preview         (GtkFileChooser      *chooser,
+                                                         GimpFileDialog      *dialog);
+
+static void     gimp_file_dialog_proc_changed           (GimpFileProcView    *view,
+                                                         GimpFileDialog      *dialog);
+
+static void     gimp_file_dialog_help_func              (const gchar         *help_id,
+                                                         gpointer             help_data);
+static void     gimp_file_dialog_help_clicked           (GtkWidget           *widget,
+                                                         gpointer             dialog);
+
+static gchar  * gimp_file_dialog_pattern_from_extension (const gchar         *extension);
 
 
 G_DEFINE_TYPE_WITH_CODE (GimpFileDialog, gimp_file_dialog,
@@ -144,16 +143,61 @@ gimp_file_dialog_class_init (GimpFileDialogClass *klass)
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
   GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
 
+  object_class->set_property = gimp_file_dialog_set_property;
+  object_class->get_property = gimp_file_dialog_get_property;
+  object_class->constructed  = gimp_file_dialog_constructed;
   object_class->dispose      = gimp_file_dialog_dispose;
 
   widget_class->delete_event = gimp_file_dialog_delete_event;
 
   dialog_class->response     = gimp_file_dialog_response;
+
+  g_object_class_install_property (object_class, PROP_GIMP,
+                                   g_param_spec_object ("gimp", NULL, NULL,
+                                                        GIMP_TYPE_GIMP,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_HELP_ID,
+                                   g_param_spec_string ("help-id", NULL, NULL,
+                                                        NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class, PROP_STOCK_ID,
+                                   g_param_spec_string ("stock-id", NULL, NULL,
+                                                        NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_AUTOMATIC_HELP_ID,
+                                   g_param_spec_string ("automatic-help-id", NULL, NULL,
+                                                        NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_AUTOMATIC_LABEL,
+                                   g_param_spec_string ("automatic-label", NULL, NULL,
+                                                        NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class, PROP_FILE_FILTER_LABEL,
+                                   g_param_spec_string ("file-filter-label", NULL, NULL,
+                                                        NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_FILE_PROCS,
+                                   g_param_spec_pointer ("file-procs", NULL, NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class, PROP_FILE_PROCS_ALL_IMAGES,
+                                   g_param_spec_pointer ("file-procs-all-images", NULL, NULL,
+                                                        GIMP_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
 }
 
 static void
 gimp_file_dialog_init (GimpFileDialog *dialog)
 {
+  dialog->stock_id = GTK_STOCK_OK;
 }
 
 static void
@@ -170,6 +214,133 @@ gimp_file_dialog_progress_iface_init (GimpProgressInterface *iface)
 }
 
 static void
+gimp_file_dialog_set_property (GObject      *object,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  GimpFileDialog        *dialog  = GIMP_FILE_DIALOG (object);
+
+  switch (property_id)
+    {
+    case PROP_GIMP:
+      dialog->gimp = g_value_get_object (value);
+      break;
+    case PROP_HELP_ID:
+      dialog->help_id = g_value_dup_string (value);
+      break;
+    case PROP_STOCK_ID:
+      dialog->stock_id = g_value_dup_string (value);
+      break;
+    case PROP_AUTOMATIC_HELP_ID:
+      dialog->automatic_help_id = g_value_dup_string (value);
+      break;
+    case PROP_AUTOMATIC_LABEL:
+      dialog->automatic_label = g_value_dup_string (value);
+      break;
+    case PROP_FILE_FILTER_LABEL:
+      dialog->file_filter_label = g_value_dup_string (value);
+      break;
+    case PROP_FILE_PROCS:
+      dialog->file_procs = g_value_get_pointer (value);
+      break;
+    case PROP_FILE_PROCS_ALL_IMAGES:
+      dialog->file_procs_all_images = g_value_get_pointer (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_file_dialog_get_property (GObject    *object,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  GimpFileDialog        *dialog  = GIMP_FILE_DIALOG (object);
+
+  switch (property_id)
+    {
+    case PROP_GIMP:
+      g_value_set_object (value, dialog->gimp);
+      break;
+    case PROP_HELP_ID:
+      g_value_set_string (value, dialog->help_id);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gimp_file_dialog_constructed (GObject *object)
+{
+  GimpFileDialog *dialog = GIMP_FILE_DIALOG (object);
+
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
+  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
+                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                          dialog->stock_id, GTK_RESPONSE_OK,
+                          NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+                                           GTK_RESPONSE_OK,
+                                           GTK_RESPONSE_CANCEL,
+                                           -1);
+
+  if (dialog->help_id)
+    {
+      gimp_help_connect (GTK_WIDGET (dialog),
+                         gimp_file_dialog_help_func, dialog->help_id, dialog);
+
+      if (GIMP_GUI_CONFIG (dialog->gimp->config)->show_help_button)
+        {
+          GtkWidget *action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
+          GtkWidget *button      = gtk_button_new_from_stock (GTK_STOCK_HELP);
+
+          gtk_box_pack_end (GTK_BOX (action_area), button, FALSE, TRUE, 0);
+          gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (action_area),
+                                              button, TRUE);
+          gtk_widget_show (button);
+
+          g_object_set_data_full (G_OBJECT (dialog), "gimp-dialog-help-id",
+                                  g_strdup (dialog->help_id),
+                                  (GDestroyNotify) g_free);
+
+          g_signal_connect (button, "clicked",
+                            G_CALLBACK (gimp_file_dialog_help_clicked),
+                            dialog);
+
+          g_object_set_data (G_OBJECT (dialog), "gimp-dialog-help-button", button);
+        }
+    }
+
+  /* All classes derivated from GimpFileDialog should show these. */
+  gimp_file_dialog_add_user_dir (dialog, G_USER_DIRECTORY_PICTURES);
+  gimp_file_dialog_add_user_dir (dialog, G_USER_DIRECTORY_DOCUMENTS);
+
+  gimp_file_dialog_add_preview (dialog);
+  gimp_file_dialog_add_filters (dialog);
+
+  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_proc_selection (dialog);
+
+  dialog->progress = gimp_progress_box_new ();
+  gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+                    dialog->progress, FALSE, FALSE, 0);
+}
+
+static void
 gimp_file_dialog_dispose (GObject *object)
 {
   GimpFileDialog *dialog = GIMP_FILE_DIALOG (object);
@@ -177,6 +348,26 @@ gimp_file_dialog_dispose (GObject *object)
   G_OBJECT_CLASS (parent_class)->dispose (object);
 
   dialog->progress = NULL;
+
+  if (dialog->help_id)
+    g_free (dialog->help_id);
+  dialog->help_id = NULL;
+
+  if (dialog->stock_id)
+    g_free (dialog->stock_id);
+  dialog->stock_id = NULL;
+
+  if (dialog->automatic_help_id)
+    g_free (dialog->automatic_help_id);
+  dialog->automatic_help_id = NULL;
+
+  if (dialog->automatic_label)
+    g_free (dialog->automatic_label);
+  dialog->automatic_label = NULL;
+
+  if (dialog->file_filter_label)
+    g_free (dialog->file_filter_label);
+  dialog->file_filter_label = NULL;
 }
 
 static gboolean
@@ -300,122 +491,15 @@ gimp_file_dialog_progress_get_window_id (GimpProgress *progress)
 
 /*  public functions  */
 
-GtkWidget *
-gimp_file_dialog_new (Gimp                  *gimp,
-                      GimpFileChooserAction  action,
-                      const gchar           *title,
-                      const gchar           *role,
-                      const gchar           *icon_name,
-                      const gchar           *help_id)
+void
+gimp_file_dialog_add_extra_widget (GimpFileDialog *dialog,
+                                   GtkWidget      *widget,
+                                   gboolean        expand,
+                                   gboolean        fill,
+                                   guint           padding)
 {
-  GimpFileDialog       *dialog                = NULL;
-  GSList               *file_procs            = NULL;
-  GSList               *file_procs_all_images = NULL;
-  const gchar          *automatic             = NULL;
-  const gchar          *automatic_help_id     = NULL;
-  GtkFileChooserAction  gtk_action            = 0;
-
-  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
-  g_return_val_if_fail (title != NULL, NULL);
-  g_return_val_if_fail (role != NULL, NULL);
-  g_return_val_if_fail (icon_name != NULL, NULL);
-  g_return_val_if_fail (help_id != NULL, NULL);
-
-  switch (action)
-    {
-    case GIMP_FILE_CHOOSER_ACTION_OPEN:
-      gtk_action            = GTK_FILE_CHOOSER_ACTION_OPEN;
-      file_procs            = gimp->plug_in_manager->load_procs;
-      file_procs_all_images = NULL;
-      automatic             = _("Automatically Detected");
-      automatic_help_id     = GIMP_HELP_FILE_OPEN_BY_EXTENSION;
-      break;
-
-    case GIMP_FILE_CHOOSER_ACTION_SAVE:
-    case GIMP_FILE_CHOOSER_ACTION_EXPORT:
-      gtk_action            = GTK_FILE_CHOOSER_ACTION_SAVE;
-      file_procs            = (action == GIMP_FILE_CHOOSER_ACTION_SAVE ?
-                               gimp->plug_in_manager->save_procs :
-                               gimp->plug_in_manager->export_procs);
-      file_procs_all_images = (action == GIMP_FILE_CHOOSER_ACTION_SAVE ?
-                               gimp->plug_in_manager->export_procs :
-                               gimp->plug_in_manager->save_procs);
-      automatic             = _("By Extension");
-      automatic_help_id     = GIMP_HELP_FILE_SAVE_BY_EXTENSION;
-      break;
-
-    default:
-      g_return_val_if_reached (NULL);
-      return NULL;
-    }
-
-  dialog = g_object_new (GIMP_TYPE_FILE_DIALOG,
-                         "title",                     title,
-                         "role",                      role,
-                         "action",                    gtk_action,
-                         "local-only",                FALSE,
-                         "do-overwrite-confirmation", TRUE,
-                         NULL);
-
-  gtk_dialog_add_buttons (GTK_DIALOG (dialog),
-                          GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                          icon_name,        GTK_RESPONSE_OK,
-                          NULL);
-
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
-                                           GTK_RESPONSE_OK,
-                                           GTK_RESPONSE_CANCEL,
-                                           -1);
-
-  gimp_help_connect (GTK_WIDGET (dialog),
-                     gimp_file_dialog_help_func, help_id, dialog);
-
-  if (GIMP_GUI_CONFIG (gimp->config)->show_help_button && help_id)
-    {
-      GtkWidget *action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
-      GtkWidget *button      = gtk_button_new_from_stock (GTK_STOCK_HELP);
-
-      gtk_box_pack_end (GTK_BOX (action_area), button, FALSE, TRUE, 0);
-      gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (action_area),
-                                          button, TRUE);
-      gtk_widget_show (button);
-
-      g_object_set_data_full (G_OBJECT (dialog), "gimp-dialog-help-id",
-                              g_strdup (help_id),
-                              (GDestroyNotify) g_free);
-
-      g_signal_connect (button, "clicked",
-                        G_CALLBACK (gimp_file_dialog_help_clicked),
-                        dialog);
-
-      g_object_set_data (G_OBJECT (dialog), "gimp-dialog-help-button", button);
-    }
-
-  gimp_file_dialog_add_user_dir (dialog, G_USER_DIRECTORY_PICTURES);
-  gimp_file_dialog_add_user_dir (dialog, G_USER_DIRECTORY_DOCUMENTS);
-
-  gimp_file_dialog_add_preview (dialog, gimp);
-
-  gimp_file_dialog_add_filters (dialog, gimp, action,
-                                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);
-
-  dialog->progress = gimp_progress_box_new ();
-  gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
-                    dialog->progress, FALSE, FALSE, 0);
-
-  return GTK_WIDGET (dialog);
+  gtk_box_pack_start (GTK_BOX (dialog->extra_vbox),
+                      widget, expand, fill, padding);
 }
 
 void
@@ -467,259 +551,6 @@ gimp_file_dialog_set_file_proc (GimpFileDialog      *dialog,
                                   file_proc);
 }
 
-void
-gimp_file_dialog_set_open_image (GimpFileDialog *dialog,
-                                 GimpImage      *image,
-                                 gboolean        open_as_layers)
-{
-  g_return_if_fail (GIMP_IS_FILE_DIALOG (dialog));
-  g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
-
-  dialog->image          = image;
-  dialog->open_as_layers = open_as_layers;
-}
-
-void
-gimp_file_dialog_set_save_image (GimpFileDialog *dialog,
-                                 Gimp           *gimp,
-                                 GimpImage      *image,
-                                 gboolean        save_a_copy,
-                                 gboolean        export,
-                                 gboolean        close_after_saving,
-                                 GimpObject     *display)
-{
-  GFile *dir_file  = NULL;
-  GFile *name_file = NULL;
-  GFile *ext_file  = NULL;
-  gchar *basename;
-
-  g_return_if_fail (GIMP_IS_FILE_DIALOG (dialog));
-  g_return_if_fail (GIMP_IS_IMAGE (image));
-
-  dialog->image              = image;
-  dialog->save_a_copy        = save_a_copy;
-  dialog->export             = export;
-  dialog->close_after_saving = close_after_saving;
-  dialog->display_to_close   = display;
-
-  gimp_file_dialog_set_file_proc (dialog, NULL);
-
-  if (! export)
-    {
-      gint         rle_version;
-      gint         zlib_version;
-      const gchar *version_string;
-      gchar       *tooltip;
-
-      /*
-       * Priority of default paths for Save:
-       *
-       *   1. Last Save a copy-path (applies only to Save a copy)
-       *   2. Last Save path
-       *   3. Path of source XCF
-       *   4. Path of Import source
-       *   5. Last Save path of any GIMP document
-       *   6. The default path (usually the OS 'Documents' path)
-       */
-
-      if (save_a_copy)
-        dir_file = gimp_image_get_save_a_copy_file (image);
-
-      if (! dir_file)
-        dir_file = gimp_image_get_file (image);
-
-      if (! dir_file)
-        dir_file = g_object_get_data (G_OBJECT (image),
-                                      "gimp-image-source-file");
-
-      if (! dir_file)
-        dir_file = gimp_image_get_imported_file (image);
-
-      if (! dir_file)
-        dir_file = g_object_get_data (G_OBJECT (gimp),
-                                      GIMP_FILE_SAVE_LAST_FILE_KEY);
-
-      if (! dir_file)
-        dir_file = gimp_file_dialog_get_default_folder (gimp);
-
-
-      /* Priority of default basenames for Save:
-       *
-       *   1. Last Save a copy-name (applies only to Save a copy)
-       *   2. Last Save name
-       *   3. Last Export name
-       *   3. The source image path
-       *   3. 'Untitled'
-       */
-
-      if (save_a_copy)
-        name_file = gimp_image_get_save_a_copy_file (image);
-
-      if (! name_file)
-        name_file = gimp_image_get_file (image);
-
-      if (! name_file)
-        name_file = gimp_image_get_exported_file (image);
-
-      if (! name_file)
-        name_file = gimp_image_get_imported_file (image);
-
-      if (! name_file)
-        name_file = gimp_image_get_untitled_file (image);
-
-
-      /* Priority of default type/extension for Save:
-       *
-       *   1. Type of last Save
-       *   2. .xcf (which we don't explicitly append)
-       */
-      ext_file = gimp_image_get_file (image);
-
-      if (ext_file)
-        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) */
-    {
-      /*
-       * Priority of default paths for Export:
-       *
-       *   1. Last Export path
-       *   2. Path of import source
-       *   3. Path of XCF source
-       *   4. Last path of any save to XCF
-       *   5. Last Export path of any document
-       *   6. The default path (usually the OS 'Documents' path)
-       */
-
-      dir_file = gimp_image_get_exported_file (image);
-
-      if (! dir_file)
-        dir_file = g_object_get_data (G_OBJECT (image),
-                                      "gimp-image-source-file");
-
-      if (! dir_file)
-        dir_file = gimp_image_get_imported_file (image);
-
-      if (! dir_file)
-        dir_file = gimp_image_get_file (image);
-
-      if (! dir_file)
-        dir_file = g_object_get_data (G_OBJECT (gimp),
-                                      GIMP_FILE_SAVE_LAST_FILE_KEY);
-
-      if (! dir_file)
-        dir_file = g_object_get_data (G_OBJECT (gimp),
-                                      GIMP_FILE_EXPORT_LAST_FILE_KEY);
-
-      if (! dir_file)
-        dir_file = gimp_file_dialog_get_default_folder (gimp);
-
-
-      /* Priority of default basenames for Export:
-       *
-       *   1. Last Export name
-       *   3. Save URI
-       *   2. Source file name
-       *   3. 'Untitled'
-       */
-
-      name_file = gimp_image_get_exported_file (image);
-
-      if (! name_file)
-        name_file = gimp_image_get_file (image);
-
-      if (! name_file)
-        name_file = gimp_image_get_imported_file (image);
-
-      if (! name_file)
-        name_file = gimp_image_get_untitled_file (image);
-
-
-      /* Priority of default type/extension for Export:
-       *
-       *   1. Type of last Export
-       *   2. Type of the image Import
-       *   3. Type of latest Export of any document
-       *   4. .png
-       */
-      ext_file = gimp_image_get_exported_file (image);
-
-      if (! ext_file)
-        ext_file = gimp_image_get_imported_file (image);
-
-      if (! ext_file)
-        ext_file = g_object_get_data (G_OBJECT (gimp),
-                                      GIMP_FILE_EXPORT_LAST_FILE_KEY);
-
-      if (ext_file)
-        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);
-    }
-
-  if (gtk_widget_get_sensitive (dialog->compat_toggle))
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->compat_toggle),
-                                    gimp_image_get_xcf_compat_mode (image));
-
-  if (ext_file)
-    {
-      GFile *tmp_file = file_utils_file_with_new_ext (name_file, ext_file);
-      basename = g_path_get_basename (gimp_file_get_utf8_name (tmp_file));
-      g_object_unref (tmp_file);
-      g_object_unref (ext_file);
-    }
-  else
-    {
-      basename = g_path_get_basename (gimp_file_get_utf8_name (name_file));
-    }
-
-  if (g_file_query_file_type (dir_file, G_FILE_QUERY_INFO_NONE, NULL) ==
-      G_FILE_TYPE_DIRECTORY)
-    {
-      gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
-                                                dir_file, NULL);
-    }
-  else
-    {
-      GFile *parent_file = g_file_get_parent (dir_file);
-      gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
-                                                parent_file, NULL);
-      g_object_unref (parent_file);
-    }
-
-  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
-}
-
 GimpFileDialogState *
 gimp_file_dialog_get_state (GimpFileDialog *dialog)
 {
@@ -792,10 +623,9 @@ gimp_file_dialog_add_user_dir (GimpFileDialog *dialog,
 }
 
 static void
-gimp_file_dialog_add_preview (GimpFileDialog *dialog,
-                              Gimp           *gimp)
+gimp_file_dialog_add_preview (GimpFileDialog *dialog)
 {
-  if (gimp->config->thumbnail_size <= 0)
+  if (dialog->gimp->config->thumbnail_size <= 0)
     return;
 
   gtk_file_chooser_set_use_preview_label (GTK_FILE_CHOOSER (dialog), FALSE);
@@ -807,7 +637,7 @@ gimp_file_dialog_add_preview (GimpFileDialog *dialog,
                     G_CALLBACK (gimp_file_dialog_update_preview),
                     dialog);
 
-  dialog->thumb_box = gimp_thumb_box_new (gimp_get_user_context (gimp));
+  dialog->thumb_box = gimp_thumb_box_new (gimp_get_user_context (dialog->gimp));
   gtk_widget_set_sensitive (GTK_WIDGET (dialog->thumb_box), FALSE);
   gtk_file_chooser_set_preview_widget (GTK_FILE_CHOOSER (dialog),
                                        dialog->thumb_box);
@@ -830,11 +660,7 @@ gimp_file_dialog_add_preview (GimpFileDialog *dialog,
  *
  **/
 static void
-gimp_file_dialog_add_filters (GimpFileDialog        *dialog,
-                              Gimp                  *gimp,
-                              GimpFileChooserAction  action,
-                              GSList                *file_procs,
-                              GSList                *file_procs_all_images)
+gimp_file_dialog_add_filters (GimpFileDialog *dialog)
 {
   GtkFileFilter *all;
   GtkFileFilter *all_savable = NULL;
@@ -849,18 +675,15 @@ gimp_file_dialog_add_filters (GimpFileDialog        *dialog,
   gtk_file_filter_set_name (all, _("All images"));
   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), all);
 
-  if (file_procs_all_images)
+  if (dialog->file_procs_all_images)
     {
       all_savable = gtk_file_filter_new ();
-      if (action == GIMP_FILE_CHOOSER_ACTION_SAVE)
-        gtk_file_filter_set_name (all_savable, _("All XCF images"));
-      else
-        gtk_file_filter_set_name (all_savable, _("All export images"));
+      gtk_file_filter_set_name (all_savable, dialog->file_filter_label);
       gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), all_savable);
     }
 
   /* Add the normal file procs */
-  for (list = file_procs; list; list = g_slist_next (list))
+  for (list = dialog->file_procs; list; list = g_slist_next (list))
     {
       GimpPlugInProcedure *file_proc = list->data;
       GtkFileFilter       *filter    = NULL;
@@ -879,7 +702,7 @@ gimp_file_dialog_add_filters (GimpFileDialog        *dialog,
   /* Add the "rest" of the file procs only as filters to
    * "All images"
    */
-  for (list = file_procs_all_images; list; list = g_slist_next (list))
+  for (list = dialog->file_procs_all_images; list; list = g_slist_next (list))
     {
       GimpPlugInProcedure *file_proc = list->data;
 
@@ -894,18 +717,6 @@ 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:
  * @file_proc:
@@ -988,17 +799,14 @@ gimp_file_dialog_process_procedure (GimpPlugInProcedure  *file_proc,
 }
 
 static void
-gimp_file_dialog_add_proc_selection (GimpFileDialog *dialog,
-                                     Gimp           *gimp,
-                                     GSList         *file_procs,
-                                     const gchar    *automatic,
-                                     const gchar    *automatic_help_id)
+gimp_file_dialog_add_proc_selection (GimpFileDialog *dialog)
 {
   GtkWidget *scrolled_window;
 
   dialog->proc_expander = gtk_expander_new_with_mnemonic (NULL);
-  gtk_box_pack_start (GTK_BOX (dialog->extra_vbox), dialog->proc_expander,
-                      TRUE, TRUE, 0);
+  gimp_file_dialog_add_extra_widget (dialog,
+                                     dialog->proc_expander,
+                                     TRUE, TRUE, 0);
   gtk_widget_show (dialog->proc_expander);
 
   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
@@ -1011,8 +819,9 @@ gimp_file_dialog_add_proc_selection (GimpFileDialog *dialog,
 
   gtk_widget_set_size_request (scrolled_window, -1, 200);
 
-  dialog->proc_view = gimp_file_proc_view_new (gimp, file_procs, automatic,
-                                               automatic_help_id);
+  dialog->proc_view = gimp_file_proc_view_new (dialog->gimp, dialog->file_procs,
+                                               dialog->automatic_label,
+                                               dialog->automatic_help_id);
   gtk_container_add (GTK_CONTAINER (scrolled_window), dialog->proc_view);
   gtk_widget_show (dialog->proc_view);
 
@@ -1040,13 +849,6 @@ 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)
 {
@@ -1204,43 +1006,3 @@ gimp_file_dialog_pattern_from_extension (const gchar *extension)
 
   return pattern;
 }
-
-static GFile *
-gimp_file_dialog_get_default_folder (Gimp *gimp)
-{
-  if (gimp->default_folder)
-    {
-      return gimp->default_folder;
-    }
-  else
-    {
-      GFile *file = g_object_get_data (G_OBJECT (gimp),
-                                       "gimp-documents-folder");
-
-      if (! file)
-        {
-          gchar *path;
-
-          /* Make sure it ends in '/' */
-          path = g_build_path (G_DIR_SEPARATOR_S,
-                               g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS),
-                               G_DIR_SEPARATOR_S,
-                               NULL);
-
-          /* Paranoia fallback, see bug #722400 */
-          if (! path)
-            path = g_build_path (G_DIR_SEPARATOR_S,
-                                 g_get_home_dir (),
-                                 G_DIR_SEPARATOR_S,
-                                 NULL);
-
-          file = g_file_new_for_path (path);
-          g_free (path);
-
-          g_object_set_data_full (G_OBJECT (gimp), "gimp-documents-folder",
-                                  file, (GDestroyNotify) g_object_unref);
-        }
-
-      return file;
-    }
-}
diff --git a/app/widgets/gimpfiledialog.h b/app/widgets/gimpfiledialog.h
index 723dd4c..7dcf420 100644
--- a/app/widgets/gimpfiledialog.h
+++ b/app/widgets/gimpfiledialog.h
@@ -38,25 +38,28 @@ struct _GimpFileDialog
 {
   GtkFileChooserDialog  parent_instance;
 
-  GimpPlugInProcedure  *file_proc;
-
+  Gimp                 *gimp;
   GimpImage            *image;
-  gboolean              open_as_layers;
-  gboolean              save_a_copy;
-  gboolean              export;
-  gboolean              compat;
-  gboolean              close_after_saving;
-  GimpObject           *display_to_close;
+
+  GimpPlugInProcedure  *file_proc;
 
   GtkWidget            *thumb_box;
   GtkWidget            *extra_vbox;
-  GtkWidget            *compat_toggle;
   GtkWidget            *proc_expander;
   GtkWidget            *proc_view;
   GtkWidget            *progress;
 
   gboolean              busy;
   gboolean              canceled;
+
+  gchar                *help_id;
+  gchar                *stock_id;
+  gchar                *automatic_help_id;
+  gchar                *automatic_label;
+  gchar                *file_filter_label;
+
+  GSList               *file_procs;
+  GSList               *file_procs_all_images;
 };
 
 struct _GimpFileDialogClass
@@ -70,29 +73,17 @@ typedef struct _GimpFileDialogState GimpFileDialogState;
 
 GType       gimp_file_dialog_get_type       (void) G_GNUC_CONST;
 
-GtkWidget * gimp_file_dialog_new            (Gimp                 *gimp,
-                                             GimpFileChooserAction action,
-                                             const gchar          *title,
-                                             const gchar          *role,
-                                             const gchar          *icon_name,
-                                             const gchar          *help_id);
-
-void        gimp_file_dialog_set_sensitive  (GimpFileDialog       *dialog,
-                                             gboolean              sensitive);
-
-void        gimp_file_dialog_set_file_proc  (GimpFileDialog       *dialog,
-                                             GimpPlugInProcedure  *file_proc);
-
-void        gimp_file_dialog_set_open_image (GimpFileDialog       *dialog,
-                                             GimpImage            *image,
-                                             gboolean              open_as_layers);
-void        gimp_file_dialog_set_save_image (GimpFileDialog       *dialog,
-                                             Gimp                 *gimp,
-                                             GimpImage            *image,
-                                             gboolean              save_a_copy,
-                                             gboolean              export,
-                                             gboolean              close_after_saving,
-                                             GimpObject           *display);
+void        gimp_file_dialog_add_extra_widget (GimpFileDialog       *dialog,
+                                               GtkWidget            *widget,
+                                               gboolean              expand,
+                                               gboolean              fill,
+                                               guint                 padding);
+
+void        gimp_file_dialog_set_sensitive    (GimpFileDialog       *dialog,
+                                               gboolean              sensitive);
+
+void        gimp_file_dialog_set_file_proc    (GimpFileDialog       *dialog,
+                                               GimpPlugInProcedure  *file_proc);
 
 GimpFileDialogState * gimp_file_dialog_get_state     (GimpFileDialog      *dialog);
 void                  gimp_file_dialog_set_state     (GimpFileDialog      *dialog,
diff --git a/app/widgets/gimpopendialog.c b/app/widgets/gimpopendialog.c
new file mode 100644
index 0000000..a89896f
--- /dev/null
+++ b/app/widgets/gimpopendialog.c
@@ -0,0 +1,104 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpopendialog.c
+ * Copyright (C) 2015 Jehan <jehan girinstud io>
+ *
+ * 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 <http://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 "widgets-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+
+#include "pdb/gimppdb.h"
+
+#include "plug-in/gimppluginmanager.h"
+
+#include "gimpfiledialog.h"
+#include "gimphelp-ids.h"
+#include "gimpopendialog.h"
+
+#include "gimp-intl.h"
+
+
+G_DEFINE_TYPE (GimpOpenDialog, gimp_open_dialog,
+               GIMP_TYPE_FILE_DIALOG)
+
+#define parent_class gimp_open_dialog_parent_class
+
+static void
+gimp_open_dialog_class_init (GimpOpenDialogClass *klass)
+{
+}
+
+static void
+gimp_open_dialog_init (GimpOpenDialog *dialog)
+{
+}
+
+/*  public functions  */
+
+GtkWidget *
+gimp_open_dialog_new (Gimp *gimp)
+{
+  GimpOpenDialog *dialog;
+
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+
+  dialog = g_object_new (GIMP_TYPE_OPEN_DIALOG,
+                         "gimp",                      gimp,
+                         "title",                     _("Open Image"),
+                         "role",                      "gimp-file-open",
+                         "help-id",                   GIMP_HELP_FILE_OPEN,
+                         "stock-id",                  GTK_STOCK_OPEN,
+
+                         "automatic-label",           _("Automatically Detected"),
+                         "automatic-help-id",         GIMP_HELP_FILE_OPEN_BY_EXTENSION,
+
+                         "action",                    GTK_FILE_CHOOSER_ACTION_OPEN,
+                         "file-procs",                gimp->plug_in_manager->load_procs,
+                         "file-procs-all-images",     NULL,
+                         "file-filter-label",         NULL,
+                         "local-only",                FALSE,
+                         "do-overwrite-confirmation", TRUE,
+                         NULL);
+
+  return GTK_WIDGET (dialog);
+}
+
+void
+gimp_open_dialog_set_image (GimpOpenDialog *dialog,
+                            GimpImage      *image,
+                            gboolean        open_as_layers)
+{
+  g_return_if_fail (GIMP_IS_OPEN_DIALOG (dialog));
+  g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
+
+  GIMP_FILE_DIALOG (dialog)->image = image;
+  dialog->open_as_layers           = open_as_layers;
+}
+
+/*  private functions  */
diff --git a/app/widgets/gimpopendialog.h b/app/widgets/gimpopendialog.h
new file mode 100644
index 0000000..8a1c246
--- /dev/null
+++ b/app/widgets/gimpopendialog.h
@@ -0,0 +1,59 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpopendialog.h
+ * Copyright (C) 2015 Jehan <jehan girinstud io>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_OPEN_DIALOG_H__
+#define __GIMP_OPEN_DIALOG_H__
+
+G_BEGIN_DECLS
+
+#define GIMP_TYPE_OPEN_DIALOG            (gimp_open_dialog_get_type ())
+#define GIMP_OPEN_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_OPEN_DIALOG, 
GimpOpenDialog))
+#define GIMP_OPEN_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_OPEN_DIALOG, 
GimpOpenDialogClass))
+#define GIMP_IS_OPEN_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_OPEN_DIALOG))
+#define GIMP_IS_OPEN_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_OPEN_DIALOG))
+#define GIMP_OPEN_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_OPEN_DIALOG, 
GimpOpenDialogClass))
+
+
+typedef struct _GimpOpenDialogClass  GimpOpenDialogClass;
+
+struct _GimpOpenDialog
+{
+  GimpFileDialog       parent_instance;
+
+  gboolean             open_as_layers;
+};
+
+struct _GimpOpenDialogClass
+{
+  GimpFileDialogClass  parent_class;
+};
+
+
+GType       gimp_open_dialog_get_type       (void) G_GNUC_CONST;
+
+GtkWidget * gimp_open_dialog_new            (Gimp                 *gimp);
+
+void        gimp_open_dialog_set_image      (GimpOpenDialog       *dialog,
+                                             GimpImage            *image,
+                                             gboolean              open_as_layers);
+
+G_END_DECLS
+
+#endif /* __GIMP_OPEN_DIALOG_H__ */
diff --git a/app/widgets/gimpsavedialog.c b/app/widgets/gimpsavedialog.c
new file mode 100644
index 0000000..e9156da
--- /dev/null
+++ b/app/widgets/gimpsavedialog.c
@@ -0,0 +1,333 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpsavedialog.c
+ * Copyright (C) 2015 Jehan <jehan girinstud io>
+ *
+ * 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 <http://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 "widgets-types.h"
+
+#include "core/gimp.h"
+#include "core/gimpimage.h"
+
+#include "file/file-utils.h"
+#include "file/gimp-file.h"
+
+#include "pdb/gimppdb.h"
+
+#include "plug-in/gimppluginmanager.h"
+
+#include "gimpfiledialog.h"
+#include "gimphelp-ids.h"
+#include "gimpsavedialog.h"
+
+#include "gimp-intl.h"
+
+
+static void     gimp_save_dialog_constructed         (GObject         *object);
+
+static GFile  * gimp_save_dialog_get_default_folder  (Gimp            *gimp);
+static void     gimp_save_dialog_add_compat_toggle   (GimpSaveDialog  *dialog);
+static void     gimp_save_dialog_compat_toggled      (GtkToggleButton *button,
+                                                      GimpSaveDialog  *dialog);
+
+G_DEFINE_TYPE (GimpSaveDialog, gimp_save_dialog,
+               GIMP_TYPE_FILE_DIALOG)
+
+#define parent_class gimp_save_dialog_parent_class
+
+static void
+gimp_save_dialog_class_init (GimpSaveDialogClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed  = gimp_save_dialog_constructed;
+}
+
+static void
+gimp_save_dialog_init (GimpSaveDialog *dialog)
+{
+}
+
+static void
+gimp_save_dialog_constructed (GObject *object)
+{
+  GimpSaveDialog *dialog = GIMP_SAVE_DIALOG (object);
+
+  /* GimpFileDialog's constructed() is doing a few initialization
+   * common to all file dialogs. */
+  G_OBJECT_CLASS (parent_class)->constructed (object);
+
+  gimp_save_dialog_add_compat_toggle (dialog);
+}
+
+/*  public functions  */
+
+GtkWidget *
+gimp_save_dialog_new (Gimp *gimp)
+{
+  GimpSaveDialog *dialog;
+
+  g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
+
+  dialog = g_object_new (GIMP_TYPE_SAVE_DIALOG,
+                         "gimp",                      gimp,
+                         "title",                     _("Save Image"),
+                         "role",                      "gimp-file-save",
+                         "help-id",                   GIMP_HELP_FILE_SAVE,
+                         "stock-id",                  GTK_STOCK_SAVE,
+
+                         "automatic-label",           _("By Extension"),
+                         "automatic-help-id",         GIMP_HELP_FILE_SAVE_BY_EXTENSION,
+
+                         "action",                    GTK_FILE_CHOOSER_ACTION_SAVE,
+                         "file-procs",                gimp->plug_in_manager->save_procs,
+                         "file-procs-all-images",     gimp->plug_in_manager->export_procs,
+                         "file-filter-label",         _("All XCF images"),
+                         "local-only",                FALSE,
+                         "do-overwrite-confirmation", TRUE,
+                         NULL);
+
+  return GTK_WIDGET (dialog);
+}
+
+void
+gimp_save_dialog_set_image (GimpSaveDialog *dialog,
+                            Gimp           *gimp,
+                            GimpImage      *image,
+                            gboolean        save_a_copy,
+                            gboolean        close_after_saving,
+                            GimpObject     *display)
+{
+  GFile       *dir_file  = NULL;
+  GFile       *name_file = NULL;
+  GFile       *ext_file  = NULL;
+  gchar       *basename;
+  const gchar *version_string;
+  gint         rle_version;
+  gint         zlib_version;
+  gchar       *tooltip;
+
+  g_return_if_fail (GIMP_IS_SAVE_DIALOG (dialog));
+  g_return_if_fail (GIMP_IS_IMAGE (image));
+
+  GIMP_FILE_DIALOG (dialog)->image = image;
+  dialog->save_a_copy              = save_a_copy;
+  dialog->close_after_saving       = close_after_saving;
+  dialog->display_to_close         = display;
+
+  gimp_file_dialog_set_file_proc (GIMP_FILE_DIALOG (dialog), NULL);
+
+  /*
+   * Priority of default paths for Save:
+   *
+   *   1. Last Save a copy-path (applies only to Save a copy)
+   *   2. Last Save path
+   *   3. Path of source XCF
+   *   4. Path of Import source
+   *   5. Last Save path of any GIMP document
+   *   6. The default path (usually the OS 'Documents' path)
+   */
+
+  if (save_a_copy)
+    dir_file = gimp_image_get_save_a_copy_file (image);
+
+  if (! dir_file)
+    dir_file = gimp_image_get_file (image);
+
+  if (! dir_file)
+    dir_file = g_object_get_data (G_OBJECT (image),
+                                  "gimp-image-source-file");
+
+  if (! dir_file)
+    dir_file = gimp_image_get_imported_file (image);
+
+  if (! dir_file)
+    dir_file = g_object_get_data (G_OBJECT (gimp),
+                                  GIMP_FILE_SAVE_LAST_FILE_KEY);
+
+  if (! dir_file)
+    dir_file = gimp_save_dialog_get_default_folder (gimp);
+
+
+  /* Priority of default basenames for Save:
+   *
+   *   1. Last Save a copy-name (applies only to Save a copy)
+   *   2. Last Save name
+   *   3. Last Export name
+   *   3. The source image path
+   *   3. 'Untitled'
+   */
+
+  if (save_a_copy)
+    name_file = gimp_image_get_save_a_copy_file (image);
+
+  if (! name_file)
+    name_file = gimp_image_get_file (image);
+
+  if (! name_file)
+    name_file = gimp_image_get_exported_file (image);
+
+  if (! name_file)
+    name_file = gimp_image_get_imported_file (image);
+
+  if (! name_file)
+    name_file = gimp_image_get_untitled_file (image);
+
+
+  /* Priority of default type/extension for Save:
+   *
+   *   1. Type of last Save
+   *   2. .xcf (which we don't explicitly append)
+   */
+  ext_file = gimp_image_get_file (image);
+
+  if (ext_file)
+    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);
+
+  if (gtk_widget_get_sensitive (dialog->compat_toggle))
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->compat_toggle),
+                                    gimp_image_get_xcf_compat_mode (image));
+
+  if (ext_file)
+    {
+      GFile *tmp_file = file_utils_file_with_new_ext (name_file, ext_file);
+      basename = g_path_get_basename (gimp_file_get_utf8_name (tmp_file));
+      g_object_unref (tmp_file);
+      g_object_unref (ext_file);
+    }
+  else
+    {
+      basename = g_path_get_basename (gimp_file_get_utf8_name (name_file));
+    }
+
+  if (g_file_query_file_type (dir_file, G_FILE_QUERY_INFO_NONE, NULL) ==
+      G_FILE_TYPE_DIRECTORY)
+    {
+      gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
+                                                dir_file, NULL);
+    }
+  else
+    {
+      GFile *parent_file = g_file_get_parent (dir_file);
+      gtk_file_chooser_set_current_folder_file (GTK_FILE_CHOOSER (dialog),
+                                                parent_file, NULL);
+      g_object_unref (parent_file);
+    }
+
+  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), basename);
+}
+
+/*  private functions  */
+
+static GFile *
+gimp_save_dialog_get_default_folder (Gimp *gimp)
+{
+  if (gimp->default_folder)
+    {
+      return gimp->default_folder;
+    }
+  else
+    {
+      GFile *file = g_object_get_data (G_OBJECT (gimp),
+                                       "gimp-documents-folder");
+
+      if (! file)
+        {
+          gchar *path;
+
+          /* Make sure it ends in '/' */
+          path = g_build_path (G_DIR_SEPARATOR_S,
+                               g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS),
+                               G_DIR_SEPARATOR_S,
+                               NULL);
+
+          /* Paranoia fallback, see bug #722400 */
+          if (! path)
+            path = g_build_path (G_DIR_SEPARATOR_S,
+                                 g_get_home_dir (),
+                                 G_DIR_SEPARATOR_S,
+                                 NULL);
+
+          file = g_file_new_for_path (path);
+          g_free (path);
+
+          g_object_set_data_full (G_OBJECT (gimp), "gimp-documents-folder",
+                                  file, (GDestroyNotify) g_object_unref);
+        }
+
+      return file;
+    }
+}
+
+static void
+gimp_save_dialog_add_compat_toggle (GimpSaveDialog *dialog)
+{
+  dialog->compat_toggle = gtk_check_button_new_with_label (_("Save this XCF file with maximum 
compatibility"));
+
+  gimp_file_dialog_add_extra_widget (GIMP_FILE_DIALOG (dialog),
+                                     dialog->compat_toggle,
+                                     FALSE, FALSE, 0);
+
+  g_signal_connect (dialog->compat_toggle, "toggled",
+                    G_CALLBACK (gimp_save_dialog_compat_toggled),
+                    dialog);
+}
+
+static void
+gimp_save_dialog_compat_toggled (GtkToggleButton *button,
+                                 GimpSaveDialog  *dialog)
+{
+  dialog->compat = gtk_toggle_button_get_active (button);
+}
diff --git a/app/widgets/gimpsavedialog.h b/app/widgets/gimpsavedialog.h
new file mode 100644
index 0000000..b043d78
--- /dev/null
+++ b/app/widgets/gimpsavedialog.h
@@ -0,0 +1,69 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpsavedialog.h
+ * Copyright (C) 2015 Jehan <jehan girinstud io>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_SAVE_DIALOG_H__
+#define __GIMP_SAVE_DIALOG_H__
+
+#include "gimpfiledialog.h"
+
+G_BEGIN_DECLS
+
+#define GIMP_TYPE_SAVE_DIALOG            (gimp_save_dialog_get_type ())
+#define GIMP_SAVE_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SAVE_DIALOG, 
GimpSaveDialog))
+#define GIMP_SAVE_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SAVE_DIALOG, 
GimpSaveDialogClass))
+#define GIMP_IS_SAVE_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SAVE_DIALOG))
+#define GIMP_IS_SAVE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SAVE_DIALOG))
+#define GIMP_SAVE_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SAVE_DIALOG, 
GimpSaveDialogClass))
+
+
+typedef struct _GimpSaveDialogClass  GimpSaveDialogClass;
+
+struct _GimpSaveDialog
+{
+  GimpFileDialog       parent_instance;
+
+  gboolean             save_a_copy;
+  gboolean             close_after_saving;
+  GimpObject          *display_to_close;
+
+  GtkWidget           *compat_toggle;
+  gboolean             compat;
+};
+
+struct _GimpSaveDialogClass
+{
+  GimpFileDialogClass  parent_class;
+};
+
+
+GType       gimp_save_dialog_get_type       (void) G_GNUC_CONST;
+
+GtkWidget * gimp_save_dialog_new            (Gimp                 *gimp);
+
+void        gimp_save_dialog_set_image      (GimpSaveDialog       *dialog,
+                                             Gimp                 *gimp,
+                                             GimpImage            *image,
+                                             gboolean              save_a_copy,
+                                             gboolean              close_after_saving,
+                                             GimpObject           *display);
+
+G_END_DECLS
+
+#endif /* __GIMP_SAVE_DIALOG_H__ */
diff --git a/app/widgets/widgets-enums.h b/app/widgets/widgets-enums.h
index 068a477..0bd7ead 100644
--- a/app/widgets/widgets-enums.h
+++ b/app/widgets/widgets-enums.h
@@ -297,13 +297,6 @@ typedef enum  /*< skip >*/
 
 typedef enum  /*< skip >*/
 {
-  GIMP_FILE_CHOOSER_ACTION_OPEN,
-  GIMP_FILE_CHOOSER_ACTION_SAVE,
-  GIMP_FILE_CHOOSER_ACTION_EXPORT
-} GimpFileChooserAction;
-
-typedef enum  /*< skip >*/
-{
   GIMP_DIALOGS_SHOWN,
   GIMP_DIALOGS_HIDDEN_EXPLICITLY,  /* user used the Tab key to hide dialogs */
   GIMP_DIALOGS_HIDDEN_WITH_DISPLAY /* dialogs are hidden with the display   */
diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h
index b037638..79a3bee 100644
--- a/app/widgets/widgets-types.h
+++ b/app/widgets/widgets-types.h
@@ -129,12 +129,17 @@ typedef struct _GimpPlugInAction             GimpPlugInAction;
 typedef struct _GimpStringAction             GimpStringAction;
 typedef struct _GimpUIManager                GimpUIManager;
 
+/*  file dialogs  */
+
+typedef struct _GimpExportDialog             GimpExportDialog;
+typedef struct _GimpFileDialog               GimpFileDialog;
+typedef struct _GimpOpenDialog               GimpOpenDialog;
+typedef struct _GimpSaveDialog               GimpSaveDialog;
 
 /*  misc dialogs  */
 
 typedef struct _GimpColorDialog              GimpColorDialog;
 typedef struct _GimpErrorDialog              GimpErrorDialog;
-typedef struct _GimpFileDialog               GimpFileDialog;
 typedef struct _GimpMessageDialog            GimpMessageDialog;
 typedef struct _GimpProgressDialog           GimpProgressDialog;
 typedef struct _GimpTextEditor               GimpTextEditor;
diff --git a/devel-docs/app/app-sections.txt b/devel-docs/app/app-sections.txt
index 96b9a42..f044663 100644
--- a/devel-docs/app/app-sections.txt
+++ b/devel-docs/app/app-sections.txt
@@ -13053,7 +13053,6 @@ GimpDeviceValues
 GimpDialogsState
 GimpDndType
 GimpDropType
-GimpFileChooserAction
 GimpHistogramScale
 GimpTabStyle
 GimpTagEntryMode



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