diff options
author | Alexander Larsson <alexl@src.gnome.org> | 2007-11-30 14:51:10 +0000 |
---|---|---|
committer | Alexander Larsson <alexl@src.gnome.org> | 2007-11-30 14:51:10 +0000 |
commit | 469047a2a58430026d68a3b99b223b922b18b8d1 (patch) | |
tree | 0d7422285604a348f98f3c93e39afdf570050678 /src/nautilus-location-entry.c | |
parent | ce669bd18cf00a3fc485ffedc53850e2d89b57e0 (diff) | |
download | nautilus-469047a2a58430026d68a3b99b223b922b18b8d1.tar.gz |
Merge gio-branch
svn path=/trunk/; revision=13464
Diffstat (limited to 'src/nautilus-location-entry.c')
-rw-r--r-- | src/nautilus-location-entry.c | 257 |
1 files changed, 35 insertions, 222 deletions
diff --git a/src/nautilus-location-entry.c b/src/nautilus-location-entry.c index c5e5053a1..491d64e7d 100644 --- a/src/nautilus-location-entry.c +++ b/src/nautilus-location-entry.c @@ -39,17 +39,17 @@ #include <eel/eel-gtk-macros.h> #include <eel/eel-stock-dialogs.h> #include <eel/eel-string.h> -#include <eel/eel-vfs-extensions.h> #include <gtk/gtkdnd.h> #include <gtk/gtksignal.h> #include <glib/gi18n.h> +#include <gio/gfilenamecompleter.h> #include <libgnomeui/gnome-stock-icons.h> #include <libgnomeui/gnome-uidefs.h> -#include <libgnomevfs/gnome-vfs.h> #include <libnautilus-private/nautilus-file-utilities.h> #include <libnautilus-private/nautilus-entry.h> #include <libnautilus-private/nautilus-icon-dnd.h> #include <libnautilus-private/nautilus-clipboard.h> +#include <gio/gfilenamecompleter.h> #include <stdio.h> #include <string.h> @@ -57,7 +57,7 @@ struct NautilusLocationEntryDetails { GtkLabel *label; char *current_directory; - GList *file_info_list; + GFilenameCompleter *completer; guint idle_id; @@ -73,87 +73,7 @@ EEL_CLASS_BOILERPLATE (NautilusLocationEntry, nautilus_location_entry, NAUTILUS_TYPE_ENTRY) -/* utility routine to determine the string to expand to. If we don't have anything yet, accept - the whole string, otherwise accept the largest part common to both */ - -static char * -accumulate_name_utf8 (char *full_name, char *candidate_name) -{ - char *result_name, *str1, *str2; - - if (!g_utf8_validate (candidate_name, -1, NULL)) { - return full_name; - } - - if (full_name == NULL) { - result_name = g_strdup (candidate_name); - } else { - result_name = full_name; - if (!eel_str_has_prefix (full_name, candidate_name)) { - str1 = full_name; - str2 = candidate_name; - - while ((g_utf8_get_char (str1) == g_utf8_get_char (str2))) { - str1 = g_utf8_next_char (str1); - str2 = g_utf8_next_char (str2); - } - *str1 = '\0'; - } - } - - return result_name; -} - -static char * -accumulate_name_locale (char *full_name, char *candidate_name) -{ - char *result_name, *str1, *str2; - - if (full_name == NULL) - result_name = g_strdup (candidate_name); - else { - result_name = full_name; - if (!eel_str_has_prefix (full_name, candidate_name)) { - str1 = full_name; - str2 = candidate_name; - - while (*str1 == *str2) { - str1++; - str2++; - } - *str1 = '\0'; - } - } - - return result_name; -} - -/* utility routine to load the file info list for the current directory, if necessary */ -static void -get_file_info_list (NautilusLocationEntry *entry, const char* dir_name) -{ - GnomeVFSResult result; - - if (eel_strcmp (entry->details->current_directory, dir_name) != 0) { - g_free (entry->details->current_directory); - if (entry->details->file_info_list) { - gnome_vfs_file_info_list_free (entry->details->file_info_list); - entry->details->file_info_list = NULL; - } - - entry->details->current_directory = g_strdup (dir_name); - result = gnome_vfs_directory_list_load (&entry->details->file_info_list, dir_name, - GNOME_VFS_FILE_INFO_DEFAULT); - if (result != GNOME_VFS_OK) { - if (entry->details->file_info_list) { - gnome_vfs_file_info_list_free (entry->details->file_info_list); - entry->details->file_info_list = NULL; - } - } - } -} - -/* routine that performs the tab expansion using gnome-vfs. Extract the directory name and +/* routine that performs the tab expansion. Extract the directory name and incomplete basename, then iterate through the directory trying to complete it. If we find something, add it to the entry */ @@ -161,148 +81,29 @@ static gboolean try_to_expand_path (gpointer callback_data) { NautilusLocationEntry *entry; - - GnomeVFSFileInfo *current_file_info; - GList *element; - GnomeVFSURI *uri; GtkEditable *editable; - gboolean utf8_filenames; - const char *filename_charset; - - char *base_name_uri_escaped; - char *base_name; - char *base_name_utf8; - char *user_location; - char *current_path; - char *dir_name; - char *expand_text; - char *expand_text_utf8; - char *expand_name; - char *insert_text; - - int base_name_length; - int user_location_length; - int expand_text_length; - int pos; + char *suffix, *user_location; + int user_location_length, pos; entry = NAUTILUS_LOCATION_ENTRY (callback_data); editable = GTK_EDITABLE (entry); user_location = gtk_editable_get_chars (editable, 0, -1); - entry->details->idle_id = 0; - - /* if it's just '~' don't expand because slash shouldn't be appended */ - if (eel_strcmp (user_location, "~") == 0) { - g_free (user_location); - return FALSE; - } - - /* Trailing whitespace is OK here since the cursor is known to - be at the end of the text and therefor after the whitespace. */ - current_path = gnome_vfs_make_uri_from_input_with_trailing_ws (user_location); - if (!eel_istr_has_prefix (current_path, "file://")) { - g_free (user_location); - g_free (current_path); - return FALSE; - } - - /* We already completed if we have a trailing '/' */ - if (current_path[strlen (current_path) - 1] == GNOME_VFS_URI_PATH_CHR) { - g_free (user_location); - g_free (current_path); - return FALSE; - } - user_location_length = g_utf8_strlen (user_location, -1); - - g_free (user_location); - - uri = gnome_vfs_uri_new (current_path); - - base_name_uri_escaped = gnome_vfs_uri_extract_short_name (uri); - if (base_name_uri_escaped == NULL) { - base_name = NULL; - } else { - base_name = gnome_vfs_unescape_string (base_name_uri_escaped, NULL); - } - g_free (base_name_uri_escaped); - - if (base_name == NULL) { - gnome_vfs_uri_unref (uri); - g_free (current_path); - return FALSE; - } - - dir_name = gnome_vfs_uri_extract_dirname (uri); - - gnome_vfs_uri_unref (uri); - uri = NULL; - - /* get file info for the directory, if it hasn't changed since last time */ - get_file_info_list (entry, dir_name); - if (entry->details->file_info_list == NULL) { - g_free (dir_name); - g_free (base_name); - g_free (current_path); - return FALSE; - } - - utf8_filenames = eel_get_filename_charset (&filename_charset); - - /* iterate through the directory, keeping the intersection of all the names that - have the current basename as a prefix. */ - expand_text = NULL; - for (element = entry->details->file_info_list; element != NULL; element = element->next) { - current_file_info = element->data; - if (eel_str_has_prefix (current_file_info->name, base_name)) { - if (current_file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { - expand_name = g_strconcat (current_file_info->name, "/", NULL); - } else { - expand_name = g_strdup (current_file_info->name); - } - if (utf8_filenames) { - expand_text = accumulate_name_utf8 (expand_text, expand_name); - } else { - expand_text = accumulate_name_locale (expand_text, expand_name); - } - g_free (expand_name); - } - } - - if (!utf8_filenames) { - if (expand_text) { - expand_text_utf8 = g_convert (expand_text, -1, "UTF-8", filename_charset, NULL, NULL, NULL); - g_free (expand_text); - expand_text = expand_text_utf8; - } - - base_name_utf8 = g_convert (base_name, -1, "UTF-8", filename_charset, NULL, NULL, NULL); - g_free (base_name); - base_name = base_name_utf8; - } - + entry->details->idle_id = 0; + + suffix = g_filename_completer_get_completion_suffix (entry->details->completer, + user_location); + /* if we've got something, add it to the entry */ - if (expand_text != NULL && base_name != NULL) { - expand_text_length = g_utf8_strlen (expand_text, -1); - base_name_length = g_utf8_strlen (base_name, -1); + if (suffix != NULL) { + pos = user_location_length; + gtk_editable_insert_text (editable, + suffix, -1, &pos); + pos = user_location_length; + gtk_editable_select_region (editable, pos, -1); - if (!eel_str_has_suffix (base_name, expand_text) - && base_name_length < expand_text_length) { - insert_text = g_utf8_offset_to_pointer (expand_text, base_name_length); - pos = user_location_length; - gtk_editable_insert_text (editable, - insert_text, - strlen (insert_text), - &pos); - - pos = user_location_length; - gtk_editable_select_region (editable, pos, -1); - } + g_free (suffix); } - g_free (expand_text); - - g_free (dir_name); - g_free (base_name); - g_free (current_path); return FALSE; } @@ -381,6 +182,17 @@ position_and_selection_are_at_end (GtkEditable *editable) } static void +got_completion_data_callback (GFilenameCompleter *completer, + NautilusLocationEntry *entry) +{ + if (entry->details->idle_id) { + g_source_remove (entry->details->idle_id); + entry->details->idle_id = 0; + } + try_to_expand_path (entry); +} + +static void editable_event_after_callback (GtkEntry *entry, GdkEvent *event, NautilusLocationEntry *location_entry) @@ -435,6 +247,7 @@ finalize (GObject *object) entry = NAUTILUS_LOCATION_ENTRY (object); + g_object_unref (entry->details->completer); g_free (entry->details->special_text); g_free (entry->details); @@ -454,11 +267,6 @@ destroy (GtkObject *object) entry->details->idle_id = 0; } - if (entry->details->file_info_list) { - gnome_vfs_file_info_list_free (entry->details->file_info_list); - entry->details->file_info_list = NULL; - } - g_free (entry->details->current_directory); entry->details->current_directory = NULL; @@ -514,6 +322,9 @@ nautilus_location_entry_init (NautilusLocationEntry *entry) { entry->details = g_new0 (NautilusLocationEntryDetails, 1); + entry->details->completer = g_filename_completer_new (); + g_filename_completer_set_dirs_only (entry->details->completer, TRUE); + nautilus_entry_set_special_tab_handling (NAUTILUS_ENTRY (entry), TRUE); g_signal_connect (entry, "event_after", @@ -522,6 +333,8 @@ nautilus_location_entry_init (NautilusLocationEntry *entry) g_signal_connect (entry, "notify::text", G_CALLBACK (nautilus_location_entry_text_changed), NULL); + g_signal_connect (entry->details->completer, "got_completion_data", + G_CALLBACK (got_completion_data_callback), entry); } GtkWidget * |