views/month: Recycle event widgets using the pool

Create a new GcalEventWidgetPool shared between all month view rows.
The event widgets are distributed to rows as needed.

When rows are done with the event widget, the give them back to the
pool so that other rows can reuse them.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-calendar/-/merge_requests/758>
This commit is contained in:
Georges Basile Stavracas Neto
2026-05-19 22:20:10 +00:00
committed by Marge Bot
parent 3692747362
commit bbc041eed9
3 changed files with 82 additions and 18 deletions
+73 -16
View File
@@ -53,6 +53,8 @@ struct _GcalMonthViewRow
GListModel *events;
GcalEventWidgetPool *event_widget_pool;
GHashTable *layout_blocks;
gboolean layout_blocks_valid;
};
@@ -684,6 +686,37 @@ extract_current_event_widgets (GcalMonthViewRow *self)
return g_steal_pointer (&event_widgets);
}
static void
return_remaining_event_widgets_to_pool (GcalMonthViewRow *self,
GHashTable *event_widgets)
{
GHashTableIter iter;
GPtrArray *widgets;
g_assert (GCAL_IS_MONTH_VIEW_ROW (self));
g_assert (event_widgets != NULL);
g_hash_table_iter_init (&iter, event_widgets);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &widgets))
{
g_assert (widgets != NULL);
while (widgets->len > 0)
{
GtkWidget *widget = g_ptr_array_steal_index_fast (widgets, 0);
g_signal_handlers_disconnect_by_func (widget, on_event_widget_activated_cb, self);
gtk_widget_unparent (widget);
gcal_event_widget_pool_reclaim (self->event_widget_pool, g_steal_pointer (&widget));
}
g_hash_table_iter_remove (&iter);
}
g_assert (g_hash_table_size (event_widgets) == 0);
}
static GtkWidget *
pick_existing_event_widget (GHashTable *event_widgets,
GcalEvent *event)
@@ -700,6 +733,26 @@ pick_existing_event_widget (GHashTable *event_widgets,
return g_ptr_array_steal_index_fast (widgets, 0);
}
static GtkWidget *
pick_or_create_event_widget_for_event (GcalMonthViewRow *self,
GHashTable *event_widgets,
GcalEvent *event)
{
GtkWidget *event_widget;
event_widget = pick_existing_event_widget (event_widgets, event);
if (!event_widget)
{
event_widget = gcal_event_widget_pool_take_or_create (self->event_widget_pool, event);
g_assert (GCAL_IS_EVENT_WIDGET (event_widget));
setup_child_widget (self, event_widget);
}
return g_steal_pointer (&event_widget);
}
static void
recalculate_layout_blocks (GcalMonthViewRow *self)
{
@@ -745,14 +798,10 @@ recalculate_layout_blocks (GcalMonthViewRow *self)
{
GtkWidget *event_widget;
event_widget = pick_existing_event_widget (event_widgets, event);
if (!event_widget)
{
event_widget = gcal_event_widget_new (event);
if (!gcal_event_get_all_day (event) && !gcal_event_is_multiday (event))
gcal_event_widget_set_timestamp_policy (GCAL_EVENT_WIDGET (event_widget), GCAL_TIMESTAMP_POLICY_START);
setup_child_widget (self, event_widget);
}
event_widget = pick_or_create_event_widget_for_event (self, event_widgets, event);
if (!gcal_event_get_all_day (event) && !gcal_event_is_multiday (event))
gcal_event_widget_set_timestamp_policy (GCAL_EVENT_WIDGET (event_widget), GCAL_TIMESTAMP_POLICY_START);
block = g_new (GcalEventBlock, 1);
block->event_widget = g_steal_pointer (&event_widget);
@@ -765,12 +814,10 @@ recalculate_layout_blocks (GcalMonthViewRow *self)
{
GtkWidget *new_event_widget;
new_event_widget = pick_existing_event_widget (event_widgets, event);
if (!new_event_widget)
{
new_event_widget = gcal_event_widget_clone (GCAL_EVENT_WIDGET (block->event_widget));
setup_child_widget (self, new_event_widget);
}
new_event_widget = pick_or_create_event_widget_for_event (self, event_widgets, event);
if (!gcal_event_get_all_day (event) && !gcal_event_is_multiday (event))
gcal_event_widget_set_timestamp_policy (GCAL_EVENT_WIDGET (new_event_widget), GCAL_TIMESTAMP_POLICY_START);
block = g_new (GcalEventBlock, 1);
block->event_widget = g_steal_pointer (&new_event_widget);
@@ -814,6 +861,8 @@ recalculate_layout_blocks (GcalMonthViewRow *self)
g_hash_table_insert (self->layout_blocks, event, g_steal_pointer (&blocks));
}
return_remaining_event_widgets_to_pool (self, event_widgets);
self->layout_blocks_valid = TRUE;
GCAL_EXIT;
@@ -1172,6 +1221,7 @@ gcal_month_view_row_finalize (GObject *object)
{
GcalMonthViewRow *self = (GcalMonthViewRow *)object;
g_clear_object (&self->event_widget_pool);
g_clear_pointer (&self->range, gcal_range_unref);
G_OBJECT_CLASS (gcal_month_view_row_parent_class)->finalize (object);
@@ -1304,9 +1354,16 @@ gcal_month_view_row_init (GcalMonthViewRow *self)
}
GtkWidget *
gcal_month_view_row_new (void)
gcal_month_view_row_new (GcalEventWidgetPool *event_widget_pool)
{
return g_object_new (GCAL_TYPE_MONTH_VIEW_ROW, NULL);
g_autoptr (GcalMonthViewRow) self = NULL;
g_assert (GCAL_IS_EVENT_WIDGET_POOL (event_widget_pool));
self = g_object_new (GCAL_TYPE_MONTH_VIEW_ROW, NULL);
self->event_widget_pool = g_object_ref (event_widget_pool);
return GTK_WIDGET (g_steal_pointer (&self));
}
GcalRange *
+2 -1
View File
@@ -25,6 +25,7 @@
#include "gcal-context.h"
#include "gcal-event.h"
#include "gcal-event-widget-pool.h"
#include "gcal-range.h"
G_BEGIN_DECLS
@@ -32,7 +33,7 @@ G_BEGIN_DECLS
#define GCAL_TYPE_MONTH_VIEW_ROW (gcal_month_view_row_get_type())
G_DECLARE_FINAL_TYPE (GcalMonthViewRow, gcal_month_view_row, GCAL, MONTH_VIEW_ROW, GtkWidget)
GtkWidget * gcal_month_view_row_new (void);
GtkWidget * gcal_month_view_row_new (GcalEventWidgetPool *event_widget_pool);
GcalRange * gcal_month_view_row_get_range (GcalMonthViewRow *self);
+7 -1
View File
@@ -23,6 +23,7 @@
#include "config.h"
#include "gcal-debug.h"
#include "gcal-event-widget-pool.h"
#include "gcal-month-cell.h"
#include "gcal-month-popover.h"
#include "gcal-month-view.h"
@@ -56,6 +57,8 @@ struct _GcalMonthView
GPtrArray *week_rows;
GcalEventWidgetPool *event_widget_pool;
struct {
GtkWidget *popover;
GcalMonthViewRow *row;
@@ -1737,6 +1740,7 @@ gcal_month_view_finalize (GObject *object)
{
GcalMonthView *self = (GcalMonthView *)object;
g_clear_object (&self->event_widget_pool);
gcal_clear_date_time (&self->selection.start);
gcal_clear_date_time (&self->selection.end);
gcal_clear_date_time (&self->date);
@@ -1836,6 +1840,8 @@ gcal_month_view_init (GcalMonthView *self)
{
g_autoptr (GDateTime) now = NULL;
self->event_widget_pool = gcal_event_widget_pool_new ();
gtk_widget_init_template (GTK_WIDGET (self));
update_weekday_labels (self);
@@ -1847,7 +1853,7 @@ gcal_month_view_init (GcalMonthView *self)
self->week_rows = g_ptr_array_new_full (N_TOTAL_ROWS, (GDestroyNotify) gtk_widget_unparent);
for (gint i = 0; i < N_TOTAL_ROWS; i++)
{
GtkWidget *row = gcal_month_view_row_new ();
GtkWidget *row = gcal_month_view_row_new (self->event_widget_pool);
g_signal_connect (row, "event-activated", G_CALLBACK (on_event_widget_activated_cb), self);
g_signal_connect (row, "cell-activated", G_CALLBACK (on_month_row_cell_activated_cb), self);
g_signal_connect (row, "show-overflow", G_CALLBACK (on_month_row_show_overflow_cb), self);