core/calendar-monitor: Implement GListModel

This uses GcalEventList to as the backing store of events, and proxies
the "items-changed" signal.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-calendar/-/merge_requests/742>
This commit is contained in:
Georges Basile Stavracas Neto
2026-05-03 16:57:49 +00:00
committed by Marge Bot
parent 9eea2ee985
commit cc6736a16f
+75 -8
View File
@@ -25,6 +25,7 @@
#include "gcal-date-time-utils.h"
#include "gcal-debug.h"
#include "gcal-event.h"
#include "gcal-event-list.h"
#include <gio/gio.h>
#include <libecal/libecal.h>
@@ -59,6 +60,7 @@ struct _GcalCalendarMonitor
GAsyncQueue *messages;
GcalCalendar *calendar;
gboolean complete;
GcalEventList *event_list;
const GcalCalendarMonitorListener *listener;
gpointer listener_user_data;
@@ -89,8 +91,10 @@ static gboolean add_events_to_timeline_in_idle_cb (gpointer
static gboolean update_events_in_idle_cb (gpointer user_data);
static gboolean remove_events_from_timeline_in_idle_cb (gpointer user_data);
static gboolean complete_in_idle_cb (gpointer user_data);
static void g_list_model_interface_init (GListModelInterface *iface);
G_DEFINE_TYPE (GcalCalendarMonitor, gcal_calendar_monitor, G_TYPE_OBJECT)
G_DEFINE_TYPE_WITH_CODE (GcalCalendarMonitor, gcal_calendar_monitor, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, g_list_model_interface_init))
enum
{
@@ -102,6 +106,48 @@ enum
static GParamSpec *properties [N_PROPS] = { NULL, };
/*
* GListModel interface
*/
static GType
gcal_calendar_monitor_get_item_type (GListModel *model G_GNUC_UNUSED)
{
return GCAL_TYPE_EVENT;
}
static guint
gcal_calendar_monitor_get_n_items (GListModel *model)
{
GcalCalendarMonitor *self = (GcalCalendarMonitor *) model;
g_assert (GCAL_IS_CALENDAR_MONITOR (self));
return g_list_model_get_n_items (G_LIST_MODEL (self->event_list));
}
static gpointer
gcal_calendar_monitor_get_item (GListModel *model,
guint position)
{
GcalCalendarMonitor *self = (GcalCalendarMonitor *) model;
g_assert (GCAL_IS_CALENDAR_MONITOR (self));
return g_list_model_get_item (G_LIST_MODEL (self->event_list), position);
}
static void
g_list_model_interface_init (GListModelInterface *iface)
{
iface->get_item_type = gcal_calendar_monitor_get_item_type;
iface->get_n_items = gcal_calendar_monitor_get_n_items;
iface->get_item = gcal_calendar_monitor_get_item;
}
/*
* Threads
*
@@ -995,8 +1041,9 @@ remove_events_outside_range (GcalCalendarMonitor *self,
G_RW_LOCK_WRITER_AUTO_LOCK (&self->shared.lock, writer_locker);
events_to_remove = g_ptr_array_new_full (g_hash_table_size (self->shared.events),
g_object_unref);
events_to_remove = g_ptr_array_new_null_terminated (g_hash_table_size (self->shared.events),
g_object_unref,
TRUE);
g_hash_table_iter_init (&iter, self->shared.events);
while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &event))
@@ -1011,7 +1058,10 @@ remove_events_outside_range (GcalCalendarMonitor *self,
}
if (events_to_remove->len > 0)
self->listener->remove_events (self, events_to_remove, self->listener_user_data);
{
self->listener->remove_events (self, events_to_remove, self->listener_user_data);
gcal_event_list_remove_events (self->event_list, (GcalEvent **) events_to_remove->pdata);
}
}
static void
@@ -1028,7 +1078,10 @@ remove_all_events (GcalCalendarMonitor *self)
events_to_remove = g_hash_table_steal_all_values (self->shared.events);
if (events_to_remove->len > 0)
self->listener->remove_events (self, events_to_remove, self->listener_user_data);
{
self->listener->remove_events (self, events_to_remove, self->listener_user_data);
gcal_event_list_remove_all_events (self->event_list);
}
}
static void
@@ -1087,7 +1140,10 @@ add_events_to_timeline_in_idle_cb (gpointer user_data)
}
if (events_to_add->len > 0)
self->listener->add_events (self, events_to_add, self->listener_user_data);
{
self->listener->add_events (self, events_to_add, self->listener_user_data);
gcal_event_list_add_events (self->event_list, (GcalEvent **) events_to_add->pdata);
}
GCAL_RETURN (G_SOURCE_REMOVE);
}
@@ -1138,7 +1194,11 @@ update_events_in_idle_cb (gpointer user_data)
g_assert (old_events->len == new_events->len);
if (new_events->len > 0)
self->listener->update_events (self, old_events, new_events, self->listener_user_data);
{
self->listener->update_events (self, old_events, new_events, self->listener_user_data);
gcal_event_list_remove_events (self->event_list, (GcalEvent **) old_events->pdata);
gcal_event_list_add_events (self->event_list, (GcalEvent **) new_events->pdata);
}
GCAL_RETURN (G_SOURCE_REMOVE);
}
@@ -1181,7 +1241,10 @@ remove_events_from_timeline_in_idle_cb (gpointer user_data)
}
if (events_to_remove->len > 0)
self->listener->remove_events (self, events_to_remove, self->listener_user_data);
{
self->listener->remove_events (self, events_to_remove, self->listener_user_data);
gcal_event_list_remove_events (self->event_list, (GcalEvent **) events_to_remove->pdata);
}
GCAL_RETURN (G_SOURCE_REMOVE);
}
@@ -1253,6 +1316,7 @@ gcal_calendar_monitor_finalize (GObject *object)
{
GcalCalendarMonitor *self = (GcalCalendarMonitor *)object;
g_clear_object (&self->event_list);
g_clear_object (&self->calendar);
g_clear_pointer (&self->thread_context, g_main_context_unref);
g_clear_pointer (&self->main_context, g_main_context_unref);
@@ -1341,8 +1405,11 @@ gcal_calendar_monitor_init (GcalCalendarMonitor *self)
self->main_context = g_main_context_ref_thread_default ();
self->messages = g_async_queue_new ();
self->complete = FALSE;
self->event_list = gcal_event_list_new ();
g_rw_lock_init (&self->shared.lock);
g_signal_connect_swapped (self->event_list, "items-changed", G_CALLBACK (g_list_model_items_changed), self);
}
GcalCalendarMonitor*