[nautilus/wip/cdavis/toolbar-refactor: 4/7] general: Refactor toolbar children into ToolbarStart and ToolbarEnd
- From: Christopher Davis <christopherdavis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/cdavis/toolbar-refactor: 4/7] general: Refactor toolbar children into ToolbarStart and ToolbarEnd
- Date: Sat, 23 Jul 2022 04:03:39 +0000 (UTC)
commit f106ab06afe4999077ca602a6f7f06a6d68a0c78
Author: Christopher Davis <christopherdavis gnome org>
Date: Wed Jul 20 21:31:46 2022 -0400
general: Refactor toolbar children into ToolbarStart and ToolbarEnd
We need to use the children from the header bar in multiple places,
but we don't want to duplicate the code or the logic. Thus, we should
encapsulate the code and logic we need into distinct reusable components:
NautilusToolbarStart and NautilusToolbarEnd.
These components update their state properly when the window slot
changes without needing to call any functions ourselves.
src/meson.build | 4 +
src/nautilus-toolbar-end.c | 696 +++++++++++++++++++++++++++
src/nautilus-toolbar-end.h | 37 ++
src/nautilus-toolbar-start.c | 317 +++++++++++++
src/nautilus-toolbar-start.h | 37 ++
src/nautilus-toolbar.c | 731 +----------------------------
src/resources/nautilus.gresource.xml | 2 +
src/resources/ui/nautilus-toolbar-end.ui | 101 ++++
src/resources/ui/nautilus-toolbar-start.ui | 35 ++
src/resources/ui/nautilus-toolbar.ui | 117 +----
10 files changed, 1239 insertions(+), 838 deletions(-)
---
diff --git a/src/meson.build b/src/meson.build
index e76fe7c25..1b8ee673e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -124,7 +124,11 @@ libnautilus_sources = [
'nautilus-star-cell.h',
'nautilus-toolbar.c',
'nautilus-toolbar.h',
+ 'nautilus-toolbar-end.c',
+ 'nautilus-toolbar-end.h',
'nautilus-toolbar-menu-sections.h',
+ 'nautilus-toolbar-start.c',
+ 'nautilus-toolbar-start.h',
'nautilus-trash-bar.c',
'nautilus-trash-bar.h',
'nautilus-view.c',
diff --git a/src/nautilus-toolbar-end.c b/src/nautilus-toolbar-end.c
new file mode 100644
index 000000000..4e481963d
--- /dev/null
+++ b/src/nautilus-toolbar-end.c
@@ -0,0 +1,696 @@
+/* nautilus-toolbar-end.c
+ *
+ * Copyright 2022 Christopher Davis <christopherdavis gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "nautilus-toolbar-end.h"
+
+#include "nautilus-file-operations.h"
+#include "nautilus-progress-info-manager.h"
+#include "nautilus-progress-info-widget.h"
+#include "nautilus-toolbar-menu-sections.h"
+#include "nautilus-window.h"
+
+#define OPERATION_MINIMUM_TIME 2 /*s */
+#define NEEDS_ATTENTION_ANIMATION_TIMEOUT 2000 /*ms */
+#define REMOVE_FINISHED_OPERATIONS_TIEMOUT 3 /*s */
+
+struct _NautilusToolbarEnd
+{
+ AdwBin parent_instance;
+
+ guint start_operations_timeout_id;
+ guint remove_finished_operations_timeout_id;
+ guint operations_button_attention_timeout_id;
+
+ GtkWidget *operations_button;
+ GtkWidget *operations_popover;
+ GtkWidget *operations_list;
+ GListStore *progress_infos_model;
+ GtkWidget *operations_revealer;
+ GtkWidget *operations_icon;
+
+ GtkWidget *view_split_button;
+ GMenuModel *view_menu;
+
+ NautilusProgressInfoManager *progress_manager;
+
+ NautilusWindowSlot *window_slot;
+};
+
+G_DEFINE_FINAL_TYPE (NautilusToolbarEnd, nautilus_toolbar_end, ADW_TYPE_BIN);
+
+
+static void update_operations (NautilusToolbarEnd *self);
+
+enum {
+ PROP_0,
+ PROP_WINDOW_SLOT,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+
+static gboolean
+should_show_progress_info (NautilusProgressInfo *info)
+{
+ return nautilus_progress_info_get_total_elapsed_time (info) +
+ nautilus_progress_info_get_remaining_time (info) > OPERATION_MINIMUM_TIME;
+}
+
+static GList *
+get_filtered_progress_infos (NautilusToolbarEnd *self)
+{
+ GList *l;
+ GList *filtered_progress_infos;
+ GList *progress_infos;
+
+ progress_infos = nautilus_progress_info_manager_get_all_infos (self->progress_manager);
+ filtered_progress_infos = NULL;
+
+ for (l = progress_infos; l != NULL; l = l->next)
+ {
+ if (should_show_progress_info (l->data))
+ {
+ filtered_progress_infos = g_list_append (filtered_progress_infos, l->data);
+ }
+ }
+
+ return filtered_progress_infos;
+}
+
+static gboolean
+should_hide_operations_button (NautilusToolbarEnd *self)
+{
+ GList *progress_infos;
+ GList *l;
+
+ progress_infos = get_filtered_progress_infos (self);
+
+ for (l = progress_infos; l != NULL; l = l->next)
+ {
+ if (nautilus_progress_info_get_total_elapsed_time (l->data) +
+ nautilus_progress_info_get_remaining_time (l->data) > OPERATION_MINIMUM_TIME &&
+ !nautilus_progress_info_get_is_cancelled (l->data) &&
+ !nautilus_progress_info_get_is_finished (l->data))
+ {
+ return FALSE;
+ }
+ }
+
+ g_list_free (progress_infos);
+
+ return TRUE;
+}
+
+static gboolean
+on_remove_finished_operations_timeout (NautilusToolbarEnd *self)
+{
+ nautilus_progress_info_manager_remove_finished_or_cancelled_infos (self->progress_manager);
+ if (should_hide_operations_button (self))
+ {
+ gtk_revealer_set_reveal_child (GTK_REVEALER (self->operations_revealer),
+ FALSE);
+ }
+ else
+ {
+ update_operations (self);
+ }
+
+ self->remove_finished_operations_timeout_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+unschedule_remove_finished_operations (NautilusToolbarEnd *self)
+{
+ if (self->remove_finished_operations_timeout_id != 0)
+ {
+ g_source_remove (self->remove_finished_operations_timeout_id);
+ self->remove_finished_operations_timeout_id = 0;
+ }
+}
+
+static void
+schedule_remove_finished_operations (NautilusToolbarEnd *self)
+{
+ if (self->remove_finished_operations_timeout_id == 0)
+ {
+ self->remove_finished_operations_timeout_id =
+ g_timeout_add_seconds (REMOVE_FINISHED_OPERATIONS_TIEMOUT,
+ (GSourceFunc) on_remove_finished_operations_timeout,
+ self);
+ }
+}
+
+static void
+remove_operations_button_attention_style (NautilusToolbarEnd *self)
+{
+ gtk_widget_remove_css_class (self->operations_button,
+ "nautilus-operations-button-needs-attention");
+}
+
+static gboolean
+on_remove_operations_button_attention_style_timeout (NautilusToolbarEnd *self)
+{
+ remove_operations_button_attention_style (self);
+ self->operations_button_attention_timeout_id = 0;
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+unschedule_operations_button_attention_style (NautilusToolbarEnd *self)
+{
+ if (self->operations_button_attention_timeout_id != 0)
+ {
+ g_source_remove (self->operations_button_attention_timeout_id);
+ self->operations_button_attention_timeout_id = 0;
+ }
+}
+
+static void
+add_operations_button_attention_style (NautilusToolbarEnd *self)
+{
+ unschedule_operations_button_attention_style (self);
+ remove_operations_button_attention_style (self);
+
+ gtk_widget_add_css_class (self->operations_button,
+ "nautilus-operations-button-needs-attention");
+ self->operations_button_attention_timeout_id = g_timeout_add (NEEDS_ATTENTION_ANIMATION_TIMEOUT,
+ (GSourceFunc)
on_remove_operations_button_attention_style_timeout,
+ self);
+}
+
+static void
+on_progress_info_cancelled (NautilusToolbarEnd *self)
+{
+ /* Update the pie chart progress */
+ gtk_widget_queue_draw (self->operations_icon);
+
+ if (!nautilus_progress_manager_has_viewers (self->progress_manager))
+ {
+ schedule_remove_finished_operations (self);
+ }
+}
+
+static void
+on_progress_info_progress_changed (NautilusToolbarEnd *self)
+{
+ /* Update the pie chart progress */
+ gtk_widget_queue_draw (self->operations_icon);
+}
+
+static void
+on_progress_info_finished (NautilusToolbarEnd *self,
+ NautilusProgressInfo *info)
+{
+ NautilusWindow *window;
+ gchar *main_label;
+ GFile *folder_to_open;
+
+ window = NAUTILUS_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ /* Update the pie chart progress */
+ gtk_widget_queue_draw (self->operations_icon);
+
+ if (!nautilus_progress_manager_has_viewers (self->progress_manager))
+ {
+ schedule_remove_finished_operations (self);
+ }
+
+ folder_to_open = nautilus_progress_info_get_destination (info);
+ /* If destination is null, don't show a notification. This happens when the
+ * operation is a trash operation, which we already show a diferent kind of
+ * notification */
+ if (!gtk_widget_is_visible (self->operations_popover) &&
+ folder_to_open != NULL)
+ {
+ add_operations_button_attention_style (self);
+ main_label = nautilus_progress_info_get_status (info);
+ nautilus_window_show_operation_notification (window,
+ main_label,
+ folder_to_open);
+ g_free (main_label);
+ }
+
+ g_clear_object (&folder_to_open);
+}
+
+static void
+disconnect_progress_infos (NautilusToolbarEnd *self)
+{
+ GList *progress_infos;
+ GList *l;
+
+ progress_infos = nautilus_progress_info_manager_get_all_infos (self->progress_manager);
+ for (l = progress_infos; l != NULL; l = l->next)
+ {
+ g_signal_handlers_disconnect_by_data (l->data, self);
+ }
+}
+
+static void
+update_operations (NautilusToolbarEnd *self)
+{
+ GList *progress_infos;
+ GList *l;
+ gboolean should_show_progress_button = FALSE;
+
+ disconnect_progress_infos (self);
+ g_list_store_remove_all (self->progress_infos_model);
+
+ progress_infos = get_filtered_progress_infos (self);
+ for (l = progress_infos; l != NULL; l = l->next)
+ {
+ should_show_progress_button = should_show_progress_button ||
+ should_show_progress_info (l->data);
+
+ g_signal_connect_swapped (l->data, "finished",
+ G_CALLBACK (on_progress_info_finished), self);
+ g_signal_connect_swapped (l->data, "cancelled",
+ G_CALLBACK (on_progress_info_cancelled), self);
+ g_signal_connect_swapped (l->data, "progress-changed",
+ G_CALLBACK (on_progress_info_progress_changed), self);
+ g_list_store_append (self->progress_infos_model, l->data);
+ }
+
+ g_list_free (progress_infos);
+
+ if (should_show_progress_button &&
+ !gtk_revealer_get_reveal_child (GTK_REVEALER (self->operations_revealer)))
+ {
+ add_operations_button_attention_style (self);
+ gtk_revealer_set_reveal_child (GTK_REVEALER (self->operations_revealer),
+ TRUE);
+ gtk_widget_queue_draw (self->operations_icon);
+ }
+
+ /* Since we removed the info widgets, we need to restore the focus */
+ if (gtk_widget_get_visible (self->operations_popover))
+ {
+ gtk_widget_grab_focus (self->operations_popover);
+ }
+}
+
+static gboolean
+on_progress_info_started_timeout (NautilusToolbarEnd *self)
+{
+ GList *progress_infos;
+ GList *filtered_progress_infos;
+
+ update_operations (self);
+
+ /* In case we didn't show the operations button because the operation total
+ * time stimation is not good enough, update again to make sure we don't miss
+ * a long time operation because of that */
+
+ progress_infos = nautilus_progress_info_manager_get_all_infos (self->progress_manager);
+ filtered_progress_infos = get_filtered_progress_infos (self);
+ if (!nautilus_progress_manager_are_all_infos_finished_or_cancelled (self->progress_manager) &&
+ g_list_length (progress_infos) != g_list_length (filtered_progress_infos))
+ {
+ g_list_free (filtered_progress_infos);
+ return G_SOURCE_CONTINUE;
+ }
+ else
+ {
+ g_list_free (filtered_progress_infos);
+ self->start_operations_timeout_id = 0;
+ return G_SOURCE_REMOVE;
+ }
+}
+
+static void
+schedule_operations_start (NautilusToolbarEnd *self)
+{
+ if (self->start_operations_timeout_id == 0)
+ {
+ /* Timeout is a little more than what we require for a stimated operation
+ * total time, to make sure the stimated total time is correct */
+ self->start_operations_timeout_id =
+ g_timeout_add (SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE * 1000 + 500,
+ (GSourceFunc) on_progress_info_started_timeout,
+ self);
+ }
+}
+
+static void
+unschedule_operations_start (NautilusToolbarEnd *self)
+{
+ if (self->start_operations_timeout_id != 0)
+ {
+ g_source_remove (self->start_operations_timeout_id);
+ self->start_operations_timeout_id = 0;
+ }
+}
+
+static void
+on_progress_info_started (NautilusProgressInfo *info,
+ NautilusToolbarEnd *self)
+{
+ g_signal_handlers_disconnect_by_data (info, self);
+ schedule_operations_start (self);
+}
+
+static void
+on_new_progress_info (NautilusProgressInfoManager *manager,
+ NautilusProgressInfo *info,
+ NautilusToolbarEnd *self)
+{
+ g_signal_connect (info, "started",
+ G_CALLBACK (on_progress_info_started), self);
+}
+
+static void
+on_operations_icon_draw (GtkDrawingArea *drawing_area,
+ cairo_t *cr,
+ int width,
+ int height,
+ NautilusToolbarEnd *self)
+{
+ GtkWidget *widget = GTK_WIDGET (drawing_area);
+ gfloat elapsed_progress = 0;
+ gint remaining_progress = 0;
+ gint total_progress;
+ gdouble ratio;
+ GList *progress_infos;
+ GList *l;
+ gboolean all_cancelled;
+ GdkRGBA background;
+ GdkRGBA foreground;
+ GtkStyleContext *style_context;
+
+ style_context = gtk_widget_get_style_context (widget);
+ gtk_style_context_get_color (style_context, &foreground);
+ background = foreground;
+ background.alpha *= 0.3;
+
+ all_cancelled = TRUE;
+ progress_infos = get_filtered_progress_infos (self);
+ for (l = progress_infos; l != NULL; l = l->next)
+ {
+ if (!nautilus_progress_info_get_is_cancelled (l->data))
+ {
+ all_cancelled = FALSE;
+ remaining_progress += nautilus_progress_info_get_remaining_time (l->data);
+ elapsed_progress += nautilus_progress_info_get_elapsed_time (l->data);
+ }
+ }
+
+ g_list_free (progress_infos);
+
+ total_progress = remaining_progress + elapsed_progress;
+
+ if (all_cancelled)
+ {
+ ratio = 1.0;
+ }
+ else
+ {
+ if (total_progress > 0)
+ {
+ ratio = MAX (0.05, elapsed_progress / total_progress);
+ }
+ else
+ {
+ ratio = 0.05;
+ }
+ }
+
+
+ width = gtk_widget_get_allocated_width (widget);
+ height = gtk_widget_get_allocated_height (widget);
+
+ gdk_cairo_set_source_rgba (cr, &background);
+ cairo_arc (cr,
+ width / 2.0, height / 2.0,
+ MIN (width, height) / 2.0,
+ 0, 2 * G_PI);
+ cairo_fill (cr);
+ cairo_move_to (cr, width / 2.0, height / 2.0);
+ gdk_cairo_set_source_rgba (cr, &foreground);
+ cairo_arc (cr,
+ width / 2.0, height / 2.0,
+ MIN (width, height) / 2.0,
+ -G_PI / 2.0, ratio * 2 * G_PI - G_PI / 2.0);
+
+ cairo_fill (cr);
+}
+
+static void
+on_operations_popover_notify_visible (NautilusToolbarEnd *self,
+ GParamSpec *pspec,
+ GObject *popover)
+{
+ if (gtk_widget_get_visible (GTK_WIDGET (popover)))
+ {
+ unschedule_remove_finished_operations (self);
+ nautilus_progress_manager_add_viewer (self->progress_manager,
+ G_OBJECT (self));
+ }
+ else
+ {
+ nautilus_progress_manager_remove_viewer (self->progress_manager,
+ G_OBJECT (self));
+ }
+}
+
+static void
+on_progress_has_viewers_changed (NautilusProgressInfoManager *manager,
+ NautilusToolbarEnd *self)
+{
+ if (nautilus_progress_manager_has_viewers (manager))
+ {
+ unschedule_remove_finished_operations (self);
+ return;
+ }
+
+ if (nautilus_progress_manager_are_all_infos_finished_or_cancelled (manager))
+ {
+ unschedule_remove_finished_operations (self);
+ schedule_remove_finished_operations (self);
+ }
+}
+
+static GtkWidget *
+operations_list_create_widget (GObject *item,
+ gpointer user_data)
+{
+ NautilusProgressInfo *info = NAUTILUS_PROGRESS_INFO (item);
+ GtkWidget *widget;
+
+ widget = nautilus_progress_info_widget_new (info);
+ gtk_widget_show (widget);
+
+ return widget;
+}
+
+static void
+on_slot_toolbar_menu_sections_changed (NautilusToolbarEnd *self,
+ GParamSpec *param,
+ NautilusWindowSlot *slot)
+{
+ NautilusToolbarMenuSections *new_sections;
+ g_autoptr (GMenuItem) zoom_item = NULL;
+ g_autoptr (GMenuItem) sort_item = NULL;
+
+ new_sections = nautilus_window_slot_get_toolbar_menu_sections (slot);
+
+ gtk_widget_set_sensitive (self->view_split_button, (new_sections != NULL));
+ if (new_sections == NULL)
+ {
+ return;
+ }
+
+ /* Let's assume that sort section is the first item
+ * in view_menu, as per nautilus-toolbar.ui. */
+
+ sort_item = g_menu_item_new_from_model (self->view_menu, 0);
+ g_menu_remove (G_MENU (self->view_menu), 0);
+ g_menu_item_set_section (sort_item, new_sections->sort_section);
+ g_menu_insert_item (G_MENU (self->view_menu), 0, sort_item);
+}
+
+static void
+disconnect_toolbar_menu_sections_change_handler (NautilusToolbarEnd *self)
+{
+ if (self->window_slot == NULL)
+ {
+ return;
+ }
+
+ g_signal_handlers_disconnect_by_func (self->window_slot,
+ G_CALLBACK (on_slot_toolbar_menu_sections_changed),
+ self);
+}
+
+static void
+nautilus_toolbar_end_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusToolbarEnd *self = NAUTILUS_TOOLBAR_END (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW_SLOT:
+ g_value_set_object (value, G_OBJECT(self->window_slot));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nautilus_toolbar_end_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusToolbarEnd *self = NAUTILUS_TOOLBAR_END (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW_SLOT:
+ nautilus_toolbar_end_set_window_slot (self, NAUTILUS_WINDOW_SLOT (g_value_get_object (value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nautilus_toolbar_end_constructed (GObject *object)
+{
+ NautilusToolbarEnd *self = NAUTILUS_TOOLBAR_END (object);
+
+ self->progress_manager = nautilus_progress_info_manager_dup_singleton ();
+ g_signal_connect (self->progress_manager, "new-progress-info",
+ G_CALLBACK (on_new_progress_info), self);
+ g_signal_connect (self->progress_manager, "has-viewers-changed",
+ G_CALLBACK (on_progress_has_viewers_changed), self);
+
+ self->progress_infos_model = g_list_store_new (NAUTILUS_TYPE_PROGRESS_INFO);
+ gtk_list_box_bind_model (GTK_LIST_BOX (self->operations_list),
+ G_LIST_MODEL (self->progress_infos_model),
+ (GtkListBoxCreateWidgetFunc) operations_list_create_widget,
+ NULL,
+ NULL);
+ update_operations (self);
+
+ g_signal_connect (self->operations_popover, "show",
+ (GCallback) gtk_widget_grab_focus, NULL);
+ g_signal_connect_swapped (self->operations_popover, "closed",
+ (GCallback) gtk_widget_grab_focus, self);
+}
+
+static void
+nautilus_toolbar_end_finalize (GObject *obj)
+{
+ NautilusToolbarEnd *self = NAUTILUS_TOOLBAR_END (obj);
+
+ if (self->window_slot != NULL)
+ {
+ g_signal_handlers_disconnect_by_data (self->window_slot, self);
+ self->window_slot = NULL;
+ }
+
+ disconnect_progress_infos (self);
+ unschedule_remove_finished_operations (self);
+ unschedule_operations_start (self);
+ unschedule_operations_button_attention_style (self);
+
+ g_clear_object (&self->progress_infos_model);
+ g_signal_handlers_disconnect_by_data (self->progress_manager, self);
+ g_clear_object (&self->progress_manager);
+
+ G_OBJECT_CLASS (nautilus_toolbar_end_parent_class)->finalize (obj);
+}
+
+static void
+nautilus_toolbar_end_class_init (NautilusToolbarEndClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = nautilus_toolbar_end_constructed;
+ object_class->finalize = nautilus_toolbar_end_finalize;
+ object_class->get_property = nautilus_toolbar_end_get_property;
+ object_class->set_property = nautilus_toolbar_end_set_property;
+
+ properties[PROP_WINDOW_SLOT] = g_param_spec_object ("window-slot",
+ NULL, NULL,
+ NAUTILUS_TYPE_WINDOW_SLOT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/nautilus/ui/nautilus-toolbar-end.ui");
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarEnd, operations_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarEnd, operations_icon);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarEnd, operations_popover);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarEnd, operations_list);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarEnd, operations_revealer);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarEnd, view_menu);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarEnd, view_split_button);
+
+ gtk_widget_class_bind_template_callback (widget_class, on_operations_popover_notify_visible);
+}
+
+static void
+nautilus_toolbar_end_init (NautilusToolbarEnd *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (self->operations_icon),
+ (GtkDrawingAreaDrawFunc) on_operations_icon_draw,
+ self,
+ NULL);
+}
+
+
+void
+nautilus_toolbar_end_set_window_slot (NautilusToolbarEnd *self,
+ NautilusWindowSlot *window_slot)
+{
+ g_return_if_fail (NAUTILUS_IS_TOOLBAR_END (self));
+ g_return_if_fail (window_slot == NULL || NAUTILUS_IS_WINDOW_SLOT (window_slot));
+
+ if (self->window_slot == window_slot)
+ {
+ return;
+ }
+
+ disconnect_toolbar_menu_sections_change_handler (self);
+
+ self->window_slot = window_slot;
+
+ if (self->window_slot != NULL)
+ {
+ on_slot_toolbar_menu_sections_changed (self, NULL, self->window_slot);
+ g_signal_connect_swapped (self->window_slot, "notify::toolbar-menu-sections",
+ G_CALLBACK (on_slot_toolbar_menu_sections_changed), self);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WINDOW_SLOT]);
+}
diff --git a/src/nautilus-toolbar-end.h b/src/nautilus-toolbar-end.h
new file mode 100644
index 000000000..c9183b90e
--- /dev/null
+++ b/src/nautilus-toolbar-end.h
@@ -0,0 +1,37 @@
+/* nautilus-toolbar-end.h
+ *
+ * Copyright 2022 Christopher Davis <christopherdavis gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <libadwaita-1/adwaita.h>
+
+#include "nautilus-window-slot.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_TOOLBAR_END (nautilus_toolbar_end_get_type())
+
+G_DECLARE_FINAL_TYPE (NautilusToolbarEnd, nautilus_toolbar_end, NAUTILUS, TOOLBAR_END, AdwBin)
+
+void nautilus_toolbar_end_set_window_slot (NautilusToolbarEnd *self,
+ NautilusWindowSlot *window_slot);
+
+G_END_DECLS
diff --git a/src/nautilus-toolbar-start.c b/src/nautilus-toolbar-start.c
new file mode 100644
index 000000000..1c472bbcb
--- /dev/null
+++ b/src/nautilus-toolbar-start.c
@@ -0,0 +1,317 @@
+/* nautilus-toolbar-start.c
+ *
+ * Copyright 2022 Christopher Davis <christopherdavis gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "nautilus-toolbar-start.h"
+
+#include "nautilus-bookmark.h"
+#include "nautilus-window.h"
+
+struct _NautilusToolbarStart
+{
+ AdwBin parent_instance;
+
+ GtkWidget *back_button;
+ GtkWidget *back_menu;
+
+ GtkWidget *forward_button;
+ GtkWidget *forward_menu;
+
+ NautilusWindowSlot *window_slot;
+};
+
+G_DEFINE_FINAL_TYPE (NautilusToolbarStart, nautilus_toolbar_start, ADW_TYPE_BIN)
+
+enum {
+ PROP_0,
+ PROP_WINDOW_SLOT,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+fill_menu (NautilusToolbarStart *self,
+ GMenu *menu,
+ gboolean back)
+{
+ guint index;
+ GList *list;
+ const gchar *name;
+
+ list = back ? nautilus_window_slot_get_back_history (self->window_slot) :
+ nautilus_window_slot_get_forward_history (self->window_slot);
+
+ index = 0;
+ while (list != NULL)
+ {
+ g_autoptr (GMenuItem) item = NULL;
+
+ name = nautilus_bookmark_get_name (NAUTILUS_BOOKMARK (list->data));
+ item = g_menu_item_new (name, NULL);
+ g_menu_item_set_action_and_target (item,
+ back ? "win.back-n" : "win.forward-n",
+ "u", index);
+ g_menu_append_item (menu, item);
+
+ list = g_list_next (list);
+ ++index;
+ }
+}
+
+static void
+show_menu (NautilusToolbarStart *self,
+ GtkWidget *widget)
+{
+ g_autoptr (GMenu) menu = NULL;
+ NautilusNavigationDirection direction;
+ GtkPopoverMenu *popover;
+
+ menu = g_menu_new ();
+
+ direction = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
+ "nav-direction"));
+
+ switch (direction)
+ {
+ case NAUTILUS_NAVIGATION_DIRECTION_FORWARD:
+ {
+ fill_menu (self, menu, FALSE);
+ popover = GTK_POPOVER_MENU (self->forward_menu);
+ }
+ break;
+
+ case NAUTILUS_NAVIGATION_DIRECTION_BACK:
+ {
+ fill_menu (self, menu, TRUE);
+ popover = GTK_POPOVER_MENU (self->back_menu);
+ }
+ break;
+
+ default:
+ {
+ g_assert_not_reached ();
+ }
+ break;
+ }
+
+ gtk_popover_menu_set_menu_model (popover, G_MENU_MODEL (menu));
+ gtk_popover_popup (GTK_POPOVER (popover));
+}
+
+static void
+navigation_button_press_cb (GtkGestureClick *gesture,
+ gint n_press,
+ gdouble x,
+ gdouble y,
+ gpointer user_data)
+{
+ NautilusToolbarStart *self;
+ NautilusWindow *window;
+ GtkWidget *widget;
+ guint button;
+
+ self = NAUTILUS_TOOLBAR_START (user_data);
+ button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+ widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
+ window = NAUTILUS_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
+
+ if (button == GDK_BUTTON_PRIMARY)
+ {
+ /* Don't do anything, primary click is handled through activate */
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+ else if (button == GDK_BUTTON_MIDDLE)
+ {
+ NautilusNavigationDirection direction;
+
+ direction = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
+ "nav-direction"));
+
+ nautilus_window_back_or_forward_in_new_tab (window, direction);
+ }
+ else if (button == GDK_BUTTON_SECONDARY)
+ {
+ show_menu (self, widget);
+ }
+}
+
+static void
+back_button_longpress_cb (GtkGestureLongPress *gesture,
+ double x,
+ double y,
+ gpointer user_data)
+{
+ NautilusToolbarStart *self = user_data;
+
+ show_menu (self, self->back_button);
+}
+
+static void
+forward_button_longpress_cb (GtkGestureLongPress *gesture,
+ double x,
+ double y,
+ gpointer user_data)
+{
+ NautilusToolbarStart *self = user_data;
+
+ show_menu (self, self->forward_button);
+}
+
+
+static void
+nautilus_toolbar_start_contructed (GObject *object)
+{
+ NautilusToolbarStart *self;
+ GtkEventController *controller;
+
+ self = NAUTILUS_TOOLBAR_START (object);
+
+ controller = GTK_EVENT_CONTROLLER (gtk_gesture_long_press_new ());
+ gtk_widget_add_controller (self->back_button, controller);
+ g_signal_connect (controller, "pressed",
+ G_CALLBACK (back_button_longpress_cb), self);
+
+ controller = GTK_EVENT_CONTROLLER (gtk_gesture_long_press_new ());
+ gtk_widget_add_controller (self->forward_button, controller);
+ g_signal_connect (controller, "pressed",
+ G_CALLBACK (forward_button_longpress_cb), self);
+
+ g_object_set_data (G_OBJECT (self->back_button), "nav-direction",
+ GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_BACK));
+ g_object_set_data (G_OBJECT (self->forward_button), "nav-direction",
+ GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_FORWARD));
+
+ controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
+ gtk_widget_add_controller (self->back_button, controller);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0);
+ g_signal_connect (controller, "pressed",
+ G_CALLBACK (navigation_button_press_cb), self);
+
+ controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
+ gtk_widget_add_controller (self->forward_button, controller);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0);
+ g_signal_connect (controller, "pressed",
+ G_CALLBACK (navigation_button_press_cb), self);
+
+}
+
+static void
+nautilus_toolbar_start_dispose (GObject *object)
+{
+ NautilusToolbarStart *self;
+
+ self = NAUTILUS_TOOLBAR_START (object);
+
+ g_clear_pointer (&self->back_menu, gtk_widget_unparent);
+ g_clear_pointer (&self->forward_menu, gtk_widget_unparent);
+
+ G_OBJECT_CLASS (nautilus_toolbar_start_parent_class)->dispose (object);
+}
+
+static void
+nautilus_toolbar_start_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusToolbarStart *self = NAUTILUS_TOOLBAR_START (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW_SLOT:
+ g_value_set_object (value, G_OBJECT(self->window_slot));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nautilus_toolbar_start_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NautilusToolbarStart *self = NAUTILUS_TOOLBAR_START (object);
+
+ switch (prop_id)
+ {
+ case PROP_WINDOW_SLOT:
+ nautilus_toolbar_start_set_window_slot (self, NAUTILUS_WINDOW_SLOT (g_value_get_object (value)));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nautilus_toolbar_start_class_init (NautilusToolbarStartClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->constructed = nautilus_toolbar_start_contructed;
+ object_class->dispose = nautilus_toolbar_start_dispose;
+ object_class->set_property = nautilus_toolbar_start_set_property;
+ object_class->get_property = nautilus_toolbar_start_get_property;
+
+ properties[PROP_WINDOW_SLOT] = g_param_spec_object ("window-slot",
+ NULL, NULL,
+ NAUTILUS_TYPE_WINDOW_SLOT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/nautilus/ui/nautilus-toolbar-start.ui");
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarStart, back_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarStart, back_menu);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarStart, forward_button);
+ gtk_widget_class_bind_template_child (widget_class, NautilusToolbarStart, forward_menu);
+}
+
+static void
+nautilus_toolbar_start_init (NautilusToolbarStart *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ gtk_widget_set_parent (self->back_menu, self->back_button);
+ g_signal_connect (self->back_menu, "destroy", G_CALLBACK (gtk_widget_unparent), NULL);
+ gtk_widget_set_parent (self->forward_menu, self->forward_button);
+ g_signal_connect (self->forward_menu, "destroy", G_CALLBACK (gtk_widget_unparent), NULL);
+}
+
+void
+nautilus_toolbar_start_set_window_slot (NautilusToolbarStart *self,
+ NautilusWindowSlot *window_slot)
+{
+ g_return_if_fail (NAUTILUS_IS_TOOLBAR_START (self));
+ g_return_if_fail (window_slot == NULL || NAUTILUS_IS_WINDOW_SLOT (window_slot));
+
+ if (self->window_slot == window_slot)
+ {
+ return;
+ }
+
+ self->window_slot = window_slot;
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WINDOW_SLOT]);
+}
diff --git a/src/nautilus-toolbar-start.h b/src/nautilus-toolbar-start.h
new file mode 100644
index 000000000..c542343fc
--- /dev/null
+++ b/src/nautilus-toolbar-start.h
@@ -0,0 +1,37 @@
+/* nautilus-toolbar-start.h
+ *
+ * Copyright 2022 Christopher Davis <christopherdavis gnome org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+#include <libadwaita-1/adwaita.h>
+
+#include "nautilus-window-slot.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_TOOLBAR_START nautilus_toolbar_start_get_type()
+
+G_DECLARE_FINAL_TYPE (NautilusToolbarStart, nautilus_toolbar_start, NAUTILUS, TOOLBAR_START, AdwBin)
+
+void nautilus_toolbar_start_set_window_slot (NautilusToolbarStart *self,
+ NautilusWindowSlot *window_slot);
+
+G_END_DECLS
diff --git a/src/nautilus-toolbar.c b/src/nautilus-toolbar.c
index f7bf7ec62..fd8ff986b 100644
--- a/src/nautilus-toolbar.c
+++ b/src/nautilus-toolbar.c
@@ -27,20 +27,17 @@
#include "nautilus-application.h"
#include "nautilus-bookmark.h"
-#include "nautilus-file-operations.h"
#include "nautilus-file-undo-manager.h"
#include "nautilus-global-preferences.h"
#include "nautilus-location-entry.h"
#include "nautilus-pathbar.h"
-#include "nautilus-progress-info-manager.h"
-#include "nautilus-progress-info-widget.h"
-#include "nautilus-toolbar-menu-sections.h"
+#include "nautilus-toolbar-start.h"
+#include "nautilus-toolbar-end.h"
#include "nautilus-ui-utilities.h"
#include "nautilus-window.h"
#define OPERATION_MINIMUM_TIME 2 /*s */
#define NEEDS_ATTENTION_ANIMATION_TIMEOUT 2000 /*ms */
-#define REMOVE_FINISHED_OPERATIONS_TIEMOUT 3 /*s */
/* Just design, context at https://gitlab.gnome.org/GNOME/nautilus/issues/548#note_274131 */
@@ -60,20 +57,6 @@ struct _NautilusToolbar
gboolean show_location_entry;
gboolean location_entry_should_auto_hide;
- guint start_operations_timeout_id;
- guint remove_finished_operations_timeout_id;
- guint operations_button_attention_timeout_id;
-
- GtkWidget *operations_button;
- GtkWidget *operations_popover;
- GtkWidget *operations_list;
- GListStore *progress_infos_model;
- GtkWidget *operations_revealer;
- GtkWidget *operations_icon;
-
- GtkWidget *view_split_button;
- GMenuModel *view_menu;
-
GtkWidget *app_button;
GMenuModel *undo_redo_section;
@@ -81,18 +64,10 @@ struct _NautilusToolbar
gboolean show_sidebar_button;
gboolean sidebar_button_active;
- GtkWidget *forward_button;
- GtkWidget *forward_menu;
-
- GtkWidget *back_button;
- GtkWidget *back_menu;
-
GtkWidget *search_button;
GtkWidget *location_entry_close_button;
- NautilusProgressInfoManager *progress_manager;
-
/* active slot & bindings */
NautilusWindowSlot *window_slot;
GBinding *search_binding;
@@ -115,8 +90,6 @@ G_DEFINE_TYPE (NautilusToolbar, nautilus_toolbar, ADW_TYPE_BIN);
static void nautilus_toolbar_set_window_slot_real (NautilusToolbar *self,
NautilusWindowSlot *slot);
-static void update_operations (NautilusToolbar *self);
-
static void
toolbar_update_appearance (NautilusToolbar *self)
{
@@ -141,560 +114,6 @@ toolbar_update_appearance (NautilusToolbar *self)
}
}
-static void
-fill_menu (NautilusToolbar *self,
- GMenu *menu,
- gboolean back)
-{
- guint index;
- GList *list;
- const gchar *name;
-
- list = back ? nautilus_window_slot_get_back_history (self->window_slot) :
- nautilus_window_slot_get_forward_history (self->window_slot);
-
- index = 0;
- while (list != NULL)
- {
- g_autoptr (GMenuItem) item = NULL;
-
- name = nautilus_bookmark_get_name (NAUTILUS_BOOKMARK (list->data));
- item = g_menu_item_new (name, NULL);
- g_menu_item_set_action_and_target (item,
- back ? "win.back-n" : "win.forward-n",
- "u", index);
- g_menu_append_item (menu, item);
-
- list = g_list_next (list);
- ++index;
- }
-}
-
-static void
-show_menu (NautilusToolbar *self,
- GtkWidget *widget)
-{
- g_autoptr (GMenu) menu = NULL;
- NautilusNavigationDirection direction;
- GtkPopoverMenu *popover;
-
- menu = g_menu_new ();
-
- direction = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
- "nav-direction"));
-
- switch (direction)
- {
- case NAUTILUS_NAVIGATION_DIRECTION_FORWARD:
- {
- fill_menu (self, menu, FALSE);
- popover = GTK_POPOVER_MENU (self->forward_menu);
- }
- break;
-
- case NAUTILUS_NAVIGATION_DIRECTION_BACK:
- {
- fill_menu (self, menu, TRUE);
- popover = GTK_POPOVER_MENU (self->back_menu);
- }
- break;
-
- default:
- {
- g_assert_not_reached ();
- }
- break;
- }
-
- gtk_popover_menu_set_menu_model (popover, G_MENU_MODEL (menu));
- gtk_popover_popup (GTK_POPOVER (popover));
-}
-
-static void
-navigation_button_press_cb (GtkGestureClick *gesture,
- gint n_press,
- gdouble x,
- gdouble y,
- gpointer user_data)
-{
- NautilusToolbar *self;
- GtkWidget *widget;
- guint button;
-
- self = NAUTILUS_TOOLBAR (user_data);
- button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
- widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
-
- if (button == GDK_BUTTON_PRIMARY)
- {
- /* Don't do anything, primary click is handled through activate */
- gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
- return;
- }
- else if (button == GDK_BUTTON_MIDDLE)
- {
- NautilusNavigationDirection direction;
-
- direction = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
- "nav-direction"));
-
- nautilus_window_back_or_forward_in_new_tab (self->window, direction);
- }
- else if (button == GDK_BUTTON_SECONDARY)
- {
- show_menu (self, widget);
- }
-}
-
-static void
-back_button_longpress_cb (GtkGestureLongPress *gesture,
- double x,
- double y,
- gpointer user_data)
-{
- NautilusToolbar *self = user_data;
-
- show_menu (self, self->back_button);
-}
-
-static void
-forward_button_longpress_cb (GtkGestureLongPress *gesture,
- double x,
- double y,
- gpointer user_data)
-{
- NautilusToolbar *self = user_data;
-
- show_menu (self, self->forward_button);
-}
-
-static gboolean
-should_show_progress_info (NautilusProgressInfo *info)
-{
- return nautilus_progress_info_get_total_elapsed_time (info) +
- nautilus_progress_info_get_remaining_time (info) > OPERATION_MINIMUM_TIME;
-}
-
-static GList *
-get_filtered_progress_infos (NautilusToolbar *self)
-{
- GList *l;
- GList *filtered_progress_infos;
- GList *progress_infos;
-
- progress_infos = nautilus_progress_info_manager_get_all_infos (self->progress_manager);
- filtered_progress_infos = NULL;
-
- for (l = progress_infos; l != NULL; l = l->next)
- {
- if (should_show_progress_info (l->data))
- {
- filtered_progress_infos = g_list_append (filtered_progress_infos, l->data);
- }
- }
-
- return filtered_progress_infos;
-}
-
-static gboolean
-should_hide_operations_button (NautilusToolbar *self)
-{
- GList *progress_infos;
- GList *l;
-
- progress_infos = get_filtered_progress_infos (self);
-
- for (l = progress_infos; l != NULL; l = l->next)
- {
- if (nautilus_progress_info_get_total_elapsed_time (l->data) +
- nautilus_progress_info_get_remaining_time (l->data) > OPERATION_MINIMUM_TIME &&
- !nautilus_progress_info_get_is_cancelled (l->data) &&
- !nautilus_progress_info_get_is_finished (l->data))
- {
- return FALSE;
- }
- }
-
- g_list_free (progress_infos);
-
- return TRUE;
-}
-
-static gboolean
-on_remove_finished_operations_timeout (NautilusToolbar *self)
-{
- nautilus_progress_info_manager_remove_finished_or_cancelled_infos (self->progress_manager);
- if (should_hide_operations_button (self))
- {
- gtk_revealer_set_reveal_child (GTK_REVEALER (self->operations_revealer),
- FALSE);
- }
- else
- {
- update_operations (self);
- }
-
- self->remove_finished_operations_timeout_id = 0;
-
- return G_SOURCE_REMOVE;
-}
-
-static void
-unschedule_remove_finished_operations (NautilusToolbar *self)
-{
- if (self->remove_finished_operations_timeout_id != 0)
- {
- g_source_remove (self->remove_finished_operations_timeout_id);
- self->remove_finished_operations_timeout_id = 0;
- }
-}
-
-static void
-schedule_remove_finished_operations (NautilusToolbar *self)
-{
- if (self->remove_finished_operations_timeout_id == 0)
- {
- self->remove_finished_operations_timeout_id =
- g_timeout_add_seconds (REMOVE_FINISHED_OPERATIONS_TIEMOUT,
- (GSourceFunc) on_remove_finished_operations_timeout,
- self);
- }
-}
-
-static void
-remove_operations_button_attention_style (NautilusToolbar *self)
-{
- GtkStyleContext *style_context;
-
- style_context = gtk_widget_get_style_context (self->operations_button);
- gtk_style_context_remove_class (style_context,
- "nautilus-operations-button-needs-attention");
-}
-
-static gboolean
-on_remove_operations_button_attention_style_timeout (NautilusToolbar *self)
-{
- remove_operations_button_attention_style (self);
- self->operations_button_attention_timeout_id = 0;
-
- return G_SOURCE_REMOVE;
-}
-
-static void
-unschedule_operations_button_attention_style (NautilusToolbar *self)
-{
- if (self->operations_button_attention_timeout_id != 0)
- {
- g_source_remove (self->operations_button_attention_timeout_id);
- self->operations_button_attention_timeout_id = 0;
- }
-}
-
-static void
-add_operations_button_attention_style (NautilusToolbar *self)
-{
- GtkStyleContext *style_context;
-
- style_context = gtk_widget_get_style_context (self->operations_button);
-
- unschedule_operations_button_attention_style (self);
- remove_operations_button_attention_style (self);
-
- gtk_style_context_add_class (style_context,
- "nautilus-operations-button-needs-attention");
- self->operations_button_attention_timeout_id = g_timeout_add (NEEDS_ATTENTION_ANIMATION_TIMEOUT,
- (GSourceFunc)
on_remove_operations_button_attention_style_timeout,
- self);
-}
-
-static void
-on_progress_info_cancelled (NautilusToolbar *self)
-{
- /* Update the pie chart progress */
- gtk_widget_queue_draw (self->operations_icon);
-
- if (!nautilus_progress_manager_has_viewers (self->progress_manager))
- {
- schedule_remove_finished_operations (self);
- }
-}
-
-static void
-on_progress_info_progress_changed (NautilusToolbar *self)
-{
- /* Update the pie chart progress */
- gtk_widget_queue_draw (self->operations_icon);
-}
-
-static void
-on_progress_info_finished (NautilusToolbar *self,
- NautilusProgressInfo *info)
-{
- gchar *main_label;
- GFile *folder_to_open;
-
- /* Update the pie chart progress */
- gtk_widget_queue_draw (self->operations_icon);
-
- if (!nautilus_progress_manager_has_viewers (self->progress_manager))
- {
- schedule_remove_finished_operations (self);
- }
-
- folder_to_open = nautilus_progress_info_get_destination (info);
- /* If destination is null, don't show a notification. This happens when the
- * operation is a trash operation, which we already show a diferent kind of
- * notification */
- if (!gtk_widget_is_visible (self->operations_popover) &&
- folder_to_open != NULL)
- {
- add_operations_button_attention_style (self);
- main_label = nautilus_progress_info_get_status (info);
- nautilus_window_show_operation_notification (self->window,
- main_label,
- folder_to_open);
- g_free (main_label);
- }
-
- g_clear_object (&folder_to_open);
-}
-
-static void
-disconnect_progress_infos (NautilusToolbar *self)
-{
- GList *progress_infos;
- GList *l;
-
- progress_infos = nautilus_progress_info_manager_get_all_infos (self->progress_manager);
- for (l = progress_infos; l != NULL; l = l->next)
- {
- g_signal_handlers_disconnect_by_data (l->data, self);
- }
-}
-
-static void
-update_operations (NautilusToolbar *self)
-{
- GList *progress_infos;
- GList *l;
- gboolean should_show_progress_button = FALSE;
-
- disconnect_progress_infos (self);
- g_list_store_remove_all (self->progress_infos_model);
-
- progress_infos = get_filtered_progress_infos (self);
- for (l = progress_infos; l != NULL; l = l->next)
- {
- should_show_progress_button = should_show_progress_button ||
- should_show_progress_info (l->data);
-
- g_signal_connect_swapped (l->data, "finished",
- G_CALLBACK (on_progress_info_finished), self);
- g_signal_connect_swapped (l->data, "cancelled",
- G_CALLBACK (on_progress_info_cancelled), self);
- g_signal_connect_swapped (l->data, "progress-changed",
- G_CALLBACK (on_progress_info_progress_changed), self);
- g_list_store_append (self->progress_infos_model, l->data);
- }
-
- g_list_free (progress_infos);
-
- if (should_show_progress_button &&
- !gtk_revealer_get_reveal_child (GTK_REVEALER (self->operations_revealer)))
- {
- add_operations_button_attention_style (self);
- gtk_revealer_set_reveal_child (GTK_REVEALER (self->operations_revealer),
- TRUE);
- gtk_widget_queue_draw (self->operations_icon);
- }
-
- /* Since we removed the info widgets, we need to restore the focus */
- if (gtk_widget_get_visible (self->operations_popover))
- {
- gtk_widget_grab_focus (self->operations_popover);
- }
-}
-
-static gboolean
-on_progress_info_started_timeout (NautilusToolbar *self)
-{
- GList *progress_infos;
- GList *filtered_progress_infos;
-
- update_operations (self);
-
- /* In case we didn't show the operations button because the operation total
- * time stimation is not good enough, update again to make sure we don't miss
- * a long time operation because of that */
-
- progress_infos = nautilus_progress_info_manager_get_all_infos (self->progress_manager);
- filtered_progress_infos = get_filtered_progress_infos (self);
- if (!nautilus_progress_manager_are_all_infos_finished_or_cancelled (self->progress_manager) &&
- g_list_length (progress_infos) != g_list_length (filtered_progress_infos))
- {
- g_list_free (filtered_progress_infos);
- return G_SOURCE_CONTINUE;
- }
- else
- {
- g_list_free (filtered_progress_infos);
- self->start_operations_timeout_id = 0;
- return G_SOURCE_REMOVE;
- }
-}
-
-static void
-schedule_operations_start (NautilusToolbar *self)
-{
- if (self->start_operations_timeout_id == 0)
- {
- /* Timeout is a little more than what we require for a stimated operation
- * total time, to make sure the stimated total time is correct */
- self->start_operations_timeout_id =
- g_timeout_add (SECONDS_NEEDED_FOR_APROXIMATE_TRANSFER_RATE * 1000 + 500,
- (GSourceFunc) on_progress_info_started_timeout,
- self);
- }
-}
-
-static void
-unschedule_operations_start (NautilusToolbar *self)
-{
- if (self->start_operations_timeout_id != 0)
- {
- g_source_remove (self->start_operations_timeout_id);
- self->start_operations_timeout_id = 0;
- }
-}
-
-static void
-on_progress_info_started (NautilusProgressInfo *info,
- NautilusToolbar *self)
-{
- g_signal_handlers_disconnect_by_data (info, self);
- schedule_operations_start (self);
-}
-
-static void
-on_new_progress_info (NautilusProgressInfoManager *manager,
- NautilusProgressInfo *info,
- NautilusToolbar *self)
-{
- g_signal_connect (info, "started",
- G_CALLBACK (on_progress_info_started), self);
-}
-
-static void
-on_operations_icon_draw (GtkDrawingArea *drawing_area,
- cairo_t *cr,
- int width,
- int height,
- NautilusToolbar *self)
-{
- GtkWidget *widget = GTK_WIDGET (drawing_area);
- gfloat elapsed_progress = 0;
- gint remaining_progress = 0;
- gint total_progress;
- gdouble ratio;
- GList *progress_infos;
- GList *l;
- gboolean all_cancelled;
- GdkRGBA background;
- GdkRGBA foreground;
- GtkStyleContext *style_context;
-
- style_context = gtk_widget_get_style_context (widget);
- gtk_style_context_get_color (style_context, &foreground);
- background = foreground;
- background.alpha *= 0.3;
-
- all_cancelled = TRUE;
- progress_infos = get_filtered_progress_infos (self);
- for (l = progress_infos; l != NULL; l = l->next)
- {
- if (!nautilus_progress_info_get_is_cancelled (l->data))
- {
- all_cancelled = FALSE;
- remaining_progress += nautilus_progress_info_get_remaining_time (l->data);
- elapsed_progress += nautilus_progress_info_get_elapsed_time (l->data);
- }
- }
-
- g_list_free (progress_infos);
-
- total_progress = remaining_progress + elapsed_progress;
-
- if (all_cancelled)
- {
- ratio = 1.0;
- }
- else
- {
- if (total_progress > 0)
- {
- ratio = MAX (0.05, elapsed_progress / total_progress);
- }
- else
- {
- ratio = 0.05;
- }
- }
-
-
- width = gtk_widget_get_allocated_width (widget);
- height = gtk_widget_get_allocated_height (widget);
-
- gdk_cairo_set_source_rgba (cr, &background);
- cairo_arc (cr,
- width / 2.0, height / 2.0,
- MIN (width, height) / 2.0,
- 0, 2 * G_PI);
- cairo_fill (cr);
- cairo_move_to (cr, width / 2.0, height / 2.0);
- gdk_cairo_set_source_rgba (cr, &foreground);
- cairo_arc (cr,
- width / 2.0, height / 2.0,
- MIN (width, height) / 2.0,
- -G_PI / 2.0, ratio * 2 * G_PI - G_PI / 2.0);
-
- cairo_fill (cr);
-}
-
-static void
-on_operations_popover_notify_visible (NautilusToolbar *self,
- GParamSpec *pspec,
- GObject *popover)
-{
- if (gtk_widget_get_visible (GTK_WIDGET (popover)))
- {
- unschedule_remove_finished_operations (self);
- nautilus_progress_manager_add_viewer (self->progress_manager,
- G_OBJECT (self));
- }
- else
- {
- nautilus_progress_manager_remove_viewer (self->progress_manager,
- G_OBJECT (self));
- }
-}
-
-static void
-on_progress_has_viewers_changed (NautilusProgressInfoManager *manager,
- NautilusToolbar *self)
-{
- if (nautilus_progress_manager_has_viewers (manager))
- {
- unschedule_remove_finished_operations (self);
- return;
- }
-
- if (nautilus_progress_manager_are_all_infos_finished_or_cancelled (manager))
- {
- unschedule_remove_finished_operations (self);
- schedule_remove_finished_operations (self);
- }
-}
-
static void
update_action (NautilusToolbar *self,
const char *action_name,
@@ -791,24 +210,10 @@ on_location_entry_focus_changed (GObject *object,
}
}
-static GtkWidget *
-operations_list_create_widget (GObject *item,
- gpointer user_data)
-{
- NautilusProgressInfo *info = NAUTILUS_PROGRESS_INFO (item);
- GtkWidget *widget;
-
- widget = nautilus_progress_info_widget_new (info);
- gtk_widget_show (widget);
-
- return widget;
-}
-
static void
nautilus_toolbar_constructed (GObject *object)
{
NautilusToolbar *self = NAUTILUS_TOOLBAR (object);
- GtkEventController *controller;
self->path_bar = GTK_WIDGET (g_object_new (NAUTILUS_TYPE_PATH_BAR, NULL));
gtk_box_append (GTK_BOX (self->path_bar_container),
@@ -822,52 +227,6 @@ nautilus_toolbar_constructed (GObject *object)
self->location_entry_close_button);
g_signal_connect (self->location_entry_close_button, "clicked",
G_CALLBACK (on_location_entry_close), self);
-
- self->progress_manager = nautilus_progress_info_manager_dup_singleton ();
- g_signal_connect (self->progress_manager, "new-progress-info",
- G_CALLBACK (on_new_progress_info), self);
- g_signal_connect (self->progress_manager, "has-viewers-changed",
- G_CALLBACK (on_progress_has_viewers_changed), self);
-
- self->progress_infos_model = g_list_store_new (NAUTILUS_TYPE_PROGRESS_INFO);
- gtk_list_box_bind_model (GTK_LIST_BOX (self->operations_list),
- G_LIST_MODEL (self->progress_infos_model),
- (GtkListBoxCreateWidgetFunc) operations_list_create_widget,
- NULL,
- NULL);
- update_operations (self);
-
- controller = GTK_EVENT_CONTROLLER (gtk_gesture_long_press_new ());
- gtk_widget_add_controller (self->back_button, controller);
- g_signal_connect (controller, "pressed",
- G_CALLBACK (back_button_longpress_cb), self);
-
- controller = GTK_EVENT_CONTROLLER (gtk_gesture_long_press_new ());
- gtk_widget_add_controller (self->forward_button, controller);
- g_signal_connect (controller, "pressed",
- G_CALLBACK (forward_button_longpress_cb), self);
-
- g_object_set_data (G_OBJECT (self->back_button), "nav-direction",
- GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_BACK));
- g_object_set_data (G_OBJECT (self->forward_button), "nav-direction",
- GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_FORWARD));
-
- controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
- gtk_widget_add_controller (self->back_button, controller);
- gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0);
- g_signal_connect (controller, "pressed",
- G_CALLBACK (navigation_button_press_cb), self);
-
- controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
- gtk_widget_add_controller (self->forward_button, controller);
- gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0);
- g_signal_connect (controller, "pressed",
- G_CALLBACK (navigation_button_press_cb), self);
-
- g_signal_connect (self->operations_popover, "show",
- (GCallback) gtk_widget_grab_focus, NULL);
- g_signal_connect_swapped (self->operations_popover, "closed",
- (GCallback) gtk_widget_grab_focus, self);
g_signal_connect (self->location_entry, "notify::has-focus",
G_CALLBACK (on_location_entry_focus_changed), self);
@@ -882,17 +241,10 @@ nautilus_toolbar_constructed (GObject *object)
static void
nautilus_toolbar_init (NautilusToolbar *self)
{
- gtk_widget_init_template (GTK_WIDGET (self));
+ g_type_ensure (NAUTILUS_TYPE_TOOLBAR_START);
+ g_type_ensure (NAUTILUS_TYPE_TOOLBAR_END);
- gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (self->operations_icon),
- (GtkDrawingAreaDrawFunc) on_operations_icon_draw,
- self,
- NULL);
-
- gtk_widget_set_parent (self->back_menu, self->back_button);
- g_signal_connect (self->back_menu, "destroy", G_CALLBACK (gtk_widget_unparent), NULL);
- gtk_widget_set_parent (self->forward_menu, self->forward_button);
- g_signal_connect (self->forward_menu, "destroy", G_CALLBACK (gtk_widget_unparent), NULL);
+ gtk_widget_init_template (GTK_WIDGET (self));
}
void
@@ -1083,8 +435,6 @@ nautilus_toolbar_dispose (GObject *object)
self = NAUTILUS_TOOLBAR (object);
g_clear_pointer (&self->search_binding, g_binding_unbind);
- g_clear_pointer (&self->back_menu, gtk_widget_unparent);
- g_clear_pointer (&self->forward_menu, gtk_widget_unparent);
G_OBJECT_CLASS (nautilus_toolbar_parent_class)->dispose (object);
}
@@ -1104,14 +454,6 @@ nautilus_toolbar_finalize (GObject *obj)
on_window_slot_destroyed, self);
self->window_slot = NULL;
}
- disconnect_progress_infos (self);
- unschedule_remove_finished_operations (self);
- unschedule_operations_start (self);
- unschedule_operations_button_attention_style (self);
-
- g_clear_object (&self->progress_infos_model);
- g_signal_handlers_disconnect_by_data (self->progress_manager, self);
- g_clear_object (&self->progress_manager);
g_signal_handlers_disconnect_by_func (self->window,
on_window_focus_changed, self);
@@ -1174,27 +516,14 @@ nautilus_toolbar_class_init (NautilusToolbarClass *klass)
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/nautilus/ui/nautilus-toolbar.ui");
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_button);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_icon);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_popover);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_list);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, operations_revealer);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, view_menu);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, view_split_button);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, app_button);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, undo_redo_section);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, back_button);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, back_menu);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, forward_button);
- gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, forward_menu);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, toolbar_switcher);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, search_container);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, path_bar_container);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, location_entry_container);
gtk_widget_class_bind_template_child (widget_class, NautilusToolbar, search_button);
-
- gtk_widget_class_bind_template_callback (widget_class, on_operations_popover_notify_visible);
}
GtkWidget *
@@ -1263,46 +592,6 @@ slot_on_templates_menu_changed (NautilusToolbar *self,
menu);
}
-static void
-on_slot_toolbar_menu_sections_changed (NautilusToolbar *self,
- GParamSpec *param,
- NautilusWindowSlot *slot)
-{
- NautilusToolbarMenuSections *new_sections;
- g_autoptr (GMenuItem) zoom_item = NULL;
- g_autoptr (GMenuItem) sort_item = NULL;
-
- new_sections = nautilus_window_slot_get_toolbar_menu_sections (slot);
-
- gtk_widget_set_sensitive (self->view_split_button, (new_sections != NULL));
- if (new_sections == NULL)
- {
- return;
- }
-
- /* Let's assume that sort section is the first item
- * in view_menu, as per nautilus-toolbar.ui. */
-
- sort_item = g_menu_item_new_from_model (self->view_menu, 0);
- g_menu_remove (G_MENU (self->view_menu), 0);
- g_menu_item_set_section (sort_item, new_sections->sort_section);
- g_menu_insert_item (G_MENU (self->view_menu), 0, sort_item);
-}
-
-
-static void
-disconnect_toolbar_menu_sections_change_handler (NautilusToolbar *self)
-{
- if (self->window_slot == NULL)
- {
- return;
- }
-
- g_signal_handlers_disconnect_by_func (self->window_slot,
- G_CALLBACK (on_slot_toolbar_menu_sections_changed),
- self);
-}
-
/* Called from on_window_slot_destroyed(), since bindings and signal handlers
* are automatically removed once the slot goes away.
*/
@@ -1324,9 +613,6 @@ nautilus_toolbar_set_window_slot_real (NautilusToolbar *self,
self, "searching",
G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
- on_slot_toolbar_menu_sections_changed (self, NULL, self->window_slot);
- g_signal_connect_swapped (self->window_slot, "notify::toolbar-menu-sections",
- G_CALLBACK (on_slot_toolbar_menu_sections_changed), self);
g_signal_connect_swapped (self->window_slot, "notify::extensions-background-menu",
G_CALLBACK (slot_on_extensions_background_menu_changed), self);
g_signal_connect_swapped (self->window_slot, "notify::templates-menu",
@@ -1363,7 +649,6 @@ nautilus_toolbar_set_window_slot (NautilusToolbar *self,
g_clear_pointer (&self->search_binding, g_binding_unbind);
- disconnect_toolbar_menu_sections_change_handler (self);
if (self->window_slot != NULL)
{
g_signal_handlers_disconnect_by_data (self->window_slot, self);
@@ -1386,9 +671,3 @@ nautilus_toolbar_is_menu_visible (NautilusToolbar *self)
return gtk_widget_is_visible (menu);
}
-
-gboolean
-nautilus_toolbar_is_operations_button_active (NautilusToolbar *self)
-{
- return gtk_widget_is_visible (GTK_WIDGET (self->operations_popover));
-}
diff --git a/src/resources/nautilus.gresource.xml b/src/resources/nautilus.gresource.xml
index 0b36a989a..153a45844 100644
--- a/src/resources/nautilus.gresource.xml
+++ b/src/resources/nautilus.gresource.xml
@@ -5,6 +5,8 @@
<file compressed="true">ui/nautilus-search-popover.ui</file>
<file>ui/nautilus-pathbar-context-menu.ui</file>
<file>ui/nautilus-toolbar.ui</file>
+ <file>ui/nautilus-toolbar-end.ui</file>
+ <file>ui/nautilus-toolbar-start.ui</file>
<file>ui/nautilus-toolbar-view-menu.ui</file>
<file>ui/nautilus-column-chooser.ui</file>
<file>ui/nautilus-list-view-column-editor.ui</file>
diff --git a/src/resources/ui/nautilus-toolbar-end.ui b/src/resources/ui/nautilus-toolbar-end.ui
new file mode 100644
index 000000000..22bcffc88
--- /dev/null
+++ b/src/resources/ui/nautilus-toolbar-end.ui
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <menu id="view_menu">
+ <section>
+ <attribute name="label" translatable="yes" context="menu item" comments="Translators: a menu item in a
group of sorting options in a toolbar menu, with criterions such as "A-Z" or "Last
Modified".">Sort</attribute>
+ <!--
+ Sort section.
+
+ The toolbar code assumes this is the second item of this menu model.
+ Its contents is provided by the view.
+ -->
+ </section>
+ <section>
+ <item>
+ <attribute name="label" translatable="yes">_Visible Columns…</attribute>
+ <attribute name="action">view.visible-columns</attribute>
+ <attribute name="hidden-when">action-missing</attribute>
+ </item>
+ </section>
+ </menu>
+ <object class="GtkPopover" id="operations_popover">
+ <property name="child">
+ <object class="GtkScrolledWindow">
+ <property name="hscrollbar_policy">never</property>
+ <property name="max_content_height">270</property>
+ <property name="propagate_natural_height">True</property>
+ <property name="child">
+ <object class="GtkListBox" id="operations_list">
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="selection-mode">none</property>
+ <property name="activate-on-single-click">False</property>
+ <style>
+ <class name="operations-list"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </property>
+ <signal name="notify::visible" handler="on_operations_popover_notify_visible"
object="NautilusToolbarEnd" swapped="yes"/>
+ </object>
+ <template class="NautilusToolbarEnd" parent="AdwBin">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSeparator">
+ <style>
+ <class name="spacer"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkRevealer" id="operations_revealer">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="transition_type">slide-right</property>
+ <property name="child">
+ <object class="GtkMenuButton" id="operations_button">
+ <property name="tooltip_text" translatable="yes">Show operations</property>
+ <property name="popover">operations_popover</property>
+ <child>
+ <object class="GtkDrawingArea" id="operations_icon">
+ <property name="width_request">16</property>
+ <property name="height_request">16</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ </object>
+ </child>
+ <style>
+ <class name="image-button"/>
+ </style>
+ </object>
+ </property>
+ </object>
+ </child>
+ <child>
+ <object class="AdwSplitButton" id="view_split_button">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="tooltip_text" translatable="yes">Toggle view</property>
+ <property name="action_name">slot.files-view-mode-toggle</property>
+ <property name="menu-model">view_menu</property>
+ <binding name="icon-name">
+ <lookup name="icon-name">
+ <lookup name="window-slot">NautilusToolbarEnd</lookup>
+ </lookup>
+ </binding>
+ <binding name="tooltip-text">
+ <lookup name="tooltip">
+ <lookup name="window-slot">NautilusToolbarEnd</lookup>
+ </lookup>
+ </binding>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
diff --git a/src/resources/ui/nautilus-toolbar-start.ui b/src/resources/ui/nautilus-toolbar-start.ui
new file mode 100644
index 000000000..86f45f3f4
--- /dev/null
+++ b/src/resources/ui/nautilus-toolbar-start.ui
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkPopoverMenu" id="back_menu"/>
+ <object class="GtkPopoverMenu" id="forward_menu"/>
+ <template class="NautilusToolbarStart" parent="AdwBin">
+ <property name="child">
+ <object class="GtkBox">
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="back_button">
+ <property name="tooltip_text" translatable="yes">Go back</property>
+ <property name="valign">center</property>
+ <property name="action_name">win.back</property>
+ <property name="icon_name">go-previous-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="forward_button">
+ <property name="tooltip_text" translatable="yes">Go forward</property>
+ <property name="valign">center</property>
+ <property name="action_name">win.forward</property>
+ <property name="icon_name">go-next-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparator">
+ <style>
+ <class name="spacer"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </property>
+ </template>
+</interface>
diff --git a/src/resources/ui/nautilus-toolbar.ui b/src/resources/ui/nautilus-toolbar.ui
index ccf4ee8fe..c324f6591 100644
--- a/src/resources/ui/nautilus-toolbar.ui
+++ b/src/resources/ui/nautilus-toolbar.ui
@@ -1,26 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
- <object class="GtkPopoverMenu" id="back_menu"/>
- <object class="GtkPopoverMenu" id="forward_menu"/>
- <menu id="view_menu">
- <section>
- <attribute name="label" translatable="yes" context="menu item" comments="Translators: a menu item in a
group of sorting options in a toolbar menu, with criterions such as "A-Z" or "Last
Modified".">Sort</attribute>
- <!--
- Sort section.
-
- The toolbar code assumes this is the second item of this menu model.
- Its contents is provided by the view.
- -->
- </section>
- <section>
- <item>
- <attribute name="label" translatable="yes">_Visible Columns…</attribute>
- <attribute name="action">view.visible-columns</attribute>
- <attribute name="hidden-when">action-missing</attribute>
- </item>
- </section>
- </menu>
<menu id="app_menu">
<section>
<item>
@@ -82,29 +62,6 @@
</item>
</section>
</menu>
- <object class="GtkPopover" id="operations_popover">
- <property name="child">
- <object class="GtkScrolledWindow">
- <property name="hscrollbar_policy">never</property>
- <property name="max_content_height">270</property>
- <property name="propagate_natural_height">True</property>
- <property name="child">
- <object class="GtkListBox" id="operations_list">
- <property name="margin_start">6</property>
- <property name="margin_end">6</property>
- <property name="margin_top">6</property>
- <property name="margin_bottom">6</property>
- <property name="selection-mode">none</property>
- <property name="activate-on-single-click">False</property>
- <style>
- <class name="operations-list"/>
- </style>
- </object>
- </property>
- </object>
- </property>
- <signal name="notify::visible" handler="on_operations_popover_notify_visible" object="NautilusToolbar"
swapped="yes"/>
- </object>
<template class="NautilusToolbar" parent="AdwBin">
<child>
<object class="AdwHeaderBar">
@@ -169,28 +126,8 @@
</object>
</child>
<child type="start">
- <object class="GtkButton" id="back_button">
- <property name="tooltip_text" translatable="yes">Go back</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="action_name">win.back</property>
- <property name="icon_name">go-previous-symbolic</property>
- </object>
- </child>
- <child type="start">
- <object class="GtkButton" id="forward_button">
- <property name="tooltip_text" translatable="yes">Go forward</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="action_name">win.forward</property>
- <property name="icon_name">go-next-symbolic</property>
- </object>
- </child>
- <child type="start">
- <object class="GtkSeparator">
- <style>
- <class name="spacer"/>
- </style>
+ <object class="NautilusToolbarStart">
+ <property name="window-slot" bind-source="NautilusToolbar" bind-property="window-slot"
bind-flags="sync-create"/>
</object>
</child>
<child type="end">
@@ -226,56 +163,12 @@
</object>
</child>
<child type="end">
- <object class="AdwSplitButton" id="view_split_button">
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="tooltip_text" translatable="yes">Toggle view</property>
- <property name="action_name">slot.files-view-mode-toggle</property>
- <property name="menu-model">view_menu</property>
- <binding name="icon-name">
- <lookup name="icon-name">
- <lookup name="window-slot">NautilusToolbar</lookup>
- </lookup>
- </binding>
- <binding name="tooltip-text">
- <lookup name="tooltip">
- <lookup name="window-slot">NautilusToolbar</lookup>
- </lookup>
- </binding>
- </object>
- </child>
- <child type="end">
- <object class="GtkRevealer" id="operations_revealer">
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="transition_type">slide-right</property>
- <property name="child">
- <object class="GtkMenuButton" id="operations_button">
- <property name="tooltip_text" translatable="yes">Show operations</property>
- <property name="popover">operations_popover</property>
- <child>
- <object class="GtkDrawingArea" id="operations_icon">
- <property name="width_request">16</property>
- <property name="height_request">16</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- </object>
- </child>
- <style>
- <class name="image-button"/>
- </style>
- </object>
- </property>
- </object>
- </child>
- <child type="end">
- <object class="GtkSeparator">
- <style>
- <class name="spacer"/>
- </style>
+ <object class="NautilusToolbarEnd">
+ <property name="window-slot" bind-source="NautilusToolbar" bind-property="window-slot"
bind-flags="sync-create"/>
</object>
</child>
</object>
</child>
</template>
</interface>
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]