aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/e-meeting-attendee.c
diff options
context:
space:
mode:
authorJP Rosevear <jpr@ximian.com>2001-09-19 12:33:33 +0800
committerJP Rosevear <jpr@src.gnome.org>2001-09-19 12:33:33 +0800
commitd639a620a6438ea93787cedfe9f3eb87014275a3 (patch)
tree602d9156e8e33197fc27752d8fb976cce99d896c /calendar/gui/e-meeting-attendee.c
parentd284de85386149adba1e94f1b05b6b2d631e8585 (diff)
downloadgsoc2013-evolution-d639a620a6438ea93787cedfe9f3eb87014275a3.tar
gsoc2013-evolution-d639a620a6438ea93787cedfe9f3eb87014275a3.tar.gz
gsoc2013-evolution-d639a620a6438ea93787cedfe9f3eb87014275a3.tar.bz2
gsoc2013-evolution-d639a620a6438ea93787cedfe9f3eb87014275a3.tar.lz
gsoc2013-evolution-d639a620a6438ea93787cedfe9f3eb87014275a3.tar.xz
gsoc2013-evolution-d639a620a6438ea93787cedfe9f3eb87014275a3.tar.zst
gsoc2013-evolution-d639a620a6438ea93787cedfe9f3eb87014275a3.zip
A page that shows the meeting time selector and free/busy data for
2001-09-18 JP Rosevear <jpr@ximian.com> * gui/dialogs/schedule-page.*: A page that shows the meeting time selector and free/busy data for attendees * gui/dialogs/meeting-page.c: use the meeting model to track/edit attendees, remove table value conversion routines and simple table routines (set_attendees): take a pointer array (meeting_page_destroy): destroy the pointer array, save state (meeting_page_init): new pointer array (meeting_page_fill_widgets): don't null the deleted attendees field (popup_delegate_cb): array add (popup_delete_cb): array add (cleanup_attendees): iterate over the array to unref now (meeting_page_fill_widgets): don't null out fields, no need to add attendees here (invite_entry_changed): use e_meeting_attendee routines (popup_delegate_cb): ditto (popup_delete_cb): ditto (meeting_page_new): take new arg and pass it to construct (meeting_page_construct): take new arg, use e-meeting-model routines to construct table * gui/dialogs/task-editor.c (task_editor_init): new meeting model (task_editor_destroy): unref the model * gui/dialogs/event-editor.c (event_editor_init): make new model and pass it to meeting and schedule pages (event_editor_set_cal_client): virtual function, set meeting model client (event_editor_edit_comp): add the attendees to the model (event_editor_destroy): unref model * gui/dialogs/comp-editor.h: add virtual function * gui/dialogs/comp-editor.c (comp_editor_set_cal_client): make set_cal_client a virutal function * gui/e-meeting-types.h: generally useful type defines * gui/e-meeting-time-sel*.[hc]: Move here and use an e-table for the attendee list and extract display information from the new meeting model and attendees * gui/e-meeting-time-sel.etspec: spec for the table * gui/e-meeting-attendee.[hc]: meeting attendees for the model, with to/from conversions for CalComponentAttendee structure, emits changed signal and allows getting and setting of free busy periods * gui/e-meeting-model.[hc]: move the model out on its own * gui/e-itip-control.c (write_error_html): clean up warnings svn path=/trunk/; revision=12968
Diffstat (limited to 'calendar/gui/e-meeting-attendee.c')
-rw-r--r--calendar/gui/e-meeting-attendee.c998
1 files changed, 998 insertions, 0 deletions
diff --git a/calendar/gui/e-meeting-attendee.c b/calendar/gui/e-meeting-attendee.c
new file mode 100644
index 0000000000..08ec9a1152
--- /dev/null
+++ b/calendar/gui/e-meeting-attendee.c
@@ -0,0 +1,998 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-attendee.c
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * This program 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 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: JP Rosevear
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include "e-meeting-attendee.h"
+
+struct _EMeetingAttendeePrivate {
+ EMeetingAttendeeType type;
+
+ gchar *address;
+ gchar *member;
+
+ icalparameter_cutype cutype;
+ icalparameter_role role;
+
+ gboolean rsvp;
+
+ gchar *delto;
+ gchar *delfrom;
+
+ icalparameter_partstat status;
+
+ gchar *sentby;
+ gchar *cn;
+ gchar *language;
+
+ gboolean has_calendar_info;
+
+ GArray *busy_periods;
+ gboolean busy_periods_sorted;
+
+ EMeetingTime busy_periods_start;
+ EMeetingTime busy_periods_end;
+ gboolean start_busy_range_set;
+ gboolean end_busy_range_set;
+
+ gint longest_period_in_days;
+};
+
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL];
+
+static void class_init (EMeetingAttendeeClass *klass);
+static void init (EMeetingAttendee *ia);
+static void destroy (GtkObject *obj);
+
+
+static GtkObjectClass *parent_class = NULL;
+
+
+GtkType
+e_meeting_attendee_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (type == 0)
+ {
+ static const GtkTypeInfo info =
+ {
+ "EMeetingAttendee",
+ sizeof (EMeetingAttendee),
+ sizeof (EMeetingAttendeeClass),
+ (GtkClassInitFunc) class_init,
+ (GtkObjectInitFunc) init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (gtk_object_get_type (), &info);
+ }
+
+ return type;
+}
+
+static void
+class_init (EMeetingAttendeeClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = GTK_OBJECT_CLASS (klass);
+
+ parent_class = gtk_type_class (gtk_object_get_type ());
+
+ signals[CHANGED] =
+ gtk_signal_new ("changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EMeetingAttendeeClass, changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
+
+ object_class->destroy = destroy;
+}
+
+static gchar *
+string_test (gchar *string)
+{
+ return string != NULL ? string : g_strdup ("");
+}
+
+static gboolean
+string_is_set (gchar *string)
+{
+ if (string != NULL && *string != '\0')
+ return TRUE;
+
+ return FALSE;
+}
+
+static void
+notify_changed (EMeetingAttendee *ia)
+{
+ gtk_signal_emit (GTK_OBJECT (ia), signals[CHANGED]);
+}
+
+static void
+init (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = g_new0 (EMeetingAttendeePrivate, 1);
+
+ ia->priv = priv;
+
+ priv->type = E_MEETING_ATTENDEE_REQUIRED_PERSON;
+
+ priv->address = string_test (NULL);
+ priv->member = string_test (NULL);
+
+ priv->cutype = ICAL_CUTYPE_NONE;
+ priv->role = ICAL_ROLE_NONE;
+
+ priv->rsvp = FALSE;
+
+ priv->delto = string_test (NULL);
+ priv->delfrom = string_test (NULL);
+
+ priv->status = ICAL_PARTSTAT_NONE;
+
+ priv->sentby = string_test (NULL);
+ priv->cn = string_test (NULL);
+ priv->language = string_test (NULL);
+
+ priv->has_calendar_info = FALSE;
+
+ priv->busy_periods = g_array_new (FALSE, FALSE, sizeof (EMeetingFreeBusyPeriod));
+ priv->busy_periods_sorted = FALSE;
+
+ g_date_clear (&priv->busy_periods_start.date, 1);
+ priv->busy_periods_start.hour = 0;
+ priv->busy_periods_start.minute = 0;
+
+ g_date_clear (&priv->busy_periods_end.date, 1);
+ priv->busy_periods_end.hour = 0;
+ priv->busy_periods_end.minute = 0;
+
+ priv->start_busy_range_set = FALSE;
+ priv->end_busy_range_set = FALSE;
+
+ priv->longest_period_in_days = 0;
+}
+
+
+static void
+destroy (GtkObject *obj)
+{
+ EMeetingAttendee *ia = E_MEETING_ATTENDEE (obj);
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ g_free (priv->address);
+ g_free (priv->member);
+
+ g_free (priv->delto);
+ g_free (priv->delfrom);
+
+ g_free (priv->sentby);
+ g_free (priv->cn);
+ g_free (priv->language);
+
+ g_array_free (priv->busy_periods, TRUE);
+
+ g_free (priv);
+}
+
+GtkObject *
+e_meeting_attendee_new (void)
+{
+ return gtk_type_new (E_TYPE_MEETING_ATTENDEE);
+}
+
+GtkObject *
+e_meeting_attendee_new_from_cal_component_attendee (CalComponentAttendee *ca)
+{
+ EMeetingAttendee *ia;
+
+ ia = E_MEETING_ATTENDEE (gtk_type_new (E_TYPE_MEETING_ATTENDEE));
+
+ e_meeting_attendee_set_address (ia, g_strdup (ca->value));
+ e_meeting_attendee_set_member (ia, g_strdup (ca->member));
+ e_meeting_attendee_set_cutype (ia, ca->cutype);
+ e_meeting_attendee_set_role (ia, ca->role);
+ e_meeting_attendee_set_status (ia, ca->status);
+ e_meeting_attendee_set_rsvp (ia, ca->rsvp);
+ e_meeting_attendee_set_delto (ia, g_strdup (ca->delto));
+ e_meeting_attendee_set_delfrom (ia, g_strdup (ca->delfrom));
+ e_meeting_attendee_set_sentby (ia, g_strdup (ca->sentby));
+ e_meeting_attendee_set_cn (ia, g_strdup (ca->cn));
+ e_meeting_attendee_set_language (ia, g_strdup (ca->language));
+
+ return GTK_OBJECT (ia);
+}
+
+CalComponentAttendee *
+e_meeting_attendee_as_cal_component_attendee (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+ CalComponentAttendee *ca;
+
+ priv = ia->priv;
+
+ ca = g_new0 (CalComponentAttendee, 1);
+
+ ca->value = priv->address;
+ ca->member = string_is_set (priv->member) ? priv->member : NULL;
+ ca->cutype= priv->cutype;
+ ca->role = priv->role;
+ ca->status = priv->status;
+ ca->rsvp = priv->rsvp;
+ ca->delto = string_is_set (priv->delto) ? priv->delto : NULL;
+ ca->delfrom = string_is_set (priv->delfrom) ? priv->delfrom : NULL;
+ ca->sentby = string_is_set (priv->sentby) ? priv->sentby : NULL;
+ ca->cn = string_is_set (priv->cn) ? priv->cn : NULL;
+ ca->language = string_is_set (priv->language) ? priv->language : NULL;
+
+ return ca;
+}
+
+
+const gchar *
+e_meeting_attendee_get_address (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->address;
+}
+
+void
+e_meeting_attendee_set_address (EMeetingAttendee *ia, gchar *address)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ if (priv->address != NULL)
+ g_free (priv->address);
+
+ priv->address = string_test (address);
+
+ notify_changed (ia);
+}
+
+gboolean
+e_meeting_attendee_is_set_address (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return string_is_set (priv->address);
+}
+
+const gchar *
+e_meeting_attendee_get_member (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->member;
+}
+
+void
+e_meeting_attendee_set_member (EMeetingAttendee *ia, gchar *member)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ if (priv->member != NULL)
+ g_free (priv->member);
+
+ priv->member = string_test (member);
+
+ notify_changed (ia);
+}
+
+gboolean
+e_meeting_attendee_is_set_member (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return string_is_set (priv->member);
+}
+
+icalparameter_cutype
+e_meeting_attendee_get_cutype (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->cutype;
+}
+
+void
+e_meeting_attendee_set_cutype (EMeetingAttendee *ia, icalparameter_cutype cutype)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ priv->cutype = cutype;
+
+ notify_changed (ia);
+}
+
+icalparameter_role
+e_meeting_attendee_get_role (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->role;
+}
+
+void
+e_meeting_attendee_set_role (EMeetingAttendee *ia, icalparameter_role role)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ priv->role = role;
+
+ notify_changed (ia);
+}
+
+gboolean
+e_meeting_attendee_get_rsvp (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->rsvp;
+}
+
+void
+e_meeting_attendee_set_rsvp (EMeetingAttendee *ia, gboolean rsvp)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ priv->rsvp = rsvp;
+
+ notify_changed (ia);
+}
+
+const gchar *
+e_meeting_attendee_get_delto (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->delto;
+}
+
+void
+e_meeting_attendee_set_delto (EMeetingAttendee *ia, gchar *delto)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ if (priv->delto != NULL)
+ g_free (priv->delto);
+
+ priv->delto = string_test (delto);
+
+ notify_changed (ia);
+}
+
+gboolean
+e_meeting_attendee_is_set_delto (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return string_is_set (priv->delto);
+}
+
+const gchar *
+e_meeting_attendee_get_delfrom (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->delfrom;
+}
+
+void
+e_meeting_attendee_set_delfrom (EMeetingAttendee *ia, gchar *delfrom)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ if (priv->delfrom != NULL)
+ g_free (priv->delfrom);
+
+ priv->delfrom = string_test (delfrom);
+
+ notify_changed (ia);
+}
+
+gboolean
+e_meeting_attendee_is_set_delfrom (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return string_is_set (priv->delfrom);
+}
+
+icalparameter_partstat
+e_meeting_attendee_get_status (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->status;
+}
+
+void
+e_meeting_attendee_set_status (EMeetingAttendee *ia, icalparameter_partstat status)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ priv->status = status;
+
+ notify_changed (ia);
+}
+
+const gchar *
+e_meeting_attendee_get_sentby (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->sentby;
+}
+
+void
+e_meeting_attendee_set_sentby (EMeetingAttendee *ia, gchar *sentby)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ if (priv->sentby != NULL)
+ g_free (priv->sentby);
+
+ priv->sentby = string_test (sentby);
+
+ notify_changed (ia);
+}
+
+gboolean
+e_meeting_attendee_is_set_sentby (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return string_is_set (priv->sentby);
+}
+
+const gchar *
+e_meeting_attendee_get_cn (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->cn;
+}
+
+void
+e_meeting_attendee_set_cn (EMeetingAttendee *ia, gchar *cn)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ if (priv->cn != NULL)
+ g_free (priv->cn);
+
+ priv->cn = string_test (cn);
+
+ notify_changed (ia);
+}
+
+gboolean
+e_meeting_attendee_is_set_cn (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return string_is_set (priv->cn);
+}
+
+const gchar *
+e_meeting_attendee_get_language (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->language;
+}
+
+void
+e_meeting_attendee_set_language (EMeetingAttendee *ia, gchar *language)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ if (priv->language != NULL)
+ g_free (priv->language);
+
+ priv->language = string_test (language);
+
+ notify_changed (ia);
+}
+
+gboolean
+e_meeting_attendee_is_set_language (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return string_is_set (priv->language);
+}
+
+EMeetingAttendeeType
+e_meeting_attendee_get_atype (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->type;
+}
+
+void
+e_meeting_attendee_set_atype (EMeetingAttendee *ia, EMeetingAttendeeType type)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ priv->type = type;
+}
+
+
+static gint
+compare_times (EMeetingTime *time1,
+ EMeetingTime *time2)
+{
+ gint day_comparison;
+
+ day_comparison = g_date_compare (&time1->date,
+ &time2->date);
+ if (day_comparison != 0)
+ return day_comparison;
+
+ if (time1->hour < time2->hour)
+ return -1;
+ if (time1->hour > time2->hour)
+ return 1;
+
+ if (time1->minute < time2->minute)
+ return -1;
+ if (time1->minute > time2->minute)
+ return 1;
+
+ /* The start times are exactly the same. */
+ return 0;
+}
+
+static gint
+compare_period_starts (const void *arg1,
+ const void *arg2)
+{
+ EMeetingFreeBusyPeriod *period1, *period2;
+
+ period1 = (EMeetingFreeBusyPeriod *) arg1;
+ period2 = (EMeetingFreeBusyPeriod *) arg2;
+
+ return compare_times (&period1->start, &period2->start);
+}
+
+static void
+ensure_periods_sorted (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ if (priv->busy_periods_sorted)
+ return;
+
+ qsort (priv->busy_periods->data, priv->busy_periods->len,
+ sizeof (EMeetingFreeBusyPeriod),
+ compare_period_starts);
+
+ priv->busy_periods_sorted = TRUE;
+}
+
+gboolean
+e_meeting_attendee_get_has_calendar_info (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->has_calendar_info;
+}
+
+void
+e_meeting_attendee_set_has_calendar_info (EMeetingAttendee *ia, gboolean has_calendar_info)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ priv->has_calendar_info = has_calendar_info;
+}
+
+const GArray *
+e_meeting_attendee_get_busy_periods (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ ensure_periods_sorted (ia);
+
+ return priv->busy_periods;
+}
+
+gint
+e_meeting_attendee_find_first_busy_period (EMeetingAttendee *ia, GDate *date)
+{
+ EMeetingAttendeePrivate *priv;
+ EMeetingFreeBusyPeriod *period;
+ gint lower, upper, middle = 0, cmp = 0;
+ GDate tmp_date;
+
+ priv = ia->priv;
+
+ /* Make sure the busy periods have been sorted. */
+ ensure_periods_sorted (ia);
+
+ /* Calculate the first day which could have a busy period which
+ continues onto our given date. */
+ tmp_date = *date;
+ g_date_subtract_days (&tmp_date, priv->longest_period_in_days);
+
+ /* We want the first busy period which starts on tmp_date. */
+ lower = 0;
+ upper = priv->busy_periods->len;
+
+ if (upper == 0)
+ return -1;
+
+ while (lower < upper) {
+ middle = (lower + upper) >> 1;
+
+ period = &g_array_index (priv->busy_periods,
+ EMeetingFreeBusyPeriod, middle);
+
+ cmp = g_date_compare (&tmp_date, &period->start.date);
+
+ if (cmp == 0)
+ break;
+ else if (cmp < 0)
+ upper = middle;
+ else
+ lower = middle + 1;
+ }
+
+ /* There may be several busy periods on the same day so we step
+ backwards to the first one. */
+ if (cmp == 0) {
+ while (middle > 0) {
+ period = &g_array_index (priv->busy_periods,
+ EMeetingFreeBusyPeriod, middle - 1);
+ if (g_date_compare (&tmp_date, &period->start.date) != 0)
+ break;
+ middle--;
+ }
+ } else if (cmp > 0) {
+ /* This means we couldn't find a period on the given day, and
+ the last one we looked at was before it, so if there are
+ any more periods after this one we return it. */
+ middle++;
+ if (priv->busy_periods->len <= middle)
+ return -1;
+ }
+
+ return middle;
+}
+
+gboolean
+e_meeting_attendee_add_busy_period (EMeetingAttendee *ia,
+ gint start_year,
+ gint start_month,
+ gint start_day,
+ gint start_hour,
+ gint start_minute,
+ gint end_year,
+ gint end_month,
+ gint end_day,
+ gint end_hour,
+ gint end_minute,
+ EMeetingFreeBusyType busy_type)
+{
+ EMeetingAttendeePrivate *priv;
+ EMeetingFreeBusyPeriod period;
+ gint period_in_days;
+
+ g_return_val_if_fail (ia != NULL, FALSE);
+ g_return_val_if_fail (E_IS_MEETING_ATTENDEE (ia), FALSE);
+ g_return_val_if_fail (busy_type >= 0, FALSE);
+ g_return_val_if_fail (busy_type < E_MEETING_FREE_BUSY_LAST, FALSE);
+
+ priv = ia->priv;
+
+ /* Check the dates are valid. */
+ if (!g_date_valid_dmy (start_day, start_month, start_year))
+ return FALSE;
+ if (!g_date_valid_dmy (end_day, end_month, end_year))
+ return FALSE;
+ if (start_hour < 0 || start_hour > 23)
+ return FALSE;
+ if (end_hour < 0 || end_hour > 23)
+ return FALSE;
+ if (start_minute < 0 || start_minute > 59)
+ return FALSE;
+ if (end_minute < 0 || end_minute > 59)
+ return FALSE;
+
+ g_date_clear (&period.start.date, 1);
+ g_date_clear (&period.end.date, 1);
+ g_date_set_dmy (&period.start.date, start_day, start_month, start_year);
+ g_date_set_dmy (&period.end.date, end_day, end_month, end_year);
+ period.start.hour = start_hour;
+ period.start.minute = start_minute;
+ period.end.hour = end_hour;
+ period.end.minute = end_minute;
+ period.busy_type = busy_type;
+
+ /* Check that the start time is before or equal to the end time. */
+ if (compare_times (&period.start, &period.end) > 0)
+ return FALSE;
+
+ /* If the busy range is not set elsewhere, track it as best we can */
+ if (!priv->start_busy_range_set) {
+ if (!g_date_valid (&priv->busy_periods_start.date)) {
+ priv->busy_periods_start.date = period.start.date;
+ priv->busy_periods_start.hour = period.start.hour;
+ priv->busy_periods_start.minute = period.start.minute;
+ } else {
+ switch (g_date_compare (&period.start.date, &priv->busy_periods_start.date)) {
+ case -1:
+ priv->busy_periods_start.date = period.start.date;
+ priv->busy_periods_start.hour = period.start.hour;
+ priv->busy_periods_start.minute = period.start.minute;
+ break;
+ case 0:
+ if (period.start.hour < priv->busy_periods_start.hour
+ || (period.start.hour == priv->busy_periods_start.hour
+ && period.start.minute < priv->busy_periods_start.minute)) {
+ priv->busy_periods_start.date = period.start.date;
+ priv->busy_periods_start.hour = period.start.hour;
+ priv->busy_periods_start.minute = period.start.minute;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ if (!priv->end_busy_range_set) {
+ if (!g_date_valid (&priv->busy_periods_end.date)) {
+ priv->busy_periods_end.date = period.end.date;
+ priv->busy_periods_end.hour = period.end.hour;
+ priv->busy_periods_end.minute = period.end.minute;
+ } else {
+ switch (g_date_compare (&period.end.date, &priv->busy_periods_end.date)) {
+ case 0:
+ if (period.end.hour > priv->busy_periods_end.hour
+ || (period.end.hour == priv->busy_periods_end.hour
+ && period.end.minute > priv->busy_periods_end.minute)) {
+ priv->busy_periods_end.date = period.end.date;
+ priv->busy_periods_end.hour = period.end.hour;
+ priv->busy_periods_end.minute = period.end.minute;
+ break;
+ }
+ break;
+ case 1:
+ priv->busy_periods_end.date = period.end.date;
+ priv->busy_periods_end.hour = period.end.hour;
+ priv->busy_periods_end.minute = period.end.minute;
+ break;
+ }
+ }
+ }
+
+ g_array_append_val (priv->busy_periods, period);
+ priv->has_calendar_info = TRUE;
+ priv->busy_periods_sorted = FALSE;
+
+ period_in_days = g_date_julian (&period.end.date) - g_date_julian (&period.start.date) + 1;
+ priv->longest_period_in_days = MAX (priv->longest_period_in_days, period_in_days);
+
+ return TRUE;
+}
+
+EMeetingTime
+e_meeting_attendee_get_start_busy_range (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->busy_periods_start;
+}
+
+EMeetingTime
+e_meeting_attendee_get_end_busy_range (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ priv = ia->priv;
+
+ return priv->busy_periods_end;
+}
+
+gboolean
+e_meeting_attendee_set_start_busy_range (EMeetingAttendee *ia,
+ gint start_year,
+ gint start_month,
+ gint start_day,
+ gint start_hour,
+ gint start_minute)
+{
+ EMeetingAttendeePrivate *priv;
+
+ g_return_val_if_fail (E_IS_MEETING_ATTENDEE (ia), FALSE);
+
+ priv = ia->priv;
+
+ /* Check the dates are valid. */
+ if (!g_date_valid_dmy (start_day, start_month, start_year))
+ return FALSE;
+ if (start_hour < 0 || start_hour > 23)
+ return FALSE;
+ if (start_minute < 0 || start_minute > 59)
+ return FALSE;
+
+ g_date_clear (&priv->busy_periods_start.date, 1);
+ g_date_set_dmy (&priv->busy_periods_start.date,
+ start_day, start_month, start_year);
+ priv->busy_periods_start.hour = start_hour;
+ priv->busy_periods_start.minute = start_minute;
+
+ priv->start_busy_range_set = TRUE;
+
+ return TRUE;
+}
+
+gboolean
+e_meeting_attendee_set_end_busy_range (EMeetingAttendee *ia,
+ gint end_year,
+ gint end_month,
+ gint end_day,
+ gint end_hour,
+ gint end_minute)
+{
+ EMeetingAttendeePrivate *priv;
+
+ g_return_val_if_fail (E_IS_MEETING_ATTENDEE (ia), FALSE);
+
+ priv = ia->priv;
+
+ /* Check the dates are valid. */
+ if (!g_date_valid_dmy (end_day, end_month, end_year))
+ return FALSE;
+ if (end_hour < 0 || end_hour > 23)
+ return FALSE;
+ if (end_minute < 0 || end_minute > 59)
+ return FALSE;
+
+ g_date_clear (&priv->busy_periods_end.date, 1);
+ g_date_set_dmy (&priv->busy_periods_end.date,
+ end_day, end_month, end_year);
+ priv->busy_periods_end.hour = end_hour;
+ priv->busy_periods_end.minute = end_minute;
+
+ priv->end_busy_range_set = TRUE;
+
+ return TRUE;
+}
+
+/* Clears all busy times for the given attendee. */
+void
+e_meeting_attendee_clear_busy_periods (EMeetingAttendee *ia)
+{
+ EMeetingAttendeePrivate *priv;
+
+ g_return_if_fail (E_IS_MEETING_ATTENDEE (ia));
+
+ priv = ia->priv;
+
+ g_array_set_size (priv->busy_periods, 0);
+ priv->busy_periods_sorted = TRUE;
+
+ g_date_clear (&priv->busy_periods_start.date, 1);
+ priv->busy_periods_start.hour = 0;
+ priv->busy_periods_start.minute = 0;
+
+ g_date_clear (&priv->busy_periods_end.date, 1);
+ priv->busy_periods_end.hour = 0;
+ priv->busy_periods_end.minute = 0;
+
+ priv->longest_period_in_days = 0;
+}