Commit 69f62828 authored by Federico Mena Quintero's avatar Federico Mena Quintero Committed by Federico Mena Quintero

Cancel all forms of completion at the appropriate times, not just in ::changed

Signed-off-by: default avatarFederico Mena Quintero <federico@gnu.org>

svn path=/trunk/; revision=19817
parent 9c9b5e60
...@@ -57,7 +57,6 @@ struct _GtkFileChooserEntry ...@@ -57,7 +57,6 @@ struct _GtkFileChooserEntry
GtkFilePath *base_folder; GtkFilePath *base_folder;
gchar *file_part; gchar *file_part;
gint file_part_pos; gint file_part_pos;
guint check_completion_idle;
/* Folder being loaded or already loaded */ /* Folder being loaded or already loaded */
GtkFilePath *current_folder_path; GtkFilePath *current_folder_path;
...@@ -89,15 +88,21 @@ static void gtk_file_chooser_entry_dispose (GObject *object) ...@@ -89,15 +88,21 @@ static void gtk_file_chooser_entry_dispose (GObject *object)
static void gtk_file_chooser_entry_grab_focus (GtkWidget *widget); static void gtk_file_chooser_entry_grab_focus (GtkWidget *widget);
static gboolean gtk_file_chooser_entry_focus (GtkWidget *widget, static gboolean gtk_file_chooser_entry_focus (GtkWidget *widget,
GtkDirectionType direction); GtkDirectionType direction);
static gboolean gtk_file_chooser_entry_focus_out_event (GtkWidget *widget,
GdkEventFocus *event);
static void gtk_file_chooser_entry_activate (GtkEntry *entry); static void gtk_file_chooser_entry_activate (GtkEntry *entry);
static void gtk_file_chooser_entry_changed (GtkEditable *editable);
static void gtk_file_chooser_entry_do_insert_text (GtkEditable *editable, static void gtk_file_chooser_entry_do_insert_text (GtkEditable *editable,
const gchar *new_text, const gchar *new_text,
gint new_text_length, gint new_text_length,
gint *position); gint *position);
static void gtk_file_chooser_entry_do_delete_text (GtkEditable *editable,
static void clear_completion_callback (GtkFileChooserEntry *chooser_entry, gint start_pos,
GParamSpec *pspec); gint end_pos);
static void gtk_file_chooser_entry_set_position (GtkEditable *editable,
gint position);
static void gtk_file_chooser_entry_set_selection_bounds (GtkEditable *editable,
gint start_pos,
gint end_pos);
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
static gint insert_text_callback (GtkFileChooserEntry *widget, static gint insert_text_callback (GtkFileChooserEntry *widget,
...@@ -126,6 +131,7 @@ static char *maybe_append_separator_to_path (GtkFileChooserEntry *chooser_ent ...@@ -126,6 +131,7 @@ static char *maybe_append_separator_to_path (GtkFileChooserEntry *chooser_ent
static void finished_loading_cb (GtkFileFolder *folder, static void finished_loading_cb (GtkFileFolder *folder,
gpointer data); gpointer data);
static void autocomplete (GtkFileChooserEntry *chooser_entry); static void autocomplete (GtkFileChooserEntry *chooser_entry);
static void install_start_autocompletion_idle (GtkFileChooserEntry *chooser_entry);
static GtkEditableClass *parent_editable_iface; static GtkEditableClass *parent_editable_iface;
...@@ -145,6 +151,7 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class) ...@@ -145,6 +151,7 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class)
widget_class->grab_focus = gtk_file_chooser_entry_grab_focus; widget_class->grab_focus = gtk_file_chooser_entry_grab_focus;
widget_class->focus = gtk_file_chooser_entry_focus; widget_class->focus = gtk_file_chooser_entry_focus;
widget_class->focus_out_event = gtk_file_chooser_entry_focus_out_event;
entry_class->activate = gtk_file_chooser_entry_activate; entry_class->activate = gtk_file_chooser_entry_activate;
} }
...@@ -155,7 +162,9 @@ gtk_file_chooser_entry_iface_init (GtkEditableClass *iface) ...@@ -155,7 +162,9 @@ gtk_file_chooser_entry_iface_init (GtkEditableClass *iface)
parent_editable_iface = g_type_interface_peek_parent (iface); parent_editable_iface = g_type_interface_peek_parent (iface);
iface->do_insert_text = gtk_file_chooser_entry_do_insert_text; iface->do_insert_text = gtk_file_chooser_entry_do_insert_text;
iface->changed = gtk_file_chooser_entry_changed; iface->do_delete_text = gtk_file_chooser_entry_do_delete_text;
iface->set_position = gtk_file_chooser_entry_set_position;
iface->set_selection_bounds = gtk_file_chooser_entry_set_selection_bounds;
} }
static void static void
...@@ -187,11 +196,6 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry) ...@@ -187,11 +196,6 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
gtk_entry_set_completion (GTK_ENTRY (chooser_entry), comp); gtk_entry_set_completion (GTK_ENTRY (chooser_entry), comp);
g_object_unref (comp); g_object_unref (comp);
g_signal_connect (chooser_entry, "notify::cursor-position",
G_CALLBACK (clear_completion_callback), NULL);
g_signal_connect (chooser_entry, "notify::selection-bound",
G_CALLBACK (clear_completion_callback), NULL);
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
g_signal_connect (chooser_entry, "insert_text", g_signal_connect (chooser_entry, "insert_text",
G_CALLBACK (insert_text_callback), NULL); G_CALLBACK (insert_text_callback), NULL);
...@@ -249,12 +253,6 @@ gtk_file_chooser_entry_dispose (GObject *object) ...@@ -249,12 +253,6 @@ gtk_file_chooser_entry_dispose (GObject *object)
chooser_entry->file_system = NULL; chooser_entry->file_system = NULL;
} }
if (chooser_entry->check_completion_idle)
{
g_source_remove (chooser_entry->check_completion_idle);
chooser_entry->check_completion_idle = 0;
}
G_OBJECT_CLASS (_gtk_file_chooser_entry_parent_class)->dispose (object); G_OBJECT_CLASS (_gtk_file_chooser_entry_parent_class)->dispose (object);
} }
...@@ -450,6 +448,15 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry, ...@@ -450,6 +448,15 @@ find_common_prefix (GtkFileChooserEntry *chooser_entry,
parsed_folder_path ? (char *) parsed_folder_path : "<NONE>", parsed_folder_path ? (char *) parsed_folder_path : "<NONE>",
parsed_file_part ? parsed_file_part : "<NONE>"); parsed_file_part ? parsed_file_part : "<NONE>");
/* FIXME: the old check_completion_callback() did this:
if (strcmp (chooser_entry->file_part, "") == 0)
goto done;
Don't do completion if the file part is empty!
*/
g_free (text_up_to_cursor); g_free (text_up_to_cursor);
if (!parsed) if (!parsed)
...@@ -561,72 +568,72 @@ append_common_prefix (GtkFileChooserEntry *chooser_entry, ...@@ -561,72 +568,72 @@ append_common_prefix (GtkFileChooserEntry *chooser_entry,
} }
} }
static gboolean static void
check_completion_callback (GtkFileChooserEntry *chooser_entry) gtk_file_chooser_entry_do_insert_text (GtkEditable *editable,
const gchar *new_text,
gint new_text_length,
gint *position)
{ {
GDK_THREADS_ENTER (); GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (editable);
gint old_text_len;
gint insert_pos;
g_assert (chooser_entry->file_part); old_text_len = GTK_ENTRY (chooser_entry)->text_length;
insert_pos = *position;
chooser_entry->check_completion_idle = 0; parent_editable_iface->do_insert_text (editable, new_text, new_text_length, position);
if (strcmp (chooser_entry->file_part, "") == 0) if (chooser_entry->in_change)
goto done; return;
/* We only insert the common prefix without requiring the user to hit Tab in
* the "open" modes. For "save" modes, the user must hit Tab to cause the prefix
* to be inserted. That happens in gtk_file_chooser_entry_focus().
*/
if ((chooser_entry->action == GTK_FILE_CHOOSER_ACTION_OPEN if ((chooser_entry->action == GTK_FILE_CHOOSER_ACTION_OPEN
|| chooser_entry->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) || chooser_entry->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
&& gtk_editable_get_position (GTK_EDITABLE (chooser_entry)) == GTK_ENTRY (chooser_entry)->text_length) && insert_pos == old_text_len)
append_common_prefix (chooser_entry, TRUE); install_start_autocompletion_idle (chooser_entry);
done:
GDK_THREADS_LEAVE ();
return FALSE;
} }
static guint static void
idle_add (GtkFileChooserEntry *chooser_entry, gtk_file_chooser_entry_do_delete_text (GtkEditable *editable,
GCallback cb) gint start_pos,
gint end_pos)
{ {
GSource *source; GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (editable);
guint id;
parent_editable_iface->do_delete_text (editable, start_pos, end_pos);
source = g_idle_source_new (); if (chooser_entry->in_change)
g_source_set_priority (source, G_PRIORITY_HIGH); return;
g_source_set_closure (source,
g_cclosure_new_object (cb, G_OBJECT (chooser_entry)));
id = g_source_attach (source, NULL);
g_source_unref (source);
return id; chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING;
} }
static void static void
add_completion_idle (GtkFileChooserEntry *chooser_entry) gtk_file_chooser_entry_set_position (GtkEditable *editable,
gint position)
{ {
/* idle to update the selection based on the file list */ GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (editable);
if (chooser_entry->check_completion_idle == 0)
chooser_entry->check_completion_idle = parent_editable_iface->set_position (editable, position);
idle_add (chooser_entry, G_CALLBACK (check_completion_callback));
if (chooser_entry->in_change)
return;
chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING;
} }
static void static void
gtk_file_chooser_entry_do_insert_text (GtkEditable *editable, gtk_file_chooser_entry_set_selection_bounds (GtkEditable *editable,
const gchar *new_text, gint start_pos,
gint new_text_length, gint end_pos)
gint *position)
{ {
GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (editable); GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (editable);
parent_editable_iface->do_insert_text (editable, new_text, new_text_length, position); parent_editable_iface->set_selection_bounds (editable, start_pos, end_pos);
if (chooser_entry->in_change)
return;
if (! chooser_entry->in_change) chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING;
add_completion_idle (GTK_FILE_CHOOSER_ENTRY (editable));
} }
static void static void
...@@ -690,6 +697,17 @@ gtk_file_chooser_entry_focus (GtkWidget *widget, ...@@ -690,6 +697,17 @@ gtk_file_chooser_entry_focus (GtkWidget *widget,
return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->focus (widget, direction); return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->focus (widget, direction);
} }
static gboolean
gtk_file_chooser_entry_focus_out_event (GtkWidget *widget,
GdkEventFocus *event)
{
GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (widget);
chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING;
return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->focus_out_event (widget, event);
}
static void static void
gtk_file_chooser_entry_activate (GtkEntry *entry) gtk_file_chooser_entry_activate (GtkEntry *entry)
{ {
...@@ -997,12 +1015,9 @@ start_autocompletion (GtkFileChooserEntry *chooser_entry) ...@@ -997,12 +1015,9 @@ start_autocompletion (GtkFileChooserEntry *chooser_entry)
static gboolean static gboolean
start_autocompletion_idle_handler (gpointer data) start_autocompletion_idle_handler (gpointer data)
{ {
GtkFileChooserEntry *chooser_entry; GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (data);
chooser_entry = GTK_FILE_CHOOSER_ENTRY (data);
if (gtk_editable_get_position (GTK_EDITABLE (chooser_entry)) == GTK_ENTRY (chooser_entry)->text_length) start_autocompletion (chooser_entry);
start_autocompletion (chooser_entry);
chooser_entry->start_autocompletion_idle_id = 0; chooser_entry->start_autocompletion_idle_id = 0;
...@@ -1012,54 +1027,32 @@ start_autocompletion_idle_handler (gpointer data) ...@@ -1012,54 +1027,32 @@ start_autocompletion_idle_handler (gpointer data)
static void static void
install_start_autocompletion_idle (GtkFileChooserEntry *chooser_entry) install_start_autocompletion_idle (GtkFileChooserEntry *chooser_entry)
{ {
/* We set up an idle handler because we must test the cursor position. However,
* the cursor is not updated in GtkEntry::changed, so we wait for the idle loop.
*/
if (chooser_entry->start_autocompletion_idle_id != 0) if (chooser_entry->start_autocompletion_idle_id != 0)
return; return;
chooser_entry->start_autocompletion_idle_id = g_idle_add (start_autocompletion_idle_handler, chooser_entry); chooser_entry->start_autocompletion_idle_id = g_idle_add (start_autocompletion_idle_handler, chooser_entry);
} }
static void #if 0
gtk_file_chooser_entry_changed (GtkEditable *editable) /* FIXME: what does has_completion mean? After you figure that out and fix it, remove this unused function. */
{
GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (editable);
if (chooser_entry->in_change)
return;
chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING;
if ((chooser_entry->action == GTK_FILE_CHOOSER_ACTION_OPEN
|| chooser_entry->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER))
install_start_autocompletion_idle (chooser_entry);
/* FIXME: see when the cursor changes (see GtkEntry's cursor_position property, or GtkEditable::set_position and GtkEntry::move_cursor).
* When the cursor changes, cancel the load_complete_action.
* When the entry is activated, cancel the load_complete_action.
* In general, cancel the load_complete_action when the entry loses the focus.
*/
/* FIXME: is ::changed too coarse? We need
*
* if insert_text, start autocompletion if the cursor is at the end
* if delete_text, don't do anything
* if cursor moves, don't do anything
*/
}
static void static void
clear_completion_callback (GtkFileChooserEntry *chooser_entry, clear_completion_callback (GtkFileChooserEntry *chooser_entry,
GParamSpec *pspec) GParamSpec *pspec)
{ {
/* FIXME: this was in the constructor for the chooser entry
g_signal_connect (chooser_entry, "notify::cursor-position",
G_CALLBACK (clear_completion_callback), NULL);
g_signal_connect (chooser_entry, "notify::selection-bound",
G_CALLBACK (clear_completion_callback), NULL);
*/
if (chooser_entry->has_completion) if (chooser_entry->has_completion)
{ {
chooser_entry->has_completion = FALSE; chooser_entry->has_completion = FALSE;
gtk_file_chooser_entry_changed (GTK_EDITABLE (chooser_entry)); gtk_file_chooser_entry_changed (GTK_EDITABLE (chooser_entry));
} }
} }
#endif
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
static gint static gint
...@@ -1186,7 +1179,9 @@ _gtk_file_chooser_entry_set_base_folder (GtkFileChooserEntry *chooser_entry, ...@@ -1186,7 +1179,9 @@ _gtk_file_chooser_entry_set_base_folder (GtkFileChooserEntry *chooser_entry,
chooser_entry->base_folder = gtk_file_path_copy (path); chooser_entry->base_folder = gtk_file_path_copy (path);
/* FIXME: the base folder changes. Do we need to restart completion or something, to reload the folder if needed?
gtk_file_chooser_entry_changed (GTK_EDITABLE (chooser_entry)); gtk_file_chooser_entry_changed (GTK_EDITABLE (chooser_entry));
*/
_gtk_file_chooser_entry_select_filename (chooser_entry); _gtk_file_chooser_entry_select_filename (chooser_entry);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment