Make C-l interpret relative paths better
It is quite hard to make this work good. At least it's not terrible.
This commit is contained in:
parent
216767d7ee
commit
6eb78f1a5c
|
@ -185,7 +185,9 @@ on_open_location(G_GNUC_UNUSED GtkPlacesSidebar *sidebar, GFile *location,
|
||||||
static void
|
static void
|
||||||
complete_path(GFile *location, GtkListStore *model)
|
complete_path(GFile *location, GtkListStore *model)
|
||||||
{
|
{
|
||||||
GFile *parent =
|
// TODO(p): Do not enter directories unless followed by '/'.
|
||||||
|
// This information has already been stripped from `location`.
|
||||||
|
GFile *parent = G_FILE_TYPE_DIRECTORY ==
|
||||||
g_file_query_file_type(location, G_FILE_QUERY_INFO_NONE, NULL)
|
g_file_query_file_type(location, G_FILE_QUERY_INFO_NONE, NULL)
|
||||||
? g_object_ref(location)
|
? g_object_ref(location)
|
||||||
: g_file_get_parent(location);
|
: g_file_get_parent(location);
|
||||||
|
@ -193,12 +195,13 @@ complete_path(GFile *location, GtkListStore *model)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GFileEnumerator *enumerator = g_file_enumerate_children(parent,
|
GFileEnumerator *enumerator = g_file_enumerate_children(parent,
|
||||||
G_FILE_ATTRIBUTE_STANDARD_NAME,
|
G_FILE_ATTRIBUTE_STANDARD_NAME
|
||||||
|
"," G_FILE_ATTRIBUTE_STANDARD_TYPE
|
||||||
|
"," G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN,
|
||||||
G_FILE_QUERY_INFO_NONE, NULL, NULL);
|
G_FILE_QUERY_INFO_NONE, NULL, NULL);
|
||||||
if (!enumerator)
|
if (!enumerator)
|
||||||
goto fail_enumerator;
|
goto fail_enumerator;
|
||||||
|
|
||||||
// TODO(p): Resolve ~ paths a bit better.
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
GFileInfo *info = NULL;
|
GFileInfo *info = NULL;
|
||||||
GFile *child = NULL;
|
GFile *child = NULL;
|
||||||
|
@ -206,10 +209,14 @@ complete_path(GFile *location, GtkListStore *model)
|
||||||
!info)
|
!info)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
GtkTreeIter iter;
|
if (g_file_info_get_file_type(info) != G_FILE_TYPE_DIRECTORY ||
|
||||||
gtk_list_store_append(model, &iter);
|
g_file_info_get_is_hidden(info))
|
||||||
gtk_list_store_set(
|
continue;
|
||||||
model, &iter, 0, g_file_get_parse_name(child), -1);
|
|
||||||
|
// TODO(p): Resolve ~ paths a bit better.
|
||||||
|
char *parse_name = g_file_get_parse_name(child);
|
||||||
|
gtk_list_store_insert_with_values(model, NULL, -1, 0, parse_name, -1);
|
||||||
|
g_free(parse_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_object_unref(enumerator);
|
g_object_unref(enumerator);
|
||||||
|
@ -217,38 +224,45 @@ fail_enumerator:
|
||||||
g_object_unref(parent);
|
g_object_unref(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GFile *
|
||||||
on_enter_location_changed(GtkEntry *entry, G_GNUC_UNUSED gpointer user_data)
|
resolve_location(FastivSidebar *self, const char *text)
|
||||||
{
|
{
|
||||||
const char *text = gtk_entry_get_text(entry);
|
// Relative paths produce invalid GFile objects with this function.
|
||||||
GFile *location = g_file_parse_name(text);
|
// And even if they didn't, we have our own root for them.
|
||||||
|
GFile *file = g_file_parse_name(text);
|
||||||
// Don't touch the network, URIs are a no-no.
|
|
||||||
// FIXME: This uses a different relative root from the fastiv.c opener.
|
|
||||||
GtkStyleContext *style = gtk_widget_get_style_context(GTK_WIDGET(entry));
|
|
||||||
if (g_uri_is_valid(text, G_URI_FLAGS_PARSE_RELAXED, NULL) ||
|
if (g_uri_is_valid(text, G_URI_FLAGS_PARSE_RELAXED, NULL) ||
|
||||||
g_file_query_exists(location, NULL))
|
g_file_peek_path(file))
|
||||||
|
return file;
|
||||||
|
|
||||||
|
GFile *absolute =
|
||||||
|
g_file_get_child_for_display_name(self->location, text, NULL);
|
||||||
|
if (!absolute)
|
||||||
|
return file;
|
||||||
|
|
||||||
|
g_object_unref(file);
|
||||||
|
return absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_enter_location_changed(GtkEntry *entry, gpointer user_data)
|
||||||
|
{
|
||||||
|
FastivSidebar *self = FASTIV_SIDEBAR(user_data);
|
||||||
|
const char *text = gtk_entry_get_text(entry);
|
||||||
|
GFile *location = resolve_location(self, text);
|
||||||
|
|
||||||
|
// Don't touch the network anywhere around here, URIs are a no-no.
|
||||||
|
GtkStyleContext *style = gtk_widget_get_style_context(GTK_WIDGET(entry));
|
||||||
|
if (!g_file_peek_path(location) || g_file_query_exists(location, NULL))
|
||||||
gtk_style_context_remove_class(style, GTK_STYLE_CLASS_WARNING);
|
gtk_style_context_remove_class(style, GTK_STYLE_CLASS_WARNING);
|
||||||
else
|
else
|
||||||
gtk_style_context_add_class(style, GTK_STYLE_CLASS_WARNING);
|
gtk_style_context_add_class(style, GTK_STYLE_CLASS_WARNING);
|
||||||
|
|
||||||
GtkListStore *model = gtk_list_store_new(1, G_TYPE_STRING);
|
// XXX: For some reason, this jumps around with longer lists.
|
||||||
gtk_tree_sortable_set_sort_column_id(
|
|
||||||
GTK_TREE_SORTABLE(model), 0, GTK_SORT_ASCENDING);
|
|
||||||
if (!g_uri_is_valid(text, G_URI_FLAGS_PARSE_RELAXED, NULL))
|
|
||||||
complete_path(location, model);
|
|
||||||
|
|
||||||
// TODO(p): Try to make this not be as jumpy.
|
|
||||||
GtkEntryCompletion *completion = gtk_entry_get_completion(entry);
|
GtkEntryCompletion *completion = gtk_entry_get_completion(entry);
|
||||||
gtk_entry_completion_set_model(completion, NULL);
|
GtkTreeModel *model = gtk_entry_completion_get_model(completion);
|
||||||
gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(model));
|
gtk_list_store_clear(GTK_LIST_STORE(model));
|
||||||
gtk_entry_completion_set_text_column(completion, 0);
|
if (g_file_peek_path(location))
|
||||||
gtk_entry_completion_set_inline_completion(completion, TRUE);
|
complete_path(location, GTK_LIST_STORE(model));
|
||||||
gtk_entry_completion_set_match_func(
|
|
||||||
completion, (GtkEntryCompletionMatchFunc) gtk_true, NULL, NULL);
|
|
||||||
gtk_entry_completion_complete(completion);
|
|
||||||
g_object_unref(model);
|
|
||||||
|
|
||||||
g_object_unref(location);
|
g_object_unref(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,8 +277,18 @@ on_show_enter_location(G_GNUC_UNUSED GtkPlacesSidebar *sidebar,
|
||||||
GTK_DIALOG_USE_HEADER_BAR,
|
GTK_DIALOG_USE_HEADER_BAR,
|
||||||
"_Open", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);
|
"_Open", GTK_RESPONSE_ACCEPT, "_Cancel", GTK_RESPONSE_CANCEL, NULL);
|
||||||
|
|
||||||
GtkWidget *entry = gtk_entry_new();
|
GtkListStore *model = gtk_list_store_new(1, G_TYPE_STRING);
|
||||||
|
gtk_tree_sortable_set_sort_column_id(
|
||||||
|
GTK_TREE_SORTABLE(model), 0, GTK_SORT_ASCENDING);
|
||||||
|
|
||||||
GtkEntryCompletion *completion = gtk_entry_completion_new();
|
GtkEntryCompletion *completion = gtk_entry_completion_new();
|
||||||
|
gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(model));
|
||||||
|
gtk_entry_completion_set_text_column(completion, 0);
|
||||||
|
gtk_entry_completion_set_match_func(
|
||||||
|
completion, (GtkEntryCompletionMatchFunc) gtk_true, NULL, NULL);
|
||||||
|
g_object_unref(model);
|
||||||
|
|
||||||
|
GtkWidget *entry = gtk_entry_new();
|
||||||
gtk_entry_set_completion(GTK_ENTRY(entry), completion);
|
gtk_entry_set_completion(GTK_ENTRY(entry), completion);
|
||||||
gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
|
gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
|
||||||
g_signal_connect(entry, "changed",
|
g_signal_connect(entry, "changed",
|
||||||
|
@ -274,19 +298,21 @@ on_show_enter_location(G_GNUC_UNUSED GtkPlacesSidebar *sidebar,
|
||||||
gtk_container_add(GTK_CONTAINER(content), entry);
|
gtk_container_add(GTK_CONTAINER(content), entry);
|
||||||
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
|
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
|
||||||
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE);
|
gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE);
|
||||||
gtk_widget_show_all(dialog);
|
gtk_window_set_default_size(GTK_WINDOW(dialog), 800, -1);
|
||||||
|
|
||||||
GdkGeometry geometry = {.max_width = G_MAXSHORT, .max_height = -1};
|
GdkGeometry geometry = {.max_width = G_MAXSHORT, .max_height = -1};
|
||||||
gtk_window_set_geometry_hints(
|
gtk_window_set_geometry_hints(
|
||||||
GTK_WINDOW(dialog), NULL, &geometry, GDK_HINT_MAX_SIZE);
|
GTK_WINDOW(dialog), NULL, &geometry, GDK_HINT_MAX_SIZE);
|
||||||
|
gtk_widget_show_all(dialog);
|
||||||
|
|
||||||
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
||||||
const char *text = gtk_entry_get_text(GTK_ENTRY(entry));
|
const char *text = gtk_entry_get_text(GTK_ENTRY(entry));
|
||||||
GFile *location = g_file_parse_name(text);
|
GFile *location = resolve_location(self, text);
|
||||||
g_signal_emit(self, sidebar_signals[OPEN_LOCATION], 0, location);
|
g_signal_emit(self, sidebar_signals[OPEN_LOCATION], 0, location);
|
||||||
g_object_unref(location);
|
g_object_unref(location);
|
||||||
}
|
}
|
||||||
gtk_widget_destroy(dialog);
|
gtk_widget_destroy(dialog);
|
||||||
|
g_object_unref(completion);
|
||||||
|
|
||||||
// Deselect the item in GtkPlacesSidebar, if unsuccessful.
|
// Deselect the item in GtkPlacesSidebar, if unsuccessful.
|
||||||
update_location(self, NULL);
|
update_location(self, NULL);
|
||||||
|
|
Loading…
Reference in New Issue