Compare commits
4 Commits
b0de0e09bd
...
8fdf9e2bc3
Author | SHA1 | Date | |
---|---|---|---|
8fdf9e2bc3 | |||
235af37382 | |||
06ab13797d | |||
e70bb20934 |
@ -31,6 +31,7 @@ struct _FivSidebar {
|
||||
G_DEFINE_TYPE(FivSidebar, fiv_sidebar, GTK_TYPE_SCROLLED_WINDOW)
|
||||
|
||||
G_DEFINE_QUARK(fiv-sidebar-location-quark, fiv_sidebar_location)
|
||||
G_DEFINE_QUARK(fiv-sidebar-self-quark, fiv_sidebar_self)
|
||||
|
||||
enum {
|
||||
OPEN_LOCATION,
|
||||
@ -66,7 +67,7 @@ fiv_sidebar_class_init(FivSidebarClass *klass)
|
||||
|
||||
// TODO(p): Consider a return value, and using it.
|
||||
sidebar_signals[OPEN_LOCATION] =
|
||||
g_signal_new("open_location", G_TYPE_FROM_CLASS(klass), 0, 0,
|
||||
g_signal_new("open-location", G_TYPE_FROM_CLASS(klass), 0, 0,
|
||||
NULL, NULL, NULL, G_TYPE_NONE,
|
||||
2, G_TYPE_FILE, GTK_TYPE_PLACES_OPEN_FLAGS);
|
||||
}
|
||||
@ -84,10 +85,44 @@ on_rowlabel_query_tooltip(GtkWidget *widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_row(GFile *file, const char *icon_name)
|
||||
static gboolean
|
||||
on_breadcrumb_release(
|
||||
G_GNUC_UNUSED GtkWidget *widget, GdkEventButton *event, gpointer user_data)
|
||||
{
|
||||
// This also prevents unwanted primary button click handling in GtkListBox.
|
||||
if (event->x > gdk_window_get_width(event->window) ||
|
||||
event->y > gdk_window_get_height(event->window))
|
||||
return TRUE;
|
||||
|
||||
guint state = event->state & gtk_accelerator_get_default_mod_mask();
|
||||
if (event->button != GDK_BUTTON_MIDDLE || state != 0)
|
||||
return FALSE;
|
||||
|
||||
GtkListBoxRow *row = GTK_LIST_BOX_ROW(user_data);
|
||||
g_signal_emit(g_object_get_qdata(G_OBJECT(row), fiv_sidebar_self_quark()),
|
||||
sidebar_signals[OPEN_LOCATION], 0,
|
||||
g_object_get_qdata(G_OBJECT(row), fiv_sidebar_location_quark()),
|
||||
GTK_PLACES_OPEN_NEW_WINDOW);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_breadcrumb_drag_data_get(G_GNUC_UNUSED GtkWidget *widget,
|
||||
G_GNUC_UNUSED GdkDragContext *context, GtkSelectionData *selection_data,
|
||||
G_GNUC_UNUSED guint info, G_GNUC_UNUSED guint time_, gpointer user_data)
|
||||
{
|
||||
GtkListBoxRow *row = GTK_LIST_BOX_ROW(user_data);
|
||||
GFile *location =
|
||||
g_object_get_qdata(G_OBJECT(row), fiv_sidebar_location_quark());
|
||||
|
||||
gchar *uris[] = {g_file_get_uri(location), NULL};
|
||||
gtk_selection_data_set_uris(selection_data, uris);
|
||||
g_free(*uris);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_row(FivSidebar *self, GFile *file, const char *icon_name)
|
||||
{
|
||||
// TODO(p): Handle errors better.
|
||||
GError *error = NULL;
|
||||
GFileInfo *info =
|
||||
g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
|
||||
@ -116,16 +151,34 @@ create_row(GFile *file, const char *icon_name)
|
||||
gtk_widget_get_style_context(rowlabel), "sidebar-label");
|
||||
gtk_container_add(GTK_CONTAINER(rowbox), rowlabel);
|
||||
|
||||
// The revealer is primarily necessary to match Adwaita CSS rules,
|
||||
// but it conveniently also has its own GdkWindow to hook events on.
|
||||
GtkWidget *revealer = gtk_revealer_new();
|
||||
gtk_widget_add_events(
|
||||
revealer, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
|
||||
gtk_revealer_set_reveal_child(
|
||||
GTK_REVEALER(revealer), TRUE);
|
||||
gtk_revealer_set_transition_type(
|
||||
GTK_REVEALER(revealer), GTK_REVEALER_TRANSITION_TYPE_NONE);
|
||||
gtk_container_add(GTK_CONTAINER(revealer), rowbox);
|
||||
|
||||
GtkTargetList *target_list = gtk_target_list_new(NULL, 0);
|
||||
gtk_target_list_add_uri_targets(target_list, 0);
|
||||
gtk_drag_source_set(revealer, GDK_BUTTON1_MASK, NULL, 0, GDK_ACTION_LINK);
|
||||
gtk_drag_source_set_target_list(revealer, target_list);
|
||||
gtk_drag_source_set_icon_name(revealer, "inode-directory-symbolic");
|
||||
gtk_target_list_unref(target_list);
|
||||
|
||||
GtkWidget *row = gtk_list_box_row_new();
|
||||
g_object_set_qdata_full(G_OBJECT(row), fiv_sidebar_location_quark(),
|
||||
g_object_ref(file), (GDestroyNotify) g_object_unref);
|
||||
g_object_set_qdata_full(G_OBJECT(row), fiv_sidebar_self_quark(),
|
||||
g_object_ref(self), (GDestroyNotify) g_object_unref);
|
||||
g_signal_connect(revealer, "button-release-event",
|
||||
G_CALLBACK(on_breadcrumb_release), row);
|
||||
g_signal_connect(revealer, "drag-data-get",
|
||||
G_CALLBACK(on_breadcrumb_drag_data_get), row);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(row), revealer);
|
||||
gtk_widget_show_all(row);
|
||||
return row;
|
||||
@ -150,19 +203,19 @@ update_location(FivSidebar *self)
|
||||
if (!(iter = parent))
|
||||
break;
|
||||
|
||||
if ((row = create_row(parent, "go-up-symbolic")))
|
||||
if ((row = create_row(self, parent, "go-up-symbolic")))
|
||||
gtk_list_box_prepend(GTK_LIST_BOX(self->listbox), row);
|
||||
}
|
||||
|
||||
// Other options are "folder-{visiting,open}-symbolic", though the former
|
||||
// is mildly inappropriate (means: open in another window).
|
||||
if ((row = create_row(location, "circle-filled-symbolic")))
|
||||
if ((row = create_row(self, location, "circle-filled-symbolic")))
|
||||
gtk_container_add(GTK_CONTAINER(self->listbox), row);
|
||||
|
||||
GPtrArray *subdirs = fiv_io_model_get_subdirectories(self->model);
|
||||
for (guint i = 0; i < subdirs->len; i++) {
|
||||
GFile *file = g_file_new_for_uri(subdirs->pdata[i]);
|
||||
if ((row = create_row(file, "go-down-symbolic")))
|
||||
if ((row = create_row(self, file, "go-down-symbolic")))
|
||||
gtk_container_add(GTK_CONTAINER(self->listbox), row);
|
||||
g_object_unref(file);
|
||||
}
|
||||
@ -333,6 +386,8 @@ on_show_enter_location(
|
||||
g_free(label);
|
||||
|
||||
GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
|
||||
g_object_set(content, "margin", 5, NULL);
|
||||
gtk_box_set_spacing(GTK_BOX(content), 5);
|
||||
gtk_container_add(GTK_CONTAINER(content), entry);
|
||||
gtk_container_add(GTK_CONTAINER(content), protocols);
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
|
||||
|
13
fiv.c
13
fiv.c
@ -1406,12 +1406,16 @@ main(int argc, char *argv[])
|
||||
G_CALLBACK(on_button_press_view), NULL);
|
||||
gtk_container_add(GTK_CONTAINER(view_scroller), g.view);
|
||||
|
||||
// We need to hide it together with the separator.
|
||||
g.view_toolbar = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_box_pack_start(GTK_BOX(g.view_toolbar),
|
||||
make_view_toolbar(), FALSE, FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(g.view_toolbar),
|
||||
gtk_separator_new(GTK_ORIENTATION_VERTICAL), FALSE, FALSE, 0);
|
||||
|
||||
// Need to put the toolbar at the top, because of the horizontal scrollbar.
|
||||
g.view_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||
g.view_toolbar = make_view_toolbar();
|
||||
gtk_box_pack_start(GTK_BOX(g.view_box), g.view_toolbar, FALSE, FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(g.view_box),
|
||||
gtk_separator_new(GTK_ORIENTATION_VERTICAL), FALSE, FALSE, 0);
|
||||
gtk_box_pack_start(GTK_BOX(g.view_box), view_scroller, TRUE, TRUE, 0);
|
||||
|
||||
g.browser_scroller = gtk_scrolled_window_new(NULL, NULL);
|
||||
@ -1427,8 +1431,7 @@ main(int argc, char *argv[])
|
||||
gtk_container_set_focus_hadjustment(GTK_CONTAINER(browser_port), NULL);
|
||||
gtk_container_set_focus_vadjustment(GTK_CONTAINER(browser_port), NULL);
|
||||
|
||||
// TODO(p): As with GtkFileChooserWidget, bind C-h to filtering,
|
||||
// and mayhaps forward the rest to the sidebar, somehow.
|
||||
// TODO(p): Mayhaps forward some key presses to the sidebar, somehow.
|
||||
g.browser_sidebar = make_browser_sidebar(g.model);
|
||||
|
||||
g.browser_paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
|
||||
|
Loading…
x
Reference in New Issue
Block a user