[gimp/gimp-2-10] Issue #1160: file dialog view filter getting confused with file...



commit 88d126c31a3f7515ef49535c6e6da8457a96f6aa
Author: Jehan <jehan girinstud io>
Date:   Wed Jul 25 14:37:10 2018 +0200

    Issue #1160: file dialog view filter getting confused with file...
    
    ... format selection.
    As discussed, the first step is to get rid of the filter list. Our extra
    widget now has both roles of filtering the file list and forcing a
    loading procedure.
    
    (cherry picked from commit 9ae7827f9b040e18aabe1f5484505ffe99f11425)

 app/widgets/gimpfiledialog.c   | 209 +----------------------------------------
 app/widgets/gimpfileprocview.c | 162 +++++++++++++++++++++++++++++---
 app/widgets/gimpfileprocview.h |   3 +-
 3 files changed, 155 insertions(+), 219 deletions(-)
---
diff --git a/app/widgets/gimpfiledialog.c b/app/widgets/gimpfiledialog.c
index f5d9faa6a3..a0e884dbaa 100644
--- a/app/widgets/gimpfiledialog.c
+++ b/app/widgets/gimpfiledialog.c
@@ -47,9 +47,6 @@
 #include "gimp-intl.h"
 
 
-/*  an arbitrary limit to keep the file dialog from becoming too wide  */
-#define MAX_EXTENSIONS  4
-
 enum
 {
   PROP_0,
@@ -111,11 +108,6 @@ static guint32  gimp_file_dialog_progress_get_window_id  (GimpProgress        *p
 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,
@@ -131,9 +123,6 @@ static void     gimp_file_dialog_help_func               (const gchar         *h
 static void     gimp_file_dialog_help_clicked            (GtkWidget           *widget,
                                                           gpointer             dialog);
 
-static gchar  * gimp_file_dialog_pattern_from_extension  (const gchar         *extension);
-
-
 static GimpFileDialogState
               * gimp_file_dialog_get_state               (GimpFileDialog      *dialog);
 static void     gimp_file_dialog_set_state               (GimpFileDialog      *dialog,
@@ -370,7 +359,6 @@ gimp_file_dialog_constructed (GObject *object)
   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),
@@ -734,166 +722,6 @@ gimp_file_dialog_add_preview (GimpFileDialog *dialog)
 #endif
 }
 
-/**
- * gimp_file_dialog_add_filters:
- * @dialog:
- * @gimp:
- * @action:
- * @file_procs:            The image types that can be chosen from
- *                         the file type list
- * @file_procs_all_images: The additional images types shown when
- *                         "All images" is selected
- *
- **/
-static void
-gimp_file_dialog_add_filters (GimpFileDialog *dialog)
-{
-  GtkFileFilter *all;
-  GtkFileFilter *all_savable = NULL;
-  GSList        *list;
-
-  all = gtk_file_filter_new ();
-  gtk_file_filter_set_name (all, _("All files"));
-  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), all);
-  gtk_file_filter_add_pattern (all, "*");
-
-  all = gtk_file_filter_new ();
-  gtk_file_filter_set_name (all, _("All images"));
-  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), all);
-
-  if (dialog->file_procs_all_images)
-    {
-      all_savable = gtk_file_filter_new ();
-      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 = dialog->file_procs; list; list = g_slist_next (list))
-    {
-      GimpPlugInProcedure *file_proc = list->data;
-      GtkFileFilter       *filter    = NULL;
-
-      gimp_file_dialog_process_procedure (file_proc,
-                                          &filter,
-                                          all, all_savable);
-      if (filter)
-        {
-          gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog),
-                                       filter);
-          g_object_unref (filter);
-        }
-    }
-
-  /* Add the "rest" of the file procs only as filters to
-   * "All images"
-   */
-  for (list = dialog->file_procs_all_images; list; list = g_slist_next (list))
-    {
-      GimpPlugInProcedure *file_proc = list->data;
-
-      gimp_file_dialog_process_procedure (file_proc,
-                                          NULL,
-                                          all, NULL);
-    }
-
-  if (all_savable)
-    gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), all_savable);
-  else
-    gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), all);
-}
-
-/**
- * gimp_file_dialog_process_procedure:
- * @file_proc:
- * @filter_out:
- * @all:
- * @all_savable:
- *
- * Creates a #GtkFileFilter of @file_proc and adds the extensions to
- * the @all filter. The returned #GtkFileFilter has a normal ref and
- * must be unreffed when used.
- **/
-static void
-gimp_file_dialog_process_procedure (GimpPlugInProcedure  *file_proc,
-                                    GtkFileFilter       **filter_out,
-                                    GtkFileFilter        *all,
-                                    GtkFileFilter        *all_savable)
-{
-  GtkFileFilter *filter;
-  GString       *str;
-  GSList        *list;
-  gint           i;
-
-  if (! file_proc->extensions_list)
-    return;
-
-  filter = gtk_file_filter_new ();
-  str    = g_string_new (gimp_procedure_get_label (GIMP_PROCEDURE (file_proc)));
-
-  /* Take ownership directly so we don't have to mess with a floating
-   * ref
-   */
-  g_object_ref_sink (filter);
-
-  for (list = file_proc->mime_types_list; list; list = g_slist_next (list))
-    {
-      const gchar *mime_type = list->data;
-
-      gtk_file_filter_add_mime_type (filter, mime_type);
-      gtk_file_filter_add_mime_type (all, mime_type);
-      if (all_savable)
-        gtk_file_filter_add_mime_type (all_savable, mime_type);
-    }
-
-  for (list = file_proc->extensions_list, i = 0;
-       list;
-       list = g_slist_next (list), i++)
-    {
-      const gchar *extension = list->data;
-      gchar       *pattern;
-
-      pattern = gimp_file_dialog_pattern_from_extension (extension);
-      gtk_file_filter_add_pattern (filter, pattern);
-      gtk_file_filter_add_pattern (all, pattern);
-      if (all_savable)
-        gtk_file_filter_add_pattern (all_savable, pattern);
-      g_free (pattern);
-
-      if (i == 0)
-        {
-          g_string_append (str, " (");
-        }
-      else if (i <= MAX_EXTENSIONS)
-        {
-          g_string_append (str, ", ");
-        }
-
-      if (i < MAX_EXTENSIONS)
-        {
-          g_string_append (str, "*.");
-          g_string_append (str, extension);
-        }
-      else if (i == MAX_EXTENSIONS)
-        {
-          g_string_append (str, "...");
-        }
-
-      if (! list->next)
-        {
-          g_string_append (str, ")");
-        }
-    }
-
-  gtk_file_filter_set_name (filter, str->str);
-  g_string_free (str, TRUE);
-
-  if (filter_out)
-    *filter_out = g_object_ref (filter);
-
-  g_object_unref (filter);
-}
-
 static void
 gimp_file_dialog_add_proc_selection (GimpFileDialog *dialog)
 {
@@ -950,9 +778,10 @@ gimp_file_dialog_proc_changed (GimpFileProcView *view,
                                GimpFileDialog   *dialog)
 {
   GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
+  GtkFileFilter  *filter;
   gchar          *name;
 
-  dialog->file_proc = gimp_file_proc_view_get_proc (view, &name);
+  dialog->file_proc = gimp_file_proc_view_get_proc (view, &name, &filter);
 
   if (name)
     {
@@ -963,6 +792,7 @@ gimp_file_dialog_proc_changed (GimpFileProcView *view,
       g_free (label);
       g_free (name);
     }
+  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter);
 
   if (gtk_file_chooser_get_action (chooser) == GTK_FILE_CHOOSER_ACTION_SAVE)
     {
@@ -1071,39 +901,6 @@ gimp_file_dialog_help_clicked (GtkWidget *widget,
                            NULL);
 }
 
-static gchar *
-gimp_file_dialog_pattern_from_extension (const gchar *extension)
-{
-  gchar *pattern;
-  gchar *p;
-  gint   len, i;
-
-  g_return_val_if_fail (extension != NULL, NULL);
-
-  /* This function assumes that file extensions are 7bit ASCII.  It
-   * could certainly be rewritten to handle UTF-8 if this assumption
-   * turns out to be incorrect.
-   */
-
-  len = strlen (extension);
-
-  pattern = g_new (gchar, 4 + 4 * len);
-
-  strcpy (pattern, "*.");
-
-  for (i = 0, p = pattern + 2; i < len; i++, p+= 4)
-    {
-      p[0] = '[';
-      p[1] = g_ascii_tolower (extension[i]);
-      p[2] = g_ascii_toupper (extension[i]);
-      p[3] = ']';
-    }
-
-  *p = '\0';
-
-  return pattern;
-}
-
 static GimpFileDialogState *
 gimp_file_dialog_get_state (GimpFileDialog *dialog)
 {
diff --git a/app/widgets/gimpfileprocview.c b/app/widgets/gimpfileprocview.c
index 38daed07d5..6a1371f9fe 100644
--- a/app/widgets/gimpfileprocview.c
+++ b/app/widgets/gimpfileprocview.c
@@ -36,6 +36,8 @@
 
 #include "gimp-intl.h"
 
+/*  an arbitrary limit to keep the file dialog from becoming too wide  */
+#define MAX_EXTENSIONS  4
 
 enum
 {
@@ -43,6 +45,7 @@ enum
   COLUMN_LABEL,
   COLUMN_EXTENSIONS,
   COLUMN_HELP_ID,
+  COLUMN_FILTER,
   N_COLUMNS
 };
 
@@ -53,10 +56,13 @@ enum
 };
 
 
-static void  gimp_file_proc_view_finalize          (GObject          *object);
+static void            gimp_file_proc_view_finalize               (GObject             *object);
 
-static void  gimp_file_proc_view_selection_changed (GtkTreeSelection *selection,
-                                                    GimpFileProcView *view);
+static void            gimp_file_proc_view_selection_changed      (GtkTreeSelection    *selection,
+                                                                   GimpFileProcView    *view);
+
+static GtkFileFilter * gimp_file_proc_view_process_procedure      (GimpPlugInProcedure *file_proc);
+static gchar         * gimp_file_proc_view_pattern_from_extension (const gchar         *extension);
 
 
 G_DEFINE_TYPE (GimpFileProcView, gimp_file_proc_view, GTK_TYPE_TREE_VIEW)
@@ -120,10 +126,11 @@ gimp_file_proc_view_new (Gimp        *gimp,
   g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
 
   store = gtk_list_store_new (N_COLUMNS,
-                              GIMP_TYPE_PLUG_IN_PROCEDURE, /*  COLUMN_PROC   */
-                              G_TYPE_STRING,          /*  COLUMN_LABEL       */
-                              G_TYPE_STRING,          /*  COLUMN_EXTENSIONS  */
-                              G_TYPE_STRING);         /*  COLUMN_HELP_ID     */
+                              GIMP_TYPE_PLUG_IN_PROCEDURE, /*  COLUMN_PROC       */
+                              G_TYPE_STRING,               /*  COLUMN_LABEL      */
+                              G_TYPE_STRING,               /*  COLUMN_EXTENSIONS */
+                              G_TYPE_STRING,               /*  COLUMN_HELP_ID    */
+                              GTK_TYPE_FILE_FILTER);       /*  COLUMN_FILTER     */
 
   view = g_object_new (GIMP_TYPE_FILE_PROC_VIEW,
                        "model",      store,
@@ -144,12 +151,16 @@ gimp_file_proc_view_new (Gimp        *gimp,
 
           if (label)
             {
+              GtkFileFilter *filter;
+
+              filter = gimp_file_proc_view_process_procedure (proc);
               gtk_list_store_append (store, &iter);
               gtk_list_store_set (store, &iter,
                                   COLUMN_PROC,       proc,
                                   COLUMN_LABEL,      label,
                                   COLUMN_EXTENSIONS, proc->extensions,
                                   COLUMN_HELP_ID,    help_id,
+                                  COLUMN_FILTER,     filter,
                                   -1);
             }
 
@@ -171,12 +182,18 @@ gimp_file_proc_view_new (Gimp        *gimp,
 
   if (automatic)
     {
+      GtkFileFilter *filter = gtk_file_filter_new ();
+
       gtk_list_store_prepend (store, &iter);
 
+      gtk_file_filter_set_name (filter, _("All files"));
+      gtk_file_filter_add_pattern (filter, "*");
+
       gtk_list_store_set (store, &iter,
                           COLUMN_PROC,    NULL,
                           COLUMN_LABEL,   automatic,
                           COLUMN_HELP_ID, automatic_help_id,
+                          COLUMN_FILTER,  filter,
                           -1);
     }
 
@@ -212,7 +229,8 @@ gimp_file_proc_view_new (Gimp        *gimp,
 
 GimpPlugInProcedure *
 gimp_file_proc_view_get_proc (GimpFileProcView  *view,
-                              gchar            **label)
+                              gchar            **label,
+                              GtkFileFilter    **filter)
 {
   GtkTreeModel     *model;
   GtkTreeSelection *selection;
@@ -226,14 +244,25 @@ gimp_file_proc_view_get_proc (GimpFileProcView  *view,
     {
       GimpPlugInProcedure *proc;
 
-      if (label)
+      if (label && filter)
         gtk_tree_model_get (model, &iter,
-                            COLUMN_PROC,  &proc,
-                            COLUMN_LABEL, label,
+                            COLUMN_PROC,   &proc,
+                            COLUMN_LABEL,  label,
+                            COLUMN_FILTER, filter,
+                            -1);
+      else if (label)
+        gtk_tree_model_get (model, &iter,
+                            COLUMN_PROC,   &proc,
+                            COLUMN_LABEL,  label,
+                            -1);
+      else if (filter)
+        gtk_tree_model_get (model, &iter,
+                            COLUMN_PROC,   &proc,
+                            COLUMN_FILTER, filter,
                             -1);
       else
         gtk_tree_model_get (model, &iter,
-                            COLUMN_PROC,  &proc,
+                            COLUMN_PROC,   &proc,
                             -1);
 
       if (proc)
@@ -320,3 +349,112 @@ gimp_file_proc_view_selection_changed (GtkTreeSelection *selection,
 {
   g_signal_emit (view, view_signals[CHANGED], 0);
 }
+
+/**
+ * gimp_file_proc_view_process_procedure:
+ * @file_proc:
+ *
+ * Creates a #GtkFileFilter of @file_proc.
+ * The returned #GtkFileFilter has a normal ref and must be unreffed
+ * when used.
+ **/
+static GtkFileFilter *
+gimp_file_proc_view_process_procedure (GimpPlugInProcedure *file_proc)
+{
+  GtkFileFilter *filter;
+  GString       *str;
+  GSList        *list;
+  gint           i;
+
+  if (! file_proc->extensions_list)
+    return NULL;
+
+  filter = gtk_file_filter_new ();
+  str    = g_string_new (gimp_procedure_get_label (GIMP_PROCEDURE (file_proc)));
+
+  /* Take ownership directly so we don't have to mess with a floating
+   * ref
+   */
+  g_object_ref_sink (filter);
+
+  for (list = file_proc->mime_types_list; list; list = g_slist_next (list))
+    {
+      const gchar *mime_type = list->data;
+
+      gtk_file_filter_add_mime_type (filter, mime_type);
+    }
+
+  for (list = file_proc->extensions_list, i = 0;
+       list;
+       list = g_slist_next (list), i++)
+    {
+      const gchar *extension = list->data;
+      gchar       *pattern;
+
+      pattern = gimp_file_proc_view_pattern_from_extension (extension);
+      gtk_file_filter_add_pattern (filter, pattern);
+      g_free (pattern);
+
+      if (i == 0)
+        {
+          g_string_append (str, " (");
+        }
+      else if (i <= MAX_EXTENSIONS)
+        {
+          g_string_append (str, ", ");
+        }
+
+      if (i < MAX_EXTENSIONS)
+        {
+          g_string_append (str, "*.");
+          g_string_append (str, extension);
+        }
+      else if (i == MAX_EXTENSIONS)
+        {
+          g_string_append (str, "...");
+        }
+
+      if (! list->next)
+        {
+          g_string_append (str, ")");
+        }
+    }
+
+  gtk_file_filter_set_name (filter, str->str);
+  g_string_free (str, TRUE);
+
+  return filter;
+}
+
+static gchar *
+gimp_file_proc_view_pattern_from_extension (const gchar *extension)
+{
+  gchar *pattern;
+  gchar *p;
+  gint   len, i;
+
+  g_return_val_if_fail (extension != NULL, NULL);
+
+  /* This function assumes that file extensions are 7bit ASCII.  It
+   * could certainly be rewritten to handle UTF-8 if this assumption
+   * turns out to be incorrect.
+   */
+
+  len = strlen (extension);
+
+  pattern = g_new (gchar, 4 + 4 * len);
+
+  strcpy (pattern, "*.");
+
+  for (i = 0, p = pattern + 2; i < len; i++, p+= 4)
+    {
+      p[0] = '[';
+      p[1] = g_ascii_tolower (extension[i]);
+      p[2] = g_ascii_toupper (extension[i]);
+      p[3] = ']';
+    }
+
+  *p = '\0';
+
+  return pattern;
+}
diff --git a/app/widgets/gimpfileprocview.h b/app/widgets/gimpfileprocview.h
index 29f570cd11..6facd34d7a 100644
--- a/app/widgets/gimpfileprocview.h
+++ b/app/widgets/gimpfileprocview.h
@@ -55,7 +55,8 @@ GtkWidget           * gimp_file_proc_view_new         (Gimp                 *gim
                                                        const gchar          *automatic_help_id);
 
 GimpPlugInProcedure * gimp_file_proc_view_get_proc    (GimpFileProcView     *view,
-                                                       gchar               **label);
+                                                       gchar               **label,
+                                                       GtkFileFilter       **filter);
 gboolean              gimp_file_proc_view_set_proc    (GimpFileProcView     *view,
                                                        GimpPlugInProcedure  *proc);
 


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