From d2f2c46027d3c904e0b9a79f192b6ab784575ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sat, 13 Jan 2024 22:55:44 +0000 Subject: [PATCH 01/12] files-view: Drop .get_backing_uri() virtual method Have NautilusListBase provide a virtual method for list view to implement instead. --- src/nautilus-files-view.c | 32 +++++++++++++------------------- src/nautilus-files-view.h | 8 -------- src/nautilus-list-base.c | 24 ++++++++++++++++++++++++ src/nautilus-list-base.h | 9 +++++++-- src/nautilus-list-view.c | 39 ++++++++++++++++++--------------------- 5 files changed, 62 insertions(+), 50 deletions(-) diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 926658816d..536347662c 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -734,23 +734,6 @@ real_end_loading (NautilusFilesView *self, update_cut_status (self); } -static char * -real_get_backing_uri (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); - - priv = nautilus_files_view_get_instance_private (view); - - if (priv->directory == NULL) - { - return NULL; - } - - return nautilus_directory_get_uri (priv->directory); -} - /** * * nautilus_files_view_get_backing_uri: @@ -764,7 +747,19 @@ nautilus_files_view_get_backing_uri (NautilusFilesView *view) { g_return_val_if_fail (NAUTILUS_IS_FILES_VIEW (view), NULL); - return NAUTILUS_FILES_VIEW_CLASS (G_OBJECT_GET_CLASS (view))->get_backing_uri (view); + NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); + g_autoptr (NautilusViewItem) item = nautilus_list_base_get_backing_item (NAUTILUS_LIST_BASE (view)); + + if (item != NULL) + { + return nautilus_file_get_uri (nautilus_view_item_get_file (item)); + } + else if (priv->directory != NULL) + { + return nautilus_directory_get_uri (priv->directory); + } + + return NULL; } /** @@ -9538,7 +9533,6 @@ nautilus_files_view_class_init (NautilusFilesViewClass *klass) klass->end_file_changes = real_end_file_changes; klass->begin_loading = real_begin_loading; klass->end_loading = real_end_loading; - klass->get_backing_uri = real_get_backing_uri; klass->update_context_menus = real_update_context_menus; klass->update_actions_state = real_update_actions_state; klass->check_empty_states = real_check_empty_states; diff --git a/src/nautilus-files-view.h b/src/nautilus-files-view.h index 3c198d7347..fdee33a208 100644 --- a/src/nautilus-files-view.h +++ b/src/nautilus-files-view.h @@ -98,14 +98,6 @@ struct _NautilusFilesViewClass { /* Function pointers that don't have corresponding signals */ - /* get_backing uri is a function pointer for subclasses to - * override. Subclasses may replace it with a function that - * returns the URI for the location where to create new folders, - * files, links and paste the clipboard to. - */ - - char * (* get_backing_uri) (NautilusFilesView *view); - /* update_menus is a function pointer that subclasses can override to * update the sensitivity or wording of menu items in the menu bar. * It is called (at least) whenever the selection changes. If overridden, diff --git a/src/nautilus-list-base.c b/src/nautilus-list-base.c index be2bdbeb5b..45f49b96f8 100644 --- a/src/nautilus-list-base.c +++ b/src/nautilus-list-base.c @@ -945,6 +945,12 @@ nautilus_list_base_get_selected_item_ui (NautilusListBase *self) return nautilus_view_item_get_item_ui (item); } +static NautilusViewItem * +default_get_backing_item (NautilusListBase *self) +{ + return NULL; +} + static void default_preview_selection_event (NautilusListBase *self, GtkDirectionType direction) @@ -1091,6 +1097,7 @@ nautilus_list_base_class_init (NautilusListBaseClass *klass) widget_class->focus = nautilus_list_base_focus; + klass->get_backing_item = default_get_backing_item; klass->preview_selection_event = default_preview_selection_event; klass->setup_directory = base_setup_directory; @@ -1203,6 +1210,23 @@ nautilus_list_base_setup_gestures (NautilusListBase *self) priv->view_drop_target = drop_target; } +/** + * nautilus_list_base_get_backing_item: + * + * Get a view item representing the subdirectory which, based on user action, + * should be used in place the view directory when performing file operations + * such as create new folders, paste from the clipboard, etc. + * + * If the view directory should be used, NULL is returned instead. + * + * Returns: (transfer full) (nullable): The subdirectory backing file operations. + */ +NautilusViewItem * +nautilus_list_base_get_backing_item (NautilusListBase *self) +{ + return NAUTILUS_LIST_BASE_CLASS (G_OBJECT_GET_CLASS (self))->get_backing_item (self); +} + NautilusViewInfo nautilus_list_base_get_view_info (NautilusListBase *self) { diff --git a/src/nautilus-list-base.h b/src/nautilus-list-base.h index 067b76cd87..1e92dd814f 100644 --- a/src/nautilus-list-base.h +++ b/src/nautilus-list-base.h @@ -27,13 +27,12 @@ struct _NautilusListBaseClass { NautilusFilesViewClass parent_class; + /* Subclasses must provide implementation. */ NautilusViewInfo (*get_view_info) (NautilusListBase *self); guint (*get_icon_size) (NautilusListBase *self); GVariant *(*get_sort_state) (NautilusListBase *self); GtkWidget *(*get_view_ui) (NautilusListBase *self); int (*get_zoom_level) (NautilusListBase *self); - void (*preview_selection_event) (NautilusListBase *self, - GtkDirectionType direction); void (*scroll_to) (NautilusListBase *self, guint position, GtkListScrollFlags flags, @@ -43,11 +42,17 @@ struct _NautilusListBaseClass void (*set_zoom_level) (NautilusListBase *self, int new_zoom_level); + /* Subclasses may override base implementation. */ + NautilusViewItem *(*get_backing_item) (NautilusListBase *self); + void (*preview_selection_event) (NautilusListBase *self, + GtkDirectionType direction); + /* Subclass override must chain-up to base implementation. */ void (*setup_directory) (NautilusListBase *self, NautilusDirectory *directory); }; +NautilusViewItem *nautilus_list_base_get_backing_item (NautilusListBase *self); GtkWidget *nautilus_list_base_get_selected_item_ui (NautilusListBase *self); GVariant *nautilus_list_base_get_sort_state (NautilusListBase *self); NautilusViewInfo nautilus_list_base_get_view_info (NautilusListBase *self) G_GNUC_PURE; diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index aac6a185c8..150ba5ed65 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -606,16 +606,16 @@ get_default_zoom_level (void) list_view_info.zoom_level_max); } -static char * -real_get_backing_uri (NautilusFilesView *view) +static NautilusViewItem * +real_get_backing_item (NautilusListBase *list_base) { - NautilusListView *self = NAUTILUS_LIST_VIEW (view); - NautilusViewModel *model = nautilus_list_base_get_model (NAUTILUS_LIST_BASE (self)); - g_autoptr (NautilusFile) common_parent = NULL; + NautilusListView *self = NAUTILUS_LIST_VIEW (list_base); + NautilusViewModel *model = nautilus_list_base_get_model (list_base); + g_autoptr (GtkTreeListRow) common_parent = NULL; if (!self->expand_as_a_tree) { - return NAUTILUS_FILES_VIEW_CLASS (nautilus_list_view_parent_class)->get_backing_uri (view); + return NULL; } /* If we are using tree expanders use the items parent, unless it @@ -626,38 +626,37 @@ real_get_backing_uri (NautilusFilesView *view) for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (model)); i++) { g_autoptr (GtkTreeListRow) row = g_list_model_get_item (G_LIST_MODEL (model), i); - g_autoptr (NautilusViewItem) item = NULL; - g_autoptr (NautilusFile) parent_file = NULL; - NautilusFile *file; - NautilusFile *current_parent; + g_autoptr (GtkTreeListRow) parent = gtk_tree_list_row_get_parent (row); + GtkTreeListRow *current_parent; if (!gtk_selection_model_is_selected (GTK_SELECTION_MODEL (model), i)) { continue; } - item = gtk_tree_list_row_get_item (row); - file = nautilus_view_item_get_file (item); - parent_file = nautilus_file_get_parent (file); - current_parent = gtk_tree_list_row_get_expanded (row) ? file : parent_file; + current_parent = gtk_tree_list_row_get_expanded (row) ? row : parent; + if (current_parent == NULL) + { + return NULL; + } if (common_parent == NULL) { - common_parent = nautilus_file_ref (current_parent); + common_parent = g_object_ref (current_parent); } else if (current_parent != common_parent) { - g_clear_pointer (&common_parent, nautilus_file_unref); + g_clear_object (&common_parent); break; } } if (common_parent != NULL) { - return nautilus_file_get_uri (common_parent); + return gtk_tree_list_row_get_item (common_parent); } - return NAUTILUS_FILES_VIEW_CLASS (nautilus_list_view_parent_class)->get_backing_uri (view); + return NULL; } typedef struct @@ -1216,14 +1215,12 @@ static void nautilus_list_view_class_init (NautilusListViewClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NautilusFilesViewClass *files_view_class = NAUTILUS_FILES_VIEW_CLASS (klass); NautilusListBaseClass *list_base_view_class = NAUTILUS_LIST_BASE_CLASS (klass); object_class->dispose = nautilus_list_view_dispose; object_class->finalize = nautilus_list_view_finalize; - files_view_class->get_backing_uri = real_get_backing_uri; - + list_base_view_class->get_backing_item = real_get_backing_item; list_base_view_class->get_icon_size = real_get_icon_size; list_base_view_class->get_sort_state = real_get_sort_state; list_base_view_class->get_view_info = real_get_view_info; -- GitLab From 5b7ac54ac673102f564275e564d761536d650893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 21 Jan 2024 22:33:21 +0000 Subject: [PATCH 02/12] list-view: Optimize .get_backing_item() Iterate only the selection, not the whole model. --- src/nautilus-list-view.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 150ba5ed65..c3d30bae6a 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -610,8 +610,6 @@ static NautilusViewItem * real_get_backing_item (NautilusListBase *list_base) { NautilusListView *self = NAUTILUS_LIST_VIEW (list_base); - NautilusViewModel *model = nautilus_list_base_get_model (list_base); - g_autoptr (GtkTreeListRow) common_parent = NULL; if (!self->expand_as_a_tree) { @@ -622,19 +620,20 @@ real_get_backing_item (NautilusListBase *list_base) * is an expanded folder, in which case we should use that folder directly. * When dealing with multiple selections, use the same rules, but only * if a common parent exists. */ + NautilusViewModel *model = nautilus_list_base_get_model (list_base); + g_autoptr (GtkBitset) selection = gtk_selection_model_get_selection (GTK_SELECTION_MODEL (model)); + g_autoptr (GtkTreeListRow) common_parent = NULL; + GtkBitsetIter iter; + guint i; - for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (model)); i++) + for (gtk_bitset_iter_init_first (&iter, selection, &i); + gtk_bitset_iter_is_valid (&iter); + gtk_bitset_iter_next (&iter, &i)) { g_autoptr (GtkTreeListRow) row = g_list_model_get_item (G_LIST_MODEL (model), i); g_autoptr (GtkTreeListRow) parent = gtk_tree_list_row_get_parent (row); - GtkTreeListRow *current_parent; - - if (!gtk_selection_model_is_selected (GTK_SELECTION_MODEL (model), i)) - { - continue; - } + GtkTreeListRow *current_parent = gtk_tree_list_row_get_expanded (row) ? row : parent; - current_parent = gtk_tree_list_row_get_expanded (row) ? row : parent; if (current_parent == NULL) { return NULL; -- GitLab From 566a6522856cdc9292c4293c99dec3d363731b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sat, 13 Jan 2024 23:04:15 +0000 Subject: [PATCH 03/12] files-view: Drop get_nautilus_window_slot() Reload the list view via calling the respective action on self. This removes the last external usage of `get_nautilus_window_slot`. --- src/nautilus-files-view.c | 18 +++--------------- src/nautilus-files-view.h | 3 --- src/nautilus-list-view.c | 5 +---- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 536347662c..4de754eb1f 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -1220,18 +1220,6 @@ nautilus_files_view_get_window (NautilusFilesView *view) return nautilus_window_slot_get_window (priv->slot); } -NautilusWindowSlot * -nautilus_files_view_get_nautilus_window_slot (NautilusFilesView *view) -{ - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - g_assert (priv->slot != NULL); - - return priv->slot; -} - /* Returns the GtkWindow that this directory view occupies, or NULL * if at the moment this directory view is not in a GtkWindow or the * GtkWindow cannot be determined. Primarily used for parenting dialogs. @@ -1441,7 +1429,8 @@ action_open_item_location (GSimpleAction *action, GVariant *state, gpointer user_data) { - NautilusFilesView *view; + NautilusFilesView *view = NAUTILUS_FILES_VIEW (user_data); + NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); g_autolist (NautilusFile) selection = NULL; NautilusFile *item; GFile *activation_location; @@ -1449,7 +1438,6 @@ action_open_item_location (GSimpleAction *action, NautilusFile *parent; g_autoptr (GFile) parent_location = NULL; - view = NAUTILUS_FILES_VIEW (user_data); selection = nautilus_view_get_selection (NAUTILUS_VIEW (view)); if (!selection) @@ -1474,7 +1462,7 @@ action_open_item_location (GSimpleAction *action, nautilus_application_open_location_full (NAUTILUS_APPLICATION (g_application_get_default ()), parent_location, 0, selection, NULL, - nautilus_files_view_get_nautilus_window_slot (view)); + priv->slot); nautilus_file_unref (parent); nautilus_file_unref (activation_file); diff --git a/src/nautilus-files-view.h b/src/nautilus-files-view.h index fdee33a208..3f6cdaa36a 100644 --- a/src/nautilus-files-view.h +++ b/src/nautilus-files-view.h @@ -115,9 +115,6 @@ struct _NautilusFilesViewClass { NautilusFilesView * nautilus_files_view_new (guint id, NautilusWindowSlot *slot); -/* Functions callable from the user interface and elsewhere. */ -NautilusWindowSlot *nautilus_files_view_get_nautilus_window_slot (NautilusFilesView *view); - /* Wrappers for signal emitters. These are normally called * only by NautilusFilesView itself. They have corresponding signals * that observers might want to connect with. diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index c3d30bae6a..d5f292ad31 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -1101,10 +1101,7 @@ setup_view_columns (NautilusListView *self) static void nautilus_list_view_reload (NautilusListView *self) { - NautilusWindowSlot *slot; - - slot = nautilus_files_view_get_nautilus_window_slot (NAUTILUS_FILES_VIEW (self)); - nautilus_window_slot_queue_reload (slot); + gtk_widget_activate_action (GTK_WIDGET (self), "win.reload", NULL); } static void -- GitLab From a9acad6938d2ef9ef26489925578570986ec3074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 14 Jan 2024 00:09:41 +0000 Subject: [PATCH 04/12] list-view: Assume GtkTreeListRow:item is non-NULL gtk_tree_list_row_get_item() is only marked as nullable for backwards compatibility reasons. In the gtk version we depend on this is never NULL. --- src/nautilus-list-view.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index d5f292ad31..e7a98a9908 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -709,7 +709,7 @@ unload_file_timeout (gpointer data) { g_autoptr (GtkTreeListRow) row = g_list_model_get_item (G_LIST_MODEL (model), i); g_autoptr (NautilusViewItem) item = gtk_tree_list_row_get_item (row); - if (item != NULL && item == unload_data->item) + if (item == unload_data->item) { if (gtk_tree_list_row_get_expanded (row)) { @@ -765,12 +765,6 @@ on_row_expanded_changed (GObject *gobject, gboolean expanded; item = NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (row)); - if (item == NULL) - { - /* Row has been destroyed. */ - return; - } - directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); expanded = gtk_tree_list_row_get_expanded (row); if (expanded) -- GitLab From e5ce4db3f8c8f1f59a0f43221f08832f46c9129e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 14 Jan 2024 00:26:28 +0000 Subject: [PATCH 05/12] view-item: Refine subfolder loading property --- src/nautilus-name-cell.c | 11 ++++------- src/nautilus-view-item.c | 33 ++++++++++++++++++++++----------- src/nautilus-view-item.h | 1 + 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/nautilus-name-cell.c b/src/nautilus-name-cell.c index f18a83efbd..61f588eaac 100644 --- a/src/nautilus-name-cell.c +++ b/src/nautilus-name-cell.c @@ -277,13 +277,10 @@ on_loading_timeout (gpointer user_data) { NautilusNameCell *self = NAUTILUS_NAME_CELL (user_data); g_autoptr (NautilusViewItem) item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self)); - gboolean is_loading; + gboolean is_loading = nautilus_view_item_get_loading (item); self->loading_timeout_id = 0; - g_object_get (item, - "is-loading", &is_loading, - NULL); if (is_loading) { gtk_widget_set_visible (self->spinner, TRUE); @@ -296,11 +293,11 @@ on_loading_timeout (gpointer user_data) static void on_item_is_loading_changed (NautilusNameCell *self) { - gboolean is_loading; g_autoptr (NautilusViewItem) item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self)); + gboolean is_loading = nautilus_view_item_get_loading (item); g_clear_handle_id (&self->loading_timeout_id, g_source_remove); - g_object_get (item, "is-loading", &is_loading, NULL); + if (is_loading) { self->loading_timeout_id = g_timeout_add_seconds (LOADING_TIMEOUT_SECONDS, @@ -356,7 +353,7 @@ nautilus_name_cell_init (NautilusNameCell *self) (GCallback) on_item_drag_accept_changed, self); g_signal_group_connect_swapped (self->item_signal_group, "notify::is-cut", (GCallback) on_item_is_cut_changed, self); - g_signal_group_connect_swapped (self->item_signal_group, "notify::is-loading", + g_signal_group_connect_swapped (self->item_signal_group, "notify::loading", (GCallback) on_item_is_loading_changed, self); g_signal_group_connect_swapped (self->item_signal_group, "file-changed", (GCallback) on_file_changed, self); diff --git a/src/nautilus-view-item.c b/src/nautilus-view-item.c index b83862b78f..6c2247c1eb 100644 --- a/src/nautilus-view-item.c +++ b/src/nautilus-view-item.c @@ -11,7 +11,7 @@ struct _NautilusViewItem GObject parent_instance; gboolean is_cut; gboolean drag_accept; - gboolean is_loading; + gboolean loading; NautilusFile *file; GtkWidget *item_ui; }; @@ -24,7 +24,7 @@ enum PROP_FILE, PROP_IS_CUT, PROP_DRAG_ACCEPT, - PROP_IS_LOADING, + PROP_LOADING, N_PROPS }; @@ -86,9 +86,9 @@ nautilus_view_item_get_property (GObject *object, } break; - case PROP_IS_LOADING: + case PROP_LOADING: { - g_value_set_boolean (value, self->is_loading); + g_value_set_boolean (value, self->loading); } break; @@ -127,9 +127,9 @@ nautilus_view_item_set_property (GObject *object, } break; - case PROP_IS_LOADING: + case PROP_LOADING: { - self->is_loading = g_value_get_boolean (value); + nautilus_view_item_set_loading (self, g_value_get_boolean (value)); } break; @@ -167,10 +167,9 @@ nautilus_view_item_class_init (NautilusViewItemClass *klass) "", "", NAUTILUS_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - properties[PROP_IS_LOADING] = g_param_spec_boolean ("is-loading", - "", "", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + properties[PROP_LOADING] = g_param_spec_boolean ("loading", NULL, NULL, + FALSE, + G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPS, properties); signals[FILE_CHANGED] = g_signal_new ("file-changed", @@ -208,13 +207,25 @@ nautilus_view_item_set_drag_accept (NautilusViewItem *self, g_object_set (self, "drag-accept", drag_accept, NULL); } +gboolean +nautilus_view_item_get_loading (NautilusViewItem *self) +{ + g_return_val_if_fail (NAUTILUS_IS_VIEW_ITEM (self), FALSE); + + return self->loading; +} + void nautilus_view_item_set_loading (NautilusViewItem *self, gboolean loading) { g_return_if_fail (NAUTILUS_IS_VIEW_ITEM (self)); - g_object_set (self, "is-loading", loading, NULL); + if (self->loading != loading) + { + self->loading = loading; + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LOADING]); + } } NautilusFile * diff --git a/src/nautilus-view-item.h b/src/nautilus-view-item.h index 6b21645f59..42f74a708c 100644 --- a/src/nautilus-view-item.h +++ b/src/nautilus-view-item.h @@ -23,6 +23,7 @@ void nautilus_view_item_set_cut (NautilusViewItem *self, gboolean is_cut); void nautilus_view_item_set_drag_accept (NautilusViewItem *self, gboolean drag_accept); +gboolean nautilus_view_item_get_loading (NautilusViewItem *self); void nautilus_view_item_set_loading (NautilusViewItem *self, gboolean is_loading); -- GitLab From c5e56ecaeb32c521be69f9220a2fa6d5efbb6bf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 14 Jan 2024 15:27:28 +0000 Subject: [PATCH 06/12] files-view: Handle directory load state correctly Multiple subdirectories may be loading at the same time, so it's incorrect to set .subdirectory_loading to FALSE when one of them is done loading. Instead keep a list of subdirectories which are loading. --- src/nautilus-files-view.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 4de754eb1f..d88c823c98 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -212,7 +212,6 @@ typedef struct * after it finishes loading the directory and its view. */ gboolean loading; - gboolean subdirectory_loading; gboolean in_destruction; @@ -224,6 +223,7 @@ typedef struct gboolean metadata_for_files_in_directory_pending; GList *subdirectory_list; + GList *subdirectories_loading; GMenu *selection_menu_model; GMenu *background_menu_model; @@ -3332,6 +3332,7 @@ nautilus_files_view_dispose (GObject *object) remove_directory_from_templates_directory_list (view, node->data); } + g_clear_pointer (&priv->subdirectories_loading, g_list_free); while (priv->subdirectory_list != NULL) { nautilus_files_view_remove_subdirectory (view, @@ -4595,7 +4596,7 @@ queue_pending_files (NautilusFilesView *view, * search it can be a long wait, and we actually want to show files as * they are getting found. So for search is fine if not all files are * seen */ - if ((!priv->loading && !priv->subdirectory_loading) || + if ((!priv->loading && priv->subdirectories_loading == NULL) || (nautilus_directory_are_all_files_seen (directory) || nautilus_view_is_searching (NAUTILUS_VIEW (view)))) { @@ -4807,7 +4808,7 @@ subdirectory_done_loading (NautilusDirectory *directory, NautilusFilesView *view = user_data; NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); - priv->subdirectory_loading = FALSE; + priv->subdirectories_loading = g_list_remove (priv->subdirectories_loading, directory); } void @@ -4815,11 +4816,7 @@ nautilus_files_view_add_subdirectory (NautilusFilesView *view, NautilusDirectory *directory) { NautilusFileAttributes attributes; - NautilusFilesViewPrivate *priv; - - priv = nautilus_files_view_get_instance_private (view); - - priv->subdirectory_loading = TRUE; + NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); g_return_if_fail (!g_list_find (priv->subdirectory_list, directory)); @@ -4848,23 +4845,20 @@ nautilus_files_view_add_subdirectory (NautilusFilesView *view, G_CALLBACK (subdirectory_done_loading), view, 0); - priv->subdirectory_list = g_list_prepend ( - priv->subdirectory_list, directory); + priv->subdirectory_list = g_list_prepend (priv->subdirectory_list, directory); + priv->subdirectories_loading = g_list_prepend (priv->subdirectories_loading, directory); } void nautilus_files_view_remove_subdirectory (NautilusFilesView *view, NautilusDirectory *directory) { - NautilusFilesViewPrivate *priv; - priv = nautilus_files_view_get_instance_private (view); - - priv->subdirectory_loading = FALSE; + NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); g_return_if_fail (g_list_find (priv->subdirectory_list, directory)); - priv->subdirectory_list = g_list_remove ( - priv->subdirectory_list, directory); + priv->subdirectory_list = g_list_remove (priv->subdirectory_list, directory); + priv->subdirectories_loading = g_list_remove (priv->subdirectories_loading, directory); g_signal_handlers_disconnect_by_func (directory, G_CALLBACK (files_added_callback), @@ -8671,6 +8665,7 @@ load_directory (NautilusFilesView *view, */ schedule_update_context_menus (view); + g_clear_pointer (&priv->subdirectories_loading, g_list_free); while (priv->subdirectory_list != NULL) { nautilus_files_view_remove_subdirectory (view, -- GitLab From 36fec089ec60c608a8fdd0a27049d733832c9cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 14 Jan 2024 15:35:03 +0000 Subject: [PATCH 07/12] list-view: Stop handling NautilusDirectory:done-loading That's the job of NautilusFilesView, and, incidentally, it already handles it. So, it may as well take care of everything. However, NautilusFilesView has no access to the expander, so the NautilusNameCell itself takes over that job. As it should. --- src/nautilus-files-view.c | 22 ++++++++++++++++++++++ src/nautilus-list-view.c | 30 ------------------------------ src/nautilus-name-cell.c | 6 ++++++ 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index d88c823c98..b2d715cbd5 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -4807,8 +4807,15 @@ subdirectory_done_loading (NautilusDirectory *directory, { NautilusFilesView *view = user_data; NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); + g_autoptr (NautilusFile) file = nautilus_directory_get_corresponding_file (directory); + NautilusViewItem *item = nautilus_view_model_get_item_for_file (priv->model, file); priv->subdirectories_loading = g_list_remove (priv->subdirectories_loading, directory); + + if (item != NULL) + { + nautilus_view_item_set_loading (item, FALSE); + } } void @@ -4817,6 +4824,8 @@ nautilus_files_view_add_subdirectory (NautilusFilesView *view, { NautilusFileAttributes attributes; NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); + g_autoptr (NautilusFile) file = nautilus_directory_get_corresponding_file (directory); + NautilusViewItem *item = nautilus_view_model_get_item_for_file (priv->model, file); g_return_if_fail (!g_list_find (priv->subdirectory_list, directory)); @@ -4847,6 +4856,12 @@ nautilus_files_view_add_subdirectory (NautilusFilesView *view, priv->subdirectory_list = g_list_prepend (priv->subdirectory_list, directory); priv->subdirectories_loading = g_list_prepend (priv->subdirectories_loading, directory); + + if (item != NULL && + !nautilus_directory_are_all_files_seen (directory)) + { + nautilus_view_item_set_loading (item, TRUE); + } } void @@ -4854,12 +4869,19 @@ nautilus_files_view_remove_subdirectory (NautilusFilesView *view, NautilusDirectory *directory) { NautilusFilesViewPrivate *priv = nautilus_files_view_get_instance_private (view); + g_autoptr (NautilusFile) file = nautilus_directory_get_corresponding_file (directory); + NautilusViewItem *item = nautilus_view_model_get_item_for_file (priv->model, file); g_return_if_fail (g_list_find (priv->subdirectory_list, directory)); priv->subdirectory_list = g_list_remove (priv->subdirectory_list, directory); priv->subdirectories_loading = g_list_remove (priv->subdirectories_loading, directory); + if (item != NULL) + { + nautilus_view_item_set_loading (item, FALSE); + } + g_signal_handlers_disconnect_by_func (directory, G_CALLBACK (files_added_callback), view); diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index e7a98a9908..86f17b141b 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -733,26 +733,6 @@ unload_file_timeout (gpointer data) return G_SOURCE_REMOVE; } -static void -on_subdirectory_done_loading (NautilusDirectory *directory, - GtkTreeListRow *row) -{ - g_autoptr (NautilusViewItem) item = NULL; - - g_signal_handlers_disconnect_by_func (directory, on_subdirectory_done_loading, row); - - item = NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (row)); - nautilus_view_item_set_loading (item, FALSE); - - if (!nautilus_directory_is_not_empty (directory)) - { - GtkWidget *name_cell = nautilus_view_item_get_item_ui (item); - GtkTreeExpander *expander = nautilus_name_cell_get_expander (NAUTILUS_NAME_CELL (name_cell)); - - gtk_tree_expander_set_hide_expander (expander, TRUE); - } -} - static void on_row_expanded_changed (GObject *gobject, GParamSpec *pspec, @@ -773,16 +753,6 @@ on_row_expanded_changed (GObject *gobject, { nautilus_files_view_add_subdirectory (NAUTILUS_FILES_VIEW (self), directory); } - if (!nautilus_directory_are_all_files_seen (directory)) - { - nautilus_view_item_set_loading (item, TRUE); - - g_signal_connect_object (directory, - "done-loading", - G_CALLBACK (on_subdirectory_done_loading), - row, - 0); - } } else { diff --git a/src/nautilus-name-cell.c b/src/nautilus-name-cell.c index 61f588eaac..6c27b8f883 100644 --- a/src/nautilus-name-cell.c +++ b/src/nautilus-name-cell.c @@ -6,6 +6,7 @@ #include "nautilus-name-cell.h" +#include "nautilus-directory.h" #include "nautilus-file-utilities.h" #include "nautilus-thumbnails.h" @@ -306,6 +307,11 @@ on_item_is_loading_changed (NautilusNameCell *self) } else { + g_autoptr (NautilusDirectory) directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); + + gtk_tree_expander_set_hide_expander (GTK_TREE_EXPANDER (self->expander), + !nautilus_directory_is_not_empty (directory)); + gtk_widget_set_visible (self->spinner, FALSE); gtk_spinner_stop (GTK_SPINNER (self->spinner)); } -- GitLab From d1d482a490cca495d5767ad8e87d204d013d178c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 14 Jan 2024 16:38:08 +0000 Subject: [PATCH 08/12] name-cell: Improve subfolder loading indication Reduce the timeout from 1 s to 200 ms and move the spinner after the name, not to move things around. --- src/nautilus-name-cell.c | 12 +++++------- src/resources/ui/nautilus-name-cell.ui | 16 ++++++++-------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/nautilus-name-cell.c b/src/nautilus-name-cell.c index 6c27b8f883..09667a488a 100644 --- a/src/nautilus-name-cell.c +++ b/src/nautilus-name-cell.c @@ -10,7 +10,7 @@ #include "nautilus-file-utilities.h" #include "nautilus-thumbnails.h" -#define LOADING_TIMEOUT_SECONDS 1 +#define SPINNER_DELAY_MS 200 struct _NautilusNameCell { @@ -273,7 +273,7 @@ on_item_is_cut_changed (NautilusNameCell *self) } } -static gboolean +static void on_loading_timeout (gpointer user_data) { NautilusNameCell *self = NAUTILUS_NAME_CELL (user_data); @@ -287,8 +287,6 @@ on_loading_timeout (gpointer user_data) gtk_widget_set_visible (self->spinner, TRUE); gtk_spinner_start (GTK_SPINNER (self->spinner)); } - - return G_SOURCE_REMOVE; } static void @@ -301,9 +299,9 @@ on_item_is_loading_changed (NautilusNameCell *self) if (is_loading) { - self->loading_timeout_id = g_timeout_add_seconds (LOADING_TIMEOUT_SECONDS, - G_SOURCE_FUNC (on_loading_timeout), - self); + self->loading_timeout_id = g_timeout_add_once (SPINNER_DELAY_MS, + on_loading_timeout, + self); } else { diff --git a/src/resources/ui/nautilus-name-cell.ui b/src/resources/ui/nautilus-name-cell.ui index 3041503205..ba0ea0cd49 100644 --- a/src/resources/ui/nautilus-name-cell.ui +++ b/src/resources/ui/nautilus-name-cell.ui @@ -19,14 +19,6 @@ horizontal fill center - - - False - False - center - center - - vertical @@ -85,6 +77,14 @@ 6 + + + False + False + center + center + + -- GitLab From 3890c997d5df0399d1f72ee486cbf20ee0996a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 14 Jan 2024 17:00:22 +0000 Subject: [PATCH 09/12] files-view: Ensure subdirectory models are cleared There is no reason to delegate this task on the list view. --- src/nautilus-files-view.c | 3 +++ src/nautilus-list-view.c | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index b2d715cbd5..680849479a 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -4880,6 +4880,9 @@ nautilus_files_view_remove_subdirectory (NautilusFilesView *view, if (item != NULL) { nautilus_view_item_set_loading (item, FALSE); + + /* The model holds a GListStore for every subdirectory. Empty it. */ + nautilus_view_model_clear_subdirectory (priv->model, item); } g_signal_handlers_disconnect_by_func (directory, diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 86f17b141b..be513ae89b 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -727,9 +727,6 @@ unload_file_timeout (gpointer data) unload_data->directory); } - /* The model holds a GListStore for every subdirectory. Empty it. */ - nautilus_view_model_clear_subdirectory (model, unload_data->item); - return G_SOURCE_REMOVE; } -- GitLab From f4870ee042c066b79ea016cff2357c6c8d12003f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 14 Jan 2024 17:01:05 +0000 Subject: [PATCH 10/12] list-view: Optimize subdirectory unloading Instead of iterating the model to find the row matching the item, store the row itself. --- src/nautilus-list-view.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index be513ae89b..67de52b120 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -661,7 +661,7 @@ real_get_backing_item (NautilusListBase *list_base) typedef struct { NautilusListView *self; - NautilusViewItem *item; + GtkTreeListRow *row; NautilusDirectory *directory; } UnloadDelayData; @@ -669,7 +669,7 @@ static void unload_delay_data_free (UnloadDelayData *unload_data) { g_clear_weak_pointer (&unload_data->self); - g_clear_object (&unload_data->item); + g_clear_object (&unload_data->row); g_clear_object (&unload_data->directory); g_free (unload_data); @@ -679,14 +679,14 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (UnloadDelayData, unload_delay_data_free) static UnloadDelayData * unload_delay_data_new (NautilusListView *self, - NautilusViewItem *item, + GtkTreeListRow *row, NautilusDirectory *directory) { UnloadDelayData *unload_data; unload_data = g_new0 (UnloadDelayData, 1); g_set_weak_pointer (&unload_data->self, self); - g_set_object (&unload_data->item, item); + g_set_object (&unload_data->row, row); g_set_object (&unload_data->directory, directory); return unload_data; @@ -697,27 +697,16 @@ unload_file_timeout (gpointer data) { g_autoptr (UnloadDelayData) unload_data = data; NautilusListView *self = unload_data->self; - NautilusViewModel *model; if (unload_data->self == NULL) { return G_SOURCE_REMOVE; } - model = nautilus_list_base_get_model (NAUTILUS_LIST_BASE (self)); - for (guint i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (model)); i++) + if (gtk_tree_list_row_get_expanded (unload_data->row)) { - g_autoptr (GtkTreeListRow) row = g_list_model_get_item (G_LIST_MODEL (model), i); - g_autoptr (NautilusViewItem) item = gtk_tree_list_row_get_item (row); - if (item == unload_data->item) - { - if (gtk_tree_list_row_get_expanded (row)) - { - /* It has been expanded again before the timeout. Do nothing. */ - return G_SOURCE_REMOVE; - } - break; - } + /* It has been expanded again before the timeout. Do nothing. */ + return G_SOURCE_REMOVE; } if (nautilus_files_view_has_subdirectory (NAUTILUS_FILES_VIEW (self), @@ -756,7 +745,7 @@ on_row_expanded_changed (GObject *gobject, nautilus_view_item_set_loading (item, FALSE); g_timeout_add_seconds (COLLAPSE_TO_UNLOAD_DELAY, unload_file_timeout, - unload_delay_data_new (self, item, directory)); + unload_delay_data_new (self, row, directory)); } } -- GitLab From 8d1cca7d2a65ea4091651a58a9d573b9166d2b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 14 Jan 2024 19:42:09 +0000 Subject: [PATCH 11/12] list-view: Stop calling NautilusFilesView for subdirectories We want to stop being a NautilusFilesView subclass. Emit signals instead and have NautilusFilesView handle them. The logical flow is the same. Also simplify on_row_expanded_changed() while touching it. --- src/nautilus-files-view.c | 38 ++++++++++++++++++++++ src/nautilus-list-view.c | 67 +++++++++++++++++++++------------------ 2 files changed, 75 insertions(+), 30 deletions(-) diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 680849479a..5057f3b20d 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -3265,6 +3265,34 @@ on_popup_selection_context_menu (NautilusListBase *list_base, nautilus_files_view_pop_up_selection_context_menu (self, &view_point); } +static void +on_load_subdirectory (NautilusListBase *list_base, + NautilusViewItem *item, + gpointer user_data) +{ + NautilusFilesView *self = NAUTILUS_FILES_VIEW (user_data); + g_autoptr (NautilusDirectory) directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); + + if (!nautilus_files_view_has_subdirectory (self, directory)) + { + nautilus_files_view_add_subdirectory (self, directory); + } +} + +static void +on_unload_subdirectory (NautilusListBase *list_base, + NautilusViewItem *item, + gpointer user_data) +{ + NautilusFilesView *self = NAUTILUS_FILES_VIEW (user_data); + g_autoptr (NautilusDirectory) directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); + + if (nautilus_files_view_has_subdirectory (self, directory)) + { + nautilus_files_view_remove_subdirectory (self, directory); + } +} + static void nautilus_files_view_constructed (GObject *object) { @@ -3294,6 +3322,16 @@ nautilus_files_view_constructed (GObject *object) g_signal_connect_object (NAUTILUS_LIST_BASE (self), "popup-selection-context-menu", G_CALLBACK (on_popup_selection_context_menu), self, G_CONNECT_DEFAULT); + + if (NAUTILUS_IS_LIST_VIEW (NAUTILUS_LIST_BASE (self))) + { + g_signal_connect_object (NAUTILUS_LIST_BASE (self), "load-subdirectory", + G_CALLBACK (on_load_subdirectory), self, + G_CONNECT_DEFAULT); + g_signal_connect_object (NAUTILUS_LIST_BASE (self), "unload-subdirectory", + G_CALLBACK (on_unload_subdirectory), self, + G_CONNECT_DEFAULT); + } } static void diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 67de52b120..6e7d9439fd 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -54,6 +54,15 @@ struct _NautilusListView G_DEFINE_TYPE (NautilusListView, nautilus_list_view, NAUTILUS_TYPE_LIST_BASE) +enum +{ + LOAD_SUBDIRECTORY, + UNLOAD_SUBDIRECTORY, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + #define get_view_item(cell) \ (NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (GTK_TREE_LIST_ROW (gtk_column_view_cell_get_item (cell))))) @@ -662,7 +671,6 @@ typedef struct { NautilusListView *self; GtkTreeListRow *row; - NautilusDirectory *directory; } UnloadDelayData; static void @@ -670,7 +678,6 @@ unload_delay_data_free (UnloadDelayData *unload_data) { g_clear_weak_pointer (&unload_data->self); g_clear_object (&unload_data->row); - g_clear_object (&unload_data->directory); g_free (unload_data); } @@ -678,21 +685,19 @@ unload_delay_data_free (UnloadDelayData *unload_data) G_DEFINE_AUTOPTR_CLEANUP_FUNC (UnloadDelayData, unload_delay_data_free) static UnloadDelayData * -unload_delay_data_new (NautilusListView *self, - GtkTreeListRow *row, - NautilusDirectory *directory) +unload_delay_data_new (NautilusListView *self, + GtkTreeListRow *row) { UnloadDelayData *unload_data; unload_data = g_new0 (UnloadDelayData, 1); g_set_weak_pointer (&unload_data->self, self); g_set_object (&unload_data->row, row); - g_set_object (&unload_data->directory, directory); return unload_data; } -static gboolean +static void unload_file_timeout (gpointer data) { g_autoptr (UnloadDelayData) unload_data = data; @@ -700,23 +705,18 @@ unload_file_timeout (gpointer data) if (unload_data->self == NULL) { - return G_SOURCE_REMOVE; + return; } if (gtk_tree_list_row_get_expanded (unload_data->row)) { /* It has been expanded again before the timeout. Do nothing. */ - return G_SOURCE_REMOVE; + return; } - if (nautilus_files_view_has_subdirectory (NAUTILUS_FILES_VIEW (self), - unload_data->directory)) - { - nautilus_files_view_remove_subdirectory (NAUTILUS_FILES_VIEW (self), - unload_data->directory); - } + g_autoptr (NautilusViewItem) item = gtk_tree_list_row_get_item (unload_data->row); - return G_SOURCE_REMOVE; + g_signal_emit (self, signals[UNLOAD_SUBDIRECTORY], 0, item); } static void @@ -726,26 +726,18 @@ on_row_expanded_changed (GObject *gobject, { GtkTreeListRow *row = GTK_TREE_LIST_ROW (gobject); NautilusListView *self = NAUTILUS_LIST_VIEW (user_data); - g_autoptr (NautilusViewItem) item = NULL; - g_autoptr (NautilusDirectory) directory = NULL; - gboolean expanded; + g_autoptr (NautilusViewItem) item = NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (row)); - item = NAUTILUS_VIEW_ITEM (gtk_tree_list_row_get_item (row)); - directory = nautilus_directory_get_for_file (nautilus_view_item_get_file (item)); - expanded = gtk_tree_list_row_get_expanded (row); - if (expanded) + if (gtk_tree_list_row_get_expanded (row)) { - if (!nautilus_files_view_has_subdirectory (NAUTILUS_FILES_VIEW (self), directory)) - { - nautilus_files_view_add_subdirectory (NAUTILUS_FILES_VIEW (self), directory); - } + g_signal_emit (self, signals[LOAD_SUBDIRECTORY], 0, item); } else { nautilus_view_item_set_loading (item, FALSE); - g_timeout_add_seconds (COLLAPSE_TO_UNLOAD_DELAY, - unload_file_timeout, - unload_delay_data_new (self, row, directory)); + g_timeout_add_seconds_once (COLLAPSE_TO_UNLOAD_DELAY, + unload_file_timeout, + unload_delay_data_new (self, row)); } } @@ -1176,6 +1168,21 @@ nautilus_list_view_class_init (NautilusListViewClass *klass) list_base_view_class->set_sort_state = real_set_sort_state; list_base_view_class->set_zoom_level = real_set_zoom_level; list_base_view_class->setup_directory = nautilus_list_view_setup_directory; + + signals[LOAD_SUBDIRECTORY] = g_signal_new ("load-subdirectory", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, NAUTILUS_TYPE_VIEW_ITEM); + signals[UNLOAD_SUBDIRECTORY] = g_signal_new ("unload-subdirectory", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, NAUTILUS_TYPE_VIEW_ITEM); } NautilusListView * -- GitLab From 167fb75719f5fbd124cddcedb21f6bbcd2db1fb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Sun, 21 Jan 2024 23:13:07 +0000 Subject: [PATCH 12/12] list-view: Guard against gone file usage Between the time this was scheduled and the actual call, the file may have been removed from the directory and, as such, from the view, and the only reason the row, item and file weren't destroyed is because we kept a reference to the row. But it's invalid to access the file now. --- src/nautilus-list-view.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 6e7d9439fd..82080240e1 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -716,6 +716,12 @@ unload_file_timeout (gpointer data) g_autoptr (NautilusViewItem) item = gtk_tree_list_row_get_item (unload_data->row); + if (nautilus_file_is_gone (nautilus_view_item_get_file (item))) + { + /* It's been removed in the meantime. */ + return; + } + g_signal_emit (self, signals[UNLOAD_SUBDIRECTORY], 0, item); } -- GitLab