X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkfilechooserentry.c;h=66f0f24346fb9ecfba826524d0ec09ff039620d8;hb=2dd7cf4926bdc2edc8d27e81b86178efd091c433;hp=29149344c398f62e9fef28841090d964e15f0236;hpb=7e39f9285a1ef27606412b42b26fa79c4368050f;p=~andy%2Fgtk diff --git a/gtk/gtkfilechooserentry.c b/gtk/gtkfilechooserentry.c index 29149344c..66f0f2434 100644 --- a/gtk/gtkfilechooserentry.c +++ b/gtk/gtkfilechooserentry.c @@ -50,6 +50,15 @@ typedef enum { 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; @@ -79,6 +88,7 @@ struct _GtkFileChooserEntry guint has_completion : 1; guint in_change : 1; guint eat_tabs : 1; + guint local_only : 1; }; enum @@ -143,10 +153,10 @@ typedef enum { REFRESH_WHOLE_TEXT } RefreshMode; -static void refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, +static RefreshStatus refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, RefreshMode refresh_mode); -static void finished_loading_cb (GFile *file, - gpointer data); +static void finished_loading_cb (GtkFolder *folder, + gpointer data); static void autocomplete (GtkFileChooserEntry *chooser_entry); static void install_start_autocompletion_idle (GtkFileChooserEntry *chooser_entry); static void remove_completion_feedback (GtkFileChooserEntry *chooser_entry); @@ -194,6 +204,8 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry) GtkEntryCompletion *comp; GtkCellRenderer *cell; + chooser_entry->local_only = TRUE; + g_object_set (chooser_entry, "truncate-multiline", TRUE, NULL); comp = gtk_entry_completion_new (); @@ -211,16 +223,16 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry) cell, "text", 0); - g_signal_connect (comp, "match_selected", + g_signal_connect (comp, "match-selected", G_CALLBACK (match_selected_callback), chooser_entry); gtk_entry_set_completion (GTK_ENTRY (chooser_entry), comp); g_object_unref (comp); #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_signal_connect (chooser_entry, "delete_text", + g_signal_connect (chooser_entry, "delete-text", G_CALLBACK (delete_text_callback), NULL); #endif } @@ -244,12 +256,25 @@ gtk_file_chooser_entry_finalize (GObject *object) G_OBJECT_CLASS (_gtk_file_chooser_entry_parent_class)->finalize (object); } +static void +discard_current_folder (GtkFileChooserEntry *chooser_entry) +{ + if (chooser_entry->current_folder) + { + g_signal_handlers_disconnect_by_func (chooser_entry->current_folder, + G_CALLBACK (finished_loading_cb), chooser_entry); + g_object_unref (chooser_entry->current_folder); + chooser_entry->current_folder = NULL; + } +} + static void gtk_file_chooser_entry_dispose (GObject *object) { GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (object); remove_completion_feedback (chooser_entry); + discard_current_folder (chooser_entry); if (chooser_entry->start_autocompletion_idle_id != 0) { @@ -269,14 +294,6 @@ gtk_file_chooser_entry_dispose (GObject *object) chooser_entry->load_folder_cancellable = NULL; } - if (chooser_entry->current_folder) - { - g_signal_handlers_disconnect_by_func (chooser_entry->current_folder, - G_CALLBACK (finished_loading_cb), chooser_entry); - g_object_unref (chooser_entry->current_folder); - chooser_entry->current_folder = NULL; - } - if (chooser_entry->file_system) { g_object_unref (chooser_entry->file_system); @@ -439,7 +456,7 @@ maybe_append_separator_to_file (GtkFileChooserEntry *chooser_entry, if (info) { - if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) + if (_gtk_file_info_consider_as_directory (info)) { gchar *tmp = display_name; display_name = g_strconcat (tmp, G_DIR_SEPARATOR_S, NULL); @@ -653,7 +670,12 @@ append_common_prefix (GtkFileChooserEntry *chooser_entry, error = NULL; if (!find_common_prefix (chooser_entry, &common_prefix, &unique_file, &is_complete_not_unique, &prefix_expands_the_file_part, &error)) { - if (show_errors) + /* If the user types an incomplete hostname ("http://foo" without a slash + * after that), it's not an error. We just don't want to pop up a + * meaningless completion window in that state. + */ + if (!g_error_matches (error, GTK_FILE_CHOOSER_ERROR, GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME) + && show_errors) { beep (chooser_entry); pop_up_completion_feedback (chooser_entry, _("Invalid path")); @@ -862,31 +884,15 @@ completion_feedback_window_expose_event_cb (GtkWidget *widget, static void set_invisible_mouse_cursor (GdkWindow *window) { - /* Stolen from gtkentry.c:set_invisible_cursor() */ - /* FIXME: implement a stupid public gdk_window_set_invisible_mouse_cursor() */ - - GdkBitmap *empty_bitmap; + GdkDisplay *display; GdkCursor *cursor; - GdkColor useless; - char invisible_cursor_bits[] = { 0x0 }; - - useless.red = useless.green = useless.blue = 0; - useless.pixel = 0; - empty_bitmap = gdk_bitmap_create_from_data (window, - invisible_cursor_bits, - 1, 1); - - cursor = gdk_cursor_new_from_pixmap (empty_bitmap, - empty_bitmap, - &useless, - &useless, 0, 0); + display = gdk_drawable_get_display (window); + cursor = gdk_cursor_new_for_display (display, GDK_BLANK_CURSOR); gdk_window_set_cursor (window, cursor); gdk_cursor_unref (cursor); - - g_object_unref (empty_bitmap); } static void @@ -923,7 +929,7 @@ create_completion_feedback_window (GtkFileChooserEntry *chooser_entry) gtk_container_add (GTK_CONTAINER (chooser_entry->completion_feedback_window), alignment); gtk_widget_show (alignment); - g_signal_connect (chooser_entry->completion_feedback_window, "expose_event", + g_signal_connect (chooser_entry->completion_feedback_window, "expose-event", G_CALLBACK (completion_feedback_window_expose_event_cb), chooser_entry); g_signal_connect (chooser_entry->completion_feedback_window, "realize", G_CALLBACK (completion_feedback_window_realize_cb), chooser_entry); @@ -1105,6 +1111,7 @@ explicitly_complete (GtkFileChooserEntry *chooser_entry) static void start_explicit_completion (GtkFileChooserEntry *chooser_entry) { + /* FMQ: get result from the function below */ refresh_current_folder_and_file_part (chooser_entry, REFRESH_UP_TO_CURSOR_POSITION); if (!chooser_entry->current_folder_file) @@ -1118,6 +1125,16 @@ start_explicit_completion (GtkFileChooserEntry *chooser_entry) return; } + if (chooser_entry->local_only + && !g_file_is_native (chooser_entry->current_folder_file)) + { + beep (chooser_entry); + pop_up_completion_feedback (chooser_entry, _("Only local files can be selected")); + + chooser_entry->load_complete_action = LOAD_COMPLETE_NOTHING; + return; + } + if (chooser_entry->current_folder && _gtk_folder_is_finished_loading (chooser_entry->current_folder)) { @@ -1196,6 +1213,7 @@ commit_completion_and_refresh (GtkFileChooserEntry *chooser_entry) GTK_ENTRY (chooser_entry)->text_length); } + /* FMQ: get result from the function below */ refresh_current_folder_and_file_part (chooser_entry, REFRESH_WHOLE_TEXT); } @@ -1308,8 +1326,8 @@ finish_folder_load (GtkFileChooserEntry *chooser_entry) /* Callback when the current folder finishes loading */ static void -finished_loading_cb (GFile *file, - gpointer data) +finished_loading_cb (GtkFolder *folder, + gpointer data) { GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (data); @@ -1337,6 +1355,7 @@ load_directory_get_folder_callback (GCancellable *cancellable, 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) @@ -1347,11 +1366,7 @@ load_directory_get_folder_callback (GCancellable *cancellable, pop_up_completion_feedback (chooser_entry, error->message); } - if (chooser_entry->current_folder) - { - g_object_unref (chooser_entry->current_folder); - chooser_entry->current_folder = NULL; - } + discard_current_folder (chooser_entry); } if (cancelled || error) @@ -1380,6 +1395,10 @@ start_loading_current_folder (GtkFileChooserEntry *chooser_entry) chooser_entry->file_system == NULL) return; + if (chooser_entry->local_only + && !g_file_is_native (chooser_entry->current_folder_file)) + return; + g_assert (chooser_entry->current_folder == NULL); g_assert (chooser_entry->load_folder_cancellable == NULL); @@ -1400,7 +1419,8 @@ reload_current_folder (GtkFileChooserEntry *chooser_entry, if (chooser_entry->current_folder_file) { - if ((folder_file && !g_file_equal (folder_file, chooser_entry->current_folder_file)) + if ((folder_file && !(g_file_equal (folder_file, chooser_entry->current_folder_file) + && chooser_entry->load_folder_cancellable)) || force_reload) { reload = TRUE; @@ -1408,20 +1428,15 @@ reload_current_folder (GtkFileChooserEntry *chooser_entry, /* We changed our current directory. We need to clear out the old * directory information. */ - if (chooser_entry->current_folder) - { - if (chooser_entry->load_folder_cancellable) - { - g_cancellable_cancel (chooser_entry->load_folder_cancellable); - chooser_entry->load_folder_cancellable = NULL; - } - - g_object_unref (chooser_entry->current_folder); - chooser_entry->current_folder = NULL; - } + if (chooser_entry->load_folder_cancellable) + { + g_cancellable_cancel (chooser_entry->load_folder_cancellable); + chooser_entry->load_folder_cancellable = NULL; + } + discard_current_folder (chooser_entry); g_object_unref (chooser_entry->current_folder_file); - chooser_entry->current_folder_file = g_object_ref (folder_file); + chooser_entry->current_folder_file = (folder_file) ? g_object_ref (folder_file) : NULL; } } else @@ -1434,7 +1449,7 @@ reload_current_folder (GtkFileChooserEntry *chooser_entry, start_loading_current_folder (chooser_entry); } -static void +static RefreshStatus refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, RefreshMode refresh_mode) { @@ -1445,6 +1460,8 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, gchar *file_part; gsize total_len, file_part_len; gint file_part_pos; + GError *error; + RefreshStatus result; editable = GTK_EDITABLE (chooser_entry); @@ -1460,18 +1477,36 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, default: g_assert_not_reached (); - return; + return REFRESH_INVALID_INPUT; } text = gtk_editable_get_chars (editable, 0, end_pos); - + + error = NULL; if (!chooser_entry->file_system || !chooser_entry->base_folder || !_gtk_file_system_parse (chooser_entry->file_system, chooser_entry->base_folder, text, - &folder_file, &file_part, NULL)) /* NULL-GError */ + &folder_file, &file_part, &error)) { - folder_file = (chooser_entry->base_folder) ? g_object_ref (chooser_entry->base_folder) : NULL; + if (g_error_matches (error, GTK_FILE_CHOOSER_ERROR, GTK_FILE_CHOOSER_ERROR_INCOMPLETE_HOSTNAME)) + { + folder_file = NULL; + result = REFRESH_INCOMPLETE_HOSTNAME; + } + else + { + folder_file = (chooser_entry->base_folder) ? g_object_ref (chooser_entry->base_folder) : NULL; + + 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; } @@ -1483,6 +1518,8 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, file_part_pos = g_utf8_strlen (text, total_len - file_part_len); else file_part_pos = 0; + + result = REFRESH_OK; } g_free (text); @@ -1492,10 +1529,13 @@ refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry, chooser_entry->file_part = file_part; chooser_entry->file_part_pos = file_part_pos; + /* FMQ: this needs to return an error if the folder is not local */ reload_current_folder (chooser_entry, folder_file, file_part_pos == -1); if (folder_file) g_object_unref (folder_file); + + return result; } static void @@ -1511,6 +1551,7 @@ autocomplete (GtkFileChooserEntry *chooser_entry) static void start_autocompletion (GtkFileChooserEntry *chooser_entry) { + /* FMQ: get result from the function below */ refresh_current_folder_and_file_part (chooser_entry, REFRESH_UP_TO_CURSOR_POSITION); if (!chooser_entry->current_folder) @@ -1545,7 +1586,7 @@ install_start_autocompletion_idle (GtkFileChooserEntry *chooser_entry) if (chooser_entry->start_autocompletion_idle_id != 0) return; - chooser_entry->start_autocompletion_idle_id = g_idle_add (start_autocompletion_idle_handler, chooser_entry); + chooser_entry->start_autocompletion_idle_id = gdk_threads_add_idle (start_autocompletion_idle_handler, chooser_entry); } #ifdef G_OS_WIN32 @@ -1812,7 +1853,7 @@ _gtk_file_chooser_entry_get_is_folder (GtkFileChooserEntry *chooser_entry, if (file_info) { - retval = (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY); + retval = _gtk_file_info_consider_as_directory (file_info); g_object_unref (file_info); } } @@ -1845,3 +1886,16 @@ _gtk_file_chooser_entry_select_filename (GtkFileChooserEntry *chooser_entry) gtk_editable_select_region (GTK_EDITABLE (chooser_entry), 0, (gint) len); } +void +_gtk_file_chooser_entry_set_local_only (GtkFileChooserEntry *chooser_entry, + gboolean local_only) +{ + chooser_entry->local_only = local_only; + clear_completions (chooser_entry); +} + +gboolean +_gtk_file_chooser_entry_get_local_only (GtkFileChooserEntry *chooser_entry) +{ + return chooser_entry->local_only; +}