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;
guint has_completion : 1;
guint in_change : 1;
guint eat_tabs : 1;
+ guint local_only : 1;
};
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);
GtkEntryCompletion *comp;
GtkCellRenderer *cell;
+ chooser_entry->local_only = TRUE;
+
g_object_set (chooser_entry, "truncate-multiline", TRUE, NULL);
comp = gtk_entry_completion_new ();
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
}
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)
{
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);
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);
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"));
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
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);
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)
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))
{
GTK_ENTRY (chooser_entry)->text_length);
}
+ /* FMQ: get result from the function below */
refresh_current_folder_and_file_part (chooser_entry, REFRESH_WHOLE_TEXT);
}
/* 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);
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)
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)
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);
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;
/* 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
start_loading_current_folder (chooser_entry);
}
-static void
+static RefreshStatus
refresh_current_folder_and_file_part (GtkFileChooserEntry *chooser_entry,
RefreshMode refresh_mode)
{
gchar *file_part;
gsize total_len, file_part_len;
gint file_part_pos;
+ GError *error;
+ RefreshStatus result;
editable = GTK_EDITABLE (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;
}
file_part_pos = g_utf8_strlen (text, total_len - file_part_len);
else
file_part_pos = 0;
+
+ result = REFRESH_OK;
}
g_free (text);
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
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)
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
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);
}
}
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;
+}