From cc4e5379870eee731cb9924906700d51fd8cd65c Mon Sep 17 00:00:00 2001 From: John Cardullo Date: Mon, 5 Oct 2026 13:00:32 -0700 Subject: [PATCH] search: Fold recurring events into single results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When searching for events, users are typically interested in finding the event rather than seeing a repetitive list of every occurrence instance. By configuring the search timelines with "expand-recurrences" set to FALSE, recurring events are loaded as their single master component instead of expanding all individual occurrences. Additionally: - Update GcalSearchHitEvent subtitle to display "Recurring" (e.g. "Tomorrow • Recurring" or "Recurring") when the event has a recurrence rule. - Safeguard gcal_event_format_date() when running without a default GApplication. Fixes: https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/991 Part-of: --- src/core/gcal-event.c | 11 +++++++++-- src/core/gcal-shell-search-provider.c | 4 +++- src/search/gcal-search-engine.c | 4 +++- src/search/gcal-search-hit-event.c | 15 +++++++++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/core/gcal-event.c b/src/core/gcal-event.c index 098442c0..468c5054 100644 --- a/src/core/gcal-event.c +++ b/src/core/gcal-event.c @@ -1911,8 +1911,15 @@ gcal_event_format_date (GcalEvent *self) /* XXX: nasty... */ application = GCAL_APPLICATION (g_application_get_default ()); - context = gcal_application_get_context (application); - time_format = gcal_context_get_time_format (context); + if (application) + { + context = gcal_application_get_context (application); + time_format = gcal_context_get_time_format (context); + } + else + { + time_format = GCAL_TIME_FORMAT_24H; + } if (time_format == GCAL_TIME_FORMAT_24H) hour_format = "%R"; diff --git a/src/core/gcal-shell-search-provider.c b/src/core/gcal-shell-search-provider.c index 087b6334..ec0f0f36 100644 --- a/src/core/gcal-shell-search-provider.c +++ b/src/core/gcal-shell-search-provider.c @@ -474,7 +474,9 @@ gcal_shell_search_provider_constructed (GObject *object) GcalContext *context = gcal_application_get_context (GCAL_DEFAULT_APPLICATION); GcalManager *manager = gcal_context_get_manager (context); - self->timeline = gcal_timeline_new (); + self->timeline = g_object_new (GCAL_TYPE_TIMELINE, + "expand-recurrences", FALSE, + NULL); g_signal_connect (self->timeline, "notify::complete", G_CALLBACK (on_timeline_completed_cb), self); g_signal_connect (manager, "calendar-added", G_CALLBACK (on_manager_calendar_added_cb), self); diff --git a/src/search/gcal-search-engine.c b/src/search/gcal-search-engine.c index 97f6d24d..3dd721a8 100644 --- a/src/search/gcal-search-engine.c +++ b/src/search/gcal-search-engine.c @@ -113,7 +113,9 @@ gcal_search_engine_constructed (GObject *object) G_OBJECT_CLASS (gcal_search_engine_parent_class)->constructed (object); /* Set up the data model */ - self->timeline = gcal_timeline_new (); + self->timeline = g_object_new (GCAL_TYPE_TIMELINE, + "expand-recurrences", FALSE, + NULL); context = gcal_application_get_context (GCAL_DEFAULT_APPLICATION); manager = gcal_context_get_manager (context); diff --git a/src/search/gcal-search-hit-event.c b/src/search/gcal-search-hit-event.c index 13d3a4c6..1742624c 100644 --- a/src/search/gcal-search-hit-event.c +++ b/src/search/gcal-search-hit-event.c @@ -24,6 +24,8 @@ #include "gcal-search-hit-event.h" #include "gcal-utils.h" +#include + struct _GcalSearchHitEvent { GcalSearchHit parent; @@ -63,9 +65,22 @@ set_event (GcalSearchHitEvent *self, gcal_search_hit_set_title (search_hit, gcal_event_get_summary (event)); date_string = gcal_event_format_date (event); + + if (gcal_event_has_recurrence (event)) + { + g_autofree gchar *formatted_date = g_steal_pointer (&date_string); + + if (formatted_date && *formatted_date != '\0') + date_string = g_strdup_printf (_ ("%s • Recurring"), formatted_date); + else + date_string = g_strdup (_ ("Recurring")); + } + gcal_search_hit_set_subtitle (search_hit, date_string); calendar = gcal_event_get_calendar (self->event); + g_assert (calendar != NULL); + color = gcal_calendar_get_color (calendar); paintable = gcal_util_get_circle_paintable_from_color (color, 16); gcal_search_hit_set_primary_icon (search_hit, paintable);