recurrence: Add recurrence struct to parse recurrence-rules

Currently, gnome-calendar has no component to deal
with recurrence-rules of events. This missing component
is however required to create and modify recurring events.

This patch adds the required GcalRecurrence component
which parses the recurrence-rules with details like:

 * Frequency of the recurring event
 * Duration of the recurrences:
	** If they repeat until a particular date
	** If they repeat a fixed number of times
	** If they repeat forever

and then stores these details in a suitable format
in the GcalRecurrence structure. The gcal-recurrence
functions simplify the task of handling and editing
recurrences. This structure is the first step towards
creating a new 'recurrence' property of an event.

https://bugzilla.gnome.org/show_bug.cgi?id=782755
This commit is contained in:
Yash Singh
2017-07-04 10:32:48 -03:00
committed by Georges Basile Stavracas Neto
parent 4b4b8d23e5
commit 27bb337f54
3 changed files with 342 additions and 0 deletions
+2
View File
@@ -67,6 +67,8 @@ gnome_calendar_SOURCES = \
gcal-multi-choice.h \
gcal-quick-add-popover.c \
gcal-quick-add-popover.h \
gcal-recurrence.c \
gcal-recurrence.h \
gcal-search-view.h \
gcal-search-view.c \
gcal-shell-search-provider.h \
+264
View File
@@ -0,0 +1,264 @@
/* -*- mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* gcal-recurrence.c
* Copyright (C) 2017 Yash Singh <yashdev10p@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "gcal-recurrence.h"
#include "gcal-utils.h"
#include "gcal-event.h"
#include <glib.h>
G_DEFINE_BOXED_TYPE (GcalRecurrence, gcal_recurrence, gcal_recurrence_copy, gcal_recurrence_free)
/**
* 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;
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;
}
/**
* gcal_recurrence_free:
* @recur: a #GcalRecurrence.
*
* Frees @recur
*/
void
gcal_recurrence_free (GcalRecurrence *recur)
{
gcal_clear_datetime (&recur->limit.until);
g_slice_free (GcalRecurrence, recur);
}
/**
* 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;
struct icalrecurrencetype rrule;
if (!e_cal_component_has_recurrences (comp))
return NULL;
recur = gcal_recurrence_new ();
icalcomp = e_cal_component_get_icalcomponent (comp);
prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
g_return_val_if_fail (prop != NULL, NULL);
rrule = icalproperty_get_rrule (prop);
switch (rrule.freq)
{
case ICAL_DAILY_RECURRENCE:
recur->frequency = GCAL_RECURRENCE_DAILY;
break;
case ICAL_WEEKLY_RECURRENCE:
{
if (rrule.by_day[0] == ICAL_MONDAY_WEEKDAY &&
rrule.by_day[1] == ICAL_TUESDAY_WEEKDAY &&
rrule.by_day[2] == ICAL_WEDNESDAY_WEEKDAY &&
rrule.by_day[3] == ICAL_THURSDAY_WEEKDAY &&
rrule.by_day[4] == ICAL_FRIDAY_WEEKDAY &&
rrule.by_day[5] != ICAL_SATURDAY_WEEKDAY &&
rrule.by_day[6] != ICAL_SUNDAY_WEEKDAY)
{
recur->frequency = GCAL_RECURRENCE_MON_FRI;
}
else
{
recur->frequency = GCAL_RECURRENCE_WEEKLY;
}
break;
}
case ICAL_MONTHLY_RECURRENCE:
recur->frequency = GCAL_RECURRENCE_MONTHLY;
break;
case ICAL_YEARLY_RECURRENCE:
recur->frequency = GCAL_RECURRENCE_YEARLY;
break;
default:
recur->frequency = GCAL_RECURRENCE_OTHER;
}
if (rrule.count > 0)
{
recur->limit_type = GCAL_RECURRENCE_COUNT;
recur->limit.count = rrule.count;
}
else if (rrule.until.year != 0)
{
recur->limit_type = GCAL_RECURRENCE_UNTIL;
recur->limit.until = icaltime_to_datetime (&rrule.until);
}
else
{
recur->limit_type = GCAL_RECURRENCE_FOREVER;
}
return recur;
}
/**
* gcal_recurrence_to_rrule:
* @recur: a #GcalRecurrence
*
* Converts @recur into corresponding rrule.
*
* Returns: (transfer full): a #struct icalrecurrencetype
*/
struct icalrecurrencetype*
gcal_recurrence_to_rrule (GcalRecurrence *recur)
{
struct icalrecurrencetype *rrule;
if (!recur)
return NULL;
/* Initialize and clear the rrule to get rid of unwanted fields */
rrule = g_new0 (struct icalrecurrencetype, 1);
icalrecurrencetype_clear (rrule);
rrule->until.second = 0;
rrule->until.minute = 0;
rrule->until.hour = 0;
rrule->until.is_date = TRUE;
rrule->until.is_utc = FALSE;
switch (recur->frequency)
{
case GCAL_RECURRENCE_DAILY:
rrule->freq = ICAL_DAILY_RECURRENCE;
break;
case GCAL_RECURRENCE_WEEKLY:
rrule->freq = ICAL_WEEKLY_RECURRENCE;
break;
case GCAL_RECURRENCE_MONTHLY:
rrule->freq = ICAL_MONTHLY_RECURRENCE;
break;
case GCAL_RECURRENCE_YEARLY:
rrule->freq = ICAL_YEARLY_RECURRENCE;
break;
case GCAL_RECURRENCE_NO_REPEAT:
rrule->freq = ICAL_NO_RECURRENCE;
break;
case GCAL_RECURRENCE_MON_FRI:
{
rrule->freq = ICAL_WEEKLY_RECURRENCE;
rrule->by_day[0] = ICAL_MONDAY_WEEKDAY;
rrule->by_day[1] = ICAL_TUESDAY_WEEKDAY;
rrule->by_day[2] = ICAL_WEDNESDAY_WEEKDAY;
rrule->by_day[3] = ICAL_THURSDAY_WEEKDAY;
rrule->by_day[4] = ICAL_FRIDAY_WEEKDAY;
break;
}
default:
rrule->freq = ICAL_NO_RECURRENCE;
break;
}
switch (recur->limit_type)
{
case GCAL_RECURRENCE_COUNT:
rrule->count = recur->limit.count;
break;
case GCAL_RECURRENCE_UNTIL:
{
rrule->until.second = g_date_time_get_second (recur->limit.until);
rrule->until.minute = g_date_time_get_minute (recur->limit.until);
rrule->until.hour = g_date_time_get_hour (recur->limit.until);
rrule->until.day = g_date_time_get_day_of_month (recur->limit.until);
rrule->until.month = g_date_time_get_year (recur->limit.until);
rrule->until.year = g_date_time_get_month (recur->limit.until);
break;
}
case GCAL_RECURRENCE_FOREVER:
break;
default:
break;
}
return rrule;
}
+76
View File
@@ -0,0 +1,76 @@
/* -*- mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* gcal-recurrence.h
* Copyright (C) 2017 Yash Singh <yashdev10p@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef GCAL_RECURRENCE_H
#define GCAL_RECURRENCE_H
#include <glib-object.h>
#include <libecal/libecal.h>
G_BEGIN_DECLS
#define GCAL_TYPE_RECURRENCE (gcal_recurrence_get_type())
typedef struct _GcalRecurrence GcalRecurrence;
typedef enum
{
GCAL_RECURRENCE_NO_REPEAT,
GCAL_RECURRENCE_DAILY,
GCAL_RECURRENCE_MON_FRI,
GCAL_RECURRENCE_WEEKLY,
GCAL_RECURRENCE_MONTHLY,
GCAL_RECURRENCE_YEARLY,
GCAL_RECURRENCE_OTHER
} GcalRecurrenceFrequency;
typedef enum
{
GCAL_RECURRENCE_FOREVER,
GCAL_RECURRENCE_COUNT,
GCAL_RECURRENCE_UNTIL
} GcalRecurrenceLimitType;
struct _GcalRecurrence
{
GcalRecurrenceFrequency frequency;
GcalRecurrenceLimitType limit_type;
struct {
GDateTime *until;
guint count;
} limit;
};
GType gcal_recurrence_get_type (void) G_GNUC_CONST;
GcalRecurrence* gcal_recurrence_new (void);
GcalRecurrence* gcal_recurrence_copy (GcalRecurrence *recur);
void gcal_recurrence_free (GcalRecurrence *recur);
GcalRecurrence* gcal_recurrence_parse_recurrence_rules (ECalComponent *comp);
struct icalrecurrencetype* gcal_recurrence_to_rrule (GcalRecurrence *recur);
G_END_DECLS
#endif /* GCAL_RECURRENCE_H */