diff --git a/ChangeLog b/ChangeLog index 18791dfc39..a81859c49d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2006-09-03 Kristian Rietveld + + * gtk/gtkfilechooserdefault.c (save_entry_get_info_cb), + (file_exists_get_info_cb), (gtk_file_chooser_default_should_respond): + change file_exists_and_is_not_folder checks to get the file info + for the path directly instead of querying the current file folder + of the save entry. + + * gtk/gtkfilechooserprivate.h (struct _GtkFileChooserDefault): add + new field. + + * tests/autotestfilechooser.c (wait_for_idle_idle), (wait_for_idle), + (test_reload_sequence), (test_button_folder_states_for_action): wait + for idle after setting a folder to ensure the async operations to load + the folder are finished, + (test_confirm_overwrite), (test_confirm_overwrite_for_path): + factor out test_confirm_overwrite code so we can add tests for more + paths more easily. + 2006-09-03 Richard Hult * gdk/quartz/GdkQuartzView.c (drawRect): Don't do anything if diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index ff7482527c..6c50ef3c05 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -7327,7 +7327,7 @@ out: g_object_unref (handle); } -struct SaveEntryData +struct FileExistsData { GtkFileChooserDefault *impl; gboolean file_exists_and_is_not_folder; @@ -7343,7 +7343,7 @@ save_entry_get_info_cb (GtkFileSystemHandle *handle, { gboolean parent_is_folder; gboolean cancelled = handle->cancelled; - struct SaveEntryData *data = user_data; + struct FileExistsData *data = user_data; if (handle != data->impl->should_respond_get_info_handle) goto out; @@ -7406,6 +7406,72 @@ out: g_object_unref (handle); } +static void +file_exists_get_info_cb (GtkFileSystemHandle *handle, + const GtkFileInfo *info, + const GError *error, + gpointer user_data) +{ + gboolean data_ownership_taken = FALSE; + gboolean cancelled = handle->cancelled; + gboolean file_exists_and_is_not_folder; + struct FileExistsData *data = user_data; + + if (handle != data->impl->file_exists_get_info_handle) + goto out; + + data->impl->file_exists_get_info_handle = NULL; + + set_busy_cursor (data->impl, FALSE); + + if (cancelled) + goto out; + + file_exists_and_is_not_folder = info && !gtk_file_info_get_is_folder (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->path, + g_error_copy (error)); + } + else + { + /* check that everything up to the last component exists */ + + data->file_exists_and_is_not_folder = file_exists_and_is_not_folder; + data_ownership_taken = TRUE; + + if (data->impl->should_respond_get_info_handle) + gtk_file_system_cancel_operation (data->impl->should_respond_get_info_handle); + + data->impl->should_respond_get_info_handle = + gtk_file_system_get_info (data->impl->file_system, + data->parent_path, + GTK_FILE_INFO_IS_FOLDER, + save_entry_get_info_cb, + data); + set_busy_cursor (data->impl, TRUE); + } + +out: + if (!data_ownership_taken) + { + g_object_unref (data->impl); + gtk_file_path_free (data->path); + gtk_file_path_free (data->parent_path); + g_free (data); + } + + g_object_unref (handle); +} + static void paste_text_received (GtkClipboard *clipboard, const gchar *text, @@ -7593,46 +7659,26 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed) } else { - gboolean file_exists_and_is_not_folder; + struct FileExistsData *data; - file_exists_and_is_not_folder = g_error_matches (error, GTK_FILE_SYSTEM_ERROR, GTK_FILE_SYSTEM_ERROR_NOT_FOLDER); + /* We need to check whether path exists and is not a folder */ - if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN) - retval = TRUE; /* user typed a filename; we are done */ - else if (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 (impl, path, error); - error = NULL; /* as it will be freed below for the general case */ - retval = FALSE; - } - else - { - GtkFilePath *parent_path; - struct SaveEntryData *data; + data = g_new0 (struct FileExistsData, 1); + data->impl = g_object_ref (impl); + data->path = gtk_file_path_copy (path); + data->parent_path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry)); - /* check that everything up to the last component exists */ + if (impl->file_exists_get_info_handle) + gtk_file_system_cancel_operation (impl->file_exists_get_info_handle); - parent_path = gtk_file_path_copy (_gtk_file_chooser_entry_get_current_folder (entry)); + impl->file_exists_get_info_handle = + gtk_file_system_get_info (impl->file_system, path, + GTK_FILE_INFO_IS_FOLDER, + file_exists_get_info_cb, + data); - data = g_new0 (struct SaveEntryData, 1); - data->impl = g_object_ref (impl); - data->file_exists_and_is_not_folder = file_exists_and_is_not_folder; - data->parent_path = parent_path; /* Takes ownership */ - data->path = gtk_file_path_copy (path); - - if (impl->should_respond_get_info_handle) - gtk_file_system_cancel_operation (impl->should_respond_get_info_handle); - - impl->should_respond_get_info_handle = - gtk_file_system_get_info (impl->file_system, parent_path, - GTK_FILE_INFO_IS_FOLDER, - save_entry_get_info_cb, - data); - set_busy_cursor (impl, TRUE); - - retval = FALSE; - } + set_busy_cursor (impl, TRUE); + retval = FALSE; if (error != NULL) g_error_free (error); diff --git a/gtk/gtkfilechooserprivate.h b/gtk/gtkfilechooserprivate.h index d198e96c27..eb18035c89 100644 --- a/gtk/gtkfilechooserprivate.h +++ b/gtk/gtkfilechooserprivate.h @@ -206,6 +206,7 @@ struct _GtkFileChooserDefault GtkFileSystemHandle *update_current_folder_handle; GtkFileSystemHandle *show_and_select_paths_handle; GtkFileSystemHandle *should_respond_get_info_handle; + GtkFileSystemHandle *file_exists_get_info_handle; GtkFileSystemHandle *update_from_entry_handle; GtkFileSystemHandle *shortcuts_activate_iter_handle; GSList *pending_handles; diff --git a/tests/autotestfilechooser.c b/tests/autotestfilechooser.c index e216fd358a..e7aa8de685 100644 --- a/tests/autotestfilechooser.c +++ b/tests/autotestfilechooser.c @@ -77,6 +77,28 @@ set_filename_timeout_cb (gpointer data) return FALSE; } + +static guint wait_for_idle_id = 0; + +static gboolean +wait_for_idle_idle (gpointer data) +{ + wait_for_idle_id = 0; + + return FALSE; +} + +static void +wait_for_idle (void) +{ + wait_for_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, + wait_for_idle_idle, + NULL, NULL); + + while (wait_for_idle_id) + gtk_main_iteration (); +} + static gboolean test_set_filename (GtkFileChooserAction action, gboolean focus_button, @@ -289,7 +311,7 @@ confirm_overwrite_timeout_cb (gpointer data) /* http://bugzilla.gnome.org/show_bug.cgi?id=347883 */ static gboolean -test_confirm_overwrite (void) +test_confirm_overwrite_for_path (const char *path) { gboolean passed; struct confirm_overwrite_closure closure; @@ -308,13 +330,13 @@ test_confirm_overwrite (void) g_signal_connect (closure.chooser, "confirm-overwrite", G_CALLBACK (confirm_overwrite_cb), &closure); - gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (closure.chooser), "/etc/passwd"); /* a file we know will always exist */ + gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (closure.chooser), path); g_timeout_add (2000, confirm_overwrite_timeout_cb, &closure); gtk_dialog_run (GTK_DIALOG (closure.chooser)); filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (closure.chooser)); - passed = passed && filename && (strcmp (filename, "/etc/passwd") == 0); + passed = passed && filename && (strcmp (filename, path) == 0); g_free (filename); gtk_widget_destroy (closure.chooser); @@ -326,6 +348,16 @@ test_confirm_overwrite (void) return passed; } +static gboolean +test_confirm_overwrite (void) +{ + gboolean passed = TRUE; + + passed = passed && test_confirm_overwrite_for_path ("/etc/passwd"); /* a file we know will always exist */ + + return passed; +} + static const GtkFileChooserAction open_actions[] = { GTK_FILE_CHOOSER_ACTION_OPEN, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER @@ -585,6 +617,8 @@ test_reload_sequence (gboolean set_folder_before_map) { gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), g_get_home_dir ()); + wait_for_idle (); + passed = passed && (impl->current_folder != NULL && impl->browse_files_model != NULL && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED) @@ -594,6 +628,8 @@ test_reload_sequence (gboolean set_folder_before_map) ? (impl->load_timeout_id == 0 && impl->sort_model != NULL) : TRUE)); + wait_for_idle (); + folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); passed = passed && (folder != NULL && strcmp (folder, g_get_home_dir()) == 0); g_free (folder); @@ -608,6 +644,8 @@ test_reload_sequence (gboolean set_folder_before_map) && impl->reload_state == RELOAD_EMPTY && impl->load_timeout_id == 0); + wait_for_idle (); + folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog)); passed = passed && (folder != NULL && strcmp (folder, current_working_dir) == 0); } @@ -618,6 +656,8 @@ test_reload_sequence (gboolean set_folder_before_map) gtk_widget_show_now (dialog); + wait_for_idle (); + passed = passed && (impl->current_folder != NULL && impl->browse_files_model != NULL && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED) @@ -641,6 +681,8 @@ test_reload_sequence (gboolean set_folder_before_map) gtk_widget_hide (dialog); + wait_for_idle (); + passed = passed && (impl->current_folder != NULL && impl->browse_files_model != NULL && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED) @@ -664,6 +706,8 @@ test_reload_sequence (gboolean set_folder_before_map) gtk_widget_show_now (dialog); + wait_for_idle (); + passed = passed && (impl->current_folder != NULL && impl->browse_files_model != NULL && (impl->load_state == LOAD_PRELOAD || impl->load_state == LOAD_LOADING || impl->load_state == LOAD_FINISHED) @@ -743,6 +787,7 @@ test_button_folder_states_for_action (GtkFileChooserAction action, gboolean use_ gtk_container_add (GTK_CONTAINER (window), button); /* Pre-map; no folder is set */ + wait_for_idle (); folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button)); if (must_have_cwd) @@ -760,6 +805,9 @@ test_button_folder_states_for_action (GtkFileChooserAction action, gboolean use_ gtk_widget_show_all (window); gtk_widget_show_now (window); + + wait_for_idle (); + folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button)); if (must_have_cwd) @@ -777,6 +825,7 @@ test_button_folder_states_for_action (GtkFileChooserAction action, gboolean use_ /* Unmap; folder should be set */ gtk_widget_hide (window); + wait_for_idle (); folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (button)); if (must_have_cwd) @@ -800,7 +849,7 @@ test_button_folder_states_for_action (GtkFileChooserAction action, gboolean use_ passed = passed && (folder != NULL && strcmp (folder, current_working_dir) == 0); else passed = passed && (folder != NULL && strcmp (folder, g_get_home_dir()) == 0); - + wait_for_idle (); log_test (passed, "test_button_folder_states_for_action(): %s, use_dialog=%d, set_folder_on_dialog=%d, re-mapped, %s", get_action_name (action), use_dialog,