From 6fc2fe67e99d50c5b9569867503a64c6df333a41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 16 Jun 2024 00:43:05 +0100 Subject: [PATCH] view-model: Support single selection mode This is going to be used in some modes by the FileChooser window. --- src/nautilus-files-view.c | 13 ++++--- src/nautilus-view-model.c | 71 +++++++++++++++++++++++++++++++-------- src/nautilus-view-model.h | 2 +- 3 files changed, 64 insertions(+), 22 deletions(-) diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 68ae70872..25a6e7725 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -9485,10 +9485,16 @@ nautilus_files_view_constructed (GObject *object) NautilusFilesView *self = NAUTILUS_FILES_VIEW (object); NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (self); + NautilusMode mode = nautilus_window_slot_get_mode (priv->slot); g_signal_connect_object (priv->slot, "notify::active", G_CALLBACK (slot_active_changed), self, G_CONNECT_DEFAULT); + + priv->model = nautilus_view_model_new (nautilus_mode_is_single_selection (mode)); + g_signal_connect_object (GTK_SELECTION_MODEL (priv->model), "selection-changed", + G_CALLBACK (nautilus_files_view_notify_selection_changed), self, + G_CONNECT_SWAPPED); } static void @@ -9683,13 +9689,6 @@ nautilus_files_view_init (NautilusFilesView *view) /* Ensure opaque background, to hide the view underneath it. */ gtk_widget_add_css_class (priv->empty_view_page, "view"); - priv->model = nautilus_view_model_new (); - g_signal_connect_object (GTK_SELECTION_MODEL (priv->model), - "selection-changed", - G_CALLBACK (nautilus_files_view_notify_selection_changed), - view, - G_CONNECT_SWAPPED); - /* Toolbar menu */ builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-toolbar-view-menu.ui"); priv->toolbar_menu_sections = g_new0 (NautilusToolbarMenuSections, 1); diff --git a/src/nautilus-view-model.c b/src/nautilus-view-model.c index 195266dbb..15176ce33 100644 --- a/src/nautilus-view-model.c +++ b/src/nautilus-view-model.c @@ -12,8 +12,9 @@ struct _NautilusViewModel GtkTreeListModel *tree_model; GtkSortListModel *sort_model; - GtkMultiSelection *selection_model; + GtkSelectionModel *selection_model; + gboolean single_selection; gboolean expand_as_a_tree; GList *cut_files; }; @@ -111,9 +112,8 @@ nautilus_view_model_is_selected (GtkSelectionModel *model, guint position) { NautilusViewModel *self = NAUTILUS_VIEW_MODEL (model); - GtkSelectionModel *selection_model = GTK_SELECTION_MODEL (self->selection_model); - return gtk_selection_model_is_selected (selection_model, position); + return gtk_selection_model_is_selected (self->selection_model, position); } static GtkBitset * @@ -122,9 +122,18 @@ nautilus_view_model_get_selection_in_range (GtkSelectionModel *model, guint n_items) { NautilusViewModel *self = NAUTILUS_VIEW_MODEL (model); - GtkSelectionModel *selection_model = GTK_SELECTION_MODEL (self->selection_model); - return gtk_selection_model_get_selection_in_range (selection_model, pos, n_items); + return gtk_selection_model_get_selection_in_range (self->selection_model, pos, n_items); +} + +static gboolean +nautilus_view_model_select_item (GtkSelectionModel *model, + guint position, + gboolean unselect_rest) +{ + NautilusViewModel *self = NAUTILUS_VIEW_MODEL (model); + + return gtk_selection_model_select_item (self->selection_model, position, unselect_rest); } static gboolean @@ -133,12 +142,18 @@ nautilus_view_model_set_selection (GtkSelectionModel *model, GtkBitset *mask) { NautilusViewModel *self = NAUTILUS_VIEW_MODEL (model); - GtkSelectionModel *selection_model = GTK_SELECTION_MODEL (self->selection_model); - gboolean res; - res = gtk_selection_model_set_selection (selection_model, selected, mask); + return gtk_selection_model_set_selection (self->selection_model, selected, mask); +} - return res; + +static gboolean +nautilus_view_model_unselect_item (GtkSelectionModel *model, + guint position) +{ + NautilusViewModel *self = NAUTILUS_VIEW_MODEL (model); + + return gtk_selection_model_unselect_item (self->selection_model, position); } @@ -147,7 +162,9 @@ nautilus_view_model_selection_model_init (GtkSelectionModelInterface *iface) { iface->is_selected = nautilus_view_model_is_selected; iface->get_selection_in_range = nautilus_view_model_get_selection_in_range; + iface->select_item = nautilus_view_model_select_item; iface->set_selection = nautilus_view_model_set_selection; + iface->unselect_item = nautilus_view_model_unselect_item; } G_DEFINE_TYPE_WITH_CODE (NautilusViewModel, nautilus_view_model, G_TYPE_OBJECT, @@ -161,6 +178,7 @@ G_DEFINE_TYPE_WITH_CODE (NautilusViewModel, nautilus_view_model, G_TYPE_OBJECT, enum { PROP_0, + PROP_SINGLE_SELECTION, PROP_SORTER, N_PROPS }; @@ -244,6 +262,12 @@ set_property (GObject *object, switch (prop_id) { + case PROP_SINGLE_SELECTION: + { + self->single_selection = g_value_get_boolean (value); + } + break; + case PROP_SORTER: { nautilus_view_model_set_sorter (self, g_value_get_object (value)); @@ -292,7 +316,21 @@ constructed (GObject *object) (GtkTreeListModelCreateModelFunc) create_model_func, self, NULL); self->sort_model = gtk_sort_list_model_new (g_object_ref (G_LIST_MODEL (self->tree_model)), NULL); - self->selection_model = gtk_multi_selection_new (g_object_ref (G_LIST_MODEL (self->sort_model))); + + if (self->single_selection) + { + GtkSingleSelection *single = gtk_single_selection_new (NULL); + + gtk_single_selection_set_autoselect (single, FALSE); + gtk_single_selection_set_can_unselect (single, TRUE); + + gtk_single_selection_set_model (single, G_LIST_MODEL (self->sort_model)); + self->selection_model = GTK_SELECTION_MODEL (single); + } + else + { + self->selection_model = GTK_SELECTION_MODEL (gtk_multi_selection_new (g_object_ref (G_LIST_MODEL (self->sort_model)))); + } self->map_files_to_model = g_hash_table_new (NULL, NULL); self->directory_reverse_map = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref); @@ -316,9 +354,12 @@ nautilus_view_model_class_init (NautilusViewModelClass *klass) object_class->set_property = set_property; object_class->constructed = constructed; + properties[PROP_SINGLE_SELECTION] = + g_param_spec_boolean ("single-selection", NULL, NULL, + FALSE, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); properties[PROP_SORTER] = - g_param_spec_object ("sorter", - "", "", + g_param_spec_object ("sorter", NULL, NULL, GTK_TYPE_SORTER, G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); @@ -346,9 +387,11 @@ compare_data_func (gconstpointer a, } NautilusViewModel * -nautilus_view_model_new (void) +nautilus_view_model_new (gboolean single_selection) { - return g_object_new (NAUTILUS_TYPE_VIEW_MODEL, NULL); + return g_object_new (NAUTILUS_TYPE_VIEW_MODEL, + "single-selection", single_selection, + NULL); } GtkSorter * diff --git a/src/nautilus-view-model.h b/src/nautilus-view-model.h index 37260d2ce..714a7158f 100644 --- a/src/nautilus-view-model.h +++ b/src/nautilus-view-model.h @@ -10,7 +10,7 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (NautilusViewModel, nautilus_view_model, NAUTILUS, VIEW_MODEL, GObject) -NautilusViewModel * nautilus_view_model_new (void); +NautilusViewModel * nautilus_view_model_new (gboolean single_selection); GtkSorter *nautilus_view_model_get_sorter (NautilusViewModel *self); void nautilus_view_model_set_sorter (NautilusViewModel *self,