[gtk+] filechooserwidget: Forward file filter to entry



commit 55fda57c44ab90380a92ec36518d572b7d7992b8
Author: Timm Bäder <mail baedert org>
Date:   Tue Nov 15 10:51:41 2016 +0100

    filechooserwidget: Forward file filter to entry
    
    And in the entry, apply the currently used filter as a second step to
    the completion items.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773007

 gtk/gtkfilechooserentry.c  |   95 ++++++++++++++++++++++++++++++++++++++++++--
 gtk/gtkfilechooserentry.h  |    2 +
 gtk/gtkfilechooserwidget.c |    6 +++
 3 files changed, 99 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c
index cc6e119..e5607c1 100644
--- a/gtk/gtkfilechooserentry.c
+++ b/gtk/gtkfilechooserentry.c
@@ -32,6 +32,7 @@
 #include "gtkwindow.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
+#include "gtkfilefilterprivate.h"
 
 typedef struct _GtkFileChooserEntryClass GtkFileChooserEntryClass;
 
@@ -56,6 +57,7 @@ struct _GtkFileChooserEntry
   gchar *file_part;
 
   GtkTreeModel *completion_store;
+  GtkFileFilter *current_filter;
 
   guint current_folder_loaded : 1;
   guint complete_on_load : 1;
@@ -179,6 +181,83 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class)
                   G_TYPE_NONE, 0);
 }
 
+static gboolean
+match_func (GtkEntryCompletion *compl,
+            const gchar        *key,
+            GtkTreeIter        *iter,
+            gpointer            user_data)
+{
+  GtkFileChooserEntry *chooser_entry = user_data;
+
+  /* If we arrive here, the GtkFileSystemModel's GtkFileFilter already filtered out all
+   * files that don't start with the current prefix, so we manually apply the GtkFileChooser's
+   * current file filter (e.g. just jpg files) here. */
+  if (chooser_entry->current_filter != NULL)
+    {
+      char *mime_type = NULL;
+      gboolean matches;
+      GFile *file;
+      GFileInfo *file_info;
+      GtkFileFilterInfo filter_info;
+      GtkFileFilterFlags needed_flags;
+
+      file = _gtk_file_system_model_get_file (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
+                                              iter);
+      file_info = _gtk_file_system_model_get_info (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store),
+                                                   iter);
+
+      /* We always allow navigating into subfolders, so don't ever filter directories */
+      if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_REGULAR)
+        return TRUE;
+
+      needed_flags = gtk_file_filter_get_needed (chooser_entry->current_filter);
+
+      filter_info.display_name = g_file_info_get_display_name (file_info);
+      filter_info.contains |= GTK_FILE_FILTER_DISPLAY_NAME;
+
+      if (needed_flags & GTK_FILE_FILTER_MIME_TYPE)
+        {
+          const char *s = g_file_info_get_content_type (file_info);
+          if (s != NULL)
+            {
+              mime_type = g_content_type_get_mime_type (s);
+              if (mime_type != NULL)
+                {
+                  filter_info.mime_type = mime_type;
+                  filter_info.contains |= GTK_FILE_FILTER_MIME_TYPE;
+                }
+            }
+        }
+
+      if (needed_flags & GTK_FILE_FILTER_FILENAME)
+        {
+          const char *path = g_file_get_path (file);
+          if (path != NULL)
+            {
+              filter_info.filename = path;
+              filter_info.contains |= GTK_FILE_FILTER_FILENAME;
+            }
+        }
+
+      if (needed_flags & GTK_FILE_FILTER_URI)
+        {
+          const char *uri = g_file_get_uri (file);
+          if (uri)
+            {
+              filter_info.uri = uri;
+              filter_info.contains |= GTK_FILE_FILTER_URI;
+            }
+        }
+
+      matches = gtk_file_filter_filter (chooser_entry->current_filter, &filter_info);
+
+      g_free (mime_type);
+      return matches;
+    }
+
+  return TRUE;
+}
+
 static void
 _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
 {
@@ -198,9 +277,9 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
   /* Need a match func here or entry completion uses a wrong one.
    * We do our own filtering after all. */
   gtk_entry_completion_set_match_func (comp,
-                                      (GtkEntryCompletionMatchFunc) gtk_true,
-                                      chooser_entry,
-                                      NULL);
+                                       match_func,
+                                       chooser_entry,
+                                       NULL);
 
   cell = gtk_cell_renderer_text_new ();
   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comp),
@@ -546,7 +625,8 @@ populate_completion_store (GtkFileChooserEntry *chooser_entry)
 {
   chooser_entry->completion_store = GTK_TREE_MODEL (
       _gtk_file_system_model_new_for_directory (chooser_entry->current_folder_file,
-                                                "standard::name,standard::display-name,standard::type",
+                                                "standard::name,standard::display-name,standard::type,"
+                                                "standard::content-type",
                                                 completion_store_set,
                                                 chooser_entry,
                                                 N_COLUMNS,
@@ -983,3 +1063,10 @@ _gtk_file_chooser_entry_get_local_only (GtkFileChooserEntry *chooser_entry)
 {
   return chooser_entry->local_only;
 }
+
+void
+_gtk_file_chooser_entry_set_file_filter (GtkFileChooserEntry *chooser_entry,
+                                         GtkFileFilter       *filter)
+{
+  chooser_entry->current_filter = filter;
+}
diff --git a/gtk/gtkfilechooserentry.h b/gtk/gtkfilechooserentry.h
index cf7d850..732a87a 100644
--- a/gtk/gtkfilechooserentry.h
+++ b/gtk/gtkfilechooserentry.h
@@ -46,6 +46,8 @@ void               _gtk_file_chooser_entry_select_filename    (GtkFileChooserEnt
 void               _gtk_file_chooser_entry_set_local_only     (GtkFileChooserEntry *chooser_entry,
                                                                gboolean             local_only);
 gboolean           _gtk_file_chooser_entry_get_local_only     (GtkFileChooserEntry *chooser_entry);
+void               _gtk_file_chooser_entry_set_file_filter    (GtkFileChooserEntry *chooser_entry,
+                                                               GtkFileFilter       *filter);
 
 G_END_DECLS
 
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index 6a270ff..d0b7286 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -2610,6 +2610,8 @@ location_entry_setup (GtkFileChooserWidget *impl)
 
   _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->local_only);
   _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (priv->location_entry), priv->action);
+  _gtk_file_chooser_entry_set_file_filter (GTK_FILE_CHOOSER_ENTRY (priv->location_entry),
+                                           priv->current_filter);
   gtk_entry_set_width_chars (GTK_ENTRY (priv->location_entry), 45);
   gtk_entry_set_activates_default (GTK_ENTRY (priv->location_entry), TRUE);
 }
@@ -7669,6 +7671,10 @@ filter_combo_changed (GtkComboBox          *combo_box,
   new_index = gtk_combo_box_get_active (combo_box);
   new_filter = g_slist_nth_data (priv->filters, new_index);
   set_current_filter (impl, new_filter);
+
+  if (priv->location_entry != NULL)
+    _gtk_file_chooser_entry_set_file_filter (GTK_FILE_CHOOSER_ENTRY (priv->location_entry),
+                                             new_filter);
 }
 
 static void


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