From 2b348f9a48de3de7be1a91c6fec1392c9fe1f010 Mon Sep 17 00:00:00 2001 From: Stephen Shaw Date: Tue, 5 Oct 2010 12:55:03 -0500 Subject: [PATCH] bgo#629722 - file chooser should cope with typing a directory name and then Enter file_exists_get_info_cb() used to let some actions fall through to the code that checks for the file type of the selected file's parent (e.g. to see if /foo/bar *is* indeed a folder if you type /foo/bar/baz). However, we need to be more explicit for each file chooser action, as in SELECT_FOLDER mode typing /foo/foldername and hitting Enter would not give you an immediate selection, but rather the file chooser would complain that it couldn't create that directory as it already exists. Signed-off-by: Federico Mena Quintero --- gtk/gtkfilechooserdefault.c | 87 +++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 17 deletions(-) diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index db8e5ca017..71cc5275da 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -987,6 +987,19 @@ error_creating_folder_over_existing_file_dialog (GtkFileChooserDefault *impl, file, error); } +/* Shows an error about not being able to select a folder because a file with + * the same name is already there. + */ +static void +error_selecting_folder_over_existing_file_dialog (GtkFileChooserDefault *impl, + GFile *file) +{ + error_dialog (impl, + _("You may only select folders. The item that you selected is not a folder; " + "try using a different item."), + file, NULL); +} + /* Shows an error dialog about not being able to create a filename */ static void error_building_filename_dialog (GtkFileChooserDefault *impl, @@ -8209,7 +8222,9 @@ file_exists_get_info_cb (GCancellable *cancellable, { gboolean data_ownership_taken = FALSE; gboolean cancelled = g_cancellable_is_cancelled (cancellable); - gboolean file_exists_and_is_not_folder; + gboolean file_exists; + gboolean is_folder; + gboolean needs_file_type_check = FALSE; struct FileExistsData *data = user_data; if (cancellable != data->impl->file_exists_get_info_cancellable) @@ -8222,29 +8237,63 @@ file_exists_get_info_cb (GCancellable *cancellable, if (cancelled) goto out; - file_exists_and_is_not_folder = info && (! _gtk_file_info_consider_as_directory (info)); + file_exists = (info != NULL); + is_folder = (file_exists && _gtk_file_info_consider_as_directory (info)); if (data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN) - /* user typed a filename; we are done */ - g_signal_emit_by_name (data->impl, "response-requested"); - else if (data->impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER - && file_exists_and_is_not_folder) { - /* Oops, the user typed the name of an existing path which is not - * a folder - */ - error_creating_folder_over_existing_file_dialog (data->impl, data->file, - g_error_copy (error)); + /* user typed a filename; we are done */ + g_signal_emit_by_name (data->impl, "response-requested"); + } + else if (data->impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) + { + if (file_exists && !is_folder) + { + /* Oops, the user typed the name of an existing path which is not + * a folder + */ + error_creating_folder_over_existing_file_dialog (data->impl, data->file, + g_error_copy (error)); + } + else + { + needs_file_type_check = TRUE; + } + } + else if (data->impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) + { + if (!file_exists) + { + needs_file_type_check = TRUE; + } + else + { + if (is_folder) + { + /* User typed a folder; we are done */ + g_signal_emit_by_name (data->impl, "response-requested"); + } + else + error_selecting_folder_over_existing_file_dialog (data->impl, data->file); + } + } + else if (data->impl->action == GTK_FILE_CHOOSER_ACTION_SAVE) + { + needs_file_type_check = TRUE; } else { - /* check that everything up to the last component exists */ + g_assert_not_reached(); + } - data->file_exists_and_is_not_folder = file_exists_and_is_not_folder; - data_ownership_taken = TRUE; + if (needs_file_type_check) { + /* check that everything up to the last component exists */ - if (data->impl->should_respond_get_info_cancellable) - g_cancellable_cancel (data->impl->should_respond_get_info_cancellable); + data->file_exists_and_is_not_folder = file_exists && !is_folder; + data_ownership_taken = TRUE; + + if (data->impl->should_respond_get_info_cancellable) + g_cancellable_cancel (data->impl->should_respond_get_info_cancellable); data->impl->should_respond_get_info_cancellable = _gtk_file_system_get_info (data->impl->file_system, @@ -8454,7 +8503,11 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed) { struct FileExistsData *data; - /* We need to check whether file exists and is not a folder */ + /* We need to check whether file exists and whether it is a folder - + * the GtkFileChooserEntry *does* report is_folder==FALSE as a false + * negative (it doesn't know yet if your last path component is a + * folder). + */ data = g_new0 (struct FileExistsData, 1); data->impl = g_object_ref (impl);