+2006-07-18 Federico Mena Quintero <federico@novell.com>
+
+ Fix https://bugzilla.novell.com/show_bug.cgi?id=184875 - make the
+ location entry in Save mode preserve the stuff from
+ set_filename(); it was overwriting it with $cwd.
+
+ This is the same fix for
+ http://bugzilla.gnome.org/show_bug.cgi?id=347066
+
+ * tests/autotestfilechooser.c: (test_black_box): Added black-box
+ test for set_filename() and set_current_name().
+
+ * gtk/gtkfilechooser.c (gtk_file_chooser_get_type): Cast to
+ GClassInitFunc in the call to g_type_register_static_simple(), to
+ avoid a compiler warning.
+
+ * gtk/gtkfilechooserprivate.h (struct _GtkFileChooserDefault):
+ Added a browse_files_last_selected_name field. We'll copy the
+ logic from gtkfilesel.c to see when to clear the location entry.
+ (struct _GtkFileChooserDefault): Removed the
+ processing_pending_selections field.
+
+ * gtk/gtkfilechooserdefault.c (gtk_file_chooser_default_finalize):
+ Free impl->browse_files_last_selected_name.
+ (pending_select_paths_process): Don't use
+ impl->processing_pending_selections.
+ (update_chooser_entry): Keep track of the name that was last
+ selected in the file list. We use this to know when to clear the
+ location entry. The logic is similar to that of
+ gtkfilesel.c:gtk_file_selection_file_changed(). This also lets us
+ get rid of the processing_pending_selections flag.
+ (update_chooser_entry): Clear the entry if we didn't have a
+ selection before.
+ (location_switch_to_filename_entry): Do not set $cwd as the
+ contents of the location entry here...
+ (location_popup_handler): ... but do it here instead, only as the
+ result of the user asking to turn on the location entry.
+ (gtk_file_chooser_default_get_paths): If the location entry is
+ empty, do the fallback of seeing if it is sensible to say that
+ $cwd is the selected path.
+ (gtk_file_chooser_default_update_current_folder): Don't set the
+ text of the location entry; this is no longer needed with the
+ fixes above.
+ (shortcuts_activate_iter): Clear the location entry when
+ activating a shortcut if we are not in SAVE mode. This keeps the
+ contents of the location entry consistent even when switching
+ folders via the shortcuts.
+
2006-07-18 Michael Natterer <mitch@imendio.com>
* gtk/gtkrange.c: remember the sensitivity of the steppers in
+2006-07-18 Federico Mena Quintero <federico@novell.com>
+
+ Fix https://bugzilla.novell.com/show_bug.cgi?id=184875 - make the
+ location entry in Save mode preserve the stuff from
+ set_filename(); it was overwriting it with $cwd.
+
+ This is the same fix for
+ http://bugzilla.gnome.org/show_bug.cgi?id=347066
+
+ * tests/autotestfilechooser.c: (test_black_box): Added black-box
+ test for set_filename() and set_current_name().
+
+ * gtk/gtkfilechooser.c (gtk_file_chooser_get_type): Cast to
+ GClassInitFunc in the call to g_type_register_static_simple(), to
+ avoid a compiler warning.
+
+ * gtk/gtkfilechooserprivate.h (struct _GtkFileChooserDefault):
+ Added a browse_files_last_selected_name field. We'll copy the
+ logic from gtkfilesel.c to see when to clear the location entry.
+ (struct _GtkFileChooserDefault): Removed the
+ processing_pending_selections field.
+
+ * gtk/gtkfilechooserdefault.c (gtk_file_chooser_default_finalize):
+ Free impl->browse_files_last_selected_name.
+ (pending_select_paths_process): Don't use
+ impl->processing_pending_selections.
+ (update_chooser_entry): Keep track of the name that was last
+ selected in the file list. We use this to know when to clear the
+ location entry. The logic is similar to that of
+ gtkfilesel.c:gtk_file_selection_file_changed(). This also lets us
+ get rid of the processing_pending_selections flag.
+ (update_chooser_entry): Clear the entry if we didn't have a
+ selection before.
+ (location_switch_to_filename_entry): Do not set $cwd as the
+ contents of the location entry here...
+ (location_popup_handler): ... but do it here instead, only as the
+ result of the user asking to turn on the location entry.
+ (gtk_file_chooser_default_get_paths): If the location entry is
+ empty, do the fallback of seeing if it is sensible to say that
+ $cwd is the selected path.
+ (gtk_file_chooser_default_update_current_folder): Don't set the
+ text of the location entry; this is no longer needed with the
+ fixes above.
+ (shortcuts_activate_iter): Clear the location entry when
+ activating a shortcut if we are not in SAVE mode. This keeps the
+ contents of the location entry consistent even when switching
+ folders via the shortcuts.
+
2006-07-18 Michael Natterer <mitch@imendio.com>
* gtk/gtkrange.c: remember the sensitivity of the steppers in
file_chooser_type = g_type_register_static_simple (G_TYPE_INTERFACE,
I_("GtkFileChooser"),
sizeof (GtkFileChooserIface),
- gtk_file_chooser_class_init,
+ (GClassInitFunc) gtk_file_chooser_class_init,
0, NULL, 0);
g_type_interface_add_prerequisite (file_chooser_type, GTK_TYPE_WIDGET);
g_object_unref (impl->file_system);
+ g_free (impl->browse_files_last_selected_name);
+
for (l = impl->filters; l; l = l->next)
{
GtkFileFilter *filter;
/* Configure the entry */
_gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->current_folder);
- location_entry_set_initial_text (impl);
/* Done */
g_assert (impl->browse_files_model != NULL);
g_assert (impl->sort_model != NULL);
- impl->processing_pending_selections = TRUE;
-
if (impl->pending_select_paths)
{
/* NULL GError */
browse_files_select_first_row (impl);
}
- impl->processing_pending_selections = FALSE;
-
g_assert (impl->pending_select_paths == NULL);
}
GtkTreeIter first_selected_iter;
};
+static gint
+compare_utf8_filenames (const gchar *a,
+ const gchar *b)
+{
+ gchar *a_folded, *b_folded;
+ gint retval;
+
+ a_folded = g_utf8_strdown (a, -1);
+ b_folded = g_utf8_strdown (b, -1);
+
+ retval = strcmp (a_folded, b_folded);
+
+ g_free (a_folded);
+ g_free (b_folded);
+
+ return retval;
+}
+
static void
update_chooser_entry_selected_foreach (GtkTreeModel *model,
GtkTreePath *path,
struct update_chooser_entry_selected_foreach_closure closure;
const char *file_part;
- if (impl->processing_pending_selections)
- return;
-
if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
|| impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
|| ((impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
g_assert (impl->location_entry != NULL);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
-
closure.num_selected = 0;
gtk_tree_selection_selected_foreach (selection, update_chooser_entry_selected_foreach, &closure);
if (closure.num_selected == 0)
{
- /* If nothing is selected, we only reset the file name entry if we are in
- * CREATE_FOLDER mode. In SAVE mode, nothing will be selected when the
- * user starts typeahead in the treeview, and we don't want to clear the
- * file name entry in that case --- the user could be typing-ahead to look
- * for a folder name. See http://bugzilla.gnome.org/show_bug.cgi?id=308332
- */
- if (impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
- file_part = "";
+ goto maybe_clear_entry;
}
else if (closure.num_selected == 1)
{
info = _gtk_file_system_model_get_info (impl->browse_files_model, &child_iter);
+ g_free (impl->browse_files_last_selected_name);
+ impl->browse_files_last_selected_name = g_strdup (gtk_file_info_get_display_name (info));
+
if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
- || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
- || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ || impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
change_entry = !gtk_file_info_get_is_folder (info); /* We don't want the name to change when clicking on a folder... */
else
- change_entry = TRUE; /* ... unless we are in CREATE_FOLDER mode */
+ change_entry = TRUE; /* ... unless we are in one of the folder modes */
if (change_entry)
- file_part = gtk_file_info_get_display_name (info);
+ _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->browse_files_last_selected_name);
+
+ return;
}
else
{
+ g_assert (!(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+ || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER));
+
/* Multiple selection, so just clear the entry. */
- file_part = "";
+
+ g_free (impl->browse_files_last_selected_name);
+ impl->browse_files_last_selected_name = NULL;
+
+ _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
+ return;
}
- if (file_part)
- _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), file_part);
+ maybe_clear_entry:
+
+ if (impl->browse_files_last_selected_name)
+ {
+ const char *entry_text;
+ int len;
+ gboolean clear_entry;
+
+ entry_text = gtk_entry_get_text (GTK_ENTRY (impl->location_entry));
+ len = strlen (entry_text);
+ if (len != 0)
+ {
+ /* The file chooser entry may have appended a "/" to its text. So
+ * take it out, and compare the result to the old selection.
+ */
+ if (entry_text[len - 1] == G_DIR_SEPARATOR)
+ {
+ char *tmp;
+
+ tmp = g_strndup (entry_text, len - 1);
+ clear_entry = (compare_utf8_filenames (impl->browse_files_last_selected_name, tmp) == 0);
+ g_free (tmp);
+ }
+ else
+ clear_entry = (compare_utf8_filenames (impl->browse_files_last_selected_name, entry_text) == 0);
+ }
+ else
+ clear_entry = FALSE;
+
+ if (clear_entry)
+ _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
+ }
}
static gboolean
check_save_entry (impl, &info.path_from_entry, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
+ if (is_empty)
+ goto out;
+
if (!is_well_formed)
return NULL;
- if (!is_empty)
+ if (is_file_part_empty && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
{
- if (is_file_part_empty && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
- {
- gtk_file_path_free (info.path_from_entry);
- return NULL;
- }
+ gtk_file_path_free (info.path_from_entry);
+ return NULL;
}
+ g_assert (info.path_from_entry != NULL);
info.result = g_slist_prepend (info.result, info.path_from_entry);
}
else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
goto file_list;
}
+ out:
+
/* If there's no folder selected, and we're in SELECT_FOLDER mode, then we
* fall back to the current directory */
if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
gpointer col_data;
gboolean is_volume;
+ if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY && impl->action != GTK_FILE_CHOOSER_ACTION_SAVE)
+ _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
+
gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
SHORTCUTS_COL_DATA, &col_data,
SHORTCUTS_COL_IS_VOLUME, &is_volume,
}
location_mode_set (impl, new_mode, TRUE);
+ if (new_mode == LOCATION_MODE_FILENAME_ENTRY)
+ {
+ location_entry_set_initial_text (impl);
+ gtk_editable_select_region (GTK_EDITABLE (impl->location_entry), 0, -1);
+ }
}
else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
|| impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
GtkWidget *browse_path_bar;
GtkFileSystemModel *browse_files_model;
+ char *browse_files_last_selected_name;
GtkWidget *filter_combo_hbox;
GtkWidget *filter_combo;
guint list_sort_ascending : 1;
guint changing_folder : 1;
guint shortcuts_current_folder_active : 1;
- guint processing_pending_selections : 1;
#if 0
guint shortcuts_drag_outside : 1;
#include "gtkwidgetprofiler.h"
#include "widgets.h"
-#define ITERS 100
+#define ITERS 100000
static GtkWidget *
create_widget_cb (GtkWidgetProfiler *profiler, gpointer data)
type = NULL;
}
- fprintf (stderr, "%s: %g sec\n", type, elapsed);
+ fprintf (stdout, "%s: %g sec\n", type, elapsed);
if (report == GTK_WIDGET_PROFILER_REPORT_DESTROY)
- fputs ("\n", stderr);
+ fputs ("\n", stdout);
}
int
gtk_widget_profiler_set_num_iterations (profiler, ITERS);
- gtk_widget_profiler_profile_boot (profiler);
+/* gtk_widget_profiler_profile_boot (profiler); */
gtk_widget_profiler_profile_expose (profiler);
return 0;
*/
/* TODO:
- *
- * - Use g_log_set_default_handler() instead of the mess of specific handlers we
- * have in main().
*
* - In test_reload_sequence(), test that the selection is preserved properly
* between unmap/map.
g_free (str);
}
+typedef void (* SetFilenameFn) (GtkFileChooser *chooser, gpointer data);
+typedef gboolean (* CompareFilenameFn) (GtkFileChooser *chooser, gpointer data);
+
+struct test_set_filename_closure {
+ GtkWidget *chooser;
+ GtkWidget *accept_button;
+ gboolean focus_button;
+};
+
+static gboolean
+timeout_cb (gpointer data)
+{
+ struct test_set_filename_closure *closure;
+
+ closure = data;
+
+ if (closure->focus_button)
+ gtk_widget_grab_focus (closure->accept_button);
+
+ gtk_button_clicked (GTK_BUTTON (closure->accept_button));
+
+ return FALSE;
+}
+
+static gboolean
+test_set_filename (GtkFileChooserAction action,
+ gboolean focus_button,
+ SetFilenameFn set_filename_fn,const
+ CompareFilenameFn compare_filename_fn,
+ gpointer data)
+{
+ GtkWidget *chooser;
+ struct test_set_filename_closure closure;
+ gboolean retval;
+
+ chooser = gtk_file_chooser_dialog_new ("hello", NULL, action,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NULL);
+
+ closure.chooser = chooser;
+ closure.accept_button = gtk_dialog_add_button (GTK_DIALOG (chooser), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
+ closure.focus_button = focus_button;
+
+ gtk_dialog_set_default_response (GTK_DIALOG (chooser), GTK_RESPONSE_ACCEPT);
+
+ (* set_filename_fn) (GTK_FILE_CHOOSER (chooser), data);
+
+ g_timeout_add (2000, timeout_cb, &closure);
+ gtk_dialog_run (GTK_DIALOG (chooser));
+
+ retval = (* compare_filename_fn) (GTK_FILE_CHOOSER (chooser), data);
+
+ gtk_widget_destroy (chooser);
+
+ return retval;
+}
+
+static void
+set_filename_cb (GtkFileChooser *chooser, gpointer data)
+{
+ const char *filename;
+
+ filename = data;
+ gtk_file_chooser_set_filename (chooser, filename);
+}
+
+static gboolean
+compare_filename_cb (GtkFileChooser *chooser, gpointer data)
+{
+ const char *filename;
+ char *out_filename;
+ gboolean retval;
+
+ filename = data;
+ out_filename = gtk_file_chooser_get_filename (chooser);
+
+ if (out_filename)
+ {
+ retval = (strcmp (out_filename, filename) == 0);
+ g_free (out_filename);
+ } else
+ retval = FALSE;
+
+ return retval;
+}
+
+static gboolean
+test_black_box_set_filename (GtkFileChooserAction action, const char *filename, gboolean focus_button)
+{
+ gboolean passed;
+
+ passed = test_set_filename (action, focus_button, set_filename_cb, compare_filename_cb, (char *) filename);
+
+ log_test (passed, "set_filename: action %d, focus_button=%s",
+ (int) action,
+ focus_button ? "TRUE" : "FALSE");
+
+ return passed;
+
+}
+
+struct current_name_closure {
+ const char *path;
+ const char *current_name;
+};
+
+static void
+set_current_name_cb (GtkFileChooser *chooser, gpointer data)
+{
+ struct current_name_closure *closure;
+
+ closure = data;
+
+ gtk_file_chooser_set_current_folder (chooser, closure->path);
+ gtk_file_chooser_set_current_name (chooser, closure->current_name);
+}
+
+static gboolean
+compare_current_name_cb (GtkFileChooser *chooser, gpointer data)
+{
+ struct current_name_closure *closure;
+ char *out_filename;
+ gboolean retval;
+
+ closure = data;
+
+ out_filename = gtk_file_chooser_get_filename (chooser);
+
+ if (out_filename)
+ {
+ char *filename;
+
+ filename = g_build_filename (closure->path, closure->current_name, NULL);
+ retval = (strcmp (filename, out_filename) == 0);
+ g_free (filename);
+ g_free (out_filename);
+ } else
+ retval = FALSE;
+
+ return retval;
+}
+
+static gboolean
+test_black_box_set_current_name (const char *path, const char *current_name, gboolean focus_button)
+{
+ struct current_name_closure closure;
+ gboolean passed;
+
+ closure.path = path;
+ closure.current_name = current_name;
+
+ passed = test_set_filename (GTK_FILE_CHOOSER_ACTION_SAVE, focus_button,
+ set_current_name_cb, compare_current_name_cb, &closure);
+
+ log_test (passed, "set_current_name, focus_button=%s", focus_button ? "TRUE" : "FALSE");
+
+ return passed;
+}
+
+/* FIXME: fails in CREATE_FOLDER mode when FOLDER_NAME == "/" */
+
+#if 0
+#define FILE_NAME "/nonexistent"
+#define FOLDER_NAME "/etc"
+#else
+#define FILE_NAME "/etc/passwd"
+#define FOLDER_NAME "/etc"
+#endif
+
+#define CURRENT_NAME "parangaricutirimicuaro.txt"
+
+/* https://bugzilla.novell.com/show_bug.cgi?id=184875
+ * http://bugzilla.gnome.org/show_bug.cgi?id=347066
+ */
+static gboolean
+test_black_box (void)
+{
+ gboolean passed;
+ char *cwd;
+
+ passed = passed && test_black_box_set_filename (GTK_FILE_CHOOSER_ACTION_OPEN, FILE_NAME, FALSE);
+ passed = passed && test_black_box_set_filename (GTK_FILE_CHOOSER_ACTION_OPEN, FILE_NAME, TRUE);
+ passed = passed && test_black_box_set_filename (GTK_FILE_CHOOSER_ACTION_SAVE, FILE_NAME, FALSE);
+ passed = passed && test_black_box_set_filename (GTK_FILE_CHOOSER_ACTION_SAVE, FILE_NAME, TRUE);
+ passed = passed && test_black_box_set_filename (GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, FOLDER_NAME, FALSE);
+ passed = passed && test_black_box_set_filename (GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, FOLDER_NAME, TRUE);
+ passed = passed && test_black_box_set_filename (GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, FOLDER_NAME, FALSE);
+ passed = passed && test_black_box_set_filename (GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, FOLDER_NAME, TRUE);
+
+ cwd = g_get_current_dir ();
+
+ passed = passed && test_black_box_set_current_name (cwd, CURRENT_NAME, FALSE);
+ passed = passed && test_black_box_set_current_name (cwd, CURRENT_NAME, TRUE);
+
+ g_free (cwd);
+
+ log_test (passed, "Black box tests");
+
+ return passed;
+}
+
static const GtkFileChooserAction open_actions[] = {
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
gtk_init (&argc, &argv);
/* Start tests */
+ passed = passed && test_black_box ();
passed = passed && test_action_widgets ();
passed = passed && test_reload ();
passed = passed && test_button_folder_states ();