/* gcal-recurrence.c * * Copyright (C) 2017 Yash Singh * * gnome-calendar is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * gnome-calendar is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "gcal-recurrence.h" #include "gcal-utils.h" #include "gcal-event.h" #include G_DEFINE_BOXED_TYPE (GcalRecurrence, gcal_recurrence, gcal_recurrence_ref, gcal_recurrence_unref) static void gcal_recurrence_free (GcalRecurrence *self) { g_assert (self); g_assert_cmpint (self->ref_count, ==, 0); gcal_clear_date_time (&self->limit.until); g_slice_free (GcalRecurrence, self); } /** * gcal_recurrence_new: * * Creates a new #GcalRecurrence * * Returns: (transfer full): a #GcalRecurrence */ GcalRecurrence* gcal_recurrence_new (void) { GcalRecurrence *new_recur; new_recur = g_slice_new (GcalRecurrence); new_recur->frequency = GCAL_RECURRENCE_NO_REPEAT; new_recur->limit_type = GCAL_RECURRENCE_FOREVER; new_recur->limit.until = NULL; new_recur->limit.count = 0; new_recur->ref_count = 1; return new_recur; } /** * gcal_recurrence_copy: * @recur: a #GcalRecurrence * * Creates a copy of @recur * * Returns: (transfer full): a #GcalRecurrence */ GcalRecurrence* gcal_recurrence_copy (GcalRecurrence *recur) { GcalRecurrence *new_recur; g_return_val_if_fail (recur != NULL, NULL); new_recur = gcal_recurrence_new (); new_recur->frequency = recur->frequency; new_recur->limit_type = recur->limit_type; if (recur->limit_type == GCAL_RECURRENCE_UNTIL && recur->limit.until) new_recur->limit.until = g_date_time_ref (recur->limit.until); new_recur->limit.count = recur->limit.count; return new_recur; } GcalRecurrence * gcal_recurrence_ref (GcalRecurrence *self) { g_return_val_if_fail (self, NULL); g_return_val_if_fail (self->ref_count, NULL); g_atomic_int_inc (&self->ref_count); return self; } void gcal_recurrence_unref (GcalRecurrence *self) { g_return_if_fail (self); g_return_if_fail (self->ref_count); if (g_atomic_int_dec_and_test (&self->ref_count)) gcal_recurrence_free (self); } /** * gcal_recurrence_is_equal: * @recur1: (nullable): a #GcalRecurrence * @recur2: (nullable): a #GcalRecurrence * * Checks if @recur1 and @recur2 are equal or not * * Returns: %TRUE if both are equal, %FALSE otherwise */ gboolean gcal_recurrence_is_equal (GcalRecurrence *recur1, GcalRecurrence *recur2) { if (recur1 == recur2) return TRUE; else if (!recur1 || !recur2) return FALSE; if (recur1->frequency != recur2->frequency) return FALSE; if (recur1->limit_type != recur2->limit_type) return FALSE; if (recur1->limit_type == GCAL_RECURRENCE_UNTIL) { if (!g_date_time_equal (recur1->limit.until, recur2->limit.until)) return FALSE; } else if (recur1->limit_type == GCAL_RECURRENCE_COUNT) { if (recur1->limit.count != recur2->limit.count) return FALSE; } return TRUE; } /** * gcal_recurrence_parse_recurrence_rules: * @comp: an #ECalComponent * * Parses the rrule of the @comp and * sets the GcalRecurrence struct accordingly. * * Returns: (transfer full): a #GcalRecurrence */ GcalRecurrence* gcal_recurrence_parse_recurrence_rules (ECalComponent *comp) { GcalRecurrence *recur; ICalProperty *prop; ICalComponent *icalcomp; ICalRecurrence *rrule; if (!e_cal_component_has_recurrences (comp)) return NULL; recur = gcal_recurrence_new (); icalcomp = e_cal_component_get_icalcomponent (comp); prop = i_cal_component_get_first_property (icalcomp, I_CAL_RRULE_PROPERTY); g_return_val_if_fail (prop != NULL, NULL); rrule = i_cal_property_get_rrule (prop); g_clear_object (&prop); switch (i_cal_recurrence_get_freq (rrule)) { case I_CAL_DAILY_RECURRENCE: recur->frequency = GCAL_RECURRENCE_DAILY; break; case I_CAL_WEEKLY_RECURRENCE: { if (i_cal_recurrence_get_by_day (rrule, 0) == I_CAL_MONDAY_WEEKDAY && i_cal_recurrence_get_by_day (rrule, 1) == I_CAL_TUESDAY_WEEKDAY && i_cal_recurrence_get_by_day (rrule, 2) == I_CAL_WEDNESDAY_WEEKDAY && i_cal_recurrence_get_by_day (rrule, 3) == I_CAL_THURSDAY_WEEKDAY && i_cal_recurrence_get_by_day (rrule, 4) == I_CAL_FRIDAY_WEEKDAY && i_cal_recurrence_get_by_day (rrule, 5) != I_CAL_SATURDAY_WEEKDAY && i_cal_recurrence_get_by_day (rrule, 6) != I_CAL_SUNDAY_WEEKDAY) { recur->frequency = GCAL_RECURRENCE_MON_FRI; } else { recur->frequency = GCAL_RECURRENCE_WEEKLY; } break; } case I_CAL_MONTHLY_RECURRENCE: recur->frequency = GCAL_RECURRENCE_MONTHLY; break; case I_CAL_YEARLY_RECURRENCE: recur->frequency = GCAL_RECURRENCE_YEARLY; break; default: recur->frequency = GCAL_RECURRENCE_OTHER; } if (i_cal_recurrence_get_count (rrule) > 0) { recur->limit_type = GCAL_RECURRENCE_COUNT; recur->limit.count = i_cal_recurrence_get_count (rrule); } else { ICalTime *until; until = i_cal_recurrence_get_until (rrule); if (i_cal_time_get_year (until) != 0) { recur->limit_type = GCAL_RECURRENCE_UNTIL; recur->limit.until = gcal_date_time_from_icaltime (until); } else { recur->limit_type = GCAL_RECURRENCE_FOREVER; } g_clear_object (&until); } g_clear_object (&rrule); return recur; } /** * gcal_recurrence_to_rrule: * @recur: a #GcalRecurrence * * Converts @recur into corresponding rrule. * * Returns: (transfer full): an #ICalRecurrence */ ICalRecurrence* gcal_recurrence_to_rrule (GcalRecurrence *recur) { ICalRecurrence *rrule; if (!recur) return NULL; /* Initialize and clear the rrule to get rid of unwanted fields */ rrule = i_cal_recurrence_new (); switch (recur->frequency) { case GCAL_RECURRENCE_DAILY: i_cal_recurrence_set_freq (rrule, I_CAL_DAILY_RECURRENCE); break; case GCAL_RECURRENCE_WEEKLY: i_cal_recurrence_set_freq (rrule, I_CAL_WEEKLY_RECURRENCE); break; case GCAL_RECURRENCE_MONTHLY: i_cal_recurrence_set_freq (rrule, I_CAL_MONTHLY_RECURRENCE); break; case GCAL_RECURRENCE_YEARLY: i_cal_recurrence_set_freq (rrule, I_CAL_YEARLY_RECURRENCE); break; case GCAL_RECURRENCE_NO_REPEAT: i_cal_recurrence_set_freq (rrule, I_CAL_NO_RECURRENCE); break; case GCAL_RECURRENCE_MON_FRI: { i_cal_recurrence_set_freq (rrule, I_CAL_WEEKLY_RECURRENCE); i_cal_recurrence_set_by_day (rrule, 0, I_CAL_MONDAY_WEEKDAY); i_cal_recurrence_set_by_day (rrule, 1, I_CAL_TUESDAY_WEEKDAY); i_cal_recurrence_set_by_day (rrule, 2, I_CAL_WEDNESDAY_WEEKDAY); i_cal_recurrence_set_by_day (rrule, 3, I_CAL_THURSDAY_WEEKDAY); i_cal_recurrence_set_by_day (rrule, 4, I_CAL_FRIDAY_WEEKDAY); break; } default: i_cal_recurrence_set_freq (rrule, I_CAL_NO_RECURRENCE); break; } switch (recur->limit_type) { case GCAL_RECURRENCE_COUNT: i_cal_recurrence_set_count (rrule, recur->limit.count); break; case GCAL_RECURRENCE_UNTIL: { ICalTime *until; until = i_cal_time_new_null_time (); i_cal_time_set_date (until, g_date_time_get_year (recur->limit.until), g_date_time_get_month (recur->limit.until), g_date_time_get_day_of_month (recur->limit.until)); i_cal_time_set_time (until, g_date_time_get_hour (recur->limit.until), g_date_time_get_minute (recur->limit.until), g_date_time_get_second (recur->limit.until)); i_cal_recurrence_set_until (rrule, until); g_clear_object (&until); break; } case GCAL_RECURRENCE_FOREVER: break; default: break; } return rrule; }