From fa03c6f9af9fdbae4dbe3d47c44f47e4cf62136d Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Sat, 11 Apr 2026 15:04:55 -0300 Subject: [PATCH] views/week-grid: Port to GListModel And, while at it, rewrite the layout algorithm to operate on blocks of overlapping events, and segmented columns. Like the month view row, layouts blocks are invalidated at any point in time, but recalculated immediately before a relayout happens. The reason for doing such a massive rewrite while in the middle of the port to GListModel is because it's easier to handle GListModel data with this approach, than with the previous approach of storing it all in a GcalRangeTree. Closes: https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/1153 Part-of: --- src/gui/views/gcal-week-grid.c | 599 +++++++++++++++++++++++---------- src/gui/views/gcal-week-grid.h | 7 +- src/gui/views/gcal-week-view.c | 28 +- 3 files changed, 416 insertions(+), 218 deletions(-) diff --git a/src/gui/views/gcal-week-grid.c b/src/gui/views/gcal-week-grid.c index 80a81d7e..d2beba22 100644 --- a/src/gui/views/gcal-week-grid.c +++ b/src/gui/views/gcal-week-grid.c @@ -30,6 +30,7 @@ #include "gcal-utils.h" #include "gcal-view-private.h" #include "gcal-event-widget.h" +#include "gcal-event-list.h" #include "gcal-range-tree.h" #include @@ -43,12 +44,6 @@ typedef struct gint drop_cell; } DropData; -typedef struct -{ - GtkWidget *widget; - GcalEvent *event; -} ChildData; - struct _GcalWeekGrid { GtkWidget parent; @@ -59,7 +54,11 @@ struct _GcalWeekGrid GDateTime *active_date; - GcalRangeTree *events; + GPtrArray *layout_blocks; + GtkFilterListModel *filter_model; + GtkSortListModel *sort_model; + + gboolean layout_blocks_valid; /* * These fields are "cells" rather than minutes. Each cell @@ -78,6 +77,12 @@ struct _GcalWeekGrid } dnd; }; +static void on_event_widget_activated_cb (GcalEventWidget *widget, + GcalWeekGrid *self); +static gboolean widget_tick_cb (GtkWidget *widget, + GdkFrameClock *frame_clock, + gpointer user_data); + G_DEFINE_TYPE (GcalWeekGrid, gcal_week_grid, GTK_TYPE_WIDGET); @@ -89,10 +94,18 @@ enum static guint signals[LAST_SIGNAL] = { 0, }; + /* - * Auxiliary methods + * ChildData */ +typedef struct +{ + GtkWidget *widget; + GcalEvent *event; + uint32_t n_columns; +} ChildData; + static ChildData* child_data_new (GtkWidget *widget, GcalEvent *event) @@ -102,6 +115,7 @@ child_data_new (GtkWidget *widget, data = g_new (ChildData, 1); data->widget = widget; data->event = g_object_ref (event); + data->n_columns = 1; return data; } @@ -119,79 +133,323 @@ child_data_free (gpointer data) g_free (child_data); } -static inline gint -uint16_compare (gconstpointer a, - gconstpointer b) + +/* + * LayoutBlock + */ + +typedef struct { - return GPOINTER_TO_UINT (*(gint*)a) - GPOINTER_TO_UINT (*(gint*)b); + GcalRange *range; + GPtrArray *columns; /* GcalRangeTree */ +} LayoutBlock; + +static void +layout_block_free (gpointer data) +{ + LayoutBlock *layout_block = data; + + if (!layout_block) + return; + + g_clear_pointer (&layout_block->range, gcal_range_unref); + g_clear_pointer (&layout_block->columns, g_ptr_array_unref); + g_free (layout_block); } -static inline guint -get_event_index (GcalRangeTree *tree, - GcalRange *range) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (LayoutBlock, layout_block_free) + +static ChildData * +layout_block_add_event (LayoutBlock *layout_block, + GcalEvent *event) { - g_autoptr (GPtrArray) array = NULL; - gint idx, i; + GcalRange *event_range = NULL; + ChildData *child_data = NULL; + size_t column = 0; - idx = 0; - array = gcal_range_tree_get_data_at_range (tree, range); + g_assert (layout_block != NULL); + g_assert (GCAL_IS_EVENT (event)); - if (!array) - return 0; + event_range = gcal_event_get_range (event); - g_ptr_array_sort (array, uint16_compare); - - for (i = 0; array && i < array->len; i++) + do { - if (idx == GPOINTER_TO_INT (g_ptr_array_index (array, i))) - idx++; + GcalRangeTree *column_data = NULL; + + if (column >= layout_block->columns->len) + { + column_data = gcal_range_tree_new_with_free_func (child_data_free); + g_ptr_array_insert (layout_block->columns, column, column_data); + } else - break; - } + { + column_data = g_ptr_array_index (layout_block->columns, column); + } - return idx; + g_assert (column_data != NULL); + + if (!gcal_range_tree_has_entries_at_range (column_data, event_range)) + { + g_autoptr (GcalRange) new_block_range = NULL; + + child_data = child_data_new (NULL, event); + gcal_range_tree_add_range (column_data, event_range, child_data); + + new_block_range = gcal_range_union (layout_block->range, event_range); + g_clear_pointer (&layout_block->range, gcal_range_unref); + layout_block->range = g_steal_pointer (&new_block_range); + + break; + } + + column++; + } + while (TRUE); + + g_assert (child_data != NULL); + + return child_data; } -static guint -count_overlaps_at_range (GcalRangeTree *self, - GcalRange *range) + +/* + * Auxiliary methods + */ + +static void +add_event_to_block (GcalWeekGrid *self, + LayoutBlock *layout_block, + GcalEvent *event) { - g_autoptr (GDateTime) start = NULL; - g_autoptr (GDateTime) end = NULL; - guint64 counter; - gint minutes; - gint i; + ChildData *child_data; - g_return_val_if_fail (self, 0); + g_assert (GCAL_IS_WEEK_GRID (self)); + g_assert (layout_block != NULL); + g_assert (GCAL_IS_EVENT (event)); - counter = 0; - start = gcal_range_get_start (range); - end = gcal_range_get_end (range); - minutes = g_date_time_difference (end, start) / G_TIME_SPAN_MINUTE; + child_data = layout_block_add_event (layout_block, event); - for (i = 0; i < minutes; i++) + child_data->widget = g_object_new (GCAL_TYPE_EVENT_WIDGET, + "event", event, + "orientation", GTK_ORIENTATION_VERTICAL, + "timestamp-policy", GCAL_TIMESTAMP_POLICY_START, + NULL); + + g_signal_connect (child_data->widget, "activate", G_CALLBACK (on_event_widget_activated_cb), self); + + gtk_widget_set_parent (child_data->widget, GTK_WIDGET (self)); +} + +static void +expand_event_widgets_in_blocks (GcalWeekGrid *self) +{ + + for (size_t block_index = 0; block_index < self->layout_blocks->len; block_index++) { - g_autoptr (GcalRange) minute_range = NULL; - guint n_events; + g_autoptr (GDateTime) block_range_start = NULL; + LayoutBlock *layout_block = NULL; - minute_range = gcal_range_new_take (g_date_time_add_minutes (start, i), - g_date_time_add_minutes (start, i + 1), - GCAL_RANGE_DEFAULT); - n_events = gcal_range_tree_count_entries_at_range (self, minute_range); + layout_block = g_ptr_array_index (self->layout_blocks, block_index); + g_assert (layout_block != NULL); + g_assert (layout_block->columns != NULL); - if (n_events == 0) - break; + for (size_t column_index = 0; column_index < layout_block->columns->len; column_index++) + { + g_autoptr (GPtrArray) children_data = NULL; + GcalRangeTree *block_column; - counter = MAX (counter, n_events); + block_column = g_ptr_array_index (layout_block->columns, column_index); + g_assert (block_column != NULL); + + children_data = gcal_range_tree_get_all_data (block_column); + g_assert (children_data != NULL); + + for (size_t child_data_index = 0; child_data_index < children_data->len; child_data_index++) + { + GcalRange *event_range; + ChildData *child_data; + + child_data = g_ptr_array_index (children_data, child_data_index); + event_range = gcal_event_get_range (child_data->event); + + for (size_t next_column_index = column_index + 1; + next_column_index < layout_block->columns->len; + next_column_index++) + { + GcalRangeTree *next_column = g_ptr_array_index (layout_block->columns, next_column_index); + + if (gcal_range_tree_has_entries_at_range (next_column, event_range)) + break; + + child_data->n_columns++; + } + } + } + } +} + +static void +recalculate_layout_blocks (GcalWeekGrid *self) +{ + g_autoptr (GcalRangeTree) blocks_by_range = NULL; + size_t n_events = 0; + + GCAL_ENTRY; + + g_assert (GCAL_IS_WEEK_GRID (self)); + g_assert (self->layout_blocks != NULL); + + blocks_by_range = gcal_range_tree_new (); + + /* Remove all blocks */ + g_ptr_array_set_size (self->layout_blocks, 0); + + /* First pass: create all layout blocks, all event widgets will have 1 column of width */ + n_events = g_list_model_get_n_items (G_LIST_MODEL (self->sort_model)); + for (size_t i = 0; i < n_events; i++) + { + g_autoptr (GPtrArray) blocks_at_range = NULL; + g_autoptr (GcalRange) old_block_range = NULL; + g_autoptr (GcalRange) new_block_range = NULL; + g_autoptr (GcalEvent) event = NULL; + LayoutBlock *layout_block = NULL; + GcalRange *event_range; + + event = g_list_model_get_item (G_LIST_MODEL (self->sort_model), i); + g_assert (GCAL_IS_EVENT (event)); + + event_range = gcal_event_get_range (event); + + blocks_at_range = gcal_range_tree_get_data_at_range (blocks_by_range, event_range); + g_assert (blocks_at_range == NULL || blocks_at_range->len == 1); + + if (!blocks_at_range) + { + layout_block = g_new0 (LayoutBlock, 1); + layout_block->range = gcal_range_ref (event_range); + layout_block->columns = g_ptr_array_new_with_free_func ((GDestroyNotify) gcal_range_tree_unref); + + gcal_range_tree_add_range (blocks_by_range, layout_block->range, layout_block); + g_ptr_array_add (self->layout_blocks, layout_block); + } + else + { + layout_block = g_ptr_array_index (blocks_at_range, 0); + } + g_assert (layout_block != NULL); + + old_block_range = gcal_range_ref (layout_block->range); + + add_event_to_block (self, layout_block, event); + + new_block_range = gcal_range_ref (layout_block->range); + + if (gcal_range_calculate_overlap (old_block_range, new_block_range, NULL) != GCAL_RANGE_EQUAL) + { + gcal_range_tree_remove_range (blocks_by_range, old_block_range, layout_block); + gcal_range_tree_add_range (blocks_by_range, new_block_range, layout_block); + } } - return counter; + /* Second pass: expand event widgets to fill in empty space */ + expand_event_widgets_in_blocks (self); + + self->layout_blocks_valid = TRUE; + + GCAL_EXIT; +} + +static void +invalidate_layout_blocks (GcalWeekGrid *self) +{ + GCAL_ENTRY; + + if (!self->layout_blocks_valid) + GCAL_RETURN (); + + if (gtk_widget_get_mapped (GTK_WIDGET (self))) + { + gtk_widget_add_tick_callback (GTK_WIDGET (self), widget_tick_cb, self, NULL); + gtk_widget_queue_allocate (GTK_WIDGET (self)); + } + + self->layout_blocks_valid = FALSE; + + GCAL_EXIT; } /* * Callbacks */ +static gboolean +widget_tick_cb (GtkWidget *widget, + GdkFrameClock *frame_clock, + gpointer user_data) +{ + GcalWeekGrid *self = (GcalWeekGrid *) widget; + + GCAL_ENTRY; + + g_assert (GCAL_IS_WEEK_GRID (self)); + + recalculate_layout_blocks (self); + + GCAL_RETURN (G_SOURCE_REMOVE); +} + +static int +compare_events_cb (gconstpointer a, + gconstpointer b, + gpointer user_data) +{ + GDateTime *event_a_start; + GDateTime *event_b_start; + GDateTime *event_a_end; + GDateTime *event_b_end; + GcalEvent *event_a; + GcalEvent *event_b; + int result; + + event_a = (GcalEvent *) a; + event_b = (GcalEvent *) b; + + event_a_start = gcal_event_get_date_start (event_a); + event_b_start = gcal_event_get_date_start (event_b); + result = g_date_time_compare (event_a_start, event_b_start); + if (result != 0) + return result; + + event_a_end = gcal_event_get_date_end (event_a); + event_b_end = gcal_event_get_date_end (event_b); + result = g_date_time_compare (event_a_end, event_b_end); + if (result != 0) + return -result; + + return 0; +} + +static gboolean +event_is_timed_single_day_func (gpointer item, + gpointer user_data) +{ + GcalEvent *event = (GcalEvent *) item; + + g_assert (GCAL_IS_EVENT (event)); + + return !gcal_event_get_all_day (event) && !gcal_event_is_multiday (event); +} + +static void +events_changed_cb (GListModel *model, + unsigned int position, + unsigned int removed, + unsigned int added, + GcalWeekGrid *self) +{ + invalidate_layout_blocks (self); +} + static void on_click_gesture_pressed_cb (GtkGestureClick *click_gesture, gint n_press, @@ -507,8 +765,8 @@ gcal_week_grid_dispose (GObject *object) { GcalWeekGrid *self = GCAL_WEEK_GRID (object); + g_clear_pointer (&self->layout_blocks, g_ptr_array_unref); g_clear_pointer (&self->dnd.widget, gtk_widget_unparent); - g_clear_pointer (&self->events, gcal_range_tree_unref); g_clear_pointer (&self->now_strip, gtk_widget_unparent); g_clear_pointer (&self->selection.widget, gtk_widget_unparent); @@ -521,6 +779,8 @@ gcal_week_grid_finalize (GObject *object) GcalWeekGrid *self = GCAL_WEEK_GRID (object); gcal_clear_date_time (&self->active_date); + g_clear_object (&self->filter_model); + g_clear_object (&self->sort_model); G_OBJECT_CLASS (gcal_week_grid_parent_class)->finalize (object); } @@ -561,6 +821,19 @@ get_today_column (GcalWeekGrid *self) return days_diff; } +static void +gcal_week_grid_map (GtkWidget *widget) +{ + GcalWeekGrid *self = (GcalWeekGrid *) widget; + + g_assert (GCAL_IS_WEEK_GRID (self)); + + GTK_WIDGET_CLASS (gcal_week_grid_parent_class)->map (widget); + + if (!self->layout_blocks_valid) + recalculate_layout_blocks (self); +} + static void gcal_week_grid_measure (GtkWidget *widget, GtkOrientation orientation, @@ -580,7 +853,6 @@ static void gcal_week_grid_snapshot (GtkWidget *widget, GtkSnapshot *snapshot) { - g_autoptr (GPtrArray) widgets = NULL; GcalWeekGrid *self; gint width, height; @@ -595,12 +867,19 @@ gcal_week_grid_snapshot (GtkWidget *widget, gtk_widget_snapshot_child (widget, self->selection.widget, snapshot); gtk_widget_snapshot_child (widget, self->dnd.widget, snapshot); - widgets = gcal_range_tree_get_all_data (self->events); - for (guint i = 0; i < widgets->len; i++) + /* Then, event widgets */ + for (GtkWidget *child = gtk_widget_get_first_child (widget); + child; + child = gtk_widget_get_next_sibling (child)) { - ChildData *child_data = g_ptr_array_index (widgets, i); + if (child == self->selection.widget || + child == self->dnd.widget || + child == self->now_strip) + { + continue; + } - gtk_widget_snapshot_child (widget, child_data->widget, snapshot); + gtk_widget_snapshot_child (widget, child, snapshot); } gtk_widget_snapshot_child (widget, self->now_strip, snapshot); @@ -614,7 +893,6 @@ gcal_week_grid_size_allocate (GtkWidget *widget, { GcalWeekGrid *self = GCAL_WEEK_GRID (widget); g_autoptr (GDateTime) week_start = NULL; - GcalRangeTree *overlaps; gboolean ltr; gdouble minutes_height; gdouble column_width; @@ -697,101 +975,87 @@ gcal_week_grid_size_allocate (GtkWidget *widget, baseline); } - /* Temporary range tree to hold positioned events' indexes */ - overlaps = gcal_range_tree_new (); - week_start = gcal_date_time_get_start_of_week (self->active_date); - /* - * Iterate through weekdays; we don't have to worry about events that - * jump between days because they're already handled by GcalWeekHeader. - */ - for (size_t i = 0; i < N_WEEKDAYS; i++) + /* Event widgets */ + for (size_t block_index = 0; block_index < self->layout_blocks->len; block_index++) { - g_autoptr (GcalRange) day_range = NULL; - GPtrArray *widgets_data; - guint j; + g_autoptr (GDateTime) block_range_start = NULL; + LayoutBlock *layout_block = NULL; + double block_column_width; + int block_weekday; - day_range = gcal_range_new_take (g_date_time_add_days (week_start, i), - g_date_time_add_days (week_start, i + 1), - GCAL_RANGE_DEFAULT); - widgets_data = gcal_range_tree_get_data_at_range (self->events, day_range); + layout_block = g_ptr_array_index (self->layout_blocks, block_index); + g_assert (layout_block != NULL); + g_assert (layout_block->columns != NULL); - for (j = 0; widgets_data && j < widgets_data->len; j++) + block_range_start = gcal_range_get_start (layout_block->range); + block_weekday = gcal_date_time_compare_date (block_range_start, week_start); + g_assert (block_weekday >= 0 && block_weekday < 7); + + block_column_width = column_width / (double) layout_block->columns->len - 1; + + for (size_t block_column_index = 0; block_column_index < layout_block->columns->len; block_column_index++) { - g_autoptr (GDateTime) event_start = NULL; - g_autoptr (GDateTime) event_end = NULL; - GtkAllocation child_allocation; - GtkWidget *event_widget; - GcalRange *event_range; - ChildData *data; - guint64 events_at_range; - gint event_minutes; - gint minimum_width; - gint minimum_height; - gint widget_index; - gint offset; - gint event_height; - gint event_width; - gint x; - gint y; + g_autoptr (GPtrArray) children_data = NULL; + GcalRangeTree *block_column; - data = g_ptr_array_index (widgets_data, j); - event_widget = data->widget; + block_column = g_ptr_array_index (layout_block->columns, block_column_index); + g_assert (block_column != NULL); - if (!gtk_widget_should_layout (event_widget)) - continue; + children_data = gcal_range_tree_get_all_data (block_column); + g_assert (children_data != NULL); - event_range = gcal_event_get_range (data->event); - event_start = g_date_time_to_local (gcal_event_get_date_start (data->event)); - event_end = g_date_time_to_local (gcal_event_get_date_end (data->event)); + for (size_t child_data_index = 0; child_data_index < children_data->len; child_data_index++) + { + g_autoptr (GDateTime) event_start = NULL; + g_autoptr (GDateTime) event_end = NULL; + GtkAllocation child_allocation; + GtkWidget *event_widget; + ChildData *child_data; + gint event_minutes; + gint minimum_width; + gint minimum_height; + gint event_height; + gint event_width; + gint x; + gint y; - /* The total number of events available in this range */ - events_at_range = count_overlaps_at_range (self->events, event_range); + child_data = g_ptr_array_index (children_data, child_data_index); + event_widget = child_data->widget; - /* The real horizontal position of this event */ - widget_index = get_event_index (overlaps, event_range); + if (!gtk_widget_should_layout (event_widget)) + continue; - event_minutes = g_date_time_difference (event_end, event_start) / G_TIME_SPAN_MINUTE; + event_start = g_date_time_to_local (gcal_event_get_date_start (child_data->event)); + event_end = g_date_time_to_local (gcal_event_get_date_end (child_data->event)); + event_minutes = g_date_time_difference (event_end, event_start) / G_TIME_SPAN_MINUTE; - /* Compute the height of the widget */ - gtk_widget_measure (event_widget, GTK_ORIENTATION_VERTICAL, -1, &minimum_height, NULL, NULL, NULL); - event_height = event_minutes * minutes_height; - event_height = MAX (minimum_height, event_height); + /* Compute the height of the widget */ + gtk_widget_measure (event_widget, GTK_ORIENTATION_VERTICAL, -1, &minimum_height, NULL, NULL, NULL); + event_height = event_minutes * minutes_height; + event_height = MAX (minimum_height, event_height); - /* Compute the width of the widget */ - gtk_widget_measure (event_widget, GTK_ORIENTATION_HORIZONTAL, event_height, &minimum_width, NULL, NULL, NULL); - event_width = column_width / events_at_range; - event_width = MAX (minimum_width, event_width); + /* Compute the width of the widget */ + gtk_widget_measure (event_widget, GTK_ORIENTATION_HORIZONTAL, event_height, &minimum_width, NULL, NULL, NULL); + event_width = MAX (minimum_width, block_column_width * child_data->n_columns); - offset = event_width * widget_index; - y = (g_date_time_get_hour (event_start) * 60 + g_date_time_get_minute (event_start)) * minutes_height; + x = column_width * block_weekday + block_column_width * block_column_index + 1; + if (!ltr) + x = width - (x + event_width); + y = (g_date_time_get_hour (event_start) * 60 + g_date_time_get_minute (event_start)) * minutes_height; - if (ltr) - x = column_width * i + offset + 1; - else - x = width - event_width - (column_width * i + offset + 1); + /* Setup the child position and size */ + child_allocation.x = x; + child_allocation.y = y; + child_allocation.width = event_width; + child_allocation.height = event_height; - /* Setup the child position and size */ - child_allocation.x = x; - child_allocation.y = y; - child_allocation.width = event_width; - child_allocation.height = event_height; - - gtk_widget_size_allocate (event_widget, &child_allocation, baseline); - - /* - * Add the current event to the temporary overlaps tree so we have a way to - * know how many events are already positioned in the current column. - */ - gcal_range_tree_add_range (overlaps, event_range, GUINT_TO_POINTER (widget_index)); + gtk_widget_size_allocate (event_widget, &child_allocation, baseline); + } } - - g_clear_pointer (&widgets_data, g_ptr_array_unref); } - g_clear_pointer (&overlaps, gcal_range_tree_unref); - /* Today column */ today_column = get_today_column (GCAL_WEEK_GRID (widget)); @@ -841,6 +1105,7 @@ gcal_week_grid_class_init (GcalWeekGridClass *klass) object_class->get_property = gcal_week_grid_get_property; object_class->set_property = gcal_week_grid_set_property; + widget_class->map = gcal_week_grid_map; widget_class->measure = gcal_week_grid_measure; widget_class->size_allocate = gcal_week_grid_size_allocate; widget_class->snapshot = gcal_week_grid_snapshot; @@ -860,6 +1125,7 @@ static void gcal_week_grid_init (GcalWeekGrid *self) { GcalContext *context = gcal_application_get_context (GCAL_DEFAULT_APPLICATION); + GtkCustomFilter *filter; GtkDropTarget *drop_target; GtkGesture *click_gesture; AdwStyleManager *manager; @@ -875,7 +1141,13 @@ gcal_week_grid_init (GcalWeekGrid *self) gtk_widget_set_visible (self->dnd.widget, FALSE); gtk_widget_set_parent (self->dnd.widget, GTK_WIDGET (self)); - self->events = gcal_range_tree_new_with_free_func (child_data_free); + self->layout_blocks = g_ptr_array_new_with_free_func (layout_block_free); + + filter = gtk_custom_filter_new (event_is_timed_single_day_func, NULL, NULL); + self->filter_model = gtk_filter_list_model_new (NULL, GTK_FILTER (g_steal_pointer (&filter))); + self->sort_model = gtk_sort_list_model_new (G_LIST_MODEL (g_object_ref (self->filter_model)), + GTK_SORTER (gtk_custom_sorter_new (compare_events_cb, NULL, NULL))); + g_signal_connect (self->sort_model, "items-changed", G_CALLBACK (events_changed_cb), self); self->now_strip = adw_bin_new (); gtk_widget_add_css_class (self->now_strip, "now-strip"); @@ -915,57 +1187,13 @@ gcal_week_grid_init (GcalWeekGrid *self) G_CONNECT_SWAPPED); } -/* Public API */ void -gcal_week_grid_add_event (GcalWeekGrid *self, - GcalEvent *event) +gcal_week_grid_set_model (GcalWeekGrid *self, + GListModel *model) { - GtkWidget *widget; + g_assert (GCAL_IS_WEEK_GRID (self)); - g_return_if_fail (GCAL_IS_WEEK_GRID (self)); - - g_object_ref (event); - - widget = g_object_new (GCAL_TYPE_EVENT_WIDGET, - "event", event, - "orientation", GTK_ORIENTATION_VERTICAL, - "timestamp-policy", GCAL_TIMESTAMP_POLICY_START, - NULL); - - gcal_range_tree_add_range (self->events, - gcal_event_get_range (event), - child_data_new (widget, event)); - - g_signal_connect (widget, "activate", G_CALLBACK (on_event_widget_activated_cb), self); - - gtk_widget_set_parent (widget, GTK_WIDGET (self)); -} - -void -gcal_week_grid_remove_event (GcalWeekGrid *self, - const gchar *uid) -{ - g_autoptr (GPtrArray) widgets = NULL; - guint i; - - g_return_if_fail (GCAL_IS_WEEK_GRID (self)); - - widgets = gcal_range_tree_get_all_data (self->events); - - for (i = 0; widgets && i < widgets->len; i++) - { - ChildData *data; - GcalEvent *event; - - data = g_ptr_array_index (widgets, i); - event = gcal_event_widget_get_event (GCAL_EVENT_WIDGET (data->widget)); - - if (g_strcmp0 (gcal_event_get_uid (event), uid) != 0) - continue; - - gcal_range_tree_remove_range (self->events, gcal_event_get_range (event), data); - gtk_widget_queue_allocate (GTK_WIDGET (self)); - } + gtk_filter_list_model_set_model (self->filter_model, model); } GList* @@ -998,7 +1226,6 @@ gcal_week_grid_set_date (GcalWeekGrid *self, { gcal_set_date_time (&self->active_date, date); - gtk_widget_queue_resize (GTK_WIDGET (self)); - gtk_widget_queue_draw (GTK_WIDGET (self)); + invalidate_layout_blocks (self); } diff --git a/src/gui/views/gcal-week-grid.h b/src/gui/views/gcal-week-grid.h index 66cec765..7a9b642f 100644 --- a/src/gui/views/gcal-week-grid.h +++ b/src/gui/views/gcal-week-grid.h @@ -33,11 +33,8 @@ G_DECLARE_FINAL_TYPE (GcalWeekGrid, gcal_week_grid, GCAL, WEEK_GRID, GtkWidget) void gcal_week_grid_set_first_weekday (GcalWeekGrid *week_grid, gint nr_day); -void gcal_week_grid_add_event (GcalWeekGrid *self, - GcalEvent *event); - -void gcal_week_grid_remove_event (GcalWeekGrid *self, - const gchar *uid); +void gcal_week_grid_set_model (GcalWeekGrid *self, + GListModel *model); GList* gcal_week_grid_get_children_by_uuid (GcalWeekGrid *self, GcalRecurrenceModType mod, diff --git a/src/gui/views/gcal-week-view.c b/src/gui/views/gcal-week-view.c index 238d8bd1..993bee81 100644 --- a/src/gui/views/gcal-week-view.c +++ b/src/gui/views/gcal-week-view.c @@ -494,14 +494,6 @@ static void gcal_week_view_add_event (GcalTimelineSubscriber *subscriber, GcalEvent *event) { - GcalWeekView *self = GCAL_WEEK_VIEW (subscriber); - - GCAL_ENTRY; - - if (!gcal_event_is_multiday (event) && !gcal_event_get_all_day (event)) - gcal_week_grid_add_event (GCAL_WEEK_GRID (self->week_grid), event); - - GCAL_EXIT; } static void @@ -509,31 +501,12 @@ gcal_week_view_update_event (GcalTimelineSubscriber *subscriber, GcalEvent *old_event, GcalEvent *event) { - GcalWeekView *self = GCAL_WEEK_VIEW (subscriber); - const gchar *event_id; - - GCAL_ENTRY; - - event_id = gcal_event_get_uid (old_event); - gcal_week_grid_remove_event (GCAL_WEEK_GRID (self->week_grid), event_id); - - gcal_week_view_add_event (subscriber, event); - - GCAL_EXIT; } static void gcal_week_view_remove_event (GcalTimelineSubscriber *subscriber, GcalEvent *event) { - GcalWeekView *self = GCAL_WEEK_VIEW (subscriber); - const gchar *uuid = gcal_event_get_uid (event); - - GCAL_ENTRY; - - gcal_week_grid_remove_event (GCAL_WEEK_GRID (self->week_grid), uuid); - - GCAL_EXIT; } static void @@ -547,6 +520,7 @@ gcal_week_view_set_model (GcalTimelineSubscriber *subscriber, self = GCAL_WEEK_VIEW (subscriber); gcal_week_header_set_model (GCAL_WEEK_HEADER (self->header), model); + gcal_week_grid_set_model (GCAL_WEEK_GRID (self->week_grid), model); GCAL_EXIT; }