From b05000d8bdbe40771b59edd793574263ef6cb60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= Date: Wed, 24 Jan 2024 17:17:54 +0000 Subject: [PATCH] listitemmanager: Remove section when adding at its end We are failing to go from this: [ BLUE ] [ RED ] ...to this: [ BLUE GREEN YELLOW ] [ RED ] ...where '[' and ']' represent section header and footer. Instead, the result is... [ BLUE ] [ GREEN YELLOW ] [ RED ] ... despite the first 3 items belonging to the same section according to the section model. This leaves the view in an inconsistent state and, ultimately, to crashes the non-removed footer. Indeed, when receiving items-changed(1,0,2), we call `append_items()` which inserts a new tile before the tile at `1` (which was RED), and then notices there is a HEADER right befo-re it, so it flags both it and the corresponding FOOTER as unmatched: [ BLUE ] ( GREEN-YELLOW RED ) ... where '(' and ')' represent unmatched header and footer. Problem is subsequent code in `release_items()` doesn't even touch the section boundary footer-header pair ('] ('), because they are belong in the tracked interval (visible items). And `ensure_items()` proceeds to match the header with a new footer, producing the result described above. To handle this correctly, `append_items()` must delete the section boundary, and flag as unmatched both the HEADER of the section before and the FOOTER of section after (whose respective footer and header has been marked for removal): ( BLUE . . GREEN-YELLOW RED ) ... where '.' represents tiles marked for removal. This way, `release_items()` will release the removed footer-header section boundary, and `ensure_items()` is going to reinstate new section remove the section boundary at the correct place, resulting in the expected behavior: [ BLUE GREEN YELLOW ] [ RED ] --- gtk/gtklistitemmanager.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/gtk/gtklistitemmanager.c b/gtk/gtklistitemmanager.c index cfa2f2b843..cf0c8b7d9b 100644 --- a/gtk/gtklistitemmanager.c +++ b/gtk/gtklistitemmanager.c @@ -968,10 +968,26 @@ gtk_list_item_manager_add_items (GtkListItemManager *self, if (section != NULL && section->type == GTK_LIST_TILE_HEADER) { + guint start, end; + GtkListTile *footer = gtk_list_tile_get_footer (self, section); + GtkListTile *previous_footer = gtk_list_tile_get_previous_skip (section); + + gtk_section_model_get_section (GTK_SECTION_MODEL (self->model), position, &start, &end); + + if (previous_footer != NULL && previous_footer->type == GTK_LIST_TILE_FOOTER && + position > start && position < end) + { + gtk_list_item_change_clear_header (change, §ion->widget); + gtk_list_tile_set_type (section, GTK_LIST_TILE_REMOVED); + gtk_list_tile_set_type (previous_footer, GTK_LIST_TILE_REMOVED); + + section = gtk_list_tile_get_header (self, previous_footer); + } + gtk_list_item_change_clear_header (change, §ion->widget); gtk_list_tile_set_type (section, GTK_LIST_TILE_UNMATCHED_HEADER); - gtk_list_tile_set_type (gtk_list_tile_get_footer (self, section), + gtk_list_tile_set_type (footer, GTK_LIST_TILE_UNMATCHED_FOOTER); } }