/* * Copyright (C) 2022 The GNOME project contributors * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "nautilus-view-controls.h" #include "nautilus-file.h" #include "nautilus-file-utilities.h" #include "nautilus-scheme.h" #include "nautilus-ui-utilities.h" #include "nautilus-window-slot.h" #include /* Assume sort section is second item in view_menu. See nautilus-view-controls.blp */ #define SORT_ITEM_POSITION 1 struct _NautilusViewControls { AdwBin parent_instance; GtkWidget *view_split_button; GMenuModel *view_menu; GMenuModel *sort_section; NautilusWindowSlot *window_slot; }; G_DEFINE_FINAL_TYPE (NautilusViewControls, nautilus_view_controls, ADW_TYPE_BIN); enum { PROP_0, PROP_WINDOW_SLOT, N_PROPS }; static GParamSpec *properties[N_PROPS]; static void update_sort_section (NautilusViewControls *self, NautilusFile *file) { const char *action; /* When not in the special location, set an inexistant action to hide the * menu item. This works under the assumptiont that the menu item has its * "hidden-when" attribute set to "action-disabled", and that an inexistant * action is treated as a disabled action. */ action = nautilus_file_is_in_trash (file) ? "view.sort" : "doesnt-exist"; nautilus_menu_item_change_attribute (self->sort_section, "last_trashed", G_MENU_ATTRIBUTE_ACTION, action); action = nautilus_file_is_in_recent (file) ? "view.sort" : "doesnt-exist"; nautilus_menu_item_change_attribute (self->sort_section, "recency", G_MENU_ATTRIBUTE_ACTION, action); action = nautilus_file_is_in_search (file) ? "view.sort" : "doesnt-exist"; nautilus_menu_item_change_attribute (self->sort_section, "relevance", G_MENU_ATTRIBUTE_ACTION, action); } static void adjust_to_location (NautilusViewControls *self, GParamSpec *param, NautilusWindowSlot *slot) { GFile *location = nautilus_window_slot_get_location (slot); gboolean has_menu = location != NULL && !nautilus_is_root_for_scheme (location, SCHEME_NETWORK_VIEW); gtk_widget_set_sensitive (self->view_split_button, has_menu); if (!has_menu) { return; } g_autoptr (NautilusFile) file = nautilus_file_get (location); update_sort_section (self, file); } static void on_tooltip_changed (NautilusViewControls *self, GParamSpec *param, NautilusWindowSlot *slot) { const gchar *description; const gchar *tooltip = nautilus_window_slot_get_tooltip_with_description (slot, &description); if (tooltip == NULL) { return; } gtk_accessible_update_property (GTK_ACCESSIBLE (self->view_split_button), GTK_ACCESSIBLE_PROPERTY_LABEL, tooltip, GTK_ACCESSIBLE_PROPERTY_DESCRIPTION, description, -1); } static void disconnect_toolbar_menu_sections_change_handler (NautilusViewControls *self) { if (self->window_slot == NULL) { return; } g_signal_handlers_disconnect_by_func (self->window_slot, G_CALLBACK (adjust_to_location), self); g_signal_handlers_disconnect_by_func (self->window_slot, G_CALLBACK (on_tooltip_changed), self); } static void nautilus_view_controls_set_window_slot (NautilusViewControls *self, NautilusWindowSlot *window_slot) { g_return_if_fail (NAUTILUS_IS_VIEW_CONTROLS (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) { adjust_to_location (self, NULL, self->window_slot); g_signal_connect_swapped (self->window_slot, "notify::location", G_CALLBACK (adjust_to_location), self); g_signal_connect_swapped (self->window_slot, "notify::tooltip", G_CALLBACK (on_tooltip_changed), self); } g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WINDOW_SLOT]); } static void nautilus_view_controls_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { NautilusViewControls *self = NAUTILUS_VIEW_CONTROLS (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_view_controls_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NautilusViewControls *self = NAUTILUS_VIEW_CONTROLS (object); switch (prop_id) { case PROP_WINDOW_SLOT: { nautilus_view_controls_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_view_controls_dispose (GObject *obj) { NautilusViewControls *self = NAUTILUS_VIEW_CONTROLS (obj); disconnect_toolbar_menu_sections_change_handler (self); adw_bin_set_child (ADW_BIN (self), NULL); gtk_widget_dispose_template (GTK_WIDGET (self), NAUTILUS_TYPE_VIEW_CONTROLS); G_OBJECT_CLASS (nautilus_view_controls_parent_class)->dispose (obj); } static void nautilus_view_controls_finalize (GObject *obj) { NautilusViewControls *self = NAUTILUS_VIEW_CONTROLS (obj); g_clear_object (&self->sort_section); g_clear_object (&self->window_slot); G_OBJECT_CLASS (nautilus_view_controls_parent_class)->finalize (obj); } static void nautilus_view_controls_class_init (NautilusViewControlsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = nautilus_view_controls_dispose; object_class->finalize = nautilus_view_controls_finalize; object_class->get_property = nautilus_view_controls_get_property; object_class->set_property = nautilus_view_controls_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-view-controls.ui"); gtk_widget_class_bind_template_child (widget_class, NautilusViewControls, view_menu); gtk_widget_class_bind_template_child (widget_class, NautilusViewControls, view_split_button); } static void nautilus_view_controls_init (NautilusViewControls *self) { gtk_widget_init_template (GTK_WIDGET (self)); g_autoptr (GtkBuilder) builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/menu/nautilus-toolbar-view-menu.ui"); g_autoptr (GMenuItem) sort_item = g_menu_item_new_from_model (self->view_menu, SORT_ITEM_POSITION); self->sort_section = G_MENU_MODEL (g_object_ref (gtk_builder_get_object (builder, "sort_section"))); g_menu_item_set_section (sort_item, self->sort_section); g_menu_insert_item (G_MENU (self->view_menu), SORT_ITEM_POSITION, sort_item); }