X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkfilechooserentry.c;h=fb6c2b015a02f8766c469241e22ff34286a6374e;hb=a3abc188585156e4a6ba309e26c6d123cfe4f39d;hp=693c8d7a5766ce2f68551d2498d9e44dc17aa1b3;hpb=c9b220275a49461088baa86d117c86791fa28cc9;p=~andy%2Fgtk diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c index 693c8d7a5..fb6c2b015 100644 --- a/gtk/gtkfilechooserentry.c +++ b/gtk/gtkfilechooserentry.c @@ -45,21 +45,6 @@ struct _GtkFileChooserEntryClass GtkEntryClass parent_class; }; -/* Action to take when the current folder finishes loading (for explicit or automatic completion) */ -typedef enum { - LOAD_COMPLETE_NOTHING, - LOAD_COMPLETE_EXPLICIT_COMPLETION -} LoadCompleteAction; - -typedef enum -{ - REFRESH_OK, - REFRESH_INVALID_INPUT, - REFRESH_INCOMPLETE_HOSTNAME, - REFRESH_NONEXISTENT, - REFRESH_NOT_LOCAL -} RefreshStatus; - struct _GtkFileChooserEntry { GtkEntry parent_instance; @@ -70,14 +55,11 @@ struct _GtkFileChooserEntry GFile *current_folder_file; gchar *dir_part; gchar *file_part; - gint file_part_pos; - - LoadCompleteAction load_complete_action; GtkTreeModel *completion_store; guint current_folder_loaded : 1; - guint in_change : 1; + guint complete_on_load : 1; guint eat_tabs : 1; guint local_only : 1; }; @@ -86,15 +68,14 @@ enum { DISPLAY_NAME_COLUMN, FULL_PATH_COLUMN, - FILE_COLUMN, N_COLUMNS }; static void gtk_file_chooser_entry_finalize (GObject *object); static void gtk_file_chooser_entry_dispose (GObject *object); static void gtk_file_chooser_entry_grab_focus (GtkWidget *widget); -static gboolean gtk_file_chooser_entry_key_press_event (GtkWidget *widget, - GdkEventKey *event); +static gboolean gtk_file_chooser_entry_tab_handler (GtkWidget *widget, + GdkEventKey *event); static gboolean gtk_file_chooser_entry_focus_out_event (GtkWidget *widget, GdkEventFocus *event); @@ -114,13 +95,12 @@ static gboolean match_selected_callback (GtkEntryCompletion *completion, GtkTreeModel *model, GtkTreeIter *iter, GtkFileChooserEntry *chooser_entry); -static gboolean completion_match_func (GtkEntryCompletion *comp, - const char *key, - GtkTreeIter *iter, - gpointer data); -static RefreshStatus refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, - const char *text); +static void set_complete_on_load (GtkFileChooserEntry *chooser_entry, + gboolean complete_on_load); +static void refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry); +static void set_completion_folder (GtkFileChooserEntry *chooser_entry, + GFile *folder); static void finished_loading_cb (GtkFileSystemModel *model, GError *error, GtkFileChooserEntry *chooser_entry); @@ -150,23 +130,14 @@ gtk_file_chooser_entry_dispatch_properties_changed (GObject *object, /* What we are after: The text in front of the cursor was modified. * Unfortunately, there's no other way to catch this. */ - if (chooser_entry->in_change) - return; - for (i = 0; i < n_pspecs; i++) { if (pspecs[i]->name == I_("cursor-position") || pspecs[i]->name == I_("selection-bound") || pspecs[i]->name == I_("text")) { - char *text; - - chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING; - - text = gtk_file_chooser_entry_get_completion_text (chooser_entry); - refresh_current_folder_and_file_part (chooser_entry, text); - g_free (text); - + set_complete_on_load (chooser_entry, FALSE); + refresh_current_folder_and_file_part (chooser_entry); break; } } @@ -183,7 +154,6 @@ _gtk_file_chooser_entry_class_init (GtkFileChooserEntryClass *class) gobject_class->dispatch_properties_changed = gtk_file_chooser_entry_dispatch_properties_changed; widget_class->grab_focus = gtk_file_chooser_entry_grab_focus; - widget_class->key_press_event = gtk_file_chooser_entry_key_press_event; widget_class->focus_out_event = gtk_file_chooser_entry_focus_out_event; } @@ -194,17 +164,19 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry) GtkCellRenderer *cell; chooser_entry->local_only = TRUE; - chooser_entry->base_folder = g_file_new_for_path (g_get_home_dir ()); g_object_set (chooser_entry, "truncate-multiline", TRUE, NULL); comp = gtk_entry_completion_new (); gtk_entry_completion_set_popup_single_match (comp, FALSE); + gtk_entry_completion_set_minimum_key_length (comp, 0); /* see docs for gtk_entry_completion_set_text_column() */ g_object_set (comp, "text-column", FULL_PATH_COLUMN, NULL); + /* Need a match func here or entry completion uses a wrong one. + * We do our own filtering after all. */ gtk_entry_completion_set_match_func (comp, - completion_match_func, + (GtkEntryCompletionMatchFunc) gtk_true, chooser_entry, NULL); @@ -220,6 +192,10 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry) gtk_entry_set_completion (GTK_ENTRY (chooser_entry), comp); g_object_unref (comp); + /* NB: This needs to happen after the completion is set, so this handler + * runs before the handler installed by entrycompletion */ + g_signal_connect (chooser_entry, "key-press-event", + G_CALLBACK (gtk_file_chooser_entry_tab_handler), NULL); #ifdef G_OS_WIN32 g_signal_connect (chooser_entry, "insert-text", @@ -234,7 +210,8 @@ gtk_file_chooser_entry_finalize (GObject *object) { GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (object); - g_object_unref (chooser_entry->base_folder); + if (chooser_entry->base_folder) + g_object_unref (chooser_entry->base_folder); if (chooser_entry->current_folder_file) g_object_unref (chooser_entry->current_folder_file); @@ -245,28 +222,12 @@ gtk_file_chooser_entry_finalize (GObject *object) G_OBJECT_CLASS (_gtk_file_chooser_entry_parent_class)->finalize (object); } -static void -discard_loading_and_current_folder_file (GtkFileChooserEntry *chooser_entry) -{ - if (chooser_entry->current_folder_file) - { - g_object_unref (chooser_entry->current_folder_file); - chooser_entry->current_folder_file = NULL; - } -} - static void gtk_file_chooser_entry_dispose (GObject *object) { GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (object); - discard_loading_and_current_folder_file (chooser_entry); - - if (chooser_entry->completion_store) - { - g_object_unref (chooser_entry->completion_store); - chooser_entry->completion_store = NULL; - } + set_completion_folder (chooser_entry, NULL); G_OBJECT_CLASS (_gtk_file_chooser_entry_parent_class)->dispose (object); } @@ -284,8 +245,6 @@ match_selected_callback (GtkEntryCompletion *completion, FULL_PATH_COLUMN, &path, -1); - /* We don't set in_change here as we want to update the current_folder - * variable */ gtk_editable_delete_text (GTK_EDITABLE (chooser_entry), 0, gtk_editable_get_position (GTK_EDITABLE (chooser_entry))); @@ -299,88 +258,16 @@ match_selected_callback (GtkEntryCompletion *completion, return TRUE; } -/* Match function for the GtkEntryCompletion */ -static gboolean -completion_match_func (GtkEntryCompletion *comp, - const char *key_unused, - GtkTreeIter *iter, - gpointer data) -{ - GtkFileChooserEntry *chooser_entry; - char *name = NULL; - gboolean result; - char *norm_file_part; - char *norm_name; - - chooser_entry = GTK_FILE_CHOOSER_ENTRY (data); - - /* We ignore the key because it is the contents of the entry. Instead, we - * just use our precomputed file_part. - */ - if (!chooser_entry->file_part) - { - return FALSE; - } - - gtk_tree_model_get (chooser_entry->completion_store, iter, DISPLAY_NAME_COLUMN, &name, -1); - if (!name) - { - return FALSE; /* Uninitialized row, ugh */ - } - - /* If we have an empty file_part, then we're at the root of a directory. In - * that case, we want to match all non-dot files. We might want to match - * dot_files too if show_hidden is TRUE on the fileselector in the future. - */ - /* Additionally, support for gnome .hidden files would be sweet, too */ - if (chooser_entry->file_part[0] == '\000') - { - if (name[0] == '.') - result = FALSE; - else - result = TRUE; - g_free (name); - - return result; - } - - - norm_file_part = g_utf8_normalize (chooser_entry->file_part, -1, G_NORMALIZE_ALL); - norm_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL); - -#ifdef G_PLATFORM_WIN32 - { - gchar *temp; - - temp = norm_file_part; - norm_file_part = g_utf8_casefold (norm_file_part, -1); - g_free (temp); - - temp = norm_name; - norm_name = g_utf8_casefold (norm_name, -1); - g_free (temp); - } -#endif - - result = (strncmp (norm_file_part, norm_name, strlen (norm_file_part)) == 0); - - g_free (norm_file_part); - g_free (norm_name); - g_free (name); - - return result; -} - static void -clear_completions (GtkFileChooserEntry *chooser_entry) +set_complete_on_load (GtkFileChooserEntry *chooser_entry, + gboolean complete_on_load) { - chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING; -} + /* a completion was triggered, but we couldn't do it. + * So no text was inserted when pressing tab, so we beep */ + if (chooser_entry->complete_on_load && !complete_on_load) + gtk_widget_error_bell (GTK_WIDGET (chooser_entry)); -static void -beep (GtkFileChooserEntry *chooser_entry) -{ - gtk_widget_error_bell (GTK_WIDGET (chooser_entry)); + chooser_entry->complete_on_load = complete_on_load; } static gboolean @@ -414,8 +301,10 @@ gtk_file_chooser_get_file_for_text (GtkFileChooserEntry *chooser_entry, if (str[0] == '~' || g_path_is_absolute (str) || has_uri_scheme (str)) file = g_file_parse_name (str); - else + else if (chooser_entry->base_folder != NULL) file = g_file_resolve_relative_path (chooser_entry->base_folder, str); + else + file = NULL; return file; } @@ -428,6 +317,9 @@ gtk_file_chooser_get_directory_for_text (GtkFileChooserEntry *chooser_entry, file = gtk_file_chooser_get_file_for_text (chooser_entry, text); + if (file == NULL) + return NULL; + if (text[0] == 0 || text[strlen (text) - 1] == G_DIR_SEPARATOR) return file; @@ -437,80 +329,13 @@ gtk_file_chooser_get_directory_for_text (GtkFileChooserEntry *chooser_entry, return parent; } -static gboolean -gtk_file_chooser_entry_parse (GtkFileChooserEntry *chooser_entry, - const gchar *str, - GFile **folder, - gchar **file_part, - GError **error) -{ - GFile *file; - gboolean result = FALSE; - gboolean is_dir = FALSE; - gchar *last_slash = NULL; - - if (str && *str) - is_dir = (str [strlen (str) - 1] == G_DIR_SEPARATOR); - - last_slash = strrchr (str, G_DIR_SEPARATOR); - - file = gtk_file_chooser_get_file_for_text (chooser_entry, str); - - if (g_file_equal (chooser_entry->base_folder, file)) - { - /* this is when user types '.', could be the - * beginning of a hidden file, ./ or ../ - */ - *folder = g_object_ref (file); - *file_part = g_strdup (str); - result = TRUE; - } - else if (is_dir) - { - /* it's a dir, or at least it ends with the dir separator */ - *folder = g_object_ref (file); - *file_part = g_strdup (""); - result = TRUE; - } - else - { - GFile *parent_file; - - parent_file = g_file_get_parent (file); - - if (!parent_file) - { - g_set_error (error, - GTK_FILE_CHOOSER_ERROR, - GTK_FILE_CHOOSER_ERROR_NONEXISTENT, - "Could not get parent file"); - *folder = NULL; - *file_part = NULL; - } - else - { - *folder = parent_file; - result = TRUE; - - if (last_slash) - *file_part = g_strdup (last_slash + 1); - else - *file_part = g_strdup (str); - } - } - - g_object_unref (file); - - return result; -} - /* Finds a common prefix based on the contents of the entry * and mandatorily appends it */ static void explicitly_complete (GtkFileChooserEntry *chooser_entry) { - clear_completions (chooser_entry); + chooser_entry->complete_on_load = FALSE; if (chooser_entry->completion_store) { @@ -536,7 +361,7 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry) } } - beep (chooser_entry); + gtk_widget_error_bell (GTK_WIDGET (chooser_entry)); } static void @@ -552,50 +377,41 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry) if (chooser_entry->current_folder_loaded) explicitly_complete (chooser_entry); else - chooser_entry->load_complete_action = LOAD_COMPLETE_EXPLICIT_COMPLETION; + set_complete_on_load (chooser_entry, TRUE); } static gboolean -gtk_file_chooser_entry_key_press_event (GtkWidget *widget, - GdkEventKey *event) +gtk_file_chooser_entry_tab_handler (GtkWidget *widget, + GdkEventKey *event) { GtkFileChooserEntry *chooser_entry; GtkEditable *editable; GdkModifierType state; - gboolean control_pressed; + gint start, end; chooser_entry = GTK_FILE_CHOOSER_ENTRY (widget); editable = GTK_EDITABLE (widget); if (!chooser_entry->eat_tabs) - return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->key_press_event (widget, event); + return FALSE; - control_pressed = FALSE; + if (event->keyval != GDK_KEY_Tab) + return FALSE; - if (gtk_get_current_event_state (&state)) - { - if ((state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) - control_pressed = TRUE; - } + if (gtk_get_current_event_state (&state) && + (state & GDK_CONTROL_MASK) == GDK_CONTROL_MASK) + return FALSE; /* This is a bit evil -- it makes Tab never leave the entry. It basically * makes it 'safe' for people to hit. */ - if (event->keyval == GDK_KEY_Tab && !control_pressed) - { - gint start, end; - - gtk_editable_get_selection_bounds (editable, &start, &end); + gtk_editable_get_selection_bounds (editable, &start, &end); - if (start != end) - gtk_editable_set_position (editable, MAX (start, end)); - else - start_explicit_completion (chooser_entry); - - return TRUE; - } - - return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->key_press_event (widget, event); + if (start != end) + gtk_editable_set_position (editable, MAX (start, end)); + else + start_explicit_completion (chooser_entry); + return TRUE; } static gboolean @@ -604,11 +420,35 @@ gtk_file_chooser_entry_focus_out_event (GtkWidget *widget, { GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (widget); - chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING; + set_complete_on_load (chooser_entry, FALSE); return GTK_WIDGET_CLASS (_gtk_file_chooser_entry_parent_class)->focus_out_event (widget, event); } +static void +update_inline_completion (GtkFileChooserEntry *chooser_entry) +{ + GtkEntryCompletion *completion = gtk_entry_get_completion (GTK_ENTRY (chooser_entry)); + + if (!chooser_entry->current_folder_loaded) + { + gtk_entry_completion_set_inline_completion (completion, FALSE); + return; + } + + switch (chooser_entry->action) + { + case GTK_FILE_CHOOSER_ACTION_OPEN: + case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: + gtk_entry_completion_set_inline_completion (completion, TRUE); + break; + case GTK_FILE_CHOOSER_ACTION_SAVE: + case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER: + gtk_entry_completion_set_inline_completion (completion, FALSE); + break; + } +} + static void discard_completion_store (GtkFileChooserEntry *chooser_entry) { @@ -616,7 +456,7 @@ discard_completion_store (GtkFileChooserEntry *chooser_entry) return; gtk_entry_completion_set_model (gtk_entry_get_completion (GTK_ENTRY (chooser_entry)), NULL); - gtk_entry_completion_set_inline_completion (gtk_entry_get_completion (GTK_ENTRY (chooser_entry)), FALSE); + update_inline_completion (chooser_entry); g_object_unref (chooser_entry->completion_store); chooser_entry->completion_store = NULL; } @@ -636,9 +476,6 @@ completion_store_set (GtkFileSystemModel *model, switch (column) { - case FILE_COLUMN: - g_value_set_object (value, file); - break; case FULL_PATH_COLUMN: prefix = chooser_entry->dir_part; /* fall through */ @@ -664,8 +501,6 @@ completion_store_set (GtkFileSystemModel *model, static void populate_completion_store (GtkFileChooserEntry *chooser_entry) { - discard_completion_store (chooser_entry); - chooser_entry->completion_store = GTK_TREE_MODEL ( _gtk_file_system_model_new_for_directory (chooser_entry->current_folder_file, "standard::name,standard::display-name,standard::type", @@ -673,11 +508,15 @@ populate_completion_store (GtkFileChooserEntry *chooser_entry) chooser_entry, N_COLUMNS, G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_FILE)); + G_TYPE_STRING)); g_signal_connect (chooser_entry->completion_store, "finished-loading", G_CALLBACK (finished_loading_cb), chooser_entry); + _gtk_file_system_model_set_filter_folders (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store), + TRUE); + _gtk_file_system_model_set_show_files (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store), + chooser_entry->action == GTK_FILE_CHOOSER_ACTION_OPEN || + chooser_entry->action == GTK_FILE_CHOOSER_ACTION_SAVE); gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (chooser_entry->completion_store), DISPLAY_NAME_COLUMN, GTK_SORT_ASCENDING); @@ -685,27 +524,6 @@ populate_completion_store (GtkFileChooserEntry *chooser_entry) chooser_entry->completion_store); } -/* When we finish loading the current folder, this function should get called to - * perform the deferred explicit completion. - */ -static void -perform_load_complete_action (GtkFileChooserEntry *chooser_entry) -{ - switch (chooser_entry->load_complete_action) - { - case LOAD_COMPLETE_NOTHING: - break; - - case LOAD_COMPLETE_EXPLICIT_COMPLETION: - explicitly_complete (chooser_entry); - break; - - default: - g_assert_not_reached (); - } - -} - /* Callback when the current folder finishes loading */ static void finished_loading_cb (GtkFileSystemModel *model, @@ -718,129 +536,101 @@ finished_loading_cb (GtkFileSystemModel *model, if (error) { - LoadCompleteAction old_load_complete_action; - - old_load_complete_action = chooser_entry->load_complete_action; - discard_completion_store (chooser_entry); - clear_completions (chooser_entry); - - if (old_load_complete_action == LOAD_COMPLETE_EXPLICIT_COMPLETION) - { - /* Since this came from explicit user action (Tab completion), we'll present errors visually */ - - beep (chooser_entry); - } - + set_complete_on_load (chooser_entry, FALSE); return; } - perform_load_complete_action (chooser_entry); + if (chooser_entry->complete_on_load) + explicitly_complete (chooser_entry); gtk_widget_set_tooltip_text (GTK_WIDGET (chooser_entry), NULL); completion = gtk_entry_get_completion (GTK_ENTRY (chooser_entry)); - gtk_entry_completion_set_inline_completion (completion, TRUE); + update_inline_completion (chooser_entry); gtk_entry_completion_complete (completion); gtk_entry_completion_insert_prefix (completion); } -static RefreshStatus -reload_current_folder (GtkFileChooserEntry *chooser_entry, - GFile *folder_file) +static void +set_completion_folder (GtkFileChooserEntry *chooser_entry, + GFile *folder_file) { - g_assert (folder_file != NULL); + if (folder_file && + chooser_entry->local_only + && !g_file_is_native (folder_file)) + folder_file = NULL; - if (chooser_entry->current_folder_file - && g_file_equal (folder_file, chooser_entry->current_folder_file)) - return REFRESH_OK; + if ((chooser_entry->current_folder_file + && folder_file + && g_file_equal (folder_file, chooser_entry->current_folder_file)) + || chooser_entry->current_folder_file == folder_file) + return; if (chooser_entry->current_folder_file) { - discard_loading_and_current_folder_file (chooser_entry); + g_object_unref (chooser_entry->current_folder_file); + chooser_entry->current_folder_file = NULL; } - if (chooser_entry->local_only - && !g_file_is_native (folder_file)) - return REFRESH_NOT_LOCAL; - - chooser_entry->current_folder_file = g_object_ref (folder_file); chooser_entry->current_folder_loaded = FALSE; - populate_completion_store (chooser_entry); + discard_completion_store (chooser_entry); - return REFRESH_OK; + if (folder_file) + { + chooser_entry->current_folder_file = g_object_ref (folder_file); + populate_completion_store (chooser_entry); + } } -static RefreshStatus -refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, - const gchar * text) +static void +refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry) { GFile *folder_file; - gchar *file_part; - gsize total_len, file_part_len; - gint file_part_pos; - GError *error; - RefreshStatus result; - - error = NULL; - if (!gtk_file_chooser_entry_parse (chooser_entry, - text, &folder_file, &file_part, &error)) - { - folder_file = g_object_ref (chooser_entry->base_folder); - - if (g_error_matches (error, GTK_FILE_CHOOSER_ERROR, GTK_FILE_CHOOSER_ERROR_NONEXISTENT)) - result = REFRESH_NONEXISTENT; - else - result = REFRESH_INVALID_INPUT; - - if (error) - g_error_free (error); - - file_part = g_strdup (""); - file_part_pos = -1; - } - else - { - g_assert (folder_file != NULL); - - file_part_len = strlen (file_part); - total_len = strlen (text); - if (total_len > file_part_len) - file_part_pos = g_utf8_strlen (text, total_len - file_part_len); - else - file_part_pos = 0; + char *text, *last_slash, *old_file_part; - result = REFRESH_OK; - } - - g_free (chooser_entry->file_part); + old_file_part = chooser_entry->file_part; g_free (chooser_entry->dir_part); - chooser_entry->dir_part = file_part_pos > 0 ? g_strndup (text, file_part_pos) : g_strdup (""); - chooser_entry->file_part = file_part; - chooser_entry->file_part_pos = file_part_pos; + text = gtk_file_chooser_entry_get_completion_text (chooser_entry); - if (result == REFRESH_OK) + last_slash = strrchr (text, G_DIR_SEPARATOR); + if (last_slash) { - result = reload_current_folder (chooser_entry, folder_file); + chooser_entry->dir_part = g_strndup (text, last_slash - text + 1); + chooser_entry->file_part = g_strdup (last_slash + 1); } else { - discard_loading_and_current_folder_file (chooser_entry); + chooser_entry->dir_part = g_strdup (""); + chooser_entry->file_part = g_strdup (text); } + folder_file = gtk_file_chooser_get_directory_for_text (chooser_entry, text); + set_completion_folder (chooser_entry, folder_file); if (folder_file) g_object_unref (folder_file); - g_assert (/* we are OK and we have a current folder file and (loading process or folder handle)... */ - ((result == REFRESH_OK) - && (chooser_entry->current_folder_file != NULL)) - /* ... OR we have an error, and we don't have a current folder file nor a loading process nor a folder handle */ - || ((result != REFRESH_OK) - && (chooser_entry->current_folder_file == NULL))); + if (chooser_entry->completion_store && + (g_strcmp0 (old_file_part, chooser_entry->file_part) != 0)) + { + GtkFileFilter *filter; + char *pattern; + + filter = gtk_file_filter_new (); + pattern = g_strconcat (chooser_entry->file_part, "*", NULL); + gtk_file_filter_add_pattern (filter, pattern); + + _gtk_file_system_model_set_filter (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store), + filter); - return result; + g_free (pattern); + g_object_unref (filter); + } + + g_free (text); + g_free (old_file_part); } #ifdef G_OS_WIN32 @@ -940,23 +730,23 @@ void _gtk_file_chooser_entry_set_base_folder (GtkFileChooserEntry *chooser_entry, GFile *file) { + g_return_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (chooser_entry)); + g_return_if_fail (file == NULL || G_IS_FILE (file)); + + if (chooser_entry->base_folder == file || + (file != NULL && chooser_entry->base_folder != NULL + && g_file_equal (chooser_entry->base_folder, file))) + return; + if (file) g_object_ref (file); - else - file = g_file_new_for_path (g_get_home_dir ()); - - if (g_file_equal (chooser_entry->base_folder, file)) - { - g_object_unref (file); - return; - } if (chooser_entry->base_folder) g_object_unref (chooser_entry->base_folder); chooser_entry->base_folder = file; - clear_completions (chooser_entry); + refresh_current_folder_and_file_part (chooser_entry); } /** @@ -1009,26 +799,6 @@ _gtk_file_chooser_entry_get_file_part (GtkFileChooserEntry *chooser_entry) return text; } -/** - * _gtk_file_chooser_entry_set_file_part: - * @chooser_entry: a #GtkFileChooserEntry - * @file_part: text to display in the entry, in UTF-8 - * - * Sets the current text shown in the file chooser entry. - **/ -void -_gtk_file_chooser_entry_set_file_part (GtkFileChooserEntry *chooser_entry, - const gchar *file_part) -{ - g_return_if_fail (GTK_IS_FILE_CHOOSER_ENTRY (chooser_entry)); - - chooser_entry->in_change = TRUE; - clear_completions (chooser_entry); - gtk_entry_set_text (GTK_ENTRY (chooser_entry), file_part); - chooser_entry->in_change = FALSE; -} - - /** * _gtk_file_chooser_entry_set_action: * @chooser_entry: a #GtkFileChooserEntry @@ -1065,6 +835,13 @@ _gtk_file_chooser_entry_set_action (GtkFileChooserEntry *chooser_entry, gtk_entry_completion_set_popup_single_match (comp, TRUE); break; } + + if (chooser_entry->completion_store) + _gtk_file_system_model_set_show_files (GTK_FILE_SYSTEM_MODEL (chooser_entry->completion_store), + action == GTK_FILE_CHOOSER_ACTION_OPEN || + action == GTK_FILE_CHOOSER_ACTION_SAVE); + + update_inline_completion (chooser_entry); } } @@ -1135,7 +912,7 @@ _gtk_file_chooser_entry_set_local_only (GtkFileChooserEntry *chooser_entry, gboolean local_only) { chooser_entry->local_only = local_only; - clear_completions (chooser_entry); + refresh_current_folder_and_file_part (chooser_entry); } gboolean