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.
This commit is contained in:
Federico Mena Quintero 2006-07-18 16:36:19 +00:00 committed by Federico Mena Quintero
parent 73e3187138
commit 3f498adfb0
7 changed files with 391 additions and 39 deletions

View File

@ -1,3 +1,51 @@
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

View File

@ -1,3 +1,51 @@
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

View File

@ -42,7 +42,7 @@ gtk_file_chooser_get_type (void)
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);

View File

@ -799,6 +799,8 @@ gtk_file_chooser_default_finalize (GObject *object)
g_object_unref (impl->file_system);
g_free (impl->browse_files_last_selected_name);
for (l = impl->filters; l; l = l->next)
{
GtkFileFilter *filter;
@ -4391,7 +4393,6 @@ location_switch_to_filename_entry (GtkFileChooserDefault *impl)
/* 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 */
@ -5869,8 +5870,6 @@ pending_select_paths_process (GtkFileChooserDefault *impl)
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 */
@ -5897,8 +5896,6 @@ pending_select_paths_process (GtkFileChooserDefault *impl)
browse_files_select_first_row (impl);
}
impl->processing_pending_selections = FALSE;
g_assert (impl->pending_select_paths == NULL);
}
@ -5996,6 +5993,24 @@ struct update_chooser_entry_selected_foreach_closure {
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,
@ -6018,9 +6033,6 @@ update_chooser_entry (GtkFileChooserDefault *impl)
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
@ -6031,7 +6043,6 @@ update_chooser_entry (GtkFileChooserDefault *impl)
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);
@ -6039,14 +6050,7 @@ update_chooser_entry (GtkFileChooserDefault *impl)
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)
{
@ -6060,24 +6064,66 @@ update_chooser_entry (GtkFileChooserDefault *impl)
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
@ -6558,18 +6604,19 @@ gtk_file_chooser_default_get_paths (GtkFileChooser *chooser)
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)
@ -6586,6 +6633,8 @@ gtk_file_chooser_default_get_paths (GtkFileChooser *chooser)
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 &&
@ -7894,6 +7943,9 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
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,
@ -8349,6 +8401,11 @@ location_popup_handler (GtkFileChooserDefault *impl,
}
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)

View File

@ -178,6 +178,7 @@ struct _GtkFileChooserDefault
GtkWidget *browse_path_bar;
GtkFileSystemModel *browse_files_model;
char *browse_files_last_selected_name;
GtkWidget *filter_combo_hbox;
GtkWidget *filter_combo;
@ -263,7 +264,6 @@ struct _GtkFileChooserDefault
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;

View File

@ -3,7 +3,7 @@
#include "gtkwidgetprofiler.h"
#include "widgets.h"
#define ITERS 100
#define ITERS 100000
static GtkWidget *
create_widget_cb (GtkWidgetProfiler *profiler, gpointer data)
@ -38,10 +38,10 @@ report_cb (GtkWidgetProfiler *profiler, GtkWidgetProfilerReport report, GtkWidge
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
@ -59,7 +59,7 @@ main (int argc, char **argv)
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;

View File

@ -22,9 +22,6 @@
*/
/* 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.
@ -56,6 +53,207 @@ log_test (gboolean passed, const char *test_name, ...)
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
@ -707,6 +905,7 @@ main (int argc, char **argv)
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 ();