aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2023-03-15 03:33:48 +0100
committerPřemysl Eric Janouch <p@janouch.name>2023-04-11 06:33:22 +0200
commit8da5f807cf8a64c06377f4868f39e84539cc39c8 (patch)
tree7e25320ba102562a193af05cfcfc527c46596f4f
parent1b50a834a5d6bb1584e261efd656c8153fcf41b8 (diff)
downloadfiv-8da5f807cf8a64c06377f4868f39e84539cc39c8.tar.gz
fiv-8da5f807cf8a64c06377f4868f39e84539cc39c8.tar.xz
fiv-8da5f807cf8a64c06377f4868f39e84539cc39c8.zip
Move and extend the browser toolbar
This makes the user interface more cohesive, and easier to use. Both toolbars should ideally be made configurable.
-rw-r--r--fiv-sidebar.c20
-rw-r--r--fiv-sidebar.h1
-rw-r--r--fiv.c328
-rw-r--r--fiv.gschema.xml4
-rw-r--r--resources/resources.gresource.xml1
-rw-r--r--resources/text-symbolic.svg150
6 files changed, 373 insertions, 131 deletions
diff --git a/fiv-sidebar.c b/fiv-sidebar.c
index fc63a99..f688720 100644
--- a/fiv-sidebar.c
+++ b/fiv-sidebar.c
@@ -25,7 +25,6 @@
struct _FivSidebar {
GtkScrolledWindow parent_instance;
GtkPlacesSidebar *places;
- GtkWidget *toolbar;
GtkWidget *listbox;
FivIoModel *model;
};
@@ -78,7 +77,7 @@ fiv_sidebar_class_init(FivSidebarClass *klass)
// You're giving me no choice, Adwaita.
// Your style is hardcoded to match against the class' CSS name.
- // And I need replicate the internal widget structure.
+ // And I need to replicate the internal widget structure.
gtk_widget_class_set_css_name(widget_class, "placessidebar");
// TODO(p): Consider a return value, and using it.
@@ -583,12 +582,6 @@ fiv_sidebar_init(FivSidebar *self)
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(self->places),
GTK_POLICY_NEVER, GTK_POLICY_NEVER);
- // None of GtkActionBar, GtkToolbar, .inline-toolbar is appropriate.
- // It is either side-favouring borders or excess button padding.
- self->toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 12);
- gtk_style_context_add_class(
- gtk_widget_get_style_context(self->toolbar), GTK_STYLE_CLASS_TOOLBAR);
-
self->listbox = gtk_list_box_new();
gtk_list_box_set_selection_mode(
GTK_LIST_BOX(self->listbox), GTK_SELECTION_NONE);
@@ -603,10 +596,6 @@ fiv_sidebar_init(FivSidebar *self)
gtk_container_add(
GTK_CONTAINER(superbox), gtk_separator_new(GTK_ORIENTATION_VERTICAL));
gtk_container_add(
- GTK_CONTAINER(superbox), self->toolbar);
- gtk_container_add(
- GTK_CONTAINER(superbox), gtk_separator_new(GTK_ORIENTATION_VERTICAL));
- gtk_container_add(
GTK_CONTAINER(superbox), self->listbox);
gtk_container_add(GTK_CONTAINER(self), superbox);
@@ -648,10 +637,3 @@ fiv_sidebar_show_enter_location(FivSidebar *self)
g_return_if_fail(FIV_IS_SIDEBAR(self));
g_signal_emit_by_name(self->places, "show-enter-location");
}
-
-GtkBox *
-fiv_sidebar_get_toolbar(FivSidebar *self)
-{
- g_return_val_if_fail(FIV_IS_SIDEBAR(self), NULL);
- return GTK_BOX(self->toolbar);
-}
diff --git a/fiv-sidebar.h b/fiv-sidebar.h
index 2d0888a..125119f 100644
--- a/fiv-sidebar.h
+++ b/fiv-sidebar.h
@@ -26,4 +26,3 @@ G_DECLARE_FINAL_TYPE(FivSidebar, fiv_sidebar, FIV, SIDEBAR, GtkScrolledWindow)
GtkWidget *fiv_sidebar_new(FivIoModel *model);
void fiv_sidebar_show_enter_location(FivSidebar *self);
-GtkBox *fiv_sidebar_get_toolbar(FivSidebar *self);
diff --git a/fiv.c b/fiv.c
index c26600d..475d40b 100644
--- a/fiv.c
+++ b/fiv.c
@@ -129,6 +129,7 @@ static struct key_group help_keys_browser[] = {
{}
}},
{"View", (struct key[]) {
+ {"F7", "Toggle toolbar"},
{"F9", "Toggle navigation sidebar"},
{"F5 r <Control>r", "Reload"},
{"h <Control>h", "Toggle hiding unsupported files"},
@@ -151,7 +152,7 @@ static struct key_group help_keys_viewer[] = {
{}
}},
{"View", (struct key[]) {
- {"F9", "Toggle toolbar"},
+ {"F7", "Toggle toolbar"},
{"F5 r <Primary>r", "Reload"},
{}
}},
@@ -524,6 +525,33 @@ show_about_dialog(GtkWidget *parent)
// by some minor amount of pixels, margin-wise.
#define B make_toolbar_button
#define T make_toolbar_toggle
+#define R make_toolbar_radio
+#define BROWSEBAR(XX) \
+ XX(SIDEBAR, T("sidebar-show-symbolic", "Show sidebar")) \
+ XX(S1, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)) \
+ XX(DIR_PREVIOUS, B("go-previous-symbolic", "Previous directory")) \
+ XX(DIR_NEXT, B("go-next-symbolic", "Next directory")) \
+ XX(S2, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)) \
+ XX(PLUS, B("zoom-in-symbolic", "Larger thumbnails")) \
+ XX(MINUS, B("zoom-out-symbolic", "Smaller thumbnails")) \
+ XX(S3, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)) \
+ XX(FILENAMES, T("text-symbolic", "Show filenames")) \
+ XX(FILTER, T("funnel-symbolic", "Hide unsupported files")) \
+ XX(S4, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)) \
+ XX(SORT_DIR, B("view-sort-ascending-symbolic", "Sort ascending")) \
+ XX(SORT_NAME, R("Name", "Sort by filename")) \
+ XX(SORT_TIME, R("Time", "Sort by time of last modification")) \
+ XX(S5, gtk_separator_new(GTK_ORIENTATION_HORIZONTAL)) \
+ /* We are YouTube. */ \
+ XX(FULLSCREEN, B("view-fullscreen-symbolic", "Fullscreen"))
+
+enum {
+#define XX(id, constructor) BROWSEBAR_ ## id,
+ BROWSEBAR(XX)
+#undef XX
+ BROWSEBAR_COUNT
+};
+
#define TOOLBAR(XX) \
XX(BROWSE, B("view-grid-symbolic", "Browse")) \
XX(FILE_PREVIOUS, B("go-previous-symbolic", "Previous file")) \
@@ -586,11 +614,8 @@ struct {
GtkWidget *browser_paned;
GtkWidget *browser_sidebar;
- GtkWidget *plus;
- GtkWidget *minus;
- GtkWidget *funnel;
- GtkWidget *sort_field[FIV_IO_MODEL_SORT_COUNT];
- GtkWidget *sort_direction[2];
+ GtkWidget *browser_toolbar;
+ GtkWidget *browsebar[BROWSEBAR_COUNT];
GtkWidget *browser_scroller;
GtkWidget *browser;
@@ -773,6 +798,13 @@ on_model_files_changed(FivIoModel *model, G_GNUC_UNUSED gpointer user_data)
}
static void
+on_sidebar_toggled(GtkToggleButton *button, G_GNUC_UNUSED gpointer user_data)
+{
+ gboolean active = gtk_toggle_button_get_active(button);
+ gtk_widget_set_visible(g.browser_sidebar, active);
+}
+
+static void
on_filtering_toggled(GtkToggleButton *button, G_GNUC_UNUSED gpointer user_data)
{
gboolean active = gtk_toggle_button_get_active(button);
@@ -780,8 +812,19 @@ on_filtering_toggled(GtkToggleButton *button, G_GNUC_UNUSED gpointer user_data)
}
static void
-on_sort_field(G_GNUC_UNUSED GtkMenuItem *item, gpointer data)
+on_filenames_toggled(GtkToggleButton *button, G_GNUC_UNUSED gpointer user_data)
+{
+ gboolean active = gtk_toggle_button_get_active(button);
+ g_object_set(g.browser, "show-labels", active, NULL);
+}
+
+static void
+on_sort_field(G_GNUC_UNUSED GtkToggleButton *button, gpointer data)
{
+ gboolean active = gtk_toggle_button_get_active(button);
+ if (!active)
+ return;
+
int old = -1, new = (int) (intptr_t) data;
g_object_get(g.model, "sort-field", &old, NULL);
if (old != new)
@@ -789,12 +832,12 @@ on_sort_field(G_GNUC_UNUSED GtkMenuItem *item, gpointer data)
}
static void
-on_sort_direction(G_GNUC_UNUSED GtkMenuItem *item, gpointer data)
+on_sort_direction(G_GNUC_UNUSED GtkToggleButton *button,
+ G_GNUC_UNUSED gpointer data)
{
- gboolean old = FALSE, new = (gboolean) (intptr_t) data;
+ gboolean old = FALSE;
g_object_get(g.model, "sort-descending", &old, NULL);
- if (old != new)
- g_object_set(g.model, "sort-descending", new, NULL);
+ g_object_set(g.model, "sort-descending", !old, NULL);
}
static void
@@ -1092,6 +1135,16 @@ on_view_drag_data_received(G_GNUC_UNUSED GtkWidget *widget,
}
static void
+on_notify_sidebar_visible(
+ GObject *object, GParamSpec *param_spec, G_GNUC_UNUSED gpointer user_data)
+{
+ gboolean b = FALSE;
+ g_object_get(object, g_param_spec_get_name(param_spec), &b, NULL);
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(g.browsebar[BROWSEBAR_SIDEBAR]), b);
+}
+
+static void
on_dir_previous(void)
{
GFile *directory = fiv_io_model_get_previous_directory(g.model);
@@ -1116,14 +1169,6 @@ on_dir_next(void)
}
static void
-on_toggle_labels(void)
-{
- gboolean old = FALSE;
- g_object_get(g.browser, "show-labels", &old, NULL);
- g_object_set(g.browser, "show-labels", !old, NULL);
-}
-
-static void
on_toolbar_zoom(G_GNUC_UNUSED GtkButton *button, gpointer user_data)
{
FivThumbnailSize size = FIV_THUMBNAIL_SIZE_COUNT;
@@ -1142,8 +1187,20 @@ on_notify_thumbnail_size(
{
FivThumbnailSize size = 0;
g_object_get(object, g_param_spec_get_name(param_spec), &size, NULL);
- gtk_widget_set_sensitive(g.plus, size < FIV_THUMBNAIL_SIZE_MAX);
- gtk_widget_set_sensitive(g.minus, size > FIV_THUMBNAIL_SIZE_MIN);
+ gtk_widget_set_sensitive(
+ g.browsebar[BROWSEBAR_PLUS], size < FIV_THUMBNAIL_SIZE_MAX);
+ gtk_widget_set_sensitive(
+ g.browsebar[BROWSEBAR_MINUS], size > FIV_THUMBNAIL_SIZE_MIN);
+}
+
+static void
+on_notify_show_labels(
+ GObject *object, GParamSpec *param_spec, G_GNUC_UNUSED gpointer user_data)
+{
+ gboolean show_labels = 0;
+ g_object_get(object, g_param_spec_get_name(param_spec), &show_labels, NULL);
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(g.browsebar[BROWSEBAR_FILENAMES]), show_labels);
}
static void
@@ -1152,7 +1209,8 @@ on_notify_filtering(
{
gboolean b = FALSE;
g_object_get(object, g_param_spec_get_name(param_spec), &b, NULL);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g.funnel), b);
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(g.browsebar[BROWSEBAR_FILTER]), b);
}
static void
@@ -1161,8 +1219,8 @@ on_notify_sort_field(
{
gint field = -1;
g_object_get(object, g_param_spec_get_name(param_spec), &field, NULL);
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(g.sort_field[field]), TRUE);
+ gtk_toggle_button_set_active(
+ GTK_TOGGLE_BUTTON(g.browsebar[BROWSEBAR_SORT_NAME + field]), TRUE);
}
static void
@@ -1171,8 +1229,18 @@ on_notify_sort_descending(
{
gboolean b = FALSE;
g_object_get(object, g_param_spec_get_name(param_spec), &b, NULL);
- gtk_check_menu_item_set_active(
- GTK_CHECK_MENU_ITEM(g.sort_direction[b]), TRUE);
+
+ const char *title = b
+ ? "Sort ascending"
+ : "Sort descending";
+ const char *name = b
+ ? "view-sort-ascending-symbolic"
+ : "view-sort-descending-symbolic";
+
+ GtkButton *button = GTK_BUTTON(g.browsebar[BROWSEBAR_SORT_DIR]);
+ GtkImage *image = GTK_IMAGE(gtk_button_get_image(button));
+ gtk_widget_set_tooltip_text(GTK_WIDGET(button), title);
+ gtk_image_set_from_icon_name(image, name, GTK_ICON_SIZE_BUTTON);
}
static void
@@ -1196,9 +1264,14 @@ on_window_state_event(G_GNUC_UNUSED GtkWidget *widget,
? "view-restore-symbolic"
: "view-fullscreen-symbolic";
- GtkButton *button = GTK_BUTTON(g.toolbar[TOOLBAR_FULLSCREEN]);
- GtkImage *image = GTK_IMAGE(gtk_button_get_image(button));
- gtk_image_set_from_icon_name(image, name, GTK_ICON_SIZE_BUTTON);
+ gtk_image_set_from_icon_name(
+ GTK_IMAGE(gtk_button_get_image(
+ GTK_BUTTON(g.toolbar[TOOLBAR_FULLSCREEN]))),
+ name, GTK_ICON_SIZE_BUTTON);
+ gtk_image_set_from_icon_name(
+ GTK_IMAGE(gtk_button_get_image(
+ GTK_BUTTON(g.browsebar[BROWSEBAR_FULLSCREEN]))),
+ name, GTK_ICON_SIZE_BUTTON);
}
static void
@@ -1296,7 +1369,7 @@ on_key_press(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
case GDK_CONTROL_MASK | GDK_SHIFT_MASK:
switch (event->keyval) {
case GDK_KEY_h:
- gtk_button_clicked(GTK_BUTTON(g.funnel));
+ gtk_button_clicked(GTK_BUTTON(g.browsebar[BROWSEBAR_FILTER]));
return TRUE;
case GDK_KEY_l:
fiv_sidebar_show_enter_location(FIV_SIDEBAR(g.browser_sidebar));
@@ -1393,7 +1466,7 @@ on_key_press_view(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
switch (event->state & gtk_accelerator_get_default_mod_mask()) {
case 0:
switch (event->keyval) {
- case GDK_KEY_F9:
+ case GDK_KEY_F7:
gtk_widget_set_visible(g.view_toolbar,
!gtk_widget_is_visible(g.view_toolbar));
return TRUE;
@@ -1431,7 +1504,7 @@ on_key_press_browser_paned(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
load_directory(NULL);
return TRUE;
case GDK_KEY_t:
- on_toggle_labels();
+ gtk_button_clicked(GTK_BUTTON(g.browsebar[BROWSEBAR_FILENAMES]));
return TRUE;
}
break;
@@ -1455,6 +1528,10 @@ on_key_press_browser_paned(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
break;
case 0:
switch (event->keyval) {
+ case GDK_KEY_F7:
+ gtk_widget_set_visible(g.browser_toolbar,
+ !gtk_widget_is_visible(g.browser_toolbar));
+ return TRUE;
case GDK_KEY_F9:
gtk_widget_set_visible(g.browser_sidebar,
!gtk_widget_is_visible(g.browser_sidebar));
@@ -1471,14 +1548,14 @@ on_key_press_browser_paned(G_GNUC_UNUSED GtkWidget *widget, GdkEventKey *event,
fiv_browser_select(FIV_BROWSER(g.browser), NULL);
return TRUE;
case GDK_KEY_h:
- gtk_button_clicked(GTK_BUTTON(g.funnel));
+ gtk_button_clicked(GTK_BUTTON(g.browsebar[BROWSEBAR_FILTER]));
return TRUE;
case GDK_KEY_F5:
case GDK_KEY_r:
load_directory(NULL);
return TRUE;
case GDK_KEY_t:
- on_toggle_labels();
+ gtk_button_clicked(GTK_BUTTON(g.browsebar[BROWSEBAR_FILENAMES]));
return TRUE;
}
}
@@ -1558,6 +1635,79 @@ make_toolbar_toggle(const char *symbolic, const char *tooltip)
return button;
}
+static GtkWidget *
+make_toolbar_radio(const char *label, const char *tooltip)
+{
+ GtkWidget *button = gtk_radio_button_new_with_label(NULL, label);
+ gtk_widget_set_tooltip_text(button, tooltip);
+ gtk_widget_set_focus_on_click(button, FALSE);
+ return button;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+static void
+browsebar_connect(int index, GCallback callback)
+{
+ g_signal_connect_swapped(g.browsebar[index], "clicked", callback, NULL);
+}
+
+static GtkWidget *
+make_browser_toolbar(void)
+{
+#define XX(id, constructor) g.browsebar[BROWSEBAR_ ## id] = constructor;
+ BROWSEBAR(XX)
+#undef XX
+
+ // GtkStatusBar solves a problem we do not have here.
+ GtkWidget *browser_toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_style_context_add_class(
+ gtk_widget_get_style_context(browser_toolbar), "fiv-toolbar");
+ GtkBox *box = GTK_BOX(browser_toolbar);
+
+ // Exploring different versions of awkward layouts.
+ for (int i = 0; i <= BROWSEBAR_S2; i++)
+ gtk_box_pack_start(box, g.browsebar[i], FALSE, FALSE, 0);
+ for (int i = BROWSEBAR_COUNT; --i >= BROWSEBAR_S5; )
+ gtk_box_pack_end(box, g.browsebar[i], FALSE, FALSE, 0);
+
+ GtkWidget *center = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ for (int i = BROWSEBAR_S2; ++i < BROWSEBAR_S5; )
+ gtk_box_pack_start(GTK_BOX(center), g.browsebar[i], FALSE, FALSE, 0);
+ gtk_box_set_center_widget(box, center);
+
+ g_signal_connect(g.browsebar[BROWSEBAR_SIDEBAR], "toggled",
+ G_CALLBACK(on_sidebar_toggled), NULL);
+
+ browsebar_connect(BROWSEBAR_DIR_PREVIOUS, G_CALLBACK(on_dir_previous));
+ browsebar_connect(BROWSEBAR_DIR_NEXT, G_CALLBACK(on_dir_next));
+ browsebar_connect(BROWSEBAR_SORT_DIR, G_CALLBACK(on_sort_direction));
+ browsebar_connect(BROWSEBAR_FULLSCREEN, G_CALLBACK(toggle_fullscreen));
+
+ g_signal_connect(g.browsebar[BROWSEBAR_PLUS], "clicked",
+ G_CALLBACK(on_toolbar_zoom), (gpointer) +1);
+ g_signal_connect(g.browsebar[BROWSEBAR_MINUS], "clicked",
+ G_CALLBACK(on_toolbar_zoom), (gpointer) -1);
+
+ g_signal_connect(g.browsebar[BROWSEBAR_FILTER], "toggled",
+ G_CALLBACK(on_filtering_toggled), NULL);
+ g_signal_connect(g.browsebar[BROWSEBAR_FILENAMES], "toggled",
+ G_CALLBACK(on_filenames_toggled), NULL);
+
+ GtkRadioButton *last = GTK_RADIO_BUTTON(g.browsebar[BROWSEBAR_SORT_NAME]);
+ for (int i = BROWSEBAR_SORT_NAME; i <= BROWSEBAR_SORT_TIME; i++) {
+ GtkRadioButton *radio = GTK_RADIO_BUTTON(g.browsebar[i]);
+ g_signal_connect(radio, "toggled", G_CALLBACK(on_sort_field),
+ (gpointer) (gintptr) i - BROWSEBAR_SORT_NAME);
+ gtk_radio_button_join_group(radio, last);
+ last = radio;
+ }
+
+ return browser_toolbar;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
static void
on_view_actions_changed(void)
{
@@ -1703,7 +1853,8 @@ make_view_toolbar(void)
// GtkStatusBar solves a problem we do not have here.
GtkWidget *view_toolbar = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_set_name(view_toolbar, "toolbar");
+ gtk_style_context_add_class(
+ gtk_widget_get_style_context(view_toolbar), "fiv-toolbar");
GtkBox *box = GTK_BOX(view_toolbar);
// Exploring different versions of awkward layouts.
@@ -1794,86 +1945,27 @@ make_browser_sidebar(FivIoModel *model)
g_signal_connect(sidebar, "open-location",
G_CALLBACK(on_open_location), NULL);
- g.plus = gtk_button_new_from_icon_name("zoom-in-symbolic",
- GTK_ICON_SIZE_BUTTON);
- gtk_widget_set_tooltip_text(g.plus, "Larger thumbnails");
- g_signal_connect(g.plus, "clicked",
- G_CALLBACK(on_toolbar_zoom), (gpointer) +1);
+ g_signal_connect(sidebar, "notify::visible",
+ G_CALLBACK(on_notify_sidebar_visible), NULL);
- g.minus = gtk_button_new_from_icon_name("zoom-out-symbolic",
- GTK_ICON_SIZE_BUTTON);
- gtk_widget_set_tooltip_text(g.minus, "Smaller thumbnails");
- g_signal_connect(g.minus, "clicked",
- G_CALLBACK(on_toolbar_zoom), (gpointer) -1);
-
- GtkWidget *zoom_group = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_style_context_add_class(
- gtk_widget_get_style_context(zoom_group), GTK_STYLE_CLASS_LINKED);
- gtk_box_pack_start(GTK_BOX(zoom_group), g.plus, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(zoom_group), g.minus, FALSE, FALSE, 0);
-
- g.funnel = gtk_toggle_button_new();
- gtk_container_add(GTK_CONTAINER(g.funnel),
- gtk_image_new_from_icon_name("funnel-symbolic", GTK_ICON_SIZE_BUTTON));
- gtk_widget_set_tooltip_text(g.funnel, "Hide unsupported files");
- g_signal_connect(g.funnel, "toggled",
- G_CALLBACK(on_filtering_toggled), NULL);
-
- GtkWidget *menu = gtk_menu_new();
- g.sort_field[0] = gtk_radio_menu_item_new_with_mnemonic(NULL, "By _Name");
- g.sort_field[1] = gtk_radio_menu_item_new_with_mnemonic(
- gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(g.sort_field[0])),
- "By _Modification Time");
- for (int i = FIV_IO_MODEL_SORT_MIN; i <= FIV_IO_MODEL_SORT_MAX; i++) {
- g_signal_connect(g.sort_field[i], "activate",
- G_CALLBACK(on_sort_field), (void *) (intptr_t) i);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), g.sort_field[i]);
- }
-
- g.sort_direction[0] =
- gtk_radio_menu_item_new_with_mnemonic(NULL, "_Ascending");
- g.sort_direction[1] = gtk_radio_menu_item_new_with_mnemonic(
- gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(g.sort_direction[0])),
- "_Descending");
- g_signal_connect(g.sort_direction[0], "activate",
- G_CALLBACK(on_sort_direction), (void *) 0);
- g_signal_connect(g.sort_direction[1], "activate",
- G_CALLBACK(on_sort_direction), (void *) 1);
-
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), g.sort_direction[0]);
- gtk_menu_shell_append(GTK_MENU_SHELL(menu), g.sort_direction[1]);
- gtk_widget_show_all(menu);
-
- GtkWidget *sort = gtk_menu_button_new();
- gtk_widget_set_tooltip_text(sort, "Sort order");
- gtk_button_set_image(GTK_BUTTON(sort),
- gtk_image_new_from_icon_name(
- "view-sort-ascending-symbolic", GTK_ICON_SIZE_BUTTON));
- gtk_menu_button_set_popup(GTK_MENU_BUTTON(sort), menu);
-
- GtkWidget *model_group = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_style_context_add_class(
- gtk_widget_get_style_context(model_group), GTK_STYLE_CLASS_LINKED);
- gtk_box_pack_start(GTK_BOX(model_group), g.funnel, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(model_group), sort, FALSE, FALSE, 0);
-
- GtkBox *toolbar = fiv_sidebar_get_toolbar(FIV_SIDEBAR(sidebar));
- gtk_box_pack_start(toolbar, zoom_group, FALSE, FALSE, 0);
- gtk_box_pack_start(toolbar, model_group, FALSE, FALSE, 0);
- gtk_widget_set_halign(GTK_WIDGET(toolbar), GTK_ALIGN_CENTER);
+ g_object_notify(G_OBJECT(sidebar), "visible");
g_signal_connect(g.browser, "notify::thumbnail-size",
G_CALLBACK(on_notify_thumbnail_size), NULL);
+ g_signal_connect(g.browser, "notify::show-labels",
+ G_CALLBACK(on_notify_show_labels), NULL);
g_signal_connect(model, "notify::filtering",
G_CALLBACK(on_notify_filtering), NULL);
g_signal_connect(model, "notify::sort-field",
G_CALLBACK(on_notify_sort_field), NULL);
g_signal_connect(model, "notify::sort-descending",
G_CALLBACK(on_notify_sort_descending), NULL);
+
on_toolbar_zoom(NULL, (gpointer) 0);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g.funnel), TRUE);
- // TODO(p): Invoke sort configuration notifications explicitly.
+
+ g_object_notify(G_OBJECT(g.model), "filtering");
+ g_object_notify(G_OBJECT(g.model), "sort-field");
+ g_object_notify(G_OBJECT(g.model), "sort-descending");
return sidebar;
}
@@ -1926,12 +2018,11 @@ static const char stylesheet[] = "@define-color fiv-tile @content_view_bg; \
@define-color fiv-semiselected \
mix(@theme_selected_bg_color, @content_view_bg, 0.5); \
fiv-view, fiv-browser { background: @content_view_bg; } \
- placessidebar.fiv .toolbar { padding: 2px 6px; } \
placessidebar.fiv box > separator { margin: 4px 0; } \
- #toolbar button { padding-left: 0; padding-right: 0; } \
- #toolbar > button:first-child { padding-left: 4px; } \
- #toolbar > button:last-child { padding-right: 4px; } \
- #toolbar separator { \
+ .fiv-toolbar button { padding-left: 0; padding-right: 0; } \
+ .fiv-toolbar > button:first-child { padding-left: 4px; } \
+ .fiv-toolbar > button:last-child { padding-right: 4px; } \
+ .fiv-toolbar separator { \
background: mix(@insensitive_fg_color, \
@insensitive_bg_color, 0.4); margin: 6px 8px; \
} \
@@ -2161,7 +2252,7 @@ main(int argc, char *argv[])
G_CALLBACK(on_view_drag_data_received), NULL);
gtk_container_add(GTK_CONTAINER(view_scroller), g.view);
- // We need to hide it together with the separator.
+ // We need to hide it together with its 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);
@@ -2201,10 +2292,23 @@ main(int argc, char *argv[])
G_CALLBACK(on_item_activated), NULL);
gtk_container_add(GTK_CONTAINER(g.browser_scroller), g.browser);
+ // We need to hide it together with its separator.
+ g.browser_toolbar = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_pack_start(GTK_BOX(g.browser_toolbar),
+ make_browser_toolbar(), FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(g.browser_toolbar),
+ gtk_separator_new(GTK_ORIENTATION_VERTICAL), FALSE, FALSE, 0);
+
+ GtkWidget *browser_right = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_box_pack_start(GTK_BOX(browser_right),
+ g.browser_toolbar, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(browser_right),
+ g.browser_scroller, TRUE, TRUE, 0);
+
g.browser_sidebar = make_browser_sidebar(g.model);
g.browser_paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
gtk_paned_add1(GTK_PANED(g.browser_paned), g.browser_sidebar);
- gtk_paned_add2(GTK_PANED(g.browser_paned), g.browser_scroller);
+ gtk_paned_add2(GTK_PANED(g.browser_paned), browser_right);
g_signal_connect(g.browser_paned, "key-press-event",
G_CALLBACK(on_key_press_browser_paned), NULL);
g_signal_connect(g.browser_paned, "button-press-event",
@@ -2238,6 +2342,8 @@ main(int argc, char *argv[])
gtk_widget_show_all(menu_box);
gtk_widget_set_visible(g.browser_sidebar,
g_settings_get_boolean(settings, "show-browser-sidebar"));
+ gtk_widget_set_visible(g.browser_toolbar,
+ g_settings_get_boolean(settings, "show-browser-toolbar"));
gtk_widget_set_visible(g.view_toolbar,
g_settings_get_boolean(settings, "show-view-toolbar"));
diff --git a/fiv.gschema.xml b/fiv.gschema.xml
index a0b9aab..b399a8f 100644
--- a/fiv.gschema.xml
+++ b/fiv.gschema.xml
@@ -25,6 +25,10 @@
<default>true</default>
<summary>Show the browser's sidebar</summary>
</key>
+ <key name='show-browser-toolbar' type='b'>
+ <default>true</default>
+ <summary>Show a toolbar in the browser view</summary>
+ </key>
<key name='show-view-toolbar' type='b'>
<default>true</default>
<summary>Show a toolbar in the image view</summary>
diff --git a/resources/resources.gresource.xml b/resources/resources.gresource.xml
index b3d6b1c..bfa368e 100644
--- a/resources/resources.gresource.xml
+++ b/resources/resources.gresource.xml
@@ -4,6 +4,7 @@
<file alias="LICENSE">../LICENSE</file>
</gresource>
<gresource prefix="/org/gnome/design/IconLibrary/scalable/actions/">
+ <file preprocess="xml-stripblanks">text-symbolic.svg</file>
<file preprocess="xml-stripblanks">circle-filled-symbolic.svg</file>
<file preprocess="xml-stripblanks">funnel-symbolic.svg</file>
<file preprocess="xml-stripblanks">blend-tool-symbolic.svg</file>
diff --git a/resources/text-symbolic.svg b/resources/text-symbolic.svg
new file mode 100644
index 0000000..6528635
--- /dev/null
+++ b/resources/text-symbolic.svg
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg height="16px" viewBox="0 0 16 16" width="16px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <filter id="a" height="100%" width="100%" x="0%" y="0%">
+ <feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
+ </filter>
+ <mask id="b">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/>
+ </g>
+ </mask>
+ <clipPath id="c">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="d">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
+ </g>
+ </mask>
+ <clipPath id="e">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="f">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
+ </g>
+ </mask>
+ <clipPath id="g">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="h">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
+ </g>
+ </mask>
+ <clipPath id="i">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="j">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
+ </g>
+ </mask>
+ <clipPath id="k">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="l">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
+ </g>
+ </mask>
+ <clipPath id="m">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="n">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.05"/>
+ </g>
+ </mask>
+ <clipPath id="o">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="p">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.3"/>
+ </g>
+ </mask>
+ <clipPath id="q">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="r">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.5"/>
+ </g>
+ </mask>
+ <clipPath id="s">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="t">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.4"/>
+ </g>
+ </mask>
+ <clipPath id="u">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="v">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.4"/>
+ </g>
+ </mask>
+ <clipPath id="w">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="x">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.5"/>
+ </g>
+ </mask>
+ <clipPath id="y">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <mask id="z">
+ <g filter="url(#a)">
+ <path d="m 0 0 h 16 v 16 h -16 z" fill-opacity="0.5"/>
+ </g>
+ </mask>
+ <clipPath id="A">
+ <path d="m 0 0 h 1024 v 800 h -1024 z"/>
+ </clipPath>
+ <g clip-path="url(#c)" mask="url(#b)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 562.460938 212.058594 h 10.449218 c -1.183594 0.492187 -1.296875 2.460937 0 3 h -10.449218 z m 0 0" fill="#2e3436"/>
+ </g>
+ <g clip-path="url(#e)" mask="url(#d)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 16 632 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
+ </g>
+ <g clip-path="url(#g)" mask="url(#f)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 17 631 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
+ </g>
+ <g clip-path="url(#i)" mask="url(#h)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 18 634 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
+ </g>
+ <g clip-path="url(#k)" mask="url(#j)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 16 634 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
+ </g>
+ <g clip-path="url(#m)" mask="url(#l)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 17 635 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
+ </g>
+ <g clip-path="url(#o)" mask="url(#n)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 19 635 h 1 v 1 h -1 z m 0 0" fill="#2e3436" fill-rule="evenodd"/>
+ </g>
+ <path d="m 6 1 l -5 14 h 3 c 1.484375 -4 0.023438 0 1.507812 -4 h 4.984376 l 1.507812 4 h 3 l -5 -14 z m 2 3 l 2.023438 5 h -4 z m 0 0" fill="#2e3436"/>
+ <g clip-path="url(#q)" mask="url(#p)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 136 660 v 7 h 7 v -7 z m 0 0" fill="#2e3436"/>
+ </g>
+ <g clip-path="url(#s)" mask="url(#r)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 199 642 h 3 v 12 h -3 z m 0 0" fill="#2e3436"/>
+ </g>
+ <g clip-path="url(#u)" mask="url(#t)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 209.5 144.160156 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 s -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 0 0" fill="#2e3436"/>
+ </g>
+ <g clip-path="url(#w)" mask="url(#v)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 206.5 144.160156 c 0.277344 0 0.5 0.222656 0.5 0.5 v 1 c 0 0.277344 -0.222656 0.5 -0.5 0.5 s -0.5 -0.222656 -0.5 -0.5 v -1 c 0 -0.277344 0.222656 -0.5 0.5 -0.5 z m 0 0" fill="#2e3436"/>
+ </g>
+ <g clip-path="url(#y)" mask="url(#x)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 229.5 143.160156 c -0.546875 0 -1 0.457032 -1 1 c 0 0.546875 0.453125 1 1 1 s 1 -0.453125 1 -1 c 0 -0.542968 -0.453125 -1 -1 -1 z m 0 0" fill="#2e3436"/>
+ </g>
+ <g clip-path="url(#A)" mask="url(#z)" transform="matrix(1 0 0 1 -56 -640)">
+ <path d="m 226.453125 143.160156 c -0.519531 0 -0.953125 0.433594 -0.953125 0.953125 v 0.09375 c 0 0.519531 0.433594 0.953125 0.953125 0.953125 h 0.09375 c 0.519531 0 0.953125 -0.433594 0.953125 -0.953125 v -0.09375 c 0 -0.519531 -0.433594 -0.953125 -0.953125 -0.953125 z m 0 0" fill="#2e3436"/>
+ </g>
+</svg>