mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 14:10:30 +00:00
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.
This commit is contained in:
parent
2b773e07e3
commit
81059c35d5
@ -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))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user