diff --git a/src/gui/views/gcal-month-view-row.c b/src/gui/views/gcal-month-view-row.c index 2456d16e..c483d710 100644 --- a/src/gui/views/gcal-month-view-row.c +++ b/src/gui/views/gcal-month-view-row.c @@ -51,15 +51,12 @@ struct _GcalMonthViewRow GcalRange *range; - GListStore *events; + GListModel *events; + GHashTable *layout_blocks; gboolean layout_blocks_valid; }; -static gint compare_events_cb (gconstpointer a, - gconstpointer b, - gpointer user_data); - static void on_event_widget_activated_cb (GcalEventWidget *widget, GcalMonthViewRow *self); @@ -547,7 +544,7 @@ prepare_layout_blocks (GcalMonthViewRow *self, g_assert (self->layout_blocks_valid); - n_events = g_list_model_get_n_items (G_LIST_MODEL (self->events)); + n_events = g_list_model_get_n_items (self->events); for (guint i = 0; i < N_WEEKDAYS; i++) { @@ -568,7 +565,7 @@ prepare_layout_blocks (GcalMonthViewRow *self, g_autoptr (GcalEvent) event = NULL; GPtrArray *blocks; - event = g_list_model_get_item (G_LIST_MODEL (self->events), i); + event = g_list_model_get_item (self->events, i); blocks = g_hash_table_lookup (self->layout_blocks, event); g_assert (blocks != NULL); @@ -653,7 +650,7 @@ recalculate_layout_blocks (GcalMonthViewRow *self) g_assert (!self->layout_blocks_valid); range_start = gcal_range_get_start (self->range); - n_events = g_list_model_get_n_items (G_LIST_MODEL (self->events)); + n_events = g_list_model_get_n_items (self->events); g_hash_table_remove_all (self->layout_blocks); @@ -665,7 +662,7 @@ recalculate_layout_blocks (GcalMonthViewRow *self) gint first_cell; gint last_cell; - event = g_list_model_get_item (G_LIST_MODEL (self->events), i); + event = g_list_model_get_item (self->events, i); calculate_event_cells (self, event, &first_cell, &last_cell); g_assert (last_cell >= first_cell); @@ -770,18 +767,33 @@ invalidate_layout_blocks (GcalMonthViewRow *self) * Callbacks */ -static gint -compare_events_cb (gconstpointer a, - gconstpointer b, - gpointer user_data) +static gboolean +filter_by_range_cb (GcalEvent *event, + GcalRange *row_range, + GcalMonthViewRow *self) { - GcalEvent *event_a = (GcalEvent *)a; - GcalEvent *event_b = (GcalEvent *)b; + g_assert (GCAL_IS_EVENT (event)); + g_assert (GCAL_IS_MONTH_VIEW_ROW (self)); + g_assert (self->range == row_range); - if (gcal_event_is_multiday (event_a) != gcal_event_is_multiday (event_b)) - return gcal_event_is_multiday (event_b) - gcal_event_is_multiday (event_a); + if (!self->range) + return FALSE; - return gcal_event_compare (event_a, event_b); + return gcal_event_overlaps (event, self->range); +} + +static void +events_changed_cb (GListModel *model, + guint position, + guint removed, + guint added, + GcalMonthViewRow *self) +{ + GCAL_ENTRY; + + invalidate_layout_blocks (self); + + GCAL_EXIT; } static void @@ -1015,14 +1027,14 @@ gcal_month_view_row_size_allocate (GtkWidget *widget, for (guint i = 0; i < N_WEEKDAYS; i++) cell_y[i] = gcal_month_cell_get_header_height (GCAL_MONTH_CELL (self->day_cells[i])); - n_events = g_list_model_get_n_items (G_LIST_MODEL (self->events)); + n_events = g_list_model_get_n_items (self->events); for (guint i = 0; i < n_events; i++) { g_autoptr (GcalEvent) event = NULL; GPtrArray *blocks; - event = g_list_model_get_item (G_LIST_MODEL (self->events), i); + event = g_list_model_get_item (self->events, i); blocks = g_hash_table_lookup (self->layout_blocks, event); g_assert (blocks != NULL); @@ -1130,7 +1142,11 @@ gcal_month_view_row_class_init (GcalMonthViewRowClass *klass) static void gcal_month_view_row_init (GcalMonthViewRow *self) { - self->events = g_list_store_new (GCAL_TYPE_EVENT); + self->events = G_LIST_MODEL (gtk_filter_list_model_new (NULL, + GTK_FILTER (gtk_custom_filter_new (event_in_range_func, self, NULL)))); + gtk_filter_list_model_set_incremental (GTK_FILTER_LIST_MODEL (self->events), TRUE); + g_signal_connect (self->events, "items-changed", G_CALLBACK (events_changed_cb), self); + self->layout_blocks = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_ptr_array_unref); self->layout_blocks_valid = TRUE; @@ -1166,6 +1182,7 @@ gcal_month_view_row_set_range (GcalMonthViewRow *self, GcalRange *range) { g_autoptr (GDateTime) start = NULL; + GtkFilter *filter; g_return_if_fail (GCAL_IS_MONTH_VIEW_ROW (self)); g_return_if_fail (range != NULL); @@ -1178,10 +1195,10 @@ gcal_month_view_row_set_range (GcalMonthViewRow *self, g_clear_pointer (&self->range, gcal_range_unref); self->range = gcal_range_ref (range); - /* Preemptively remove all event widgets */ - g_list_store_remove_all (self->events); - g_hash_table_remove_all (self->layout_blocks); - invalidate_layout_blocks (self); + /* Refilter */ + filter = gtk_filter_list_model_get_filter (GTK_FILTER_LIST_MODEL (self->events)); + g_assert (GTK_IS_CUSTOM_FILTER (filter)); + gtk_filter_changed (filter, GTK_FILTER_CHANGE_DIFFERENT); start = gcal_range_get_start (range); for (guint i = 0; i < N_WEEKDAYS; i++) @@ -1194,42 +1211,15 @@ gcal_month_view_row_set_range (GcalMonthViewRow *self, } void -gcal_month_view_row_add_event (GcalMonthViewRow *self, - GcalEvent *event) +gcal_month_view_row_set_model (GcalMonthViewRow *self, + GListModel *model) { - g_assert (GCAL_IS_MONTH_VIEW_ROW (self)); - g_assert (GCAL_IS_EVENT (event)); + g_return_if_fail (GCAL_IS_MONTH_VIEW_ROW (self)); - g_list_store_insert_sorted (self->events, event, compare_events_cb, self); + gtk_filter_list_model_set_model (GTK_FILTER_LIST_MODEL (self->events), model); invalidate_layout_blocks (self); } -void -gcal_month_view_row_remove_event (GcalMonthViewRow *self, - GcalEvent *event) -{ - guint position; - - g_assert (GCAL_IS_MONTH_VIEW_ROW (self)); - g_assert (GCAL_IS_EVENT (event)); - - GCAL_ENTRY; - - if (!g_list_store_find (self->events, event, &position)) - { - g_warning ("%s: Widget with uuid: %s not found in view: %s", - G_STRFUNC, - gcal_event_get_uid (event), - G_OBJECT_TYPE_NAME (self)); - GCAL_RETURN (); - } - - g_list_store_remove (self->events, position); - invalidate_layout_blocks (self); - - GCAL_EXIT; -} - GList* gcal_month_view_row_get_children_by_uuid (GcalMonthViewRow *self, GcalRecurrenceModType mod, diff --git a/src/gui/views/gcal-month-view-row.h b/src/gui/views/gcal-month-view-row.h index e20e9d73..bedff686 100644 --- a/src/gui/views/gcal-month-view-row.h +++ b/src/gui/views/gcal-month-view-row.h @@ -39,11 +39,8 @@ GcalRange * gcal_month_view_row_get_range (GcalMonthViewR void gcal_month_view_row_set_range (GcalMonthViewRow *self, GcalRange *range); -void gcal_month_view_row_add_event (GcalMonthViewRow *self, - GcalEvent *event); - -void gcal_month_view_row_remove_event (GcalMonthViewRow *self, - GcalEvent *event); +void gcal_month_view_row_set_model (GcalMonthViewRow *self, + GListModel *model); GList* gcal_month_view_row_get_children_by_uuid (GcalMonthViewRow *self, GcalRecurrenceModType mod, diff --git a/src/gui/views/gcal-month-view.c b/src/gui/views/gcal-month-view.c index 6cb9d815..27e2fcd2 100644 --- a/src/gui/views/gcal-month-view.c +++ b/src/gui/views/gcal-month-view.c @@ -234,28 +234,6 @@ update_active_date (GcalMonthView *self) g_object_notify (G_OBJECT (self), "active-date"); } -static void -add_cached_events_to_row (GcalMonthView *self, - GcalMonthViewRow *row) -{ - g_autoptr (GcalRange) row_range = NULL; - GHashTableIter iter; - GcalEvent *event; - - row_range = gcal_month_view_row_get_range (row); - - g_hash_table_iter_init (&iter, self->events); - while (g_hash_table_iter_next (&iter, (gpointer *) &event, NULL)) - { - GcalRangeOverlap overlap = gcal_range_calculate_overlap (row_range, gcal_event_get_range (event), NULL); - - if (overlap == GCAL_RANGE_NO_OVERLAP) - continue; - - gcal_month_view_row_add_event (row, event); - } -} - static inline void maybe_popdown_overflow_popover (GcalMonthView *self) { @@ -302,8 +280,6 @@ move_bottom_row_to_top (GcalMonthView *self) last_row = g_ptr_array_steal_index (self->week_rows, self->week_rows->len - 1); gcal_month_view_row_set_range (GCAL_MONTH_VIEW_ROW (last_row), new_range); g_ptr_array_insert (self->week_rows, 0, last_row); - - add_cached_events_to_row (self, GCAL_MONTH_VIEW_ROW (last_row)); } static void @@ -336,8 +312,6 @@ move_top_row_to_bottom (GcalMonthView *self) first_row = g_ptr_array_steal_index (self->week_rows, 0); gcal_month_view_row_set_range (GCAL_MONTH_VIEW_ROW (first_row), new_range); g_ptr_array_insert (self->week_rows, -1, first_row); - - add_cached_events_to_row (self, GCAL_MONTH_VIEW_ROW (first_row)); } static inline void @@ -1283,90 +1257,12 @@ static void gcal_month_view_add_event (GcalTimelineSubscriber *subscriber, GcalEvent *event) { - GcalMonthView *self; - - GCAL_ENTRY; - - g_assert (event != NULL); - - self = GCAL_MONTH_VIEW (subscriber); - - if (!g_hash_table_add (self->events, g_object_ref (event))) - { - g_warning ("Event with uuid: %s already added", gcal_event_get_uid (event)); - GCAL_RETURN (); - } - - for (guint i = 0; i < self->week_rows->len; i++) - { - g_autoptr (GcalRange) row_range = NULL; - GcalRangePosition position; - GcalRangeOverlap overlap; - GcalMonthViewRow *row; - - row = g_ptr_array_index (self->week_rows, i); - row_range = gcal_month_view_row_get_range (row); - - overlap = gcal_range_calculate_overlap (row_range, gcal_event_get_range (event), &position); - if (overlap != GCAL_RANGE_NO_OVERLAP) - { - gcal_month_view_row_add_event (row, event); - } - else - { - if (position == GCAL_RANGE_AFTER) - break; - } - } - - GCAL_EXIT; } static void gcal_month_view_remove_event (GcalTimelineSubscriber *subscriber, GcalEvent *event) { - g_autoptr (GcalEvent) G_GNUC_UNUSED owned_event = NULL; - GcalMonthView *self; - - GCAL_ENTRY; - - g_assert (event != NULL); - - self = GCAL_MONTH_VIEW (subscriber); - - /* Keep event alive while removing it */ - owned_event = g_object_ref (event); - - if (!g_hash_table_remove (self->events, event)) - { - g_warning ("Event with uuid: %s not in %s", gcal_event_get_uid (event), G_OBJECT_TYPE_NAME (self)); - GCAL_RETURN (); - } - - for (guint i = 0; i < self->week_rows->len; i++) - { - g_autoptr (GcalRange) row_range = NULL; - GcalRangePosition position; - GcalRangeOverlap overlap; - GcalMonthViewRow *row; - - row = g_ptr_array_index (self->week_rows, i); - row_range = gcal_month_view_row_get_range (row); - - overlap = gcal_range_calculate_overlap (row_range, gcal_event_get_range (event), &position); - if (overlap != GCAL_RANGE_NO_OVERLAP) - { - gcal_month_view_row_remove_event (row, event); - } - else - { - if (position == GCAL_RANGE_AFTER) - break; - } - } - - GCAL_EXIT; } static void @@ -1374,12 +1270,24 @@ gcal_month_view_update_event (GcalTimelineSubscriber *subscriber, GcalEvent *old_event, GcalEvent *event) { +} + +static void +gcal_month_view_set_model (GcalTimelineSubscriber *subscriber, + GListModel *model) +{ + GcalMonthView *self; + GCAL_ENTRY; - g_assert (event != NULL); + self = GCAL_MONTH_VIEW (subscriber); - gcal_month_view_remove_event (subscriber, old_event); - gcal_month_view_add_event (subscriber, event); + for (guint i = 0; i < self->week_rows->len; i++) + { + GcalMonthViewRow *row = g_ptr_array_index (self->week_rows, i); + + gcal_month_view_row_set_model (row, model); + } GCAL_EXIT; } @@ -1391,6 +1299,7 @@ gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface) iface->add_event = gcal_month_view_add_event; iface->update_event = gcal_month_view_update_event; iface->remove_event = gcal_month_view_remove_event; + iface->set_model = gcal_month_view_set_model; } @@ -1807,8 +1716,6 @@ gcal_month_view_dispose (GObject *object) GCAL_ENTRY; - g_clear_pointer (&self->events, g_hash_table_destroy); - g_clear_object (&self->kinetic_scroll_animation); g_clear_object (&self->row_offset_animation); @@ -1927,8 +1834,6 @@ gcal_month_view_init (GcalMonthView *self) { g_autoptr (GDateTime) now = NULL; - self->events = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); - gtk_widget_init_template (GTK_WIDGET (self)); update_weekday_labels (self);