Set the recurrence limit type via an action

Part-of: <https://gitlab.gnome.org/GNOME/gnome-calendar/-/merge_requests/550>
This commit is contained in:
Federico Mena Quintero
2025-08-27 20:00:18 -03:00
committed by Georges Basile Stavracas Neto
parent 52a7021241
commit dfe38af9ac
+83 -34
View File
@@ -352,6 +352,7 @@ recur_change_frequency (GcalRecurrence *old_recur, GcalRecurrenceFrequency frequ
{
if (frequency == GCAL_RECURRENCE_NO_REPEAT)
{
/* Invariant: GCAL_RECURRENCE_NO_REPEAT is reduced to a NULL recurrence */
return NULL;
}
else
@@ -373,6 +374,47 @@ recur_change_frequency (GcalRecurrence *old_recur, GcalRecurrenceFrequency frequ
}
}
static GcalRecurrence *
recur_change_limit_type (GcalRecurrence *old_recur, GcalRecurrenceLimitType limit_type, GDateTime *date_start)
{
/* An old recurrence would already be present with something other than GCAL_RECURRENCE_NO_REPEAT */
g_assert (old_recur != NULL);
g_assert (old_recur->frequency != GCAL_RECURRENCE_NO_REPEAT);
GcalRecurrence *new_recur = gcal_recurrence_copy (old_recur);
if (limit_type == old_recur->limit_type)
{
return new_recur;
}
else
{
new_recur->limit_type = limit_type;
switch (limit_type)
{
case GCAL_RECURRENCE_FOREVER:
break;
case GCAL_RECURRENCE_COUNT:
/* Other policies are possible. This is just "more than once". */
new_recur->limit.count = 2;
break;
case GCAL_RECURRENCE_UNTIL:
/* Again, other policies are possible. For now, leave the decision to the user. */
g_assert (date_start != NULL);
new_recur->limit.until = g_date_time_ref (date_start);
break;
default:
g_assert_not_reached ();
}
}
return new_recur;
}
static GcalScheduleSectionValues *
gcal_schedule_section_values_set_recur_frequency (const GcalScheduleSectionValues *values,
GcalRecurrenceFrequency frequency)
@@ -385,6 +427,18 @@ gcal_schedule_section_values_set_recur_frequency (const GcalScheduleSectionValue
return copy;
}
static GcalScheduleSectionValues *
gcal_schedule_section_values_set_recur_limit_type (const GcalScheduleSectionValues *values,
GcalRecurrenceLimitType limit_type)
{
GcalScheduleSectionValues *copy = gcal_schedule_section_values_copy (values);
GcalRecurrence *new_recur = recur_change_limit_type (copy->curr.recur, limit_type, values->curr.date_start);
g_clear_pointer (&copy->curr.recur, gcal_recurrence_unref);
copy->curr.recur = new_recur;
return copy;
}
static WidgetState *
widget_state_from_values (const GcalScheduleSectionValues *values)
{
@@ -666,9 +720,8 @@ on_repeat_duration_changed_cb (GtkWidget *widget,
GcalScheduleSection *self)
{
GcalRecurrenceLimitType limit_type = get_recurence_limit_type (self);
gtk_widget_set_visible (self->number_of_occurrences_spin, limit_type == GCAL_RECURRENCE_COUNT);
gtk_widget_set_visible (self->until_date_selector, limit_type == GCAL_RECURRENCE_UNTIL);
GcalScheduleSectionValues *updated = gcal_schedule_section_values_set_recur_limit_type (self->values, limit_type);
update_from_section_values (self, updated);
}
static GcalRecurrenceFrequency
@@ -753,45 +806,28 @@ static void
gcal_schedule_section_apply_to_event (GcalScheduleSection *self,
GcalEvent *event)
{
GcalRecurrenceFrequency freq;
GCAL_ENTRY;
gcal_event_set_all_day (event, self->values->curr.all_day);
gcal_event_set_date_start (event, self->values->curr.date_start);
gcal_event_set_date_end (event, self->values->curr.date_end);
/* Check Repeat popover and set recurrence-rules accordingly */
freq = get_recurrence_frequency (self);
if (freq != GCAL_RECURRENCE_NO_REPEAT)
/* Only apply the new recurrence if it's different from the old one.
* We don't unconditionally set the recurrence since remove_recurrence_properties()
* will actually remove all the rrules, not just *a* unique one.
*
* That is, here we allow for future support for more than one rrule
* in the event, given the current capabilities of gnome-calendar.
*
*/
if (!gcal_recurrence_is_equal (self->values->curr.recur, gcal_event_get_recurrence (event)))
{
g_autoptr (GcalRecurrence) recur = NULL;
recur = gcal_recurrence_new ();
recur->frequency = freq;
recur->limit_type = get_recurence_limit_type (self);
if (recur->limit_type == GCAL_RECURRENCE_UNTIL)
recur->limit.until = g_date_time_ref (gcal_date_selector_get_date (GCAL_DATE_SELECTOR (self->until_date_selector)));
else if (recur->limit_type == GCAL_RECURRENCE_COUNT)
recur->limit.count = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (self->number_of_occurrences_spin));
/* Only apply the new recurrence if it's different from the old one */
if (!gcal_recurrence_is_equal (self->values->curr.recur, recur))
{
/* Remove the previous recurrence... */
remove_recurrence_properties (event);
/* ... and set the new one */
gcal_event_set_recurrence (event, recur);
}
}
else
{
/* When NO_REPEAT is set, make sure to remove the old recurrent */
remove_recurrence_properties (event);
if (self->values->curr.recur)
{
gcal_event_set_recurrence (event, self->values->curr.recur);
}
}
GCAL_EXIT;
@@ -1283,6 +1319,17 @@ test_recur_changes_to_no_repeat (void)
g_assert_null (new_recur);
}
static void
test_recur_changes_limit_type_to_count (void)
{
g_autoptr (GcalRecurrence) old_recur = gcal_recurrence_new ();
old_recur->frequency = GCAL_RECURRENCE_WEEKLY;
g_autoptr (GcalRecurrence) new_recur = recur_change_limit_type (old_recur, GCAL_RECURRENCE_COUNT, NULL);
g_assert_cmpint (new_recur->limit_type, ==, GCAL_RECURRENCE_COUNT);
g_assert_cmpint (new_recur->limit.count, ==, 2);
}
void
gcal_schedule_section_add_tests (void)
{
@@ -1300,4 +1347,6 @@ gcal_schedule_section_add_tests (void)
test_43_switching_to_all_day_preserves_timezones);
g_test_add_func ("/event_editor/schedule_section/recur_changes_to_no_repeat",
test_recur_changes_to_no_repeat);
g_test_add_func ("/event_editor/schedule_section/recur_changes_limit_type_to_count",
test_recur_changes_limit_type_to_count);
}