aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/dialogs/recurrence-page.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/dialogs/recurrence-page.c')
-rw-r--r--calendar/gui/dialogs/recurrence-page.c900
1 files changed, 900 insertions, 0 deletions
diff --git a/calendar/gui/dialogs/recurrence-page.c b/calendar/gui/dialogs/recurrence-page.c
new file mode 100644
index 0000000000..0b0eace9cf
--- /dev/null
+++ b/calendar/gui/dialogs/recurrence-page.c
@@ -0,0 +1,900 @@
+/* Evolution calendar - Recurrence page of the calendar component dialogs
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Authors: Federico Mena-Quintero <federico@ximian.com>
+ * Miguel de Icaza <miguel@ximian.com>
+ * Seth Alves <alves@hungry.com>
+ * JP Rosevear <jpr@ximian.com>
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gtk/gtksignal.h>
+#include <libgnome/gnome-defs.h>
+#include <libgnome/gnome-i18n.h>
+#include <glade/glade.h>
+#include <gal/widgets/e-unicode.h>
+#include "e-util/e-dialog-widgets.h"
+#include "recurrence-page.h"
+
+
+
+/* Private part of the RecurrencePage structure */
+struct _RecurrencePagePrivate {
+ /* Glade XML data */
+ GladeXML *xml;
+
+ /* Widgets from the Glade file */
+
+ GtkWidget *main;
+
+ GtkWidget *summary;
+ GtkWidget *starting_date;
+
+ GtkWidget *none;
+ GtkWidget *simple;
+ GtkWidget *custom;
+
+ GtkWidget *params;
+ GtkWidget *interval_value;
+ GtkWidget *interval_unit;
+ GtkWidget *special;
+ GtkWidget *ending_menu;
+ GtkWidget *ending_special;
+ GtkWidget *custom_warning_bin;
+
+ /* For weekly recurrences, created by hand */
+ GtkWidget *weekday_picker;
+ guint8 weekday_day_mask;
+ guint8 weekday_blocked_day_mask;
+
+ /* For monthly recurrences, created by hand */
+ GtkWidget *month_index_spin;
+ int month_index;
+
+ GtkWidget *month_day_menu;
+ enum month_day_options month_day;
+
+ /* For ending date, created by hand */
+ GtkWidget *ending_date_edit;
+ time_t ending_date;
+
+ /* For ending count of occurrences, created by hand */
+ GtkWidget *ending_count_spin;
+ int ending_count;
+
+ /* More widgets from the Glade file */
+
+ GtkWidget *exception_date;
+ GtkWidget *exception_list;
+ GtkWidget *exception_add;
+ GtkWidget *exception_modify;
+ GtkWidget *exception_delete;
+
+ GtkWidget *preview_bin;
+
+ /* For the recurrence preview, the actual widget */
+ GtkWidget *preview_calendar;
+};
+
+
+
+static void recurrence_page_class_init (RecurrencePageClass *class);
+static void recurrence_page_init (RecurrencePage *rpage);
+static void recurrence_page_destroy (RecurrencePage *rpage);
+
+static GtkWidget *recurrence_page_get_widget (EditorPage *page);
+static void recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp);
+static void recurrence_page_fill_component (EditorPage *page, CalComponent *comp);
+static void recurrence_page_set_summary (EditorPage *page, const char *summary);
+static char *recurrence_page_get_summary (EditorPage *page);
+static void recurrence_page_set_dtstart (EditorPage *page, time_t start);
+
+static EditorPageClass *parent_class = NULL;
+
+
+
+/**
+ * recurrence_page_get_type:
+ *
+ * Registers the #RecurrencePage class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #RecurrencePage class.
+ **/
+GtkType
+recurrence_page_get_type (void)
+{
+ static GtkType recurrence_page_type;
+
+ if (!recurrence_page_type) {
+ static const GtkTypeInfo recurrence_page_info = {
+ "RecurrencePage",
+ sizeof (RecurrencePage),
+ sizeof (RecurrencePageClass),
+ (GtkClassInitFunc) recurrence_page_class_init,
+ (GtkObjectInitFunc) recurrence_page_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ recurrence_page_type = gtk_type_unique (EDITOR_PAGE_TYPE, &recurrence_page_info);
+ }
+
+ return recurrence_page_type;
+}
+
+/* Class initialization function for the recurrence page */
+static void
+recurrence_page_class_init (RecurrencePageClass *class)
+{
+ EditorPageClass *editor_page_class;
+ GtkObjectClass *object_class;
+
+ editor_page_class = (EditorPageClass *) class;
+ object_class = (GtkObjectClass *) class;
+
+ parent_class = gtk_type_class (EDITOR_PAGE_TYPE);
+
+ editor_page_class->get_widget = recurrence_page_get_widget;
+ editor_page_class->fill_widgets = recurrence_page_fill_widgets;
+ editor_page_class->fill_component = recurrence_page_fill_component;
+ editor_page_class->set_summary = recurrence_page_set_summary;
+ editor_page_class->get_summary = recurrence_page_get_summary;
+ editor_page_class->set_dtstart = recurrence_page_set_dtstart;
+
+ object_class->destroy = recurrence_page_destroy;
+}
+
+/* Object initialization function for the recurrence page */
+static void
+recurrence_page_init (RecurrencePage *rpage)
+{
+ RecurrencePagePrivate *priv;
+
+ priv = g_new0 (RecurrencePagePrivate, 1);
+ rpage->priv = priv;
+
+ priv->xml = NULL;
+
+ priv->main = NULL;
+ priv->summary = NULL;
+ priv->starting_date = NULL;
+ priv->none = NULL;
+ priv->simple = NULL;
+ priv->custom = NULL;
+ priv->params = NULL;
+ priv->interval_value = NULL;
+ priv->interval_unit = NULL;
+ priv->special = NULL;
+ priv->ending_menu = NULL;
+ priv->ending_special = NULL;
+ priv->custom_warning_bin = NULL;
+ priv->weekday_picker = NULL;
+ priv->month_index_spin = NULL;
+ priv->month_day_menu = NULL;
+ priv->ending_date_edit = NULL;
+ priv->ending_count_spin = NULL;
+ priv->exception_date = NULL;
+ priv->exception_list = NULL;
+ priv->exception_add = NULL;
+ priv->exception_modify = NULL;
+ priv->exception_delete = NULL;
+ priv->preview_bin = NULL;
+ priv->preview_calendar = NULL;
+}
+
+/* Frees the rows and the row data in the exceptions GtkCList */
+static void
+free_exception_clist_data (RecurrencePage *rpage)
+{
+ RecurrencePagePrivate *priv;
+ GtkCList *clist;
+ int i;
+
+ priv = rpage->priv;
+
+ clist = GTK_CLIST (priv->exception_list);
+
+ for (i = 0; i < clist->rows; i++) {
+ gpointer data;
+
+ data = gtk_clist_get_row_data (clist, i);
+ g_free (data);
+ gtk_clist_set_row_data (clist, i, NULL);
+ }
+
+ gtk_clist_clear (clist);
+}
+
+/* Destroy handler for the recurrence page */
+static void
+recurrence_page_destroy (GtkObject *object)
+{
+ RecurrencePage *rpage;
+ RecurrencePagePrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_RECURRENCE_PAGE (object));
+
+ rpage = RECURRENCE_PAGE (object);
+ priv = rpage->priv;
+
+ if (priv->xml) {
+ gtk_object_unref (GTK_OBJECT (priv->xml));
+ priv->xml = NULL;
+ }
+
+ free_exception_clist_data (rpage);
+
+ g_free (priv);
+ rpage->priv = NULL;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+
+/* get_widget handler for the recurrence page */
+static GtkWidget *
+recurrence_page_get_widget (EditorPage *page)
+{
+ RecurrencePage *rpage;
+ RecurrencePagePrivate *priv;
+
+ rpage = RECURRENCE_PAGE (page);
+ priv = rpage->priv;
+
+ return priv->main;
+}
+
+/* Fills the widgets with default values */
+static void
+clear_widgets (RecurrencePage *rpage)
+{
+ RecurrencePagePrivate *priv;
+
+ priv = rpage->priv;
+
+ priv->weekday_day_mask = 0;
+
+ priv->month_index = 1;
+ priv->month_day = MONTH_DAY_NTH;
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->none), rpage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->simple), rpage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->custom), rpage);
+ e_dialog_radio_set (priv->none, RECUR_NONE, type_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->none), rpage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->simple), rpage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->custom), rpage);
+
+ adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->interval_value));
+ gtk_signal_handler_block_by_data (GTK_OBJECT (adj), rpage);
+ e_dialog_spin_set (priv->interval_value, 1);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (adj), rpage);
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit));
+ gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage);
+ e_dialog_option_menu_set (priv->interval_unit, ICAL_DAILY_RECURRENCE, freq_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage);
+
+ priv->ending_date = time (NULL);
+ priv->ending_count = 1;
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->ending_menu));
+ gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage);
+ e_dialog_option_menu_set (priv->ending_menu, ENDING_FOREVER, ending_types_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage);
+
+ /* Exceptions list */
+ free_exception_clist_data (GTK_CLIST (priv->exception_list));
+}
+
+/* Builds a static string out of an exception date */
+static char *
+get_exception_string (time_t t)
+{
+ static char buf[256];
+
+ strftime (buf, sizeof (buf), _("%a %b %d %Y"), localtime (&t));
+ return buf;
+}
+
+/* Appends an exception date to the list */
+static void
+append_exception (RecurrencePage *rpage, time_t t)
+{
+ RecurrencePagePrivate *priv;
+ time_t *tt;
+ char *c[1];
+ int i;
+ GtkCList *clist;
+
+ priv = rpage->priv;
+
+ tt = g_new (time_t, 1);
+ *tt = t;
+
+ clist = GTK_CLIST (priv->exception_list);
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (clist), rpage);
+
+ c[0] = get_exception_string (t);
+ i = gtk_clist_append (clist, c);
+
+ gtk_clist_set_row_data (clist, i, tt);
+
+ gtk_clist_select_row (clist, i, 0);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), rpage);
+
+ e_date_edit_set_time (E_DATE_EDIT (priv->exception_date), t);
+
+ gtk_widget_set_sensitive (priv->exception_modify, TRUE);
+ gtk_widget_set_sensitive (priv->exception_delete, TRUE);
+}
+
+/* Fills in the exception widgets with the data from the calendar component */
+static void
+fill_exception_widgets (RecurrencePage *rpage, CalComponent *comp)
+{
+ RecurrencePagePrivate *priv;
+ GSList *list, *l;
+ gboolean added;
+
+ priv = rpage->priv;
+
+ cal_component_get_exdate_list (comp, &list);
+
+ added = FALSE;
+
+ for (l = list; l; l = l->next) {
+ CalComponentDateTime *cdt;
+ time_t ext;
+
+ added = TRUE;
+
+ cdt = l->data;
+ ext = icaltime_as_timet (*cdt->value);
+ append_exception (rpage, ext);
+ }
+
+ cal_component_free_exdate_list (list);
+
+ if (added)
+ gtk_clist_select_row (GTK_CLIST (priv->exception_list), 0, 0);
+}
+
+/* Computes a weekday mask for the start day of a calendar component, for use in
+ * a WeekdayPicker widget.
+ */
+static guint8
+get_start_weekday_mask (CalComponent *comp)
+{
+ CalComponentDateTime dt;
+ guint8 retval;
+
+ cal_component_get_dtstart (comp, &dt);
+
+ if (dt.value) {
+ time_t t;
+ struct tm tm;
+
+ t = icaltime_as_timet (*dt.value);
+ tm = *localtime (&t);
+
+ retval = 0x1 << tm.tm_wday;
+ } else
+ retval = 0;
+
+ cal_component_free_datetime (&dt);
+
+ return retval;
+}
+
+/* Sets some sane defaults for the data sources for the recurrence special
+ * widgets, even if they will not be used immediately.
+ */
+static void
+set_special_defaults (RecurrencePage *rpage)
+{
+ RecurrencePagePrivate *priv;
+ guint8 mask;
+
+ priv = rpage->priv;
+
+ mask = get_start_weekday_mask (priv->comp);
+
+ priv->weekday_day_mask = mask;
+ priv->weekday_blocked_day_mask = mask;
+}
+
+/* Sensitizes the recurrence widgets based on the state of the recurrence type
+ * radio group.
+ */
+static void
+sensitize_recur_widgets (RecurrencePage *rpage)
+{
+ RecurrencePagePrivate *priv;
+ enum recur_type type;
+ GtkWidget *label;
+
+ priv = rpage->priv;
+
+ type = e_dialog_radio_get (priv->none, type_map);
+
+ if (GTK_BIN (priv->custom_warning_bin)->child)
+ gtk_widget_destroy (GTK_BIN (priv->custom_warning_bin)->child);
+
+ switch (type) {
+ case RECUR_NONE:
+ gtk_widget_set_sensitive (priv->params, FALSE);
+ gtk_widget_show (priv->params);
+ gtk_widget_hide (priv->custom_warning_bin);
+ break;
+
+ case RECUR_SIMPLE:
+ gtk_widget_set_sensitive (priv->params, TRUE);
+ gtk_widget_show (priv->params);
+ gtk_widget_hide (priv->custom_warning_bin);
+ break;
+
+ case RECUR_CUSTOM:
+ gtk_widget_set_sensitive (priv->params, FALSE);
+ gtk_widget_hide (priv->params);
+
+ label = gtk_label_new (_("This appointment contains recurrences that Evolution "
+ "cannot edit."));
+ gtk_container_add (GTK_CONTAINER (priv->custom_warning_bin), label);
+ gtk_widget_show_all (priv->custom_warning_bin);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Re-tags the recurrence preview calendar based on the current information of
+ * the widgets in the recurrence page.
+ */
+static void
+preview_recur (RecurrencePage *rpage)
+{
+ RecurrencePagePrivate *priv;
+ CalComponent *comp;
+ CalComponentDateTime cdt;
+ GSList *l;
+
+ priv = rpage->priv;
+ g_assert (priv->comp != NULL);
+
+ /* Create a scratch component with the start/end and
+ * recurrence/excepttion information from the one we are editing.
+ */
+
+ comp = cal_component_new ();
+ cal_component_set_new_vtype (comp, CAL_COMPONENT_EVENT);
+
+ cal_component_get_dtstart (priv->comp, &cdt);
+ cal_component_set_dtstart (comp, &cdt);
+ cal_component_free_datetime (&cdt);
+
+ cal_component_get_dtend (priv->comp, &cdt);
+ cal_component_set_dtend (comp, &cdt);
+ cal_component_free_datetime (&cdt);
+
+ cal_component_get_exdate_list (priv->comp, &l);
+ cal_component_set_exdate_list (comp, l);
+ cal_component_free_exdate_list (l);
+
+ cal_component_get_exrule_list (priv->comp, &l);
+ cal_component_set_exrule_list (comp, l);
+ cal_component_free_recur_list (l);
+
+ cal_component_get_rdate_list (priv->comp, &l);
+ cal_component_set_rdate_list (comp, l);
+ cal_component_free_period_list (l);
+
+ cal_component_get_rrule_list (priv->comp, &l);
+ cal_component_set_rrule_list (comp, l);
+ cal_component_free_recur_list (l);
+
+ recur_to_comp_object (rpage, comp);
+
+ tag_calendar_by_comp (E_CALENDAR (priv->preview_calendar), comp);
+ gtk_object_unref (GTK_OBJECT (comp));
+}
+
+/* fill_widgets handler for the recurrence page. This function is particularly
+ * tricky because it has to discriminate between recurrences we support for
+ * editing and the ones we don't. We only support at most one recurrence rule;
+ * no rdates or exrules (exdates are handled just fine elsewhere).
+ */
+static void
+recurrence_page_fill_widgets (EditorPage *page, CalComponent *comp)
+{
+ RecurrencePage *rpage;
+ RecurrencePagePrivate *priv;
+ GSList *rrule_list;
+ int len;
+ struct icalrecurrencetype *r;
+ int n_by_second, n_by_minute, n_by_hour;
+ int n_by_day, n_by_month_day, n_by_year_day;
+ int n_by_week_no, n_by_month, n_by_set_pos;
+ GtkWidget *menu;
+ GtkAdjustment *adj;
+
+ rpage = RECURRENCE_PAGE (page);
+ priv = rpage->priv;
+
+ clear_widgets (rpage);
+
+ fill_exception_widgets (rpage, comp);
+
+ /* Set up defaults for the special widgets */
+ set_special_defaults (rpage);
+
+ /* No recurrences? */
+
+ if (!cal_component_has_rdates (comp)
+ && !cal_component_has_rrules (comp)
+ && !cal_component_has_exrules (comp)) {
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->none), rpage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->simple), rpage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->custom), rpage);
+ e_dialog_radio_set (priv->none, RECUR_NONE, type_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->none), rpage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->simple), rpage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->custom), rpage);
+
+ gtk_widget_set_sensitive (priv->custom, FALSE);
+
+ sensitize_recur_widgets (rpage);
+ preview_recur (rpage);
+ return;
+ }
+
+ /* See if it is a custom set we don't support */
+
+ cal_component_get_rrule_list (comp, &rrule_list);
+ len = g_slist_length (rrule_list);
+ if (len > 1
+ || cal_component_has_rdates (comp)
+ || cal_component_has_exrules (comp))
+ goto custom;
+
+ /* Down to one rule, so test that one */
+
+ g_assert (len == 1);
+ r = rrule_list->data;
+
+ /* Any funky frequency? */
+
+ if (r->freq == ICAL_SECONDLY_RECURRENCE
+ || r->freq == ICAL_MINUTELY_RECURRENCE
+ || r->freq == ICAL_HOURLY_RECURRENCE)
+ goto custom;
+
+ /* Any funky shit? */
+
+#define N_HAS_BY(field) (count_by_xxx (field, sizeof (field) / sizeof (field[0])))
+
+ n_by_second = N_HAS_BY (r->by_second);
+ n_by_minute = N_HAS_BY (r->by_minute);
+ n_by_hour = N_HAS_BY (r->by_hour);
+ n_by_day = N_HAS_BY (r->by_day);
+ n_by_month_day = N_HAS_BY (r->by_month_day);
+ n_by_year_day = N_HAS_BY (r->by_year_day);
+ n_by_week_no = N_HAS_BY (r->by_week_no);
+ n_by_month = N_HAS_BY (r->by_month);
+ n_by_set_pos = N_HAS_BY (r->by_set_pos);
+
+ if (n_by_second != 0
+ || n_by_minute != 0
+ || n_by_hour != 0)
+ goto custom;
+
+ /* Filter the funky shit based on the frequency; if there is nothing
+ * weird we can actually set the widgets.
+ */
+
+ switch (r->freq) {
+ case ICAL_DAILY_RECURRENCE:
+ if (n_by_day != 0
+ || n_by_month_day != 0
+ || n_by_year_day != 0
+ || n_by_week_no != 0
+ || n_by_month != 0
+ || n_by_set_pos != 0)
+ goto custom;
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit));
+ gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage);
+ e_dialog_option_menu_set (priv->interval_unit, ICAL_DAILY_RECURRENCE, freq_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage);
+ break;
+
+ case ICAL_WEEKLY_RECURRENCE: {
+ int i;
+ guint8 day_mask;
+
+ if (n_by_month_day != 0
+ || n_by_year_day != 0
+ || n_by_week_no != 0
+ || n_by_month != 0
+ || n_by_set_pos != 0)
+ goto custom;
+
+ day_mask = 0;
+
+ for (i = 0; i < 8 && r->by_day[i] != ICAL_RECURRENCE_ARRAY_MAX; i++) {
+ enum icalrecurrencetype_weekday weekday;
+ int pos;
+
+ weekday = icalrecurrencetype_day_day_of_week (r->by_day[i]);
+ pos = icalrecurrencetype_day_position (r->by_day[i]);
+
+ if (pos != 0)
+ goto custom;
+
+ switch (weekday) {
+ case ICAL_SUNDAY_WEEKDAY:
+ day_mask |= 1 << 0;
+ break;
+
+ case ICAL_MONDAY_WEEKDAY:
+ day_mask |= 1 << 1;
+ break;
+
+ case ICAL_TUESDAY_WEEKDAY:
+ day_mask |= 1 << 2;
+ break;
+
+ case ICAL_WEDNESDAY_WEEKDAY:
+ day_mask |= 1 << 3;
+ break;
+
+ case ICAL_THURSDAY_WEEKDAY:
+ day_mask |= 1 << 4;
+ break;
+
+ case ICAL_FRIDAY_WEEKDAY:
+ day_mask |= 1 << 5;
+ break;
+
+ case ICAL_SATURDAY_WEEKDAY:
+ day_mask |= 1 << 6;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ priv->weekday_day_mask = day_mask;
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit));
+ gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage);
+ e_dialog_option_menu_set (priv->interval_unit, ICAL_WEEKLY_RECURRENCE, freq_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage);
+ break;
+ }
+
+ case ICAL_MONTHLY_RECURRENCE:
+ if (n_by_year_day != 0
+ || n_by_week_no != 0
+ || n_by_month != 0
+ || n_by_set_pos != 0)
+ goto custom;
+
+ if (n_by_month_day == 1) {
+ int nth;
+
+ nth = r->by_month_day[0];
+ if (nth < 1)
+ goto custom;
+
+ priv->month_index = nth;
+ priv->month_day = MONTH_DAY_NTH;
+ } else if (n_by_day == 1) {
+ enum icalrecurrencetype_weekday weekday;
+ int pos;
+ enum month_day_options month_day;
+
+ weekday = icalrecurrencetype_day_day_of_week (r->by_day[0]);
+ pos = icalrecurrencetype_day_position (r->by_day[0]);
+
+ if (pos < 1)
+ goto custom;
+
+ switch (weekday) {
+ case ICAL_MONDAY_WEEKDAY:
+ month_day = MONTH_DAY_MON;
+ break;
+
+ case ICAL_TUESDAY_WEEKDAY:
+ month_day = MONTH_DAY_TUE;
+ break;
+
+ case ICAL_WEDNESDAY_WEEKDAY:
+ month_day = MONTH_DAY_WED;
+ break;
+
+ case ICAL_THURSDAY_WEEKDAY:
+ month_day = MONTH_DAY_THU;
+ break;
+
+ case ICAL_FRIDAY_WEEKDAY:
+ month_day = MONTH_DAY_FRI;
+ break;
+
+ case ICAL_SATURDAY_WEEKDAY:
+ month_day = MONTH_DAY_SAT;
+ break;
+
+ case ICAL_SUNDAY_WEEKDAY:
+ month_day = MONTH_DAY_SUN;
+ break;
+
+ default:
+ goto custom;
+ }
+
+ priv->month_index = pos;
+ priv->month_day = month_day;
+ } else
+ goto custom;
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit));
+ gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage);
+ e_dialog_option_menu_set (priv->interval_unit, ICAL_MONTHLY_RECURRENCE, freq_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage);
+ break;
+
+ case ICAL_YEARLY_RECURRENCE:
+ if (n_by_day != 0
+ || n_by_month_day != 0
+ || n_by_year_day != 0
+ || n_by_week_no != 0
+ || n_by_month != 0
+ || n_by_set_pos != 0)
+ goto custom;
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->interval_unit));
+ gtk_signal_handler_block_by_data (GTK_OBJECT (menu), rpage);
+ e_dialog_option_menu_set (priv->interval_unit, ICAL_YEARLY_RECURRENCE, freq_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (menu), rpage);
+ break;
+
+ default:
+ goto custom;
+ }
+
+ /* If we got here it means it is a simple recurrence */
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->none), rpage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->simple), rpage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->custom), rpage);
+ e_dialog_radio_set (priv->simple, RECUR_SIMPLE, type_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->none), rpage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->simple), rpage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->custom), rpage);
+
+ gtk_widget_set_sensitive (priv->custom, FALSE);
+
+ sensitize_recur_widgets (rpage);
+ make_recurrence_special (rpage);
+
+ adj = gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (priv->interval_value));
+ gtk_signal_handler_block_by_data (GTK_OBJECT (adj), rpage);
+ e_dialog_spin_set (priv->interval_value, r->interval);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (adj), rpage);
+
+ fill_ending_date (rpage, r);
+
+ goto out;
+
+ custom:
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->none), rpage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->simple), rpage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->custom), rpage);
+ e_dialog_radio_set (priv->custom, RECUR_CUSTOM, type_map);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->none), rpage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->simple), rpage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->custom), rpage);
+
+ gtk_widget_set_sensitive (priv->custom, TRUE);
+ sensitize_recur_widgets (rpage);
+
+ out:
+
+ cal_component_free_recur_list (rrule_list);
+ preview_recur (rpage);
+}
+
+
+
+/* Gets the widgets from the XML file and returns if they are all available. */
+static gboolean
+get_widgets (RecurrencePage *rpage)
+{
+ RecurrencePagePrivate *priv;
+ GtkWidget *toplevel;
+
+ priv = rpage->priv;
+
+#define GW(name) glade_xml_get_widget (priv->xml, name)
+
+ toplevel = GW ("recurrence-toplevel");
+ priv->main = GW ("recurrence-page");
+ if (!(toplevel && priv->main))
+ return NULL;
+
+ gtk_widget_ref (priv->main);
+ gtk_widget_unparent (priv->main);
+ gtk_widget_destroy (toplevel);
+
+ priv->summary = GW ("summary");
+ priv->starting_date = GW ("starting-date");
+
+ priv->none = GW ("none");
+ priv->simple = GW ("simple");
+ priv->custom = GW ("custom");
+ priv->params = GW ("params");
+
+ priv->interval_value = GW ("interval-value");
+ priv->interval_unit = GW ("interval-unit");
+ priv->special = GW ("special");
+ priv->ending_menu = GW ("ending-menu");
+ priv->ending_special = GW ("ending-special");
+ priv->custom_warning_bin = GW ("custom-warning-bin");
+
+ priv->exception_date = GW ("exception-date");
+ priv->exception_list = GW ("exception-list");
+ priv->exception_add = GW ("exception-add");
+ priv->exception_modify = GW ("exception-modify");
+ priv->exception_delete = GW ("exception-delete");
+
+ priv->preview_bin = GW ("preview-bin");
+
+#undef GW
+
+ return (priv->summary
+ && priv->starting_date
+ && priv->none
+ && priv->simple
+ && priv->custom
+ && priv->params
+ && priv->interval_value
+ && priv->interval_unit
+ && priv->special
+ && priv->ending_menu
+ && priv->ending_special
+ && priv->custom_warning_bin
+ && priv->exception_date
+ && priv->exception_list
+ && priv->exception_add
+ && priv->exception_modify
+ && priv->exception_delete
+ && priv->preview_bin);
+}