From e4bc68ba04100e32a4945a753543549e306c1276 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 21 Jan 2009 03:17:01 +0000 Subject: [PATCH] Don't do completion in the middle of an incomplete hostname Fix completion so it doesn't pop up for every character in a URI hostname: * gtk/gtkfilechooser.h (GtkFileChooserError): Add a GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME. * gtk/gtkfilesystem.c (_gtk_file_system_parse): Return an "incomplete hostname" error if the user has not typed a full hostname yet in an URI. * gtk/gtkfilechooserentry.c (append_common_prefix): If we get an incomplete hostname, just don't pop up an error, since that is a transient state and the user doesn't need to be notified about it. (refresh_current_folder_and_file_part): Don't revert to showing the base folder if we have an incomplete hostname. (reload_current_folder): Handle the passed folder being NULL, even if we must force a reload. Also, reload the folder if we didn't have a cancellable for it (i.e. we hadn't started to load it before). Signed-off-by: Federico Mena Quintero svn path=/trunk/; revision=22157 --- ChangeLog | 20 ++++++++++++++++++++ gtk/gtkfilechooser.h | 3 ++- gtk/gtkfilechooserentry.c | 27 +++++++++++++++++++++------ gtk/gtkfilesystem.c | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 75 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8c91c4508c..bd748794dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -40,6 +40,26 @@ * gtk/gtkfilechooserdefault.c (set_local_only): Set the local_only property on the entry. + Fix completion so it doesn't pop up for every character in a URI + hostname: + + * gtk/gtkfilechooser.h (GtkFileChooserError): Add a + GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME. + + * gtk/gtkfilesystem.c (_gtk_file_system_parse): Return an + "incomplete hostname" error if the user has not typed a full + hostname yet in an URI. + + * gtk/gtkfilechooserentry.c (append_common_prefix): If we get an + incomplete hostname, just don't pop up an error, since that is a + transient state and the user doesn't need to be notified about it. + (refresh_current_folder_and_file_part): Don't revert to showing + the base folder if we have an incomplete hostname. + (reload_current_folder): Handle the passed folder being NULL, even + if we must force a reload. Also, reload the folder if we didn't + have a cancellable for it (i.e. we hadn't started to load it + before). + 2009-01-20 Matthias Clasen * gtk/gtk.symbols: diff --git a/gtk/gtkfilechooser.h b/gtk/gtkfilechooser.h index e085a7992d..b7983a9660 100644 --- a/gtk/gtkfilechooser.h +++ b/gtk/gtkfilechooser.h @@ -60,7 +60,8 @@ GType gtk_file_chooser_get_type (void) G_GNUC_CONST; typedef enum { GTK_FILE_CHOOSER_ERROR_NONEXISTENT, GTK_FILE_CHOOSER_ERROR_BAD_FILENAME, - GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS + GTK_FILE_CHOOSER_ERROR_ALREADY_EXISTS, + GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME } GtkFileChooserError; GQuark gtk_file_chooser_error_quark (void); diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c index c25de12c7b..149d74c45b 100644 --- a/gtk/gtkfilechooserentry.c +++ b/gtk/gtkfilechooserentry.c @@ -661,7 +661,12 @@ append_common_prefix (GtkFileChooserEntry *chooser_entry, error = NULL; if (!find_common_prefix (chooser_entry, &common_prefix, &unique_file, &is_complete_not_unique, &prefix_expands_the_file_part, &error)) { - if (show_errors) + /* If the user types an incomplete hostname ("http://foo" without a slash + * after that), it's not an error. We just don't want to pop up a + * meaningless completion window in that state. + */ + if (!g_error_matches (error, GTK_FILE_CHOOSER_ERROR, GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME) + && show_errors) { beep (chooser_entry); pop_up_completion_feedback (chooser_entry, _("Invalid path")); @@ -1403,7 +1408,8 @@ reload_current_folder (GtkFileChooserEntry *chooser_entry, if (chooser_entry->current_folder_file) { - if ((folder_file && !g_file_equal (folder_file, chooser_entry->current_folder_file)) + if ((folder_file && !(g_file_equal (folder_file, chooser_entry->current_folder_file) + && chooser_entry->load_folder_cancellable)) || force_reload) { reload = TRUE; @@ -1419,7 +1425,7 @@ reload_current_folder (GtkFileChooserEntry *chooser_entry, discard_current_folder (chooser_entry); g_object_unref (chooser_entry->current_folder_file); - chooser_entry->current_folder_file = g_object_ref (folder_file); + chooser_entry->current_folder_file = (folder_file) ? g_object_ref (folder_file) : NULL; } } else @@ -1443,6 +1449,7 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, gchar *file_part; gsize total_len, file_part_len; gint file_part_pos; + GError *error; editable = GTK_EDITABLE (chooser_entry); @@ -1462,14 +1469,22 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, } text = gtk_editable_get_chars (editable, 0, end_pos); - + + error = NULL; if (!chooser_entry->file_system || !chooser_entry->base_folder || !_gtk_file_system_parse (chooser_entry->file_system, chooser_entry->base_folder, text, - &folder_file, &file_part, NULL)) /* NULL-GError */ + &folder_file, &file_part, &error)) { - folder_file = (chooser_entry->base_folder) ? g_object_ref (chooser_entry->base_folder) : NULL; + if (g_error_matches (error, GTK_FILE_CHOOSER_ERROR, GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME)) + folder_file = NULL; + else + folder_file = (chooser_entry->base_folder) ? g_object_ref (chooser_entry->base_folder) : NULL; + + if (error) + g_error_free (error); + file_part = g_strdup (""); file_part_pos = -1; } diff --git a/gtk/gtkfilesystem.c b/gtk/gtkfilesystem.c index 46c36cb053..bc6cbf588d 100644 --- a/gtk/gtkfilesystem.c +++ b/gtk/gtkfilesystem.c @@ -672,6 +672,7 @@ _gtk_file_system_parse (GtkFileSystem *file_system, gboolean result = FALSE; gboolean is_dir = FALSE; gchar *last_slash = NULL; + gboolean is_uri; DEBUG ("parse"); @@ -680,7 +681,37 @@ _gtk_file_system_parse (GtkFileSystem *file_system, last_slash = strrchr (str, G_DIR_SEPARATOR); - if (str[0] == '~' || g_path_is_absolute (str) || has_uri_scheme (str)) + is_uri = has_uri_scheme (str); + + if (is_uri) + { + const char *colon; + const char *slash_after_hostname; + + colon = strchr (str, ':'); + g_assert (colon != NULL); + g_assert (strncmp (colon, "://", 3) == 0); + + slash_after_hostname = strchr (colon + 3, '/'); + + if (slash_after_hostname == NULL) + { + /* We don't have a full hostname yet. So, don't switch the folder + * until we have seen a full hostname. Otherwise, completion will + * happen for every character the user types for the hostname. + */ + + *folder = NULL; + *file_part = NULL; + g_set_error (error, + GTK_FILE_CHOOSER_ERROR, + GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME, + "Incomplete hostname"); + return FALSE; + } + } + + if (str[0] == '~' || g_path_is_absolute (str) || is_uri) file = g_file_parse_name (str); else file = g_file_resolve_relative_path (base_file, str);