[gtk+/gtk-3-18] GtkFileChooserEntry: regenerate the completions if the dir_part changes



commit efd52319a523e54974fdf36c44927bfeb54711f6
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Mar 10 15:05:16 2016 -0600

    GtkFileChooserEntry: regenerate the completions if the dir_part changes
    
    Consider this bug:
    
    1. Open a file chooser; switch it to $HOME
    
    2. Start typing "~/Dow" with some file that *does* exist in your $HOME
    
    3. Delete the inline-completion selection (e.g. the "nloads" after "~/Down").
    
    4. While you are at "~/Dow_" hit Tab.  No completion will occur.
    
    This happens because of the following.
    
    Say the GtkFileChooserEntry is in the process of loading $HOME,
    because _set_base_folder() was called.  If the entry contains no text,
    then the FULL_PATH_COLUMN of the file system model will be set to
    unprefixed filenames from $HOME, like
    
      .ssh/
      Documents/
      Downloads/
      somefile.txt
    
    Later we avoid reloading the folder if g_file_equal(old_folder, new_folder).
    
    However, the FULL_PATH_COLUMN gets populated in completion_store_set()
    out of the actual filenames that GIO returned, plus the chooser_entry->dir_part.
    
    If the user starts typing "~/Dow" then dir_part changes to "~/", *but*
    the folder won't be reloaded since it is also $HOME.  However, the completion
    machinery assumes that FULL_PATH_COLUMN will contain prefixed entries like
    
      ~/.ssh/
      ~/Documents/
      ~/Downloads/
      ~/somefile.txt
    
    So, we add an invariant that chooser_entry->dir_part and
    chooser_entry->current_folder_file must change at the same time, and
    must not get out of sync:  If any of them changes, then the
    completions are regenerated.

 gtk/gtkfilechooserentry.c |   48 ++++++++++++++++++++++++++++----------------
 1 files changed, 30 insertions(+), 18 deletions(-)
---
diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c
index be310ee..71c615e 100644
--- a/gtk/gtkfilechooserentry.c
+++ b/gtk/gtkfilechooserentry.c
@@ -108,7 +108,8 @@ static void set_complete_on_load (GtkFileChooserEntry *chooser_entry,
                                   gboolean             complete_on_load);
 static void refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry);
 static void set_completion_folder (GtkFileChooserEntry *chooser_entry,
-                                   GFile               *folder);
+                                   GFile               *folder,
+                                  char                *dir_part);
 static void finished_loading_cb (GtkFileSystemModel  *model,
                                  GError              *error,
                                 GtkFileChooserEntry *chooser_entry);
@@ -248,7 +249,7 @@ gtk_file_chooser_entry_dispose (GObject *object)
 {
   GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (object);
 
-  set_completion_folder (chooser_entry, NULL);
+  set_completion_folder (chooser_entry, NULL, NULL);
 
   G_OBJECT_CLASS (_gtk_file_chooser_entry_parent_class)->dispose (object);
 }
@@ -374,7 +375,7 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry)
     {
       char *completion, *text;
       gsize completion_len, text_len;
-      
+
       text = gtk_file_chooser_entry_get_completion_text (chooser_entry);
       text_len = strlen (text);
       completion = gtk_entry_completion_compute_prefix (gtk_entry_get_completion (GTK_ENTRY 
(chooser_entry)), text);
@@ -523,11 +524,11 @@ completion_store_set (GtkFileSystemModel  *model,
       if (_gtk_file_info_consider_as_directory (info))
         suffix = G_DIR_SEPARATOR_S;
 
-      g_value_take_string (value, g_strconcat (
-              prefix,
-              g_file_info_get_display_name (info),
-              suffix,
-              NULL));
+      g_value_take_string (value,
+                          g_strconcat (prefix,
+                                       g_file_info_get_display_name (info),
+                                       suffix,
+                                       NULL));
       break;
     default:
       g_assert_not_reached ();
@@ -598,24 +599,31 @@ finished_loading_cb (GtkFileSystemModel  *model,
 
 static void
 set_completion_folder (GtkFileChooserEntry *chooser_entry,
-                       GFile               *folder_file)
+                       GFile               *folder_file,
+                      char                *dir_part)
 {
   if (folder_file &&
       chooser_entry->local_only
       && !_gtk_file_has_native_path (folder_file))
     folder_file = NULL;
 
-  if ((chooser_entry->current_folder_file
-       && folder_file
-       && g_file_equal (folder_file, chooser_entry->current_folder_file))
-      || chooser_entry->current_folder_file == folder_file)
-    return;
+  if (((chooser_entry->current_folder_file
+       && folder_file
+       && g_file_equal (folder_file, chooser_entry->current_folder_file))
+       || chooser_entry->current_folder_file == folder_file)
+      && g_strcmp0 (dir_part, chooser_entry->dir_part) == 0)
+    {
+      return;
+    }
 
   if (chooser_entry->current_folder_file)
     {
       g_object_unref (chooser_entry->current_folder_file);
       chooser_entry->current_folder_file = NULL;
     }
+
+  g_free (chooser_entry->dir_part);
+  chooser_entry->dir_part = g_strdup (dir_part);
   
   chooser_entry->current_folder_loaded = FALSE;
 
@@ -633,29 +641,33 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry)
 {
   GFile *folder_file;
   char *text, *last_slash, *old_file_part;
+  char *dir_part;
 
   old_file_part = chooser_entry->file_part;
-  g_free (chooser_entry->dir_part);
 
   text = gtk_file_chooser_entry_get_completion_text (chooser_entry);
 
   last_slash = strrchr (text, G_DIR_SEPARATOR);
   if (last_slash)
     {
-      chooser_entry->dir_part = g_strndup (text, last_slash - text + 1);
+      dir_part = g_strndup (text, last_slash - text + 1);
       chooser_entry->file_part = g_strdup (last_slash + 1);
     }
   else
     {
-      chooser_entry->dir_part = g_strdup ("");
+      dir_part = g_strdup ("");
       chooser_entry->file_part = g_strdup (text);
     }
 
   folder_file = gtk_file_chooser_get_directory_for_text (chooser_entry, text);
-  set_completion_folder (chooser_entry, folder_file);
+
+  set_completion_folder (chooser_entry, folder_file, dir_part);
+
   if (folder_file)
     g_object_unref (folder_file);
 
+  g_free (dir_part);
+
   if (chooser_entry->completion_store &&
       (g_strcmp0 (old_file_part, chooser_entry->file_part) != 0))
     {


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