aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/event-editor.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/event-editor.c')
-rw-r--r--calendar/gui/event-editor.c883
1 files changed, 756 insertions, 127 deletions
diff --git a/calendar/gui/event-editor.c b/calendar/gui/event-editor.c
index dc90309fe5..e817ebcdf2 100644
--- a/calendar/gui/event-editor.c
+++ b/calendar/gui/event-editor.c
@@ -30,11 +30,11 @@
#include <cal-util/timeutil.h>
#include "event-editor.h"
#include "e-meeting-edit.h"
-
+#include "weekday-picker.h"
-typedef struct {
+struct _EventEditorPrivate {
/* Glade XML data */
GladeXML *xml;
@@ -77,6 +77,25 @@ typedef struct {
GtkWidget *classification_radio;
+ GtkWidget *recurrence_summary;
+ GtkWidget *recurrence_starting_date;
+
+ GtkWidget *recurrence_none;
+ GtkWidget *recurrence_simple;
+ GtkWidget *recurrence_custom;
+ GtkWidget *recurrence_custom_warning;
+
+ GtkWidget *recurrence_params;
+ GtkWidget *recurrence_interval_value;
+ GtkWidget *recurrence_interval_unit;
+ GtkWidget *recurrence_special;
+ GtkWidget *recurrence_ending_menu;
+ GtkWidget *recurrence_ending_special;
+
+ /* For weekly recurrences, created by hand */
+ GtkWidget *recurrence_weekday_picker;
+ guint8 recurrence_weekday_day_mask;
+
GtkWidget *recurrence_rule_notebook;
GtkWidget *recurrence_rule_none;
GtkWidget *recurrence_rule_daily;
@@ -109,15 +128,14 @@ typedef struct {
GtkWidget *recurrence_ending_date_end_after;
GtkWidget *recurrence_ending_date_end_after_count;
- GtkWidget *recurrence_exceptions_date;
- GtkWidget *recurrence_exceptions_list;
+ /* Widgets from the Glade file */
+
+ GtkWidget *recurrence_exception_date;
+ GtkWidget *recurrence_exception_list;
GtkWidget *recurrence_exception_add;
+ GtkWidget *recurrence_exception_modify;
GtkWidget *recurrence_exception_delete;
- GtkWidget *recurrence_exception_change;
-
- GtkWidget *exception_list;
- GtkWidget *exception_date;
-} EventEditorPrivate;
+};
@@ -140,15 +158,14 @@ static void alarm_toggle (GtkWidget *toggle, EventEditor *ee);
static void check_dates (EDateEdit *dedit, EventEditor *ee);
static void check_times (EDateEdit *dedit, EventEditor *ee);
static void recurrence_toggled (GtkWidget *radio, EventEditor *ee);
-static void recurrence_exception_added (GtkWidget *widget, EventEditor *ee);
-static void recurrence_exception_deleted (GtkWidget *widget, EventEditor *ee);
-static void recurrence_exception_changed (GtkWidget *widget, EventEditor *ee);
+static void recurrence_exception_add_cb (GtkWidget *widget, EventEditor *ee);
+static void recurrence_exception_modify_cb (GtkWidget *widget, EventEditor *ee);
+static void recurrence_exception_delete_cb (GtkWidget *widget, EventEditor *ee);
/**
* event_editor_get_type:
- * @void:
*
* Registers the #EventEditor class if necessary, and returns the type ID
* associated to it.
@@ -236,7 +253,7 @@ event_editor_destroy (GtkObject *object)
priv->uic = NULL;
}
- free_exception_clist_data (GTK_CLIST (priv->recurrence_exceptions_list));
+ free_exception_clist_data (GTK_CLIST (priv->recurrence_exception_list));
if (priv->app) {
gtk_signal_disconnect_by_data (GTK_OBJECT (priv->app), ee);
@@ -302,6 +319,189 @@ make_title_from_comp (CalComponent *comp)
}
}
+/* Creates the special contents for weekly recurrences */
+static void
+make_recur_weekly_special (EventEditor *ee)
+{
+ EventEditorPrivate *priv;
+ GtkWidget *hbox;
+ GtkWidget *label;
+ WeekdayPicker *wp;
+
+ priv = ee->priv;
+
+ g_assert (GTK_BIN (priv->recurrence_special)->child == NULL);
+ g_assert (priv->recurrence_weekday_picker == NULL);
+
+ /* Create the widgets */
+
+ hbox = gtk_hbox_new (FALSE, 4);
+ gtk_container_add (GTK_CONTAINER (priv->recurrence_special), hbox);
+
+ label = gtk_label_new (_("on"));
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ wp = WEEKDAY_PICKER (weekday_picker_new ());
+
+ priv->recurrence_weekday_picker = GTK_WIDGET (wp);
+ gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (wp), FALSE, FALSE, 0);
+
+ gtk_widget_show_all (hbox);
+
+ /* Set the weekdays */
+
+ weekday_picker_set_week_starts_on_monday (wp, week_starts_on_monday);
+ weekday_picker_set_days (wp, priv->recurrence_weekday_day_mask);
+}
+
+/* Creates the special contents for monthly recurrences */
+static void
+make_recur_monthly_special (EventEditor *ee)
+{
+ /* FIXME: create the "on the" <nth> [day, Weekday, last Weekday] */
+}
+
+static const int recur_freq_map[] = {
+ ICAL_DAILY_RECURRENCE,
+ ICAL_WEEKLY_RECURRENCE,
+ ICAL_MONTHLY_RECURRENCE,
+ ICAL_YEARLY_RECURRENCE,
+ -1
+};
+
+/* Changes the recurrence-special widget to match the interval units.
+ *
+ * For daily recurrences: nothing.
+ * For weekly recurrences: weekday selector.
+ * For monthly recurrences: "on the" <nth> [day, Weekday, last Weekday]
+ * For yearly recurrences: nothing.
+ */
+static void
+make_recurrence_special (EventEditor *ee)
+{
+ EventEditorPrivate *priv;
+ icalrecurrencetype_frequency frequency;
+
+ priv = ee->priv;
+
+ if (GTK_BIN (priv->recurrence_special)->child != NULL) {
+ gtk_widget_destroy (GTK_BIN (priv->recurrence_special)->child);
+
+ priv->recurrence_weekday_picker = NULL;
+ }
+
+ frequency = e_dialog_option_menu_get (priv->recurrence_interval_unit, recur_freq_map);
+
+ switch (frequency) {
+ case ICAL_DAILY_RECURRENCE:
+ gtk_widget_hide (priv->recurrence_special);
+ break;
+
+ case ICAL_WEEKLY_RECURRENCE:
+ make_recur_weekly_special (ee);
+ gtk_widget_show (priv->recurrence_special);
+ break;
+
+ case ICAL_MONTHLY_RECURRENCE:
+ make_recur_monthly_special (ee);
+ gtk_widget_show (priv->recurrence_special);
+ break;
+
+ case ICAL_YEARLY_RECURRENCE:
+ gtk_widget_hide (priv->recurrence_special);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+enum ending_type {
+ ENDING_FOR,
+ ENDING_UNTIL,
+ ENDING_FOREVER
+};
+
+static const int ending_types_map[] = {
+ ENDING_FOR,
+ ENDING_UNTIL,
+ ENDING_FOREVER,
+ -1
+};
+
+/* Changes the recurrence-ending-special widget to match the ending date option.
+ *
+ * For: <n> [days, weeks, months, years, occurrences]
+ * Until: <date selector>
+ * Forever: nothing.
+ */
+static void
+make_recurrence_ending_special (EventEditor *ee)
+{
+ /* FIXME */
+}
+
+enum recur_type {
+ RECUR_NONE,
+ RECUR_SIMPLE,
+ RECUR_CUSTOM
+};
+
+static const int recur_type_map[] = {
+ RECUR_NONE,
+ RECUR_SIMPLE,
+ RECUR_CUSTOM,
+ -1
+};
+
+/* Callback used when one of the recurrence type radio buttons is toggled. We
+ * enable or the recurrence parameters.
+ */
+static void
+recurrence_type_toggled_cb (GtkWidget *widget, gpointer data)
+{
+ EventEditor *ee;
+ EventEditorPrivate *priv;
+ enum recur_type type;
+
+ ee = EVENT_EDITOR (data);
+ priv = ee->priv;
+
+ type = e_dialog_radio_get (widget, recur_type_map);
+
+ switch (type) {
+ case RECUR_NONE:
+ gtk_widget_set_sensitive (priv->recurrence_params, FALSE);
+ gtk_widget_hide (priv->recurrence_custom_warning);
+ break;
+
+ case RECUR_SIMPLE:
+ gtk_widget_set_sensitive (priv->recurrence_params, TRUE);
+ gtk_widget_hide (priv->recurrence_custom_warning);
+ break;
+
+ case RECUR_CUSTOM:
+ gtk_widget_set_sensitive (priv->recurrence_params, FALSE);
+ gtk_widget_show (priv->recurrence_custom_warning);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Callback used when the recurrence interval option menu changes. We need to
+ * change the contents of the recurrence special widget.
+ */
+static void
+recur_interval_selection_done_cb (GtkMenuShell *menu_shell, gpointer data)
+{
+ EventEditor *ee;
+
+ ee = EVENT_EDITOR (data);
+ make_recurrence_special (ee);
+}
+
/* Gets the widgets from the XML file and returns if they are all available.
* For the widgets whose values can be simply set with e-dialog-utils, it does
* that as well.
@@ -343,6 +543,21 @@ get_widgets (EventEditor *ee)
priv->classification_radio = GW ("classification-radio");
+ priv->recurrence_summary = GW ("recurrence-summary");
+ priv->recurrence_starting_date = GW ("recurrence-starting-date");
+
+ priv->recurrence_none = GW ("recurrence-none");
+ priv->recurrence_simple = GW ("recurrence-simple");
+ priv->recurrence_custom = GW ("recurrence-custom");
+ priv->recurrence_custom_warning = GW ("recurrence-custom-warning");
+ priv->recurrence_params = GW ("recurrence-params");
+
+ priv->recurrence_interval_value = GW ("recurrence-interval-value");
+ priv->recurrence_interval_unit = GW ("recurrence-interval-unit");
+ priv->recurrence_special = GW ("recurrence-special");
+ priv->recurrence_ending_menu = GW ("recurrence-ending-menu");
+ priv->recurrence_ending_special = GW ("recurrence-ending-special");
+
priv->recurrence_rule_notebook = GW ("recurrence-rule-notebook");
priv->recurrence_rule_none = GW ("recurrence-rule-none");
priv->recurrence_rule_daily = GW ("recurrence-rule-daily");
@@ -375,14 +590,11 @@ get_widgets (EventEditor *ee)
priv->recurrence_ending_date_end_after = GW ("recurrence-ending-date-end-after");
priv->recurrence_ending_date_end_after_count = GW ("recurrence-ending-date-end-after-count");
- priv->recurrence_exceptions_date = GW ("recurrence-exceptions-date");
- priv->recurrence_exceptions_list = GW ("recurrence-exceptions-list");
- priv->recurrence_exception_add = GW ("recurrence-exceptions-add");
- priv->recurrence_exception_delete = GW ("recurrence-exceptions-delete");
- priv->recurrence_exception_change = GW ("recurrence-exceptions-change");
-
- priv->exception_list = GW ("recurrence-exceptions-list");
- priv->exception_date = GW ("recurrence-exceptions-date");
+ priv->recurrence_exception_date = GW ("recurrence-exception-date");
+ priv->recurrence_exception_list = GW ("recurrence-exception-list");
+ priv->recurrence_exception_add = GW ("recurrence-exception-add");
+ priv->recurrence_exception_modify = GW ("recurrence-exception-modify");
+ priv->recurrence_exception_delete = GW ("recurrence-exception-delete");
#undef GW
@@ -407,6 +619,19 @@ get_widgets (EventEditor *ee)
&& priv->alarm_mail_unit
&& priv->alarm_mail_mail_to
&& priv->classification_radio
+ && priv->recurrence_summary
+ && priv->recurrence_starting_date
+ && priv->recurrence_none
+ && priv->recurrence_simple
+ && priv->recurrence_custom
+ && priv->recurrence_custom_warning
+ && priv->recurrence_params
+ && priv->recurrence_interval_value
+ && priv->recurrence_interval_unit
+ && priv->recurrence_special
+ && priv->recurrence_ending_menu
+ && priv->recurrence_ending_special
+
&& priv->recurrence_rule_notebook
&& priv->recurrence_rule_none
&& priv->recurrence_rule_daily
@@ -427,69 +652,20 @@ get_widgets (EventEditor *ee)
&& priv->recurrence_ending_date_end_on_date
&& priv->recurrence_ending_date_end_after
&& priv->recurrence_ending_date_end_after_count
- && priv->recurrence_exceptions_date
- && priv->recurrence_exceptions_list
- && priv->recurrence_exception_add
- && priv->recurrence_exception_delete
- && priv->recurrence_exception_change
- && priv->exception_list
- && priv->exception_date);
-}
-
-
-
-static const int classification_map[] = {
- CAL_COMPONENT_CLASS_PUBLIC,
- CAL_COMPONENT_CLASS_PRIVATE,
- CAL_COMPONENT_CLASS_CONFIDENTIAL,
- -1
-};
-
-#if 0
-static const int alarm_unit_map[] = {
- ALARM_MINUTES,
- ALARM_HOURS,
- ALARM_DAYS,
- -1
-};
-
-static void
-alarm_unit_set (GtkWidget *widget, enum AlarmUnit unit)
-{
- e_dialog_option_menu_set (widget, unit, alarm_unit_map);
-}
-
-static enum AlarmUnit
-alarm_unit_get (GtkWidget *widget)
-{
- return e_dialog_option_menu_get (widget, alarm_unit_map);
-}
-#endif
-/* Recurrence types for mapping them to radio buttons */
-static const int recur_options_map[] = {
- ICAL_NO_RECURRENCE,
- ICAL_DAILY_RECURRENCE,
- ICAL_WEEKLY_RECURRENCE,
- ICAL_MONTHLY_RECURRENCE,
- ICAL_YEARLY_RECURRENCE,
- -1
-};
-
-static icalrecurrencetype_frequency
-recur_options_get (GtkWidget *widget)
-{
- return e_dialog_radio_get (widget, recur_options_map);
+ && priv->recurrence_exception_date
+ && priv->recurrence_exception_list
+ && priv->recurrence_exception_add
+ && priv->recurrence_exception_modify
+ && priv->recurrence_exception_delete);
}
-static const int month_pos_map[] = { 0, 1, 2, 3, 4, -1 };
-static const int weekday_map[] = { 0, 1, 2, 3, 4, 5, 6, -1 };
-
/* Hooks the widget signals */
static void
init_widgets (EventEditor *ee)
{
EventEditorPrivate *priv;
+ GtkWidget *menu;
priv = ee->priv;
@@ -521,6 +697,23 @@ init_widgets (EventEditor *ee)
/* Recurrence types */
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_none), "toggled",
+ GTK_SIGNAL_FUNC (recurrence_type_toggled_cb), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_simple), "toggled",
+ GTK_SIGNAL_FUNC (recurrence_type_toggled_cb), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_custom), "toggled",
+ GTK_SIGNAL_FUNC (recurrence_type_toggled_cb), ee);
+
+ /* Recurrence units */
+
+ menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->recurrence_interval_unit));
+ g_assert (menu != NULL);
+
+ gtk_signal_connect (GTK_OBJECT (menu), "selection_done",
+ GTK_SIGNAL_FUNC (recur_interval_selection_done_cb), ee);
+
+ /* Recurrence types */
+
gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_none), "toggled",
GTK_SIGNAL_FUNC (recurrence_toggled), ee);
gtk_signal_connect (GTK_OBJECT (priv->recurrence_rule_daily), "toggled",
@@ -535,12 +728,59 @@ init_widgets (EventEditor *ee)
/* Exception buttons */
gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_add), "clicked",
- GTK_SIGNAL_FUNC (recurrence_exception_added), ee);
+ GTK_SIGNAL_FUNC (recurrence_exception_add_cb), ee);
+ gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_modify), "clicked",
+ GTK_SIGNAL_FUNC (recurrence_exception_modify_cb), ee);
gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_delete), "clicked",
- GTK_SIGNAL_FUNC (recurrence_exception_deleted), ee);
- gtk_signal_connect (GTK_OBJECT (priv->recurrence_exception_change), "clicked",
- GTK_SIGNAL_FUNC (recurrence_exception_changed), ee);
+ GTK_SIGNAL_FUNC (recurrence_exception_delete_cb), ee);
+}
+
+static const int classification_map[] = {
+ CAL_COMPONENT_CLASS_PUBLIC,
+ CAL_COMPONENT_CLASS_PRIVATE,
+ CAL_COMPONENT_CLASS_CONFIDENTIAL,
+ -1
+};
+
+#if 0
+static const int alarm_unit_map[] = {
+ ALARM_MINUTES,
+ ALARM_HOURS,
+ ALARM_DAYS,
+ -1
+};
+
+static void
+alarm_unit_set (GtkWidget *widget, enum AlarmUnit unit)
+{
+ e_dialog_option_menu_set (widget, unit, alarm_unit_map);
+}
+
+static enum AlarmUnit
+alarm_unit_get (GtkWidget *widget)
+{
+ return e_dialog_option_menu_get (widget, alarm_unit_map);
}
+#endif
+
+/* Recurrence types for mapping them to radio buttons */
+static const int recur_options_map[] = {
+ ICAL_NO_RECURRENCE,
+ ICAL_DAILY_RECURRENCE,
+ ICAL_WEEKLY_RECURRENCE,
+ ICAL_MONTHLY_RECURRENCE,
+ ICAL_YEARLY_RECURRENCE,
+ -1
+};
+
+static icalrecurrencetype_frequency
+recur_options_get (GtkWidget *widget)
+{
+ return e_dialog_radio_get (widget, recur_options_map);
+}
+
+static const int month_pos_map[] = { 0, 1, 2, 3, 4, -1 };
+static const int weekday_map[] = { 0, 1, 2, 3, 4, 5, 6, -1 };
/* Fills the widgets with default values */
static void
@@ -573,7 +813,7 @@ clear_widgets (EventEditor *ee)
/* Alarms */
- /* FIXMe: these should use configurable defaults */
+ /* FIXME: these should use configurable defaults */
e_dialog_toggle_set (priv->alarm_display, FALSE);
e_dialog_toggle_set (priv->alarm_program, FALSE);
@@ -597,11 +837,24 @@ clear_widgets (EventEditor *ee)
/* Classification */
- e_dialog_radio_set (priv->classification_radio,
+ e_dialog_radio_set (priv->classification_radio,
CAL_COMPONENT_CLASS_PRIVATE, classification_map);
/* Recurrences */
+ priv->recurrence_weekday_day_mask = 0;
+
+ e_dialog_radio_set (priv->recurrence_none, RECUR_NONE, recur_type_map);
+
+ e_dialog_spin_set (priv->recurrence_interval_value, 1);
+ e_dialog_option_menu_set (priv->recurrence_interval_unit, ICAL_DAILY_RECURRENCE,
+ recur_freq_map);
+
+ e_dialog_option_menu_set (priv->recurrence_ending_menu, ENDING_FOREVER,
+ ending_types_map);
+
+ /* Old recurrences */
+
e_dialog_radio_set (priv->recurrence_rule_none, ICAL_NO_RECURRENCE, recur_options_map);
e_dialog_spin_set (priv->recurrence_rule_daily_days, 1);
@@ -630,10 +883,197 @@ clear_widgets (EventEditor *ee)
/* Exceptions list */
- free_exception_clist_data (GTK_CLIST (priv->recurrence_exceptions_list));
+ free_exception_clist_data (GTK_CLIST (priv->recurrence_exception_list));
+}
+
+/* Counts the number of elements in the by_xxx fields of an icalrecurrencetype */
+static int
+count_by_xxx (short *field, int max_elements)
+{
+ int i;
+
+ for (i = 0; i < max_elements; i++)
+ if (field[i] == SHRT_MAX)
+ break;
+
+ return i;
+}
+
+/* Fills in the recurrence widgets with the values from the calendar component.
+ * 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
+fill_recurrence_widgets (EventEditor *ee)
+{
+ EventEditorPrivate *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;
+
+ priv = ee->priv;
+ g_assert (priv->comp != NULL);
+
+ /* No recurrences? */
+
+ if (!cal_component_has_rdates (priv->comp)
+ && !cal_component_has_rrules (priv->comp)
+ && !cal_component_has_exrules (priv->comp)) {
+ e_dialog_radio_set (priv->recurrence_none, RECUR_NONE, recur_type_map);
+ return;
+ }
+
+ /* See if it is a custom set we don't support */
+
+ cal_component_get_rrule_list (priv->comp, &rrule_list);
+ len = g_slist_length (rrule_list);
+
+ if (len > 1
+ || cal_component_has_rdates (priv->comp)
+ || cal_component_has_exrules (priv->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;
+
+ e_dialog_option_menu_set (priv->recurrence_interval_unit, ICAL_DAILY_RECURRENCE,
+ recur_freq_map);
+ 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] != SHRT_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->recurrence_weekday_day_mask = day_mask;
+
+ e_dialog_option_menu_set (priv->recurrence_interval_unit, ICAL_WEEKLY_RECURRENCE,
+ recur_freq_map);
+ break;
+ }
+
+ case ICAL_MONTHLY_RECURRENCE:
+
+ default:
+ goto custom;
+ }
+
+ /* If we got here it means it is a simple recurrence */
+
+ e_dialog_radio_set (priv->recurrence_simple, RECUR_SIMPLE, recur_type_map);
+ e_dialog_spin_set (priv->recurrence_interval_value, r->interval);
+
+ goto out;
+
+ custom:
+
+ e_dialog_radio_set (priv->recurrence_custom, RECUR_CUSTOM, recur_type_map);
+
+ out:
+
+ cal_component_free_recur_list (rrule_list);
}
-/* Fills in the widgets with the proper values */
+/* Fills in the widgets with the value from the calendar component */
static void
fill_widgets (EventEditor *ee)
{
@@ -728,6 +1168,11 @@ fill_widgets (EventEditor *ee)
}
/* Recurrences */
+
+ fill_recurrence_widgets (ee);
+
+#if 0
+
#ifndef NO_WARNINGS
#warning "FIX ME"
#endif
@@ -843,12 +1288,12 @@ fill_widgets (EventEditor *ee)
cal_component_free_recur_list (list);
}
- /* Exceptions list */
-#ifndef NO_WARNINGS
-#warning "FIX ME"
#endif
- /* Need to handle exception rules as well as dates */
+
+ /* Exceptions list */
+
cal_component_get_exdate_list (priv->comp, &list);
+
for (l = list; l; l = l->next) {
struct icaltimetype *t;
time_t ext;
@@ -857,16 +1302,25 @@ fill_widgets (EventEditor *ee)
ext = icaltime_as_timet (*t);
append_exception (ee, ext);
}
+
cal_component_free_exdate_list (list);
}
-/* Tell the event editor to reread its widget values from the associated
- CalComponent object. If one changes the CalComponent through a means other
- than the GUI, one should call this function. */
+/**
+ * event_editor_update_widgets:
+ * @ee: An event editor.
+ *
+ * Causes an event editor dialog to re-read the values of its calendar component
+ * object. This function should be used if the #CalComponent is changed by
+ * external means while it is open in the editor.
+ **/
void
event_editor_update_widgets (EventEditor *ee)
{
+ g_return_if_fail (ee != NULL);
+ g_return_if_fail (IS_EVENT_EDITOR (ee));
+
fill_widgets (ee);
}
@@ -879,7 +1333,141 @@ classification_get (GtkWidget *widget)
return e_dialog_radio_get (widget, classification_map);
}
-/* Get the values of the widgets in the event editor and put them in the iCalObject */
+/* Gets the simple recurrence data from the recurrence widgets and stores it in
+ * the calendar component object.
+ */
+static void
+simple_recur_to_comp_object (EventEditor *ee)
+{
+ EventEditorPrivate *priv;
+ struct icalrecurrencetype r;
+ guint8 day_mask;
+ int i;
+ GSList l;
+ enum ending_type ending_type;
+
+ priv = ee->priv;
+
+ icalrecurrencetype_clear (&r);
+
+ /* Frequency and interval */
+
+ r.freq = e_dialog_option_menu_get (priv->recurrence_interval_unit, recur_freq_map);
+ r.interval = e_dialog_spin_get_int (priv->recurrence_interval_value);
+
+ /* Frequency-specific data */
+
+ switch (r.freq) {
+ case ICAL_DAILY_RECURRENCE:
+ break;
+
+ case ICAL_WEEKLY_RECURRENCE:
+ g_assert (GTK_BIN (priv->recurrence_special)->child != NULL);
+ g_assert (GTK_BIN (priv->recurrence_special)->child
+ == priv->recurrence_weekday_picker);
+ g_assert (IS_WEEKDAY_PICKER (priv->recurrence_weekday_picker));
+
+ day_mask = weekday_picker_get_days (WEEKDAY_PICKER (priv->recurrence_weekday_picker));
+
+ i = 0;
+
+ if (day_mask & (1 << 0))
+ r.by_day[i++] = ICAL_SUNDAY_WEEKDAY;
+
+ if (day_mask & (1 << 1))
+ r.by_day[i++] = ICAL_MONDAY_WEEKDAY;
+
+ if (day_mask & (1 << 2))
+ r.by_day[i++] = ICAL_TUESDAY_WEEKDAY;
+
+ if (day_mask & (1 << 3))
+ r.by_day[i++] = ICAL_WEDNESDAY_WEEKDAY;
+
+ if (day_mask & (1 << 4))
+ r.by_day[i++] = ICAL_THURSDAY_WEEKDAY;
+
+ if (day_mask & (1 << 5))
+ r.by_day[i++] = ICAL_FRIDAY_WEEKDAY;
+
+ if (day_mask & (1 << 6))
+ r.by_day[i++] = ICAL_SATURDAY_WEEKDAY;
+
+ break;
+
+ case ICAL_MONTHLY_RECURRENCE:
+ /* FIXME */
+ break;
+
+ case ICAL_YEARLY_RECURRENCE:
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Ending date */
+
+ ending_type = e_dialog_option_menu_get (priv->recurrence_ending_menu, ending_types_map);
+
+ switch (ending_type) {
+ case ENDING_FOR:
+ /* FIXME */
+ break;
+
+ case ENDING_UNTIL:
+ /* FIXME */
+ break;
+
+ case ENDING_FOREVER:
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Set the recurrence */
+
+ l.data = &r;
+ l.next = NULL;
+
+ cal_component_set_rrule_list (priv->comp, &l);
+}
+
+/* Gets the data from the recurrence widgets and stores it in the calendar
+ * component object.
+ */
+static void
+recur_to_comp_object (EventEditor *ee)
+{
+ EventEditorPrivate *priv;
+ enum recur_type recur_type;
+
+ priv = ee->priv;
+ g_assert (priv->comp != NULL);
+
+ recur_type = e_dialog_radio_get (priv->recurrence_none, recur_type_map);
+
+ switch (recur_type) {
+ case RECUR_NONE:
+ cal_component_set_rdate_list (priv->comp, NULL);
+ cal_component_set_rrule_list (priv->comp, NULL);
+ cal_component_set_exrule_list (priv->comp, NULL);
+ break;
+
+ case RECUR_SIMPLE:
+ simple_recur_to_comp_object (ee);
+ break;
+
+ case RECUR_CUSTOM:
+ /* We just keep whatever the component has currently */
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Gets the data from the widgets and stores it in the calendar component object */
static void
dialog_to_comp_object (EventEditor *ee)
{
@@ -887,14 +1475,15 @@ dialog_to_comp_object (EventEditor *ee)
CalComponent *comp;
CalComponentText *text;
CalComponentDateTime date;
- struct icalrecurrencetype recur;
time_t t;
gboolean all_day_event;
GtkCList *exception_list;
GSList *list;
- int i, pos = 0;
+ int i;
priv = ee->priv;
+ g_assert (priv->comp != NULL);
+
comp = priv->comp;
text = g_new0 (CalComponentText, 1);
@@ -953,6 +1542,10 @@ dialog_to_comp_object (EventEditor *ee)
cal_component_set_classification (comp, classification_get (priv->classification_radio));
/* Recurrence information */
+
+ recur_to_comp_object (ee);
+
+#if 0
icalrecurrencetype_clear (&recur);
recur.freq = recur_options_get (priv->recurrence_rule_none);
@@ -967,7 +1560,9 @@ dialog_to_comp_object (EventEditor *ee)
case ICAL_WEEKLY_RECURRENCE:
recur.interval = e_dialog_spin_get_int (priv->recurrence_rule_weekly_weeks);
-
+
+ pos = 0;
+
if (e_dialog_toggle_get (priv->recurrence_rule_weekly_sun))
recur.by_day[pos++] = ICAL_SUNDAY_WEEKDAY;
if (e_dialog_toggle_get (priv->recurrence_rule_weekly_mon))
@@ -1044,10 +1639,10 @@ dialog_to_comp_object (EventEditor *ee)
list = NULL;
cal_component_set_rrule_list (comp, list);
}
-
+#endif
/* Set exceptions */
list = NULL;
- exception_list = GTK_CLIST (priv->recurrence_exceptions_list);
+ exception_list = GTK_CLIST (priv->recurrence_exception_list);
for (i = 0; i < exception_list->rows; i++) {
struct icaltimetype *tt;
time_t *t;
@@ -1065,6 +1660,9 @@ dialog_to_comp_object (EventEditor *ee)
cal_component_commit_sequence (comp);
}
+/* Fills the calendar component object from the data in the widgets and commits
+ * the component to the storage.
+ */
static void
save_event_object (EventEditor *ee)
{
@@ -1194,7 +1792,6 @@ schedule_meeting_cb (GtkWidget *widget, gpointer data)
* this and the task-editor.
*/
static BonoboUIVerb verbs [] = {
-
BONOBO_UI_UNSAFE_VERB ("FileSave", file_save_cb),
BONOBO_UI_UNSAFE_VERB ("FileDelete", file_delete_cb),
BONOBO_UI_UNSAFE_VERB ("FileClose", file_close_cb),
@@ -1292,8 +1889,7 @@ event_editor_construct (EventEditor *ee)
priv->uic, bonobo_object_corba_objref (BONOBO_OBJECT (container)));
}
- bonobo_ui_component_add_verb_list_with_data (
- priv->uic, verbs, ee);
+ bonobo_ui_component_add_verb_list_with_data (priv->uic, verbs, ee);
bonobo_ui_util_set_ui (priv->uic, EVOLUTION_DATADIR,
"evolution-event-editor.xml",
@@ -1421,6 +2017,14 @@ obj_removed_cb (CalClient *client, const char *uid, gpointer data)
raise_and_focus (priv->app);
}
+/**
+ * event_editor_set_cal_client:
+ * @ee: An event editor.
+ * @client: Calendar client.
+ *
+ * Sets the calendar client than an event editor will use for updating its
+ * calendar components.
+ **/
void
event_editor_set_cal_client (EventEditor *ee, CalClient *client)
{
@@ -1459,6 +2063,27 @@ event_editor_set_cal_client (EventEditor *ee, CalClient *client)
}
/**
+ * event_editor_get_cal_client:
+ * @ee: An event editor.
+ *
+ * Queries the calendar client that an event editor is using to update its
+ * calendar components.
+ *
+ * Return value: A calendar client object.
+ **/
+CalClient *
+event_editor_get_cal_client (EventEditor *ee)
+{
+ EventEditorPrivate *priv;
+
+ g_return_val_if_fail (ee != NULL, NULL);
+ g_return_val_if_fail (IS_EVENT_EDITOR (ee), NULL);
+
+ priv = ee->priv;
+ return priv->client;
+}
+
+/**
* event_editor_set_event_object:
* @ee: An event editor.
* @comp: A calendar object.
@@ -1736,11 +2361,11 @@ recurrence_toggled (GtkWidget *radio, EventEditor *ee)
rf = e_dialog_radio_get (radio, recur_options_map);
/* This is a hack to get things working */
- gtk_notebook_set_page (GTK_NOTEBOOK (priv->recurrence_rule_notebook),
+ gtk_notebook_set_page (GTK_NOTEBOOK (priv->recurrence_rule_notebook),
(int) (rf - ICAL_HOURLY_RECURRENCE));
}
-
+/* Builds a static string out of an exception date */
static char *
get_exception_string (time_t t)
{
@@ -1750,7 +2375,7 @@ get_exception_string (time_t t)
return buf;
}
-
+/* Appends an exception date to the list */
static void
append_exception (EventEditor *ee, time_t t)
{
@@ -1765,7 +2390,7 @@ append_exception (EventEditor *ee, time_t t)
tt = g_new (time_t, 1);
*tt = t;
- clist = GTK_CLIST (priv->recurrence_exceptions_list);
+ clist = GTK_CLIST (priv->recurrence_exception_list);
c[0] = get_exception_string (t);
i = e_utf8_gtk_clist_append (clist, c);
@@ -1773,68 +2398,75 @@ append_exception (EventEditor *ee, time_t t)
gtk_clist_set_row_data (clist, i, tt);
gtk_clist_select_row (clist, i, 0);
-/* gtk_widget_set_sensitive (ee->recur_ex_vbox, TRUE); */
+ gtk_widget_set_sensitive (priv->recurrence_exception_modify, TRUE);
+ gtk_widget_set_sensitive (priv->recurrence_exception_delete, TRUE);
}
+/* Callback for the "add exception" button */
static void
-recurrence_exception_added (GtkWidget *widget, EventEditor *ee)
+recurrence_exception_add_cb (GtkWidget *widget, EventEditor *ee)
{
EventEditorPrivate *priv;
time_t t;
priv = ee->priv;
- t = e_date_edit_get_time (E_DATE_EDIT (priv->recurrence_exceptions_date));
+ t = e_date_edit_get_time (E_DATE_EDIT (priv->recurrence_exception_date));
append_exception (ee, t);
}
-
+/* Callback for the "modify exception" button */
static void
-recurrence_exception_deleted (GtkWidget *widget, EventEditor *ee)
+recurrence_exception_modify_cb (GtkWidget *widget, EventEditor *ee)
{
EventEditorPrivate *priv;
GtkCList *clist;
+ time_t *t;
int sel;
priv = ee->priv;
- clist = GTK_CLIST (priv->recurrence_exceptions_list);
+ clist = GTK_CLIST (priv->recurrence_exception_list);
if (!clist->selection)
return;
sel = GPOINTER_TO_INT (clist->selection->data);
- g_free (gtk_clist_get_row_data (clist, sel)); /* free the time_t stored there */
-
- gtk_clist_remove (clist, sel);
- if (sel >= clist->rows)
- sel--;
+ t = gtk_clist_get_row_data (clist, sel);
+ *t = e_date_edit_get_time (E_DATE_EDIT (priv->recurrence_exception_date));
- gtk_clist_select_row (clist, sel, 0);
+ e_utf8_gtk_clist_set_text (clist, sel, 0, get_exception_string (*t));
}
-
+/* Callback for the "delete exception" button */
static void
-recurrence_exception_changed (GtkWidget *widget, EventEditor *ee)
+recurrence_exception_delete_cb (GtkWidget *widget, EventEditor *ee)
{
EventEditorPrivate *priv;
GtkCList *clist;
- time_t *t;
int sel;
priv = ee->priv;
- clist = GTK_CLIST (priv->recurrence_exceptions_list);
+ clist = GTK_CLIST (priv->recurrence_exception_list);
if (!clist->selection)
return;
sel = GPOINTER_TO_INT (clist->selection->data);
- t = gtk_clist_get_row_data (clist, sel);
- *t = e_date_edit_get_time (E_DATE_EDIT (priv->recurrence_exceptions_date));
+ g_free (gtk_clist_get_row_data (clist, sel)); /* free the time_t stored there */
- e_utf8_gtk_clist_set_text (clist, sel, 0, get_exception_string (*t));
+ gtk_clist_remove (clist, sel);
+ if (sel >= clist->rows)
+ sel--;
+
+ if (clist->rows > 0)
+ gtk_clist_select_row (clist, sel, 0);
+ else {
+ gtk_widget_set_sensitive (priv->recurrence_exception_modify, FALSE);
+ gtk_widget_set_sensitive (priv->recurrence_exception_delete, FALSE);
+ }
}
@@ -1882,9 +2514,6 @@ make_spin_button (int val, int low, int high)
/* todo
- build some of the recur stuff by hand to take into account
- the start-on-monday preference?
-
get the apply button to work right
make the properties stuff unglobal