aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@ximian.com>2001-05-17 07:38:58 +0800
committerFederico Mena Quintero <federico@src.gnome.org>2001-05-17 07:38:58 +0800
commitf00e9367382fb81cdb4b689f96645357f122b051 (patch)
tree1750ce1d4c5104dd77a2d509bd00ca657915ebae /calendar/gui
parentd0243a91821d311699347c11d454314bdbdfc0fe (diff)
downloadgsoc2013-evolution-f00e9367382fb81cdb4b689f96645357f122b051.tar
gsoc2013-evolution-f00e9367382fb81cdb4b689f96645357f122b051.tar.gz
gsoc2013-evolution-f00e9367382fb81cdb4b689f96645357f122b051.tar.bz2
gsoc2013-evolution-f00e9367382fb81cdb4b689f96645357f122b051.tar.lz
gsoc2013-evolution-f00e9367382fb81cdb4b689f96645357f122b051.tar.xz
gsoc2013-evolution-f00e9367382fb81cdb4b689f96645357f122b051.tar.zst
gsoc2013-evolution-f00e9367382fb81cdb4b689f96645357f122b051.zip
Split the event and task editors into different objects for the separate
2001-05-16 Federico Mena Quintero <federico@ximian.com> Split the event and task editors into different objects for the separate pages; this way they can be shared by both editors. * gui/dialogs/editor-page.[ch]: New abstract class for a page in a calendar component editor. * gui/dialogs/event-page.[ch]: Main page of an event editor. * gui/dialogs/alarm-page.[ch]: Alarm page of a calendar component editor. * gui/dialogs/recurrence-page.[ch]: Recurrence page of a calendar component editor. * gui/dialogs/event-page.c (event_page_fill_widgets): Eeek, this was missing a bunch of break statements. (event_page_fill_component): Use a temporary variable rather than allocating a struct icaltimetype. * gui/dialogs/alarm-page.c (get_alarm_string): Do not use fixed-size buffers. (alarm_page_fill_widgets): Use cal_obj_uid_list_free(). (append_reminder): Now the list stores the plain CalComponentAlarm structures in the row data. We do *NOT* want to be frobbing the component's data directly. Rather, we clone the alarms from the component and maintain them on our own. (alarm_page_fill_component): Clone the alarms before adding them to the component so that we maintain the invariant that the alarm structures in the list did *not* come from the component. * cal-util/cal-component.c (cal_component_add_alarm): Added documentation. (cal_component_remove_alarm): Added documentation. (cal_component_remove_alarm): Do a lookup in our hash table of alarms instead of scanning the whole component. (CalComponentAlarm): Removed the `parent' field, since it was unused. (cal_component_free_alarm_uids): Removed function, since cal_component_get_alarm_uids() is documented so that the user will know that he must use cal_obj_uid_list_free(). (cal_component_alarm_clone): New function. svn path=/trunk/; revision=9861
Diffstat (limited to 'calendar/gui')
-rw-r--r--calendar/gui/Makefile.am2
-rw-r--r--calendar/gui/dialogs/Makefile.am19
-rw-r--r--calendar/gui/dialogs/alarm-page.c778
-rw-r--r--calendar/gui/dialogs/alarm-page.glade381
-rw-r--r--calendar/gui/dialogs/alarm-page.h64
-rw-r--r--calendar/gui/dialogs/editor-page.c259
-rw-r--r--calendar/gui/dialogs/editor-page.h86
-rw-r--r--calendar/gui/dialogs/event-page.c908
-rw-r--r--calendar/gui/dialogs/event-page.glade429
-rw-r--r--calendar/gui/dialogs/event-page.h70
-rw-r--r--calendar/gui/dialogs/recurrence-page.c900
-rw-r--r--calendar/gui/dialogs/recurrence-page.glade607
-rw-r--r--calendar/gui/dialogs/recurrence-page.h64
-rw-r--r--calendar/gui/dialogs/task-details-page.glade137
-rw-r--r--calendar/gui/dialogs/task-page.glade944
-rw-r--r--calendar/gui/e-day-view.c4
-rw-r--r--calendar/gui/e-week-view.c1
-rw-r--r--calendar/gui/event-editor.c2
18 files changed, 5101 insertions, 554 deletions
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index 292e1ebd28..8cd202c7c0 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -87,6 +87,8 @@ evolution_calendar_SOURCES = \
e-week-view.h \
e-tasks.c \
e-tasks.h \
+ editor-page.c \
+ editor-page.h \
event-editor.c \
event-editor.h \
gnome-cal.c \
diff --git a/calendar/gui/dialogs/Makefile.am b/calendar/gui/dialogs/Makefile.am
index 12342538ab..ec4e31379d 100644
--- a/calendar/gui/dialogs/Makefile.am
+++ b/calendar/gui/dialogs/Makefile.am
@@ -20,19 +20,30 @@ noinst_LIBRARIES = libcal-dialogs.a
libcal_dialogs_a_SOURCES = \
alarm-notify-dialog.c \
alarm-notify-dialog.h \
+ alarm-page.c \
+ alarm-page.h \
cal-prefs-dialog.c \
cal-prefs-dialog.h \
delete-comp.c \
delete-comp.h \
+ editor-page.c \
+ editor-page.h \
+ event-page.c \
+ event-page.h \
save-comp.c \
save-comp.h \
task-editor.c \
task-editor.h
-glade_DATA = \
- alarm-notify.glade \
- cal-prefs-dialog.glade \
- task-editor-dialog.glade
+glade_DATA = \
+ alarm-notify.glade \
+ alarm-page.glade \
+ cal-prefs-dialog.glade \
+ event-page.glade \
+ recurrence-page.glade \
+ task-details-page.glade \
+ task-editor-dialog.glade \
+ task-page.glade
EXTRA_DIST = \
$(glade_DATA)
diff --git a/calendar/gui/dialogs/alarm-page.c b/calendar/gui/dialogs/alarm-page.c
new file mode 100644
index 0000000000..a4e0054c6b
--- /dev/null
+++ b/calendar/gui/dialogs/alarm-page.c
@@ -0,0 +1,778 @@
+/* Evolution calendar - Alarm 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 "cal-util/cal-util.h"
+#include "e-util/e-dialog-widgets.h"
+#include "alarm-page.h"
+
+
+
+/* Private part of the AlarmPage structure */
+struct _AlarmPagePrivate {
+ /* Glade XML data */
+ GladeXML *xml;
+
+ /* Widgets from the Glade file */
+
+ GtkWidget *main;
+
+ GtkWidget *summary;
+ GtkWidget *starting_date;
+
+ GtkWidget *list;
+ GtkWidget *add;
+ GtkWidget *delete;
+
+ GtkWidget *action;
+ GtkWidget *interval_value;
+ GtkWidget *value_units;
+ GtkWidget *relative;
+ GtkWidget *time;
+};
+
+
+
+static void alarm_page_class_init (AlarmPageClass *class);
+static void alarm_page_init (AlarmPage *apage);
+static void alarm_page_destroy (GtkObject *object);
+
+static GtkWidget *alarm_page_get_widget (EditorPage *page);
+static void alarm_page_fill_widgets (EditorPage *page, CalComponent *comp);
+static void alarm_page_fill_component (EditorPage *page, CalComponent *comp);
+static void alarm_page_set_summary (EditorPage *page, const char *summary);
+static char *alarm_page_get_summary (EditorPage *page);
+static void alarm_page_set_dtstart (EditorPage *page, time_t start);
+
+static EditorPageClass *parent_class = NULL;
+
+
+
+/**
+ * alarm_page_get_type:
+ *
+ * Registers the #AlarmPage class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #AlarmPage class.
+ **/
+GtkType
+alarm_page_get_type (void)
+{
+ static GtkType alarm_page_type;
+
+ if (!alarm_page_type) {
+ static const GtkTypeInfo alarm_page_info = {
+ "AlarmPage",
+ sizeof (AlarmPage),
+ sizeof (AlarmPageClass),
+ (GtkClassInitFunc) alarm_page_class_init,
+ (GtkObjectInitFunc) alarm_page_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ alarm_page_type = gtk_type_unique (TYPE_EDITOR_PAGE, &alarm_page_info);
+ }
+
+ return alarm_page_type;
+}
+
+/* Class initialization function for the alarm page */
+static void
+alarm_page_class_init (AlarmPageClass *class)
+{
+ EditorPageClass *editor_page_class;
+ GtkObjectClass *object_class;
+
+ editor_page_class = (EditorPageClass *) class;
+ object_class = (GtkObjectClass *) class;
+
+ parent_class = gtk_type_class (TYPE_EDITOR_PAGE);
+
+ editor_page_class->get_widget = alarm_page_get_widget;
+ editor_page_class->fill_widgets = alarm_page_fill_widgets;
+ editor_page_class->fill_component = alarm_page_fill_component;
+ editor_page_class->set_summary = alarm_page_set_summary;
+ editor_page_class->get_summary = alarm_page_get_summary;
+ editor_page_class->set_dtstart = alarm_page_set_dtstart;
+
+ object_class->destroy = alarm_page_destroy;
+}
+
+/* Object initialization function for the alarm page */
+static void
+alarm_page_init (AlarmPage *apage)
+{
+ AlarmPagePrivate *priv;
+
+ priv = g_new0 (AlarmPagePrivate, 1);
+ apage->priv = priv;
+
+ priv->xml = NULL;
+
+ priv->main = NULL;
+ priv->summary = NULL;
+ priv->starting_date = NULL;
+ priv->list = NULL;
+ priv->add = NULL;
+ priv->delete = NULL;
+ priv->action = NULL;
+ priv->interval_value = NULL;
+ priv->value_units = NULL;
+ priv->relative = NULL;
+ priv->time = NULL;
+}
+
+/* Frees all the alarm data and empties the list */
+static void
+free_alarms (AlarmPage *apage)
+{
+ AlarmPagePrivate *priv;
+ GtkCList *clist;
+ int i;
+
+ priv = apage->priv;
+
+ clist = GTK_CLIST (priv->list);
+
+ for (i = 0; i < clist->rows; i++) {
+ CalComponentAlarm *alarm;
+
+ alarm = gtk_clist_get_row_data (clist, i);
+ g_assert (alarm != NULL);
+ cal_component_alarm_free (alarm);
+
+ gtk_clist_set_row_data (clist, i, NULL);
+ }
+
+ gtk_clist_clear (clist);
+}
+
+/* Destroy handler for the alarm page */
+static void
+alarm_page_destroy (GtkObject *object)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_ALARM_PAGE (object));
+
+ apage = ALARM_PAGE (object);
+ priv = apage->priv;
+
+ if (priv->xml) {
+ gtk_object_unref (GTK_OBJECT (priv->xml));
+ priv->xml = NULL;
+ }
+
+ free_alarms (apage);
+
+ g_free (priv);
+ apage->priv = NULL;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+
+/* get_widget handler for the alarm page */
+static GtkWidget *
+alarm_page_get_widget (EditorPage *page)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+
+ apage = ALARM_PAGE (page);
+ priv = apage->priv;
+
+ return priv->main;
+}
+
+/* Fills the widgets with default values */
+static void
+clear_widgets (AlarmPage *apage)
+{
+ AlarmPagePrivate *priv;
+
+ priv = apage->priv;
+
+ /* Summary */
+ e_dialog_editable_set (priv->summary, NULL);
+
+ /* Start date */
+ gtk_label_set_text (GTK_LABEL (priv->starting_date), "");
+
+ /* List data */
+ free_alarms (apage);
+}
+
+static char *
+get_alarm_duration_string (struct icaldurationtype *duration)
+{
+ GString *string = g_string_new (NULL);
+ char *ret;
+
+ if (duration->days > 1)
+ g_string_sprintf (string, _("%d days"), duration->days);
+ else if (duration->days == 1)
+ g_string_append (string, _("1 day"));
+
+ if (duration->weeks > 1)
+ g_string_sprintf (string, _("%d weeks"), duration->weeks);
+ else if (duration->weeks == 1)
+ g_string_append (string, _("1 week"));
+
+ if (duration->hours > 1)
+ g_string_sprintf (string, _("%d hours"), duration->hours);
+ else if (duration->hours == 1)
+ g_string_append (string, _("1 hour"));
+
+ if (duration->minutes > 1)
+ g_string_sprintf (string, _("%d minutes"), duration->minutes);
+ else if (duration->minutes == 1)
+ g_string_append (string, _("1 minute"));
+
+ if (duration->seconds > 1)
+ g_string_sprintf (string, _("%d seconds"), duration->seconds);
+ else if (duration->seconds == 1)
+ g_string_append (string, _("1 second"));
+
+ ret = string->str;
+ g_string_free (string, FALSE);
+
+ return ret;
+}
+
+static char *
+get_alarm_string (CalComponentAlarm *alarm)
+{
+ CalAlarmAction action;
+ CalAlarmTrigger trigger;
+ char string[256];
+ char *base;
+ char *str;
+ char *dur;
+
+ string [0] = '\0';
+
+ cal_component_alarm_get_action (alarm, &action);
+ cal_component_alarm_get_trigger (alarm, &trigger);
+
+ switch (action) {
+ case CAL_ALARM_AUDIO:
+ base = _("Play a sound");
+ break;
+
+ case CAL_ALARM_DISPLAY:
+ base = _("Show a dialog");
+ break;
+
+ case CAL_ALARM_EMAIL:
+ base = _("Send an email");
+ break;
+
+ case CAL_ALARM_PROCEDURE:
+ base = _("Run a program");
+ break;
+
+ case CAL_ALARM_NONE:
+ case CAL_ALARM_UNKNOWN:
+ base = _("Unknown");
+ break;
+ }
+
+ /* FIXME: This does not look like it will localize correctly. */
+
+ switch (trigger.type) {
+ case CAL_ALARM_TRIGGER_RELATIVE_START:
+ dur = get_alarm_duration_string (&trigger.u.rel_duration);
+
+ if (trigger.u.rel_duration.is_neg)
+ str = g_strdup_printf ("%s %s %s", base, dur,
+ _(" before start of appointment"));
+ else
+ str = g_strdup_printf ("%s %s %s", base, dur,
+ _(" after start of appointment"));
+
+ g_free (dur);
+ break;
+
+ case CAL_ALARM_TRIGGER_RELATIVE_END:
+ dur = get_alarm_duration_string (&trigger.u.rel_duration);
+
+ if (trigger.u.rel_duration.is_neg)
+ str = g_strdup_printf ("%s %s %s", base, dur,
+ _(" before end of appointment"));
+ else
+ str = g_strdup_printf ("%s %s %s", base, dur,
+ _(" after end of appointment"));
+
+ g_free (dur);
+ break;
+ case CAL_ALARM_TRIGGER_NONE:
+ case CAL_ALARM_TRIGGER_ABSOLUTE:
+ str = g_strdup_printf ("%s %s", base,
+ _("Unknown"));
+ break;
+ }
+
+ return str;
+}
+
+/* Appends an alarm to the list */
+static void
+append_reminder (AlarmPage *apage, CalComponentAlarm *alarm)
+{
+ AlarmPagePrivate *priv;
+ GtkCList *clist;
+ char *c[1];
+ int i;
+
+ priv = apage->priv;
+
+ clist = GTK_CLIST (priv->list);
+
+ c[0] = get_alarm_string (alarm);
+ i = gtk_clist_append (clist, c);
+
+ gtk_clist_set_row_data (clist, i, alarm);
+ gtk_clist_select_row (clist, i, 0);
+ g_free (c[0]);
+
+ gtk_widget_set_sensitive (priv->delete, TRUE);
+}
+
+/* fill_widgets handler for the alarm page */
+static void
+alarm_page_fill_widgets (EditorPage *page, CalComponent *comp)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+ CalComponentText text;
+ GList *alarms, *l;
+ GtkCList *clist;
+
+ apage = ALARM_PAGE (page);
+ priv = apage->priv;
+
+ clear_widgets (apage);
+
+ /* Summary */
+ cal_component_get_summary (comp, &text);
+ e_dialog_editable_set (priv->summary, text.value);
+
+ /* List */
+ if (!cal_component_has_alarms (comp))
+ return;
+
+ alarms = cal_component_get_alarm_uids (comp);
+
+ clist = GTK_CLIST (priv->list);
+ for (l = alarms; l != NULL; l = l->next) {
+ CalComponentAlarm *ca, *ca_copy;
+ const char *auid;
+
+ auid = l->data;
+ ca = cal_component_get_alarm (comp, auid);
+ g_assert (ca != NULL);
+
+ ca_copy = cal_component_alarm_clone (ca);
+ cal_component_alarm_free (ca);
+
+ append_reminder (apage, ca_copy);
+ }
+ cal_obj_uid_list_free (alarms);
+}
+
+/* fill_component handler for the alarm page */
+static void
+alarm_page_fill_component (EditorPage *page, CalComponent *comp)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+ GList *list, *l;
+ GtkCList *clist;
+ int i;
+
+ apage = ALARM_PAGE (page);
+ priv = apage->priv;
+
+ /* Remove all the alarms from the component */
+
+ list = cal_component_get_alarm_uids (comp);
+ for (l = list; l; l = l->next) {
+ const char *auid;
+
+ auid = l->data;
+ cal_component_remove_alarm (comp, auid);
+ }
+ cal_obj_uid_list_free (list);
+
+ /* Add the new alarms */
+
+ clist = GTK_CLIST (priv->list);
+ for (i = 0; i < clist->rows; i++) {
+ CalComponentAlarm *alarm, *alarm_copy;
+
+ alarm = gtk_clist_get_row_data (clist, i);
+ g_assert (alarm != NULL);
+
+ /* We clone the alarm to maintain the invariant that the alarm
+ * structures in the list did *not* come from the component.
+ */
+
+ alarm_copy = cal_component_alarm_clone (alarm);
+ cal_component_add_alarm (comp, alarm);
+ cal_component_alarm_free (alarm_copy);
+ }
+}
+
+/* set_summary handler for the alarm page */
+static void
+alarm_page_set_summary (EditorPage *page, const char *summary)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+
+ apage = ALARM_PAGE (page);
+ priv = apage->priv;
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->summary), apage);
+ e_utf8_gtk_entry_set_text (GTK_ENTRY (priv->summary), summary);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->summary), apage);
+}
+
+/* get_summary handler for the alarm page */
+static char *
+alarm_page_get_summary (EditorPage *page)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+
+ apage = ALARM_PAGE (page);
+ priv = apage->priv;
+
+ return e_utf8_gtk_entry_get_text (GTK_ENTRY (priv->summary));
+}
+
+/* set_dtstart handler for the alarm page */
+static void
+alarm_page_set_dtstart (EditorPage *page, time_t start)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+ char str[128];
+ struct tm tm;
+
+ apage = ALARM_PAGE (page);
+ priv = apage->priv;
+
+ tm = *localtime (&start);
+ strftime (str, sizeof (str), _("%A %b %d %Y %H:%M:%S"), &tm);
+
+ gtk_entry_set_text (GTK_ENTRY (priv->starting_date), str);
+}
+
+
+
+/* "relative" types */
+enum {
+ BEFORE,
+ AFTER
+};
+
+/* Time units */
+enum {
+ MINUTES,
+ HOURS,
+ DAYS
+};
+
+/* Option menu maps */
+static const int action_map[] = {
+ CAL_ALARM_DISPLAY,
+ CAL_ALARM_AUDIO,
+ CAL_ALARM_EMAIL,
+ CAL_ALARM_PROCEDURE,
+ -1
+};
+
+static const int value_map[] = {
+ MINUTES,
+ HOURS,
+ DAYS,
+ -1
+};
+
+static const int relative_map[] = {
+ BEFORE,
+ AFTER,
+ -1
+};
+
+static const int time_map[] = {
+ CAL_ALARM_TRIGGER_RELATIVE_START,
+ CAL_ALARM_TRIGGER_RELATIVE_END,
+ -1
+};
+
+/* Gets the widgets from the XML file and returns if they are all available. */
+static gboolean
+get_widgets (AlarmPage *apage)
+{
+ AlarmPagePrivate *priv;
+ GtkWidget *toplevel;
+
+ priv = apage->priv;
+
+#define GW(name) glade_xml_get_widget (priv->xml, name)
+
+ toplevel = GW ("alarm-toplevel");
+ priv->main = GW ("alarm-page");
+ if (!(toplevel && priv->main))
+ return FALSE;
+
+ 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->list = GW ("list");
+ priv->add = GW ("add");
+ priv->delete = GW ("delete");
+
+ priv->action = GW ("action");
+ priv->interval_value = GW ("interval-value");
+ priv->value_units = GW ("value-units");
+ priv->relative = GW ("relative");
+ priv->time = GW ("time");
+
+#undef GW
+
+ return (priv->summary
+ && priv->starting_date
+ && priv->list
+ && priv->add
+ && priv->delete
+ && priv->action
+ && priv->interval_value
+ && priv->value_units
+ && priv->relative
+ && priv->time);
+}
+
+/* Callback used when the summary changes; we emit the notification signal. */
+static void
+summary_changed_cb (GtkEditable *editable, gpointer data)
+{
+ AlarmPage *apage;
+
+ apage = ALARM_PAGE (data);
+ editor_page_notify_summary_changed (EDITOR_PAGE (apage));
+}
+
+/* This is called when any field is changed; it notifies upstream. */
+static void
+field_changed_cb (GtkWidget *widget, gpointer data)
+{
+ AlarmPage *apage;
+
+ apage = ALARM_PAGE (data);
+ editor_page_notify_changed (EDITOR_PAGE (apage));
+}
+
+/* Callback used for the "add reminder" button */
+static void
+add_clicked_cb (GtkButton *button, gpointer data)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+ CalComponentAlarm *alarm;
+ CalAlarmTrigger trigger;
+
+ apage = ALARM_PAGE (data);
+ priv = apage->priv;
+
+ alarm = cal_component_alarm_new ();
+
+ memset (&trigger, 0, sizeof (CalAlarmTrigger));
+ trigger.type = e_dialog_option_menu_get (priv->time, time_map);
+ if (e_dialog_option_menu_get (priv->relative, relative_map) == BEFORE)
+ trigger.u.rel_duration.is_neg = 1;
+ else
+ trigger.u.rel_duration.is_neg = 0;
+
+ switch (e_dialog_option_menu_get (priv->value_units, value_map)) {
+ case MINUTES:
+ trigger.u.rel_duration.minutes = e_dialog_spin_get_int (priv->interval_value);
+ break;
+
+ case HOURS:
+ trigger.u.rel_duration.hours = e_dialog_spin_get_int (priv->interval_value);
+ break;
+
+ case DAYS:
+ trigger.u.rel_duration.days = e_dialog_spin_get_int (priv->interval_value);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ cal_component_alarm_set_trigger (alarm, trigger);
+
+ cal_component_alarm_set_action (alarm, e_dialog_option_menu_get (priv->action, action_map));
+
+ append_reminder (apage, alarm);
+}
+
+/* Callback used for the "delete reminder" button */
+static void
+delete_clicked_cb (GtkButton *button, gpointer data)
+{
+ AlarmPage *apage;
+ AlarmPagePrivate *priv;
+ GtkCList *clist;
+ CalComponentAlarm *alarm;
+ int sel;
+
+ apage = ALARM_PAGE (data);
+ priv = apage->priv;
+
+ clist = GTK_CLIST (priv->list);
+ if (!clist->selection)
+ return;
+
+ sel = GPOINTER_TO_INT (clist->selection->data);
+
+ alarm = gtk_clist_get_row_data (clist, sel);
+ g_assert (alarm != NULL);
+ cal_component_alarm_free (alarm);
+ gtk_clist_set_row_data (clist, sel, NULL);
+
+ 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->delete, FALSE);
+}
+
+/* Hooks the widget signals */
+static void
+init_widgets (AlarmPage *apage)
+{
+ AlarmPagePrivate *priv;
+
+ priv = apage->priv;
+
+ /* Summary */
+ gtk_signal_connect (GTK_OBJECT (priv->summary), "changed",
+ GTK_SIGNAL_FUNC (summary_changed_cb), apage);
+
+ /* Reminder buttons */
+ gtk_signal_connect (GTK_OBJECT (priv->add), "clicked",
+ GTK_SIGNAL_FUNC (add_clicked_cb), apage);
+ gtk_signal_connect (GTK_OBJECT (priv->delete), "clicked",
+ GTK_SIGNAL_FUNC (delete_clicked_cb), apage);
+
+ /* Connect the default signal handler to use to make sure we notify
+ * upstream of changes to the widget values.
+ */
+ gtk_signal_connect (GTK_OBJECT (priv->add), "clicked",
+ GTK_SIGNAL_FUNC (field_changed_cb), apage);
+ gtk_signal_connect (GTK_OBJECT (priv->delete), "clicked",
+ GTK_SIGNAL_FUNC (field_changed_cb), apage);
+}
+
+
+
+/**
+ * alarm_page_construct:
+ * @apage: An alarm page.
+ *
+ * Constructs an alarm page by loading its Glade data.
+ *
+ * Return value: The same object as @apage, or NULL if the widgets could not be
+ * created.
+ **/
+AlarmPage *
+alarm_page_construct (AlarmPage *apage)
+{
+ AlarmPagePrivate *priv;
+
+ priv = apage->priv;
+
+ priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/alarm-page.glade", NULL);
+ if (!priv->xml) {
+ g_message ("alarm_page_construct(): Could not load the Glade XML file!");
+ return NULL;
+ }
+
+ if (!get_widgets (apage)) {
+ g_message ("alarm_page_construct(): Could not find all widgets in the XML file!");
+ return NULL;
+ }
+
+ init_widgets (apage);
+
+ return apage;
+}
+
+/**
+ * alarm_page_new:
+ *
+ * Creates a new alarm page.
+ *
+ * Return value: A newly-created alarm page, or NULL if the page could not be
+ * created.
+ **/
+AlarmPage *
+alarm_page_new (void)
+{
+ AlarmPage *apage;
+
+ apage = gtk_type_new (TYPE_ALARM_PAGE);
+ if (!alarm_page_construct (apage)) {
+ gtk_object_unref (GTK_OBJECT (apage));
+ return NULL;
+ }
+
+ return apage;
+}
diff --git a/calendar/gui/dialogs/alarm-page.glade b/calendar/gui/dialogs/alarm-page.glade
new file mode 100644
index 0000000000..3a4a8d6765
--- /dev/null
+++ b/calendar/gui/dialogs/alarm-page.glade
@@ -0,0 +1,381 @@
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>alarm-page</name>
+ <program_name>alarm-page</program_name>
+ <directory></directory>
+ <source_directory>.</source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>True</gnome_support>
+ <gettext_support>True</gettext_support>
+ <output_main_file>False</output_main_file>
+ <output_support_files>False</output_support_files>
+ <output_build_files>False</output_build_files>
+</project>
+
+<widget>
+ <class>GtkWindow</class>
+ <name>alarm-toplevel</name>
+ <title>window1</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>alarm-page</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame33</name>
+ <label>Appointment Basics</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table13</name>
+ <border_width>4</border_width>
+ <rows>2</rows>
+ <columns>2</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>2</row_spacing>
+ <column_spacing>2</column_spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label62</name>
+ <label>Su_mmary:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <default_focus_target>reminder-summary</default_focus_target>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>reminder-summary</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>True</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label63</name>
+ <label>_Starting date:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>starting date</name>
+ <label>assbarn it</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame34</name>
+ <label>Reminders</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox53</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox54</name>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkOptionMenu</class>
+ <name>reminder-action</name>
+ <can_focus>True</can_focus>
+ <items>Show a dialog
+Play a sound
+Send an email
+Run a program
+</items>
+ <initial_choice>0</initial_choice>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>reminder-interval-value</name>
+ <can_focus>True</can_focus>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>True</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1</value>
+ <lower>0</lower>
+ <upper>100</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkOptionMenu</class>
+ <name>reminder-value-units</name>
+ <can_focus>True</can_focus>
+ <items>minute(s)
+hour(s)
+day(s)
+</items>
+ <initial_choice>0</initial_choice>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkOptionMenu</class>
+ <name>reminder-relative</name>
+ <can_focus>True</can_focus>
+ <items>before
+after
+</items>
+ <initial_choice>0</initial_choice>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkOptionMenu</class>
+ <name>reminder-time</name>
+ <can_focus>True</can_focus>
+ <items>start of appointment
+end of appointment
+</items>
+ <initial_choice>0</initial_choice>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>button9</name>
+ <can_focus>True</can_focus>
+ <label>Settings...</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox55</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow13</name>
+ <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkCList</class>
+ <name>reminder-list</name>
+ <can_focus>True</can_focus>
+ <columns>1</columns>
+ <column_widths>80</column_widths>
+ <selection_mode>GTK_SELECTION_BROWSE</selection_mode>
+ <show_titles>False</show_titles>
+ <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>label64</name>
+ <label>label55</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVButtonBox</class>
+ <name>vbuttonbox2</name>
+ <layout_style>GTK_BUTTONBOX_START</layout_style>
+ <spacing>10</spacing>
+ <child_min_width>85</child_min_width>
+ <child_min_height>27</child_min_height>
+ <child_ipad_x>7</child_ipad_x>
+ <child_ipad_y>0</child_ipad_y>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>reminder-add</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <label>Add</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>reminder-delete</name>
+ <can_default>True</can_default>
+ <can_focus>True</can_focus>
+ <label>Delete</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
diff --git a/calendar/gui/dialogs/alarm-page.h b/calendar/gui/dialogs/alarm-page.h
new file mode 100644
index 0000000000..1cb0b301bd
--- /dev/null
+++ b/calendar/gui/dialogs/alarm-page.h
@@ -0,0 +1,64 @@
+/* Evolution calendar - Alarm 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.
+ */
+
+#ifndef ALARM_PAGE_H
+#define ALARM_PAGE_H
+
+#include "editor-page.h"
+
+BEGIN_GNOME_DECLS
+
+
+
+#define TYPE_ALARM_PAGE (alarm_page_get_type ())
+#define ALARM_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_ALARM_PAGE, AlarmPage))
+#define ALARM_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_ALARM_PAGE, \
+ AlarmPageClass))
+#define IS_ALARM_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_ALARM_PAGE))
+#define IS_ALARM_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_ALARM_PAGE))
+
+typedef struct _AlarmPagePrivate AlarmPagePrivate;
+
+typedef struct {
+ EditorPage page;
+
+ /* Private data */
+ AlarmPagePrivate *priv;
+} AlarmPage;
+
+typedef struct {
+ EditorPageClass parent_class;
+} AlarmPageClass;
+
+GtkType alarm_page_get_type (void);
+
+AlarmPage *alarm_page_construct (AlarmPage *apage);
+
+AlarmPage *alarm_page_new (void);
+
+
+
+END_GNOME_DECLS
+
+#endif
diff --git a/calendar/gui/dialogs/editor-page.c b/calendar/gui/dialogs/editor-page.c
new file mode 100644
index 0000000000..b46b247191
--- /dev/null
+++ b/calendar/gui/dialogs/editor-page.c
@@ -0,0 +1,259 @@
+/* Evolution calendar - Base class for calendar component editor pages
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Authors: Federico Mena-Quintero <federico@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 "editor-page.h"
+
+
+
+static void editor_page_class_init (EditorPageClass *class);
+
+/* Signal IDs */
+
+enum {
+ CHANGED,
+ SUMMARY_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint editor_page_signals[LAST_SIGNAL];
+
+#define CLASS(page) (EDITOR_PAGE_CLASS (GTK_OBJECT (page)->klass))
+
+
+
+/**
+ * editor_page_get_type:
+ *
+ * Registers the #EditorPage class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #EditorPage class.
+ **/
+GtkType
+editor_page_get_type (void)
+{
+ static GtkType editor_page_type = 0;
+
+ if (!editor_page_type) {
+ static const GtkTypeInfo editor_page_info = {
+ "EditorPage",
+ sizeof (EditorPage),
+ sizeof (EditorPageClass),
+ (GtkClassInitFunc) editor_page_class_init,
+ (GtkObjectInitFunc) NULL,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ editor_page_type = gtk_type_unique (GTK_TYPE_OBJECT, &editor_page_info);
+ }
+
+ return editor_page_type;
+}
+
+/* Class initialization function for the abstract editor page */
+static void
+editor_page_class_init (EditorPageClass *class)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass *) class;
+
+ editor_page_signals[CHANGED] =
+ gtk_signal_new ("changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EditorPageClass, changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ editor_page_signals[SUMMARY_CHANGED] =
+ gtk_signal_new ("summary_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EditorPageClass, summary_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, editor_page_signals, LAST_SIGNAL);
+
+ class->changed = NULL;
+ class->summary_changed = NULL;
+
+ class->get_widget = NULL;
+ class->fill_widgets = NULL;
+ class->fill_component = NULL;
+ class->set_summary = NULL;
+ class->get_summary = NULL;
+ class->set_dtstart = NULL;
+}
+
+
+
+/**
+ * editor_page_get_widget:
+ * @page: An editor page.
+ *
+ * Queries the main widget of an editor page.
+ *
+ * Return value: The widget that is the page's upper container. It should
+ * normally be inserted in a notebook widget.
+ **/
+GtkWidget *
+editor_page_get_widget (EditorPage *page)
+{
+ g_return_val_if_fail (page != NULL, NULL);
+ g_return_val_if_fail (IS_EDITOR_PAGE (page), NULL);
+
+ g_assert (CLASS (page)->get_widget != NULL);
+ return (* CLASS (page)->get_widget) (page);
+}
+
+/**
+ * editor_page_fill_widgets:
+ * @page: An editor page.
+ * @comp: A calendar component.
+ *
+ * Fills the widgets of an editor page with the data from a calendar component.
+ **/
+void
+editor_page_fill_widgets (EditorPage *page, CalComponent *comp)
+{
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_EDITOR_PAGE (page));
+ g_return_if_fail (comp != NULL);
+
+ g_assert (CLASS (page)->fill_widgets != NULL);
+ (* CLASS (page)->fill_widgets) (page, comp);
+}
+
+/**
+ * editor_page_fill_component:
+ * @page: An editor page.
+ * @comp: A calendar component.
+ *
+ * Takes the data from the widgets of an editor page and sets it on a calendar
+ * component, replacing the contents of the properties that the editor page
+ * knows how to manipulate.
+ **/
+void
+editor_page_fill_component (EditorPage *page, CalComponent *comp)
+{
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_EDITOR_PAGE (page));
+ g_return_if_fail (comp != NULL);
+
+ g_assert (CLASS (page)->fill_component != NULL);
+ (* CLASS (page)->fill_component) (page, comp);
+}
+
+/**
+ * editor_page_set_summary:
+ * @page: An editor page.
+ * @summary: Summary string to set in the page's widgets, which must be encoded
+ * in UTF8.
+ *
+ * Sets the calendar component summary string in an editor page.
+ **/
+void
+editor_page_set_summary (EditorPage *page, const char *summary)
+{
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_EDITOR_PAGE (page));
+ g_return_if_fail (summary != NULL);
+
+ g_assert (CLASS (page)->set_summary != NULL);
+ (* CLASS (page)->set_summary) (page, summary);
+}
+
+/**
+ * editor_page_get_summary:
+ * @page: An editor page.
+ *
+ * Queries the current summary string in an editor page.
+ *
+ * Return value: Summary string in UTF8; must be freed by the caller.
+ **/
+char *
+editor_page_get_summary (EditorPage *page)
+{
+ g_return_val_if_fail (page != NULL, NULL);
+ g_return_val_if_fail (IS_EDITOR_PAGE (page), NULL);
+
+ g_assert (CLASS (page)->get_summary != NULL);
+ return (* CLASS (page)->get_summary) (page);
+}
+
+/**
+ * editor_page_set_dtstart:
+ * @page: An editor page.
+ * @start: Start date for calendar component.
+ *
+ * Sets the calendar component DTSTART in an editor page.
+ **/
+void
+editor_page_set_dtstart (EditorPage *page, time_t start)
+{
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_EDITOR_PAGE (page));
+ g_return_if_fail (start != -1);
+
+ g_assert (CLASS (page)->set_dtstart != NULL);
+ (* CLASS (page)->set_dtstart) (page, start);
+}
+
+/**
+ * editor_page_notify_changed:
+ * @page: An editor page.
+ *
+ * Makes an editor page emit the "changed" signal. This is meant to be
+ * used only by page implementations.
+ **/
+void
+editor_page_notify_changed (EditorPage *page)
+{
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_EDITOR_PAGE (page));
+
+ gtk_signal_emit (GTK_OBJECT (page), editor_page_signals[CHANGED]);
+}
+
+/**
+ * editor_page_notify_summary_changed:
+ * @page: An editor page.
+ *
+ * Makes an editor page emit the "summary_changed" signal. This is meant to be
+ * used only by page implementations.
+ **/
+void
+editor_page_notify_summary_changed (EditorPage *page)
+{
+ g_return_if_fail (page != NULL);
+ g_return_if_fail (IS_EDITOR_PAGE (page));
+
+ gtk_signal_emit (GTK_OBJECT (page), editor_page_signals[SUMMARY_CHANGED]);
+}
diff --git a/calendar/gui/dialogs/editor-page.h b/calendar/gui/dialogs/editor-page.h
new file mode 100644
index 0000000000..3f9587c9de
--- /dev/null
+++ b/calendar/gui/dialogs/editor-page.h
@@ -0,0 +1,86 @@
+/* Evolution calendar - Base class for calendar component editor pages
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Authors: Federico Mena-Quintero <federico@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.
+ */
+
+#ifndef EDITOR_PAGE_H
+#define EDITOR_PAGE_H
+
+#include <time.h>
+#include <libgnome/gnome-defs.h>
+#include <gtk/gtkwidget.h>
+#include <cal-util/cal-component.h>
+
+BEGIN_GNOME_DECLS
+
+
+
+#define TYPE_EDITOR_PAGE (editor_page_get_type ())
+#define EDITOR_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_EDITOR_PAGE, EditorPage))
+#define EDITOR_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_EDITOR_PAGE, \
+ EditorPageClass))
+#define IS_EDITOR_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_EDITOR_PAGE))
+#define IS_EDITOR_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_EDITOR_PAGE))
+
+typedef struct {
+ GtkObject object;
+} EditorPage;
+
+typedef struct {
+ GtkObjectClass parent_class;
+
+ /* Notification signals */
+
+ void (* changed) (EditorPage *page);
+ void (* summary_changed) (EditorPage *page);
+ void (* dtstart_changed) (EditorPage *page);
+
+ /* Virtual methods */
+
+ GtkWidget *(* get_widget) (EditorPage *page);
+
+ void (* fill_widgets) (EditorPage *page, CalComponent *comp);
+ void (* fill_component) (EditorPage *page, CalComponent *comp);
+
+ void (* set_summary) (EditorPage *page, const char *summary);
+ char *(* get_summary) (EditorPage *page);
+
+ void (* set_dtstart) (EditorPage *page, time_t start);
+} EditorPageClass;
+
+GtkType editor_page_get_type (void);
+
+GtkWidget *editor_page_get_widget (EditorPage *page);
+
+void editor_page_fill_widgets (EditorPage *page, CalComponent *comp);
+void editor_page_fill_component (EditorPage *page, CalComponent *comp);
+
+void editor_page_set_summary (EditorPage *page, const char *summary);
+char *editor_page_get_summary (EditorPage *page);
+
+void editor_page_set_dtstart (EditorPage *page, time_t start);
+
+void editor_page_notify_changed (EditorPage *page);
+void editor_page_notify_summary_changed (EditorPage *page);
+
+
+
+END_GNOME_DECLS
+
+#endif
diff --git a/calendar/gui/dialogs/event-page.c b/calendar/gui/dialogs/event-page.c
new file mode 100644
index 0000000000..f67b898dce
--- /dev/null
+++ b/calendar/gui/dialogs/event-page.c
@@ -0,0 +1,908 @@
+/* Evolution calendar - Main page of the event editor dialog
+ *
+ * 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 <gtk/gtktogglebutton.h>
+#include <glade/glade.h>
+#include <gal/widgets/e-unicode.h>
+#include <gal/widgets/e-categories.h>
+#include "cal-util/timeutil.h"
+#include "e-util/e-dialog-widgets.h"
+#include "widgets/misc/e-dateedit.h"
+#include "../calendar-config.h"
+#include "event-page.h"
+
+
+
+/* Private part of the EventPage structure */
+struct _EventPagePrivate {
+ /* Glade XML data */
+ GladeXML *xml;
+
+ /* Widgets from the Glade file */
+
+ GtkWidget *main;
+
+ GtkWidget *summary;
+
+ GtkWidget *start_time;
+ GtkWidget *end_time;
+ GtkWidget *all_day_event;
+
+ GtkWidget *description;
+
+ GtkWidget *classification_public;
+ GtkWidget *classification_private;
+ GtkWidget *classification_confidential;
+
+ GtkWidget *contacts_btn;
+ GtkWidget *contacts;
+
+ GtkWidget *categories_btn;
+ GtkWidget *categories;
+};
+
+
+
+static void event_page_class_init (EventPageClass *class);
+static void event_page_init (EventPage *epage);
+static void event_page_destroy (GtkObject *object);
+
+static GtkWidget *event_page_get_widget (EditorPage *page);
+static void event_page_fill_widgets (EditorPage *page, CalComponent *comp);
+static void event_page_fill_component (EditorPage *page, CalComponent *comp);
+static void event_page_set_summary (EditorPage *page, const char *summary);
+static char *event_page_get_summary (EditorPage *page);
+static void event_page_set_dtstart (EditorPage *page, time_t start);
+
+/* Signal IDs */
+enum {
+ DATES_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint event_page_signals[LAST_SIGNAL] = { 0 };
+
+static EditorPageClass *parent_class = NULL;
+
+
+
+/**
+ * event_page_get_type:
+ *
+ * Registers the #EventPage class if necessary, and returns the type ID
+ * associated to it.
+ *
+ * Return value: The type ID of the #EventPage class.
+ **/
+GtkType
+event_page_get_type (void)
+{
+ static GtkType event_page_type;
+
+ if (!event_page_type) {
+ static const GtkTypeInfo event_page_info = {
+ "EventPage",
+ sizeof (EventPage),
+ sizeof (EventPageClass),
+ (GtkClassInitFunc) event_page_class_init,
+ (GtkObjectInitFunc) event_page_init,
+ NULL, /* reserved_1 */
+ NULL, /* reserved_2 */
+ (GtkClassInitFunc) NULL
+ };
+
+ event_page_type = gtk_type_unique (TYPE_EDITOR_PAGE, &event_page_info);
+ }
+
+ return event_page_type;
+}
+
+/* Class initialization function for the event page */
+static void
+event_page_class_init (EventPageClass *class)
+{
+ EditorPageClass *editor_page_class;
+ GtkObjectClass *object_class;
+
+ editor_page_class = (EditorPageClass *) class;
+ object_class = (GtkObjectClass *) class;
+
+ parent_class = gtk_type_class (TYPE_EDITOR_PAGE);
+
+ event_page_signals[DATES_CHANGED] =
+ gtk_signal_new ("dates_changed",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (EventPageClass, dates_changed),
+ gtk_marshal_NONE__NONE,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, event_page_signals, LAST_SIGNAL);
+
+ class->dates_changed = NULL;
+
+ editor_page_class->get_widget = event_page_get_widget;
+ editor_page_class->fill_widgets = event_page_fill_widgets;
+ editor_page_class->fill_component = event_page_fill_component;
+ editor_page_class->set_summary = event_page_set_summary;
+ editor_page_class->get_summary = event_page_get_summary;
+ editor_page_class->set_dtstart = event_page_set_dtstart;
+
+ object_class->destroy = event_page_destroy;
+}
+
+/* Object initialization function for the event page */
+static void
+event_page_init (EventPage *epage)
+{
+ EventPagePrivate *priv;
+
+ priv = g_new0 (EventPagePrivate, 1);
+ epage->priv = priv;
+
+ priv->xml = NULL;
+
+ priv->main = NULL;
+ priv->summary = NULL;
+ priv->start_time = NULL;
+ priv->end_time = NULL;
+ priv->all_day_event = NULL;
+ priv->description = NULL;
+ priv->classification_public = NULL;
+ priv->classification_private = NULL;
+ priv->classification_confidential = NULL;
+ priv->contacts_btn = NULL;
+ priv->contacts = NULL;
+ priv->categories_btn = NULL;
+ priv->categories = NULL;
+}
+
+/* Destroy handler for the event page */
+static void
+event_page_destroy (GtkObject *object)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (IS_EVENT_PAGE (object));
+
+ epage = EVENT_PAGE (object);
+ priv = epage->priv;
+
+ if (priv->xml) {
+ gtk_object_unref (GTK_OBJECT (priv->xml));
+ priv->xml = NULL;
+ }
+
+ g_free (priv);
+ epage->priv = NULL;
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+
+static const int classification_map[] = {
+ CAL_COMPONENT_CLASS_PUBLIC,
+ CAL_COMPONENT_CLASS_PRIVATE,
+ CAL_COMPONENT_CLASS_CONFIDENTIAL,
+ -1
+};
+
+/* get_widget handler for the event page */
+static GtkWidget *
+event_page_get_widget (EditorPage *page)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+
+ epage = EVENT_PAGE (page);
+ priv = epage->priv;
+
+ return priv->main;
+}
+
+/* Checks if the event's time starts and ends at midnight, and sets the "all day
+ * event" box accordingly.
+ */
+static void
+check_all_day (EventPage *epage)
+{
+ EventPagePrivate *priv;
+ time_t ev_start, ev_end;
+ gboolean all_day = FALSE;
+
+ priv = epage->priv;
+
+ /* Currently we just return if the date is not set or not valid.
+ I'm not entirely sure this is the corrent thing to do. */
+ ev_start = e_date_edit_get_time (E_DATE_EDIT (priv->start_time));
+ g_assert (ev_start != -1);
+
+ ev_end = e_date_edit_get_time (E_DATE_EDIT (priv->end_time));
+ g_assert (ev_end != -1);
+
+ /* all day event checkbox */
+ if (time_day_begin (ev_start) == ev_start && time_day_begin (ev_end) == ev_end)
+ all_day = TRUE;
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->all_day_event), epage);
+ e_dialog_toggle_set (priv->all_day_event, all_day);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->all_day_event), epage);
+
+ e_date_edit_set_show_time (E_DATE_EDIT (priv->start_time), !all_day);
+ e_date_edit_set_show_time (E_DATE_EDIT (priv->end_time), !all_day);
+}
+
+/* Fills the widgets with default values */
+static void
+clear_widgets (EventPage *epage)
+{
+ EventPagePrivate *priv;
+ time_t now;
+
+ priv = epage->priv;
+
+ now = time (NULL);
+
+ /* Summary, description */
+ e_dialog_editable_set (priv->summary, NULL);
+ e_dialog_editable_set (priv->description, NULL);
+
+ /* Start and end times */
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), epage);
+
+ e_date_edit_set_time (E_DATE_EDIT (priv->start_time), now);
+ e_date_edit_set_time (E_DATE_EDIT (priv->end_time), now);
+
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), epage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage);
+
+ check_all_day (epage);
+
+ /* Classification */
+ e_dialog_radio_set (priv->classification_public,
+ CAL_COMPONENT_CLASS_PRIVATE, classification_map);
+
+ /* Categories */
+ e_dialog_editable_set (priv->categories, NULL);
+}
+
+/* fill_widgets handler for the event page */
+static void
+event_page_fill_widgets (EditorPage *page, CalComponent *comp)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+ CalComponentText text;
+ CalComponentClassification cl;
+ CalComponentDateTime d;
+ GSList *l;
+ time_t dtstart, dtend;
+ const char *categories;
+
+ epage = EVENT_PAGE (page);
+ priv = epage->priv;
+
+ clear_widgets (epage);
+
+ /* Summary, description(s) */
+
+ cal_component_get_summary (comp, &text);
+ e_dialog_editable_set (priv->summary, text.value);
+
+ cal_component_get_description_list (comp, &l);
+ if (l) {
+ text = *(CalComponentText *)l->data;
+ e_dialog_editable_set (priv->description, text.value);
+ }
+ cal_component_free_text_list (l);
+
+ /* Start and end times */
+
+ /* All-day events are inclusive, i.e. if the end date shown is 2nd Feb
+ then the event includes all of the 2nd Feb. We would normally show
+ 3rd Feb as the end date, since it really ends at midnight on 3rd,
+ so we have to subtract a day so we only show the 2nd. */
+ cal_component_get_dtstart (comp, &d);
+ dtstart = icaltime_as_timet (*d.value);
+ cal_component_free_datetime (&d);
+
+ cal_component_get_dtend (comp, &d);
+ dtend = icaltime_as_timet (*d.value);
+ cal_component_free_datetime (&d);
+
+ if (time_day_begin (dtstart) == dtstart && time_day_begin (dtend) == dtend)
+ dtend = time_add_day (dtend, -1);
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), epage);
+
+ e_date_edit_set_time (E_DATE_EDIT (priv->start_time), dtstart);
+ e_date_edit_set_time (E_DATE_EDIT (priv->end_time), dtend);
+
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), epage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage);
+
+ check_all_day (epage);
+
+ /* Classification */
+
+ cal_component_get_classification (comp, &cl);
+
+ switch (cl) {
+ case CAL_COMPONENT_CLASS_PUBLIC:
+ e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_PUBLIC,
+ classification_map);
+ break;
+
+ case CAL_COMPONENT_CLASS_PRIVATE:
+ e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_PRIVATE,
+ classification_map);
+ break;
+
+ case CAL_COMPONENT_CLASS_CONFIDENTIAL:
+ e_dialog_radio_set (priv->classification_public, CAL_COMPONENT_CLASS_CONFIDENTIAL,
+ classification_map);
+ break;
+
+ default:
+ /* What do do? We can't g_assert_not_reached() since it is a
+ * value from an external file.
+ */
+ }
+
+ /* Categories */
+
+ cal_component_get_categories (comp, &categories);
+ e_dialog_editable_set (priv->categories, categories);
+}
+
+/* fill_component handler for the event page */
+static void
+event_page_fill_component (EditorPage *page, CalComponent *comp)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+ CalComponentDateTime date;
+ struct icaltimetype icaltime;
+ time_t t;
+ gboolean all_day_event;
+ char *cat, *str;
+ CalComponentClassification classif;
+
+ epage = EVENT_PAGE (page);
+ priv = epage->priv;
+
+ /* Summary */
+
+ str = e_dialog_editable_get (priv->summary);
+ if (!str || strlen (str) == 0)
+ cal_component_set_summary (comp, NULL);
+ else {
+ CalComponentText text;
+
+ text.value = str;
+ text.altrep = NULL;
+
+ cal_component_set_summary (comp, &text);
+ }
+
+ if (str)
+ g_free (str);
+
+ /* Description */
+
+ str = e_dialog_editable_get (priv->description);
+ if (!str || strlen (str) == 0)
+ cal_component_set_description_list (comp, NULL);
+ else {
+ GSList l;
+ CalComponentText text;
+
+ text.value = str;
+ text.altrep = NULL;
+ l.data = &text;
+ l.next = NULL;
+
+ cal_component_set_description_list (comp, &l);
+ }
+
+ if (str)
+ g_free (str);
+
+ /* Dates */
+
+ date.value = &icaltime;
+ date.tzid = NULL;
+
+ t = e_date_edit_get_time (E_DATE_EDIT (priv->start_time));
+ if (t != -1) {
+ *date.value = icaltime_from_timet (t, FALSE);
+ cal_component_set_dtstart (comp, &date);
+ } else {
+ /* FIXME: What do we do here? */
+ }
+
+ /* If the all_day toggle is set, the end date is inclusive of the
+ entire day on which it points to. */
+ all_day_event = e_dialog_toggle_get (priv->all_day_event);
+ t = e_date_edit_get_time (E_DATE_EDIT (priv->end_time));
+ if (t != -1) {
+ if (all_day_event)
+ t = time_day_end (t);
+
+ *date.value = icaltime_from_timet (t, FALSE);
+ cal_component_set_dtend (comp, &date);
+ } else {
+ /* FIXME: What do we do here? */
+ }
+
+ /* Categories */
+
+ cat = e_dialog_editable_get (priv->categories);
+ cal_component_set_categories (comp, cat);
+
+ if (cat)
+ g_free (cat);
+
+ /* Classification */
+
+ classif = e_dialog_radio_get (priv->classification_public, classification_map);
+ cal_component_set_classification (comp, classif);
+}
+
+/* set_summary handler for the event page */
+static void
+event_page_set_summary (EditorPage *page, const char *summary)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+
+ epage = EVENT_PAGE (page);
+ priv = epage->priv;
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->summary), epage);
+ e_utf8_gtk_entry_set_text (GTK_ENTRY (priv->summary), summary);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->summary), epage);
+}
+
+/* get_summary handler for the event page */
+static char *
+event_page_get_summary (EditorPage *page)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+
+ epage = EVENT_PAGE (page);
+ priv = epage->priv;
+
+ return e_utf8_gtk_entry_get_text (GTK_ENTRY (priv->summary));
+}
+
+/* set_dtstart handler for the event page. We do nothing since we are *the*
+ * only provider of the dtstart value.
+ */
+static void
+event_page_set_dtstart (EditorPage *page, time_t start)
+{
+ /* nothing */
+}
+
+
+
+/* Gets the widgets from the XML file and returns if they are all available. */
+static gboolean
+get_widgets (EventPage *epage)
+{
+ EventPagePrivate *priv;
+ GtkWidget *toplevel;
+
+ priv = epage->priv;
+
+#define GW(name) glade_xml_get_widget (priv->xml, name)
+
+ toplevel = GW ("event-toplevel");
+ priv->main = GW ("event-page");
+ if (!(toplevel && priv->main))
+ return FALSE;
+
+ gtk_widget_ref (priv->main);
+ gtk_widget_unparent (priv->main);
+ gtk_widget_destroy (toplevel);
+
+ priv->summary = GW ("summary");
+
+ priv->start_time = GW ("start-time");
+ priv->end_time = GW ("end-time");
+ priv->all_day_event = GW ("all-day-event");
+
+ priv->description = GW ("description");
+
+ priv->classification_public = GW ("classification-public");
+ priv->classification_private = GW ("classification-private");
+ priv->classification_confidential = GW ("classification-confidential");
+
+ priv->contacts_btn = GW ("contacts-button");
+ priv->contacts = GW ("contacts");
+
+ priv->categories_btn = GW ("categories-button");
+ priv->categories = GW ("categories");
+
+#undef GW
+
+ return (priv->summary
+ && priv->start_time
+ && priv->end_time
+ && priv->all_day_event
+ && priv->description
+ && priv->classification_public
+ && priv->classification_private
+ && priv->classification_confidential
+ && priv->contacts_btn
+ && priv->contacts
+ && priv->categories_btn
+ && priv->categories);
+}
+
+/* Callback used when the summary changes; we emit the notification signal. */
+static void
+summary_changed_cb (GtkEditable *editable, gpointer data)
+{
+ EventPage *epage;
+
+ epage = EVENT_PAGE (data);
+ editor_page_notify_summary_changed (EDITOR_PAGE (epage));
+}
+
+/* Callback used when the start or end date widgets change. We check that the
+ * start date < end date and we set the "all day event" button as appropriate.
+ */
+static void
+date_changed_cb (EDateEdit *dedit, gpointer data)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+ time_t start, end;
+ struct tm tm_start, tm_end;
+
+ epage = EVENT_PAGE (data);
+ priv = epage->priv;
+
+ /* Ensure that start < end */
+
+ start = e_date_edit_get_time (E_DATE_EDIT (priv->start_time));
+ g_assert (start != -1);
+ end = e_date_edit_get_time (E_DATE_EDIT (priv->end_time));
+ g_assert (end != -1);
+
+ if (start >= end) {
+ tm_start = *localtime (&start);
+ tm_end = *localtime (&end);
+
+ if (start == end && tm_start.tm_hour == 0
+ && tm_start.tm_min == 0 && tm_start.tm_sec == 0) {
+ /* If the start and end times are the same, but both are
+ * on day boundaries, then that is OK since it means we
+ * have an all-day event lasting 1 day. So we do
+ * nothing here.
+ */
+ } else if (GTK_WIDGET (dedit) == priv->start_time) {
+ /* Modify the end time */
+
+ tm_end.tm_year = tm_start.tm_year;
+ tm_end.tm_mon = tm_start.tm_mon;
+ tm_end.tm_mday = tm_start.tm_mday;
+ tm_end.tm_hour = tm_start.tm_hour + 1;
+ tm_end.tm_min = tm_start.tm_min;
+ tm_end.tm_sec = tm_start.tm_sec;
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), epage);
+ e_date_edit_set_time (E_DATE_EDIT (priv->end_time), mktime (&tm_end));
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage);
+ } else if (GTK_WIDGET (dedit) == priv->end_time) {
+ /* Modify the start time */
+
+ tm_start.tm_year = tm_end.tm_year;
+ tm_start.tm_mon = tm_end.tm_mon;
+ tm_start.tm_mday = tm_end.tm_mday;
+ tm_start.tm_hour = tm_end.tm_hour - 1;
+ tm_start.tm_min = tm_end.tm_min;
+ tm_start.tm_sec = tm_end.tm_sec;
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage);
+ e_date_edit_set_time (E_DATE_EDIT (priv->start_time), mktime (&tm_start));
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), epage);
+ } else
+ g_assert_not_reached ();
+ }
+
+ /* Set the "all day event" button as appropriate */
+ check_all_day (epage);
+
+ /* Notify upstream */
+ gtk_signal_emit (GTK_OBJECT (epage), event_page_signals[DATES_CHANGED]);
+}
+
+/* Callback: all day event button toggled.
+ * Note that this should only be called when the user explicitly toggles the
+ * button. Be sure to block this handler when the toggle button's state is set
+ * within the code.
+ */
+static void
+all_day_event_toggled_cb (GtkWidget *toggle, gpointer data)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+ struct tm start_tm, end_tm;
+ time_t start_t, end_t;
+ gboolean all_day;
+
+ epage = EVENT_PAGE (data);
+ priv = epage->priv;
+
+ /* When the all_day toggle is turned on, the start date is rounded down
+ * to the start of the day, and end date is rounded down to the start of
+ * the day on which the event ends. The event is then taken to be
+ * inclusive of the days between the start and end days. Note that if
+ * the event end is at midnight, we do not round it down to the previous
+ * day, since if we do that and the user repeatedly turns the all_day
+ * toggle on and off, the event keeps shrinking. (We'd also need to
+ * make sure we didn't adjust the time when the radio button is
+ * initially set.)
+ *
+ * When the all_day_toggle is turned off, we set the event start to the
+ * start of the working day, and if the event end is on or before the
+ * day of the event start we set it to one hour after the event start.
+ */
+ all_day = GTK_TOGGLE_BUTTON (toggle)->active;
+
+ /*
+ * Start time.
+ */
+ start_t = e_date_edit_get_time (E_DATE_EDIT (priv->start_time));
+ g_assert (start_t != -1);
+
+ start_tm = *localtime (&start_t);
+
+ if (all_day) {
+ /* Round down to the start of the day. */
+ start_tm.tm_hour = 0;
+ start_tm.tm_min = 0;
+ start_tm.tm_sec = 0;
+ } else {
+ /* Set to the start of the working day. */
+ start_tm.tm_hour = calendar_config_get_day_start_hour ();
+ start_tm.tm_min = calendar_config_get_day_start_minute ();
+ start_tm.tm_sec = 0;
+ }
+
+ /*
+ * End time.
+ */
+ end_t = e_date_edit_get_time (E_DATE_EDIT (priv->end_time));
+ g_assert (end_t != -1);
+
+ end_tm = *localtime (&end_t);
+
+ if (all_day) {
+ /* Round down to the start of the day. */
+ end_tm.tm_hour = 0;
+ end_tm.tm_min = 0;
+ end_tm.tm_sec = 0;
+ } else {
+ /* If the event end is now on or before the event start day,
+ * make it end one hour after the start. mktime() will fix any
+ * overflows.
+ */
+ if (end_tm.tm_year < start_tm.tm_year
+ || (end_tm.tm_year == start_tm.tm_year
+ && end_tm.tm_mon < start_tm.tm_mon)
+ || (end_tm.tm_year == start_tm.tm_year
+ && end_tm.tm_mon == start_tm.tm_mon
+ && end_tm.tm_mday <= start_tm.tm_mday)) {
+ end_tm.tm_year = start_tm.tm_year;
+ end_tm.tm_mon = start_tm.tm_mon;
+ end_tm.tm_mday = start_tm.tm_mday;
+ end_tm.tm_hour = start_tm.tm_hour + 1;
+ }
+ }
+
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time), epage);
+ gtk_signal_handler_block_by_data (GTK_OBJECT (priv->end_time), epage);
+
+ e_date_edit_set_time (E_DATE_EDIT (priv->start_time), mktime (&start_tm));
+ e_date_edit_set_time (E_DATE_EDIT (priv->end_time), mktime (&end_tm));
+
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time), epage);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time), epage);
+
+ e_date_edit_set_show_time (E_DATE_EDIT (priv->start_time), !all_day);
+ e_date_edit_set_show_time (E_DATE_EDIT (priv->end_time), !all_day);
+
+ /* Notify upstream */
+ gtk_signal_emit (GTK_OBJECT (epage), event_page_signals[DATES_CHANGED]);
+}
+
+/* Callback used when the categories button is clicked; we must bring up the
+ * category list dialog.
+ */
+static void
+categories_clicked_cb (GtkWidget *button, gpointer data)
+{
+ EventPage *epage;
+ EventPagePrivate *priv;
+ char *categories;
+ GnomeDialog *dialog;
+ int result;
+ GtkWidget *entry;
+
+ epage = EVENT_PAGE (data);
+ priv = epage->priv;
+
+ entry = priv->categories;
+ categories = e_utf8_gtk_entry_get_text (GTK_ENTRY (entry));
+
+ dialog = GNOME_DIALOG (e_categories_new (categories));
+ result = gnome_dialog_run (dialog);
+ g_free (categories);
+
+ if (result == 0) {
+ gtk_object_get (GTK_OBJECT (dialog),
+ "categories", &categories,
+ NULL);
+ e_utf8_gtk_entry_set_text (GTK_ENTRY (entry), categories);
+ g_free (categories);
+ }
+
+ gtk_object_destroy (GTK_OBJECT (dialog));
+}
+
+/* This is called when any field is changed; it notifies upstream. */
+static void
+field_changed_cb (GtkWidget *widget, gpointer data)
+{
+ EventPage *epage;
+
+ epage = EVENT_PAGE (data);
+ editor_page_notify_changed (EDITOR_PAGE (epage));
+}
+
+/* Hooks the widget signals */
+static void
+init_widgets (EventPage *epage)
+{
+ EventPagePrivate *priv;
+
+ priv = epage->priv;
+
+ /* Summary */
+ gtk_signal_connect (GTK_OBJECT (priv->summary), "changed",
+ GTK_SIGNAL_FUNC (summary_changed_cb), epage);
+
+ /* Start and end times */
+ gtk_signal_connect (GTK_OBJECT (priv->start_time), "changed",
+ GTK_SIGNAL_FUNC (date_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->end_time), "changed",
+ GTK_SIGNAL_FUNC (date_changed_cb), epage);
+
+ gtk_signal_connect (GTK_OBJECT (priv->all_day_event), "toggled",
+ GTK_SIGNAL_FUNC (all_day_event_toggled_cb), epage);
+
+ /* Categories button */
+ gtk_signal_connect (GTK_OBJECT (priv->categories_btn), "clicked",
+ GTK_SIGNAL_FUNC (categories_clicked_cb), epage);
+
+ /* Connect the default signal handler to use to make sure we notify
+ * upstream of changes to the widget values.
+ */
+
+ gtk_signal_connect (GTK_OBJECT (priv->summary), "changed",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->start_time), "changed",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->end_time), "changed",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->all_day_event), "toggled",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->description), "changed",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->classification_public), "toggled",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->classification_private), "toggled",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->classification_confidential), "toggled",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+ gtk_signal_connect (GTK_OBJECT (priv->categories), "changed",
+ GTK_SIGNAL_FUNC (field_changed_cb), epage);
+
+ /* FIXME: we do not support these fields yet, so we disable them */
+
+ gtk_widget_set_sensitive (priv->contacts_btn, FALSE);
+ gtk_widget_set_sensitive (priv->contacts, FALSE);
+}
+
+
+
+/**
+ * event_page_construct:
+ * @epage: An event page.
+ *
+ * Constructs an event page by loading its Glade data.
+ *
+ * Return value: The same object as @epage, or NULL if the widgets could not be
+ * created.
+ **/
+EventPage *
+event_page_construct (EventPage *epage)
+{
+ EventPagePrivate *priv;
+
+ priv = epage->priv;
+
+ priv->xml = glade_xml_new (EVOLUTION_GLADEDIR "/event-page.glade", NULL);
+ if (!priv->xml) {
+ g_message ("event_page_construct(): Could not load the Glade XML file!");
+ return NULL;
+ }
+
+ if (!get_widgets (epage)) {
+ g_message ("event_page_construct(): Could not find all widgets in the XML file!");
+ return NULL;
+ }
+
+ init_widgets (epage);
+
+ return epage;
+}
+
+/**
+ * event_page_new:
+ *
+ * Creates a new event page.
+ *
+ * Return value: A newly-created event page, or NULL if the page could
+ * not be created.
+ **/
+EventPage *
+event_page_new (void)
+{
+ EventPage *epage;
+
+ epage = gtk_type_new (TYPE_EVENT_PAGE);
+ if (!event_page_construct (epage)) {
+ gtk_object_unref (GTK_OBJECT (epage));
+ return NULL;
+ }
+
+ return epage;
+}
diff --git a/calendar/gui/dialogs/event-page.glade b/calendar/gui/dialogs/event-page.glade
new file mode 100644
index 0000000000..76d2d4043e
--- /dev/null
+++ b/calendar/gui/dialogs/event-page.glade
@@ -0,0 +1,429 @@
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>event-page</name>
+ <program_name>event-page</program_name>
+ <directory></directory>
+ <source_directory>.</source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>True</gnome_support>
+ <gettext_support>True</gettext_support>
+ <output_main_file>False</output_main_file>
+ <output_support_files>False</output_support_files>
+ <output_build_files>False</output_build_files>
+</project>
+
+<widget>
+ <class>GtkWindow</class>
+ <name>event-toplevel</name>
+ <title>window1</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>event-page</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>6</spacing>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table11</name>
+ <rows>1</rows>
+ <columns>2</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>4</row_spacing>
+ <column_spacing>4</column_spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label56</name>
+ <label>Su_mmary:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>7.45058e-09</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <default_focus_target>general-summary</default_focus_target>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>general-summary</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame31</name>
+ <label>Date &amp; Time</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table12</name>
+ <border_width>4</border_width>
+ <rows>2</rows>
+ <columns>3</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>4</row_spacing>
+ <column_spacing>4</column_spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label57</name>
+ <label>_Start time:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label58</name>
+ <label>_End time:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkCheckButton</class>
+ <name>all-day-event</name>
+ <can_focus>True</can_focus>
+ <label>A_ll day event</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <child>
+ <left_attach>2</left_attach>
+ <right_attach>3</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>Custom</class>
+ <name>start-time</name>
+ <creation_function>make_date_edit</creation_function>
+ <string1></string1>
+ <string2></string2>
+ <int1>0</int1>
+ <int2>0</int2>
+ <last_modification_time>Tue, 16 May 2000 19:11:05 GMT</last_modification_time>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>True</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>False</xfill>
+ <yfill>True</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>Custom</class>
+ <name>end-time</name>
+ <creation_function>make_date_edit</creation_function>
+ <int1>0</int1>
+ <int2>0</int2>
+ <last_modification_time>Tue, 16 May 2000 19:11:10 GMT</last_modification_time>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>True</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>False</xfill>
+ <yfill>True</yfill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow12</name>
+ <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkText</class>
+ <name>description</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text></text>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame32</name>
+ <label>Classification</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox52</name>
+ <border_width>2</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>classification-public</name>
+ <can_focus>True</can_focus>
+ <label>Pu_blic</label>
+ <active>True</active>
+ <draw_indicator>True</draw_indicator>
+ <group>classification_radio_group</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>classification-private</name>
+ <can_focus>True</can_focus>
+ <label>Pri_vate</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>classification_radio_group</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>classification-confidential</name>
+ <can_focus>True</can_focus>
+ <label>_Confidential</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>classification_radio_group</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox53</name>
+ <homogeneous>False</homogeneous>
+ <spacing>2</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>contacts-button</name>
+ <can_focus>True</can_focus>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label59</name>
+ <label>_Contacts...</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>4</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>contacts</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>categories-button</name>
+ <can_focus>True</can_focus>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label60</name>
+ <label>Ca_tegories...</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>4</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>categories</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
diff --git a/calendar/gui/dialogs/event-page.h b/calendar/gui/dialogs/event-page.h
new file mode 100644
index 0000000000..85281b9800
--- /dev/null
+++ b/calendar/gui/dialogs/event-page.h
@@ -0,0 +1,70 @@
+/* Evolution calendar - Main page of the event editor dialog
+ *
+ * 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.
+ */
+
+#ifndef EVENT_PAGE_H
+#define EVENT_PAGE_H
+
+#include "editor-page.h"
+
+BEGIN_GNOME_DECLS
+
+
+
+#define TYPE_EVENT_PAGE (event_page_get_type ())
+#define EVENT_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_EVENT_PAGE, EventPage))
+#define EVENT_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_EVENT_PAGE, \
+ EventPageClass))
+#define IS_EVENT_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_EVENT_PAGE))
+#define IS_EVENT_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_EVENT_PAGE))
+
+typedef struct _EventPagePrivate EventPagePrivate;
+
+typedef struct {
+ EditorPage page;
+
+ /* Private data */
+ EventPagePrivate *priv;
+} EventPage;
+
+typedef struct {
+ EditorPageClass parent_class;
+
+ /* Notification signals */
+
+ void (* dates_changed) (EventPage *epage);
+} EventPageClass;
+
+GtkType event_page_get_type (void);
+
+EventPage *event_page_construct (EventPage *epage);
+
+EventPage *event_page_new (void);
+
+time_t event_page_get_dtstart (EventPage *epage);
+
+
+
+END_GNOME_DECLS
+
+#endif
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);
+}
diff --git a/calendar/gui/dialogs/recurrence-page.glade b/calendar/gui/dialogs/recurrence-page.glade
new file mode 100644
index 0000000000..b84a3c288c
--- /dev/null
+++ b/calendar/gui/dialogs/recurrence-page.glade
@@ -0,0 +1,607 @@
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>recurrence-page</name>
+ <program_name>recurrence-page</program_name>
+ <directory></directory>
+ <source_directory>.</source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>True</gnome_support>
+ <gettext_support>True</gettext_support>
+ <output_main_file>False</output_main_file>
+ <output_support_files>False</output_support_files>
+ <output_build_files>False</output_build_files>
+</project>
+
+<widget>
+ <class>GtkWindow</class>
+ <name>recurrence-toplevel</name>
+ <title>window1</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>recurrence-page</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame35</name>
+ <label>Appointment Basics</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>table14</name>
+ <border_width>4</border_width>
+ <rows>2</rows>
+ <columns>2</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>2</row_spacing>
+ <column_spacing>2</column_spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label66</name>
+ <label>Su_mmary:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <default_focus_target>recurrence-summary</default_focus_target>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label67</name>
+ <label>_Starting date:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>recurrence-summary</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>True</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkAlignment</class>
+ <name>alignment40</name>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xscale>0</xscale>
+ <yscale>0</yscale>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>True</yfill>
+ </child>
+
+ <widget>
+ <class>Custom</class>
+ <name>recurrence-starting-date</name>
+ <creation_function>make_date_edit</creation_function>
+ <int1>0</int1>
+ <int2>0</int2>
+ <last_modification_time>Fri, 22 Sep 2000 20:51:38 GMT</last_modification_time>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox55</name>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame36</name>
+ <label>Recurrence Rule</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox56</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox56</name>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>recurrence-none</name>
+ <can_focus>True</can_focus>
+ <label>No recurrence</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>recurrence-radio</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>recurrence-simple</name>
+ <can_focus>True</can_focus>
+ <label>Simple recurrence</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>recurrence-radio</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>recurrence-custom</name>
+ <can_focus>True</can_focus>
+ <label>Custom recurrence</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>recurrence-radio</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox57</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>recurrence-params</name>
+ <homogeneous>False</homogeneous>
+ <spacing>2</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label68</name>
+ <label>Every</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkSpinButton</class>
+ <name>recurrence-interval-value</name>
+ <can_focus>True</can_focus>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>True</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>1</value>
+ <lower>1</lower>
+ <upper>10000</upper>
+ <step>1</step>
+ <page>10</page>
+ <page_size>10</page_size>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkOptionMenu</class>
+ <name>recurrence-interval-unit</name>
+ <can_focus>True</can_focus>
+ <items>day(s)
+week(s)
+month(s)
+year(s)
+</items>
+ <initial_choice>0</initial_choice>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkAlignment</class>
+ <name>recurrence-special</name>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xscale>0</xscale>
+ <yscale>0</yscale>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkOptionMenu</class>
+ <name>recurrence-ending-menu</name>
+ <can_focus>True</can_focus>
+ <items>for
+until
+forever
+</items>
+ <initial_choice>0</initial_choice>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkAlignment</class>
+ <name>recurrence-ending-special</name>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xscale>0</xscale>
+ <yscale>0</yscale>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkAlignment</class>
+ <name>recurrence-custom-warning-bin</name>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xscale>1</xscale>
+ <yscale>1</yscale>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox59</name>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame37</name>
+ <label>Exceptions</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox60</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox57</name>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>recurrence-exception-add</name>
+ <can_focus>True</can_focus>
+ <label>Add</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>recurrence-exception-modify</name>
+ <can_focus>True</can_focus>
+ <label>Modify</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkButton</class>
+ <name>recurrence-exception-delete</name>
+ <can_focus>True</can_focus>
+ <label>Delete</label>
+ <relief>GTK_RELIEF_NORMAL</relief>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox58</name>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>Custom</class>
+ <name>recurrence-exception-date</name>
+ <creation_function>make_date_edit</creation_function>
+ <int1>0</int1>
+ <int2>0</int2>
+ <last_modification_time>Tue, 16 May 2000 01:42:29 GMT</last_modification_time>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow14</name>
+ <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkCList</class>
+ <name>recurrence-exception-list</name>
+ <can_focus>True</can_focus>
+ <columns>1</columns>
+ <column_widths>80</column_widths>
+ <selection_mode>GTK_SELECTION_BROWSE</selection_mode>
+ <show_titles>False</show_titles>
+ <shadow_type>GTK_SHADOW_IN</shadow_type>
+
+ <widget>
+ <class>GtkLabel</class>
+ <child_name>CList:title</child_name>
+ <name>label69</name>
+ <label>label21</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+
+ <widget>
+ <class>GtkVBox</class>
+ <name>vbox59</name>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label70</name>
+ <label>Preview</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkAlignment</class>
+ <name>recurrence-preview-bin</name>
+ <xalign>0</xalign>
+ <yalign>0</yalign>
+ <xscale>1</xscale>
+ <yscale>1</yscale>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>Placeholder</class>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
diff --git a/calendar/gui/dialogs/recurrence-page.h b/calendar/gui/dialogs/recurrence-page.h
new file mode 100644
index 0000000000..39123644b4
--- /dev/null
+++ b/calendar/gui/dialogs/recurrence-page.h
@@ -0,0 +1,64 @@
+/* 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.
+ */
+
+#ifndef RECURRENCE_PAGE_H
+#define RECURRENCE_PAGE_H
+
+#include "editor-page.h"
+
+BEGIN_GNOME_DECLS
+
+
+
+#define TYPE_RECURRENCE_PAGE (recurrence_page_get_type ())
+#define RECURRENCE_PAGE(obj) (GTK_CHECK_CAST ((obj), TYPE_RECURRENCE_PAGE, RecurrencePage))
+#define RECURRENCE_PAGE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), TYPE_RECURRENCE_PAGE, \
+ RecurrencePageClass))
+#define IS_RECURRENCE_PAGE(obj) (GTK_CHECK_TYPE ((obj), TYPE_RECURRENCE_PAGE))
+#define IS_RECURRENCE_PAGE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), TYPE_RECURRENCE_PAGE))
+
+typedef struct _RecurrencePagePrivate RecurrencePagePrivate;
+
+typedef struct {
+ EditorPage page;
+
+ /* Private data */
+ RecurrencePagePrivate *priv;
+} RecurrencePage;
+
+typedef struct {
+ EditorPageClass parent_class;
+} RecurrencePageClass;
+
+GtkType recurrence_page_get_type (void);
+
+RecurrencePage *recurrence_page_construct (RecurrencePage *rpage);
+
+RecurrencePage *recurrence_page_new (void);
+
+
+
+END_GNOME_DECLS
+
+#endif
diff --git a/calendar/gui/dialogs/task-details-page.glade b/calendar/gui/dialogs/task-details-page.glade
new file mode 100644
index 0000000000..31e3aba6c4
--- /dev/null
+++ b/calendar/gui/dialogs/task-details-page.glade
@@ -0,0 +1,137 @@
+<?xml version="1.0"?>
+<GTK-Interface>
+
+<project>
+ <name>task-details-page</name>
+ <program_name>task-details-page</program_name>
+ <directory></directory>
+ <source_directory>src</source_directory>
+ <pixmaps_directory>pixmaps</pixmaps_directory>
+ <language>C</language>
+ <gnome_support>True</gnome_support>
+ <gettext_support>True</gettext_support>
+</project>
+
+<widget>
+ <class>GtkWindow</class>
+ <name>task-details-toplevel</name>
+ <title>window1</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
+ <position>GTK_WIN_POS_NONE</position>
+ <modal>False</modal>
+ <allow_shrink>False</allow_shrink>
+ <allow_grow>True</allow_grow>
+ <auto_shrink>False</auto_shrink>
+
+ <widget>
+ <class>GtkTable</class>
+ <name>task-details-page</name>
+ <border_width>4</border_width>
+ <rows>2</rows>
+ <columns>2</columns>
+ <homogeneous>False</homogeneous>
+ <row_spacing>2</row_spacing>
+ <column_spacing>4</column_spacing>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label12</name>
+ <label>Date Completed:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label14</name>
+ <label>URL:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <child>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkEntry</class>
+ <name>url</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>Custom</class>
+ <name>completed-date</name>
+ <creation_function>task_editor_create_date_edit</creation_function>
+ <int1>0</int1>
+ <int2>0</int2>
+ <last_modification_time>Sun, 10 Sep 2000 17:34:07 GMT</last_modification_time>
+ <child>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
+ </child>
+ </widget>
+ </widget>
+</widget>
+
+</GTK-Interface>
diff --git a/calendar/gui/dialogs/task-page.glade b/calendar/gui/dialogs/task-page.glade
index ae7ea9681a..e9f0d4700d 100644
--- a/calendar/gui/dialogs/task-page.glade
+++ b/calendar/gui/dialogs/task-page.glade
@@ -2,8 +2,8 @@
<GTK-Interface>
<project>
- <name>task-editor-dialog</name>
- <program_name>task-editor-dialog</program_name>
+ <name>task-page</name>
+ <program_name>task-page</program_name>
<directory></directory>
<source_directory>src</source_directory>
<pixmaps_directory>pixmaps</pixmaps_directory>
@@ -13,681 +13,533 @@
</project>
<widget>
- <class>GnomePropertyBox</class>
- <name>task-editor-dialog</name>
- <visible>False</visible>
+ <class>GtkWindow</class>
+ <name>task-toplevel</name>
+ <title>window1</title>
+ <type>GTK_WINDOW_TOPLEVEL</type>
<position>GTK_WIN_POS_NONE</position>
<modal>False</modal>
<allow_shrink>False</allow_shrink>
- <allow_grow>False</allow_grow>
+ <allow_grow>True</allow_grow>
<auto_shrink>False</auto_shrink>
<widget>
- <class>GtkNotebook</class>
- <child_name>GnomeDock:contents</child_name>
- <name>notebook1</name>
- <border_width>2</border_width>
- <can_focus>True</can_focus>
- <show_tabs>True</show_tabs>
- <show_border>True</show_border>
- <tab_pos>GTK_POS_TOP</tab_pos>
- <scrollable>False</scrollable>
- <tab_hborder>2</tab_hborder>
- <tab_vborder>2</tab_vborder>
- <popup_enable>False</popup_enable>
+ <class>GtkVBox</class>
+ <name>task-page</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
<widget>
- <class>GtkVBox</class>
- <name>vbox1</name>
- <border_width>4</border_width>
+ <class>GtkTable</class>
+ <name>table3</name>
+ <rows>1</rows>
+ <columns>2</columns>
<homogeneous>False</homogeneous>
- <spacing>4</spacing>
+ <row_spacing>4</row_spacing>
+ <column_spacing>4</column_spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
<widget>
- <class>GtkTable</class>
- <name>table3</name>
- <rows>1</rows>
- <columns>2</columns>
- <homogeneous>False</homogeneous>
- <row_spacing>4</row_spacing>
- <column_spacing>4</column_spacing>
+ <class>GtkLabel</class>
+ <name>label3</name>
+ <label>Su_mmary:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <default_focus_target>summary</default_focus_target>
<child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>True</fill>
- </child>
-
- <widget>
- <class>GtkLabel</class>
- <name>label3</name>
- <label>Su_mmary:</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0.5</xalign>
- <yalign>0.5</yalign>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
<xpad>0</xpad>
<ypad>0</ypad>
- <default_focus_target>summary</default_focus_target>
- <child>
- <left_attach>0</left_attach>
- <right_attach>1</right_attach>
- <top_attach>0</top_attach>
- <bottom_attach>1</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>False</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>False</xfill>
- <yfill>False</yfill>
- </child>
- </widget>
-
- <widget>
- <class>GtkEntry</class>
- <name>summary</name>
- <can_focus>True</can_focus>
- <editable>True</editable>
- <text_visible>True</text_visible>
- <text_max_length>0</text_max_length>
- <text></text>
- <child>
- <left_attach>1</left_attach>
- <right_attach>2</right_attach>
- <top_attach>0</top_attach>
- <bottom_attach>1</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>True</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
- </child>
- </widget>
- </widget>
-
- <widget>
- <class>GtkFrame</class>
- <name>frame2</name>
- <label>Date &amp; Time</label>
- <label_xalign>0</label_xalign>
- <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>True</fill>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>False</xfill>
+ <yfill>False</yfill>
</child>
-
- <widget>
- <class>GtkHBox</class>
- <name>hbox4</name>
- <border_width>4</border_width>
- <homogeneous>False</homogeneous>
- <spacing>0</spacing>
-
- <widget>
- <class>GtkTable</class>
- <name>table1</name>
- <rows>2</rows>
- <columns>2</columns>
- <homogeneous>False</homogeneous>
- <row_spacing>2</row_spacing>
- <column_spacing>4</column_spacing>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>True</fill>
- </child>
-
- <widget>
- <class>GtkLabel</class>
- <name>label6</name>
- <label>Sta_rt Date:</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <child>
- <left_attach>0</left_attach>
- <right_attach>1</right_attach>
- <top_attach>1</top_attach>
- <bottom_attach>2</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>False</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
- </child>
- </widget>
-
- <widget>
- <class>GtkLabel</class>
- <name>label5</name>
- <label>_Due Date:</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <child>
- <left_attach>0</left_attach>
- <right_attach>1</right_attach>
- <top_attach>0</top_attach>
- <bottom_attach>1</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>False</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
- </child>
- </widget>
-
- <widget>
- <class>Custom</class>
- <name>due-date</name>
- <creation_function>task_editor_create_date_edit</creation_function>
- <int1>0</int1>
- <int2>0</int2>
- <last_modification_time>Sun, 10 Sep 2000 17:32:18 GMT</last_modification_time>
- <child>
- <left_attach>1</left_attach>
- <right_attach>2</right_attach>
- <top_attach>0</top_attach>
- <bottom_attach>1</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>True</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
- </child>
- </widget>
-
- <widget>
- <class>Custom</class>
- <name>start-date</name>
- <creation_function>task_editor_create_date_edit</creation_function>
- <int1>0</int1>
- <int2>0</int2>
- <last_modification_time>Sun, 10 Sep 2000 17:33:31 GMT</last_modification_time>
- <child>
- <left_attach>1</left_attach>
- <right_attach>2</right_attach>
- <top_attach>1</top_attach>
- <bottom_attach>2</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>True</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
- </child>
- </widget>
- </widget>
- </widget>
</widget>
<widget>
- <class>GtkScrolledWindow</class>
- <name>scrolledwindow1</name>
- <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
- <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
- <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
- <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <class>GtkEntry</class>
+ <name>summary</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
<child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>True</fill>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
</child>
-
- <widget>
- <class>GtkText</class>
- <name>description</name>
- <height>80</height>
- <can_focus>True</can_focus>
- <editable>True</editable>
- <text></text>
- </widget>
</widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame2</name>
+ <label>Date &amp; Time</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
<widget>
- <class>GtkFrame</class>
- <name>frame23</name>
- <label>Progress</label>
- <label_xalign>0</label_xalign>
- <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>True</fill>
- </child>
+ <class>GtkHBox</class>
+ <name>hbox4</name>
+ <border_width>4</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>0</spacing>
<widget>
- <class>GtkHBox</class>
- <name>hbox3</name>
- <border_width>4</border_width>
+ <class>GtkTable</class>
+ <name>table1</name>
+ <rows>2</rows>
+ <columns>2</columns>
<homogeneous>False</homogeneous>
- <spacing>4</spacing>
+ <row_spacing>2</row_spacing>
+ <column_spacing>4</column_spacing>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
<widget>
<class>GtkLabel</class>
- <name>label7</name>
- <label>_Status:</label>
+ <name>label6</name>
+ <label>Sta_rt Date:</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
- <xalign>0.5</xalign>
+ <xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
- <default_focus_target>status</default_focus_target>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
- </child>
- </widget>
-
- <widget>
- <class>GtkOptionMenu</class>
- <name>status</name>
- <can_focus>True</can_focus>
- <items>Not Started
-In Progress
-Completed
-Cancelled
-</items>
- <initial_choice>0</initial_choice>
<child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
- <name>label8</name>
- <label>_Priority:</label>
+ <name>label5</name>
+ <label>_Due Date:</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<wrap>False</wrap>
- <xalign>0.5</xalign>
+ <xalign>0</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
- <default_focus_target>priority</default_focus_target>
<child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
- </child>
- </widget>
-
- <widget>
- <class>GtkOptionMenu</class>
- <name>priority</name>
- <can_focus>True</can_focus>
- <items>High
-Normal
-Low
-Undefined
-</items>
- <initial_choice>0</initial_choice>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
+ <left_attach>0</left_attach>
+ <right_attach>1</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>False</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
</child>
</widget>
<widget>
- <class>GtkLabel</class>
- <name>label9</name>
- <label>% Comp_lete:</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0.5</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <default_focus_target>percent-complete</default_focus_target>
+ <class>Custom</class>
+ <name>due-date</name>
+ <creation_function>task_editor_create_date_edit</creation_function>
+ <int1>0</int1>
+ <int2>0</int2>
+ <last_modification_time>Sun, 10 Sep 2000 17:32:18 GMT</last_modification_time>
<child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>0</top_attach>
+ <bottom_attach>1</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
</child>
</widget>
<widget>
- <class>GtkSpinButton</class>
- <name>percent-complete</name>
- <width>60</width>
- <can_focus>True</can_focus>
- <climb_rate>1</climb_rate>
- <digits>0</digits>
- <numeric>False</numeric>
- <update_policy>GTK_UPDATE_ALWAYS</update_policy>
- <snap>False</snap>
- <wrap>False</wrap>
- <value>0</value>
- <lower>0</lower>
- <upper>100</upper>
- <step>10</step>
- <page>10</page>
- <page_size>10</page_size>
+ <class>Custom</class>
+ <name>start-date</name>
+ <creation_function>task_editor_create_date_edit</creation_function>
+ <int1>0</int1>
+ <int2>0</int2>
+ <last_modification_time>Sun, 10 Sep 2000 17:33:31 GMT</last_modification_time>
<child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
+ <left_attach>1</left_attach>
+ <right_attach>2</right_attach>
+ <top_attach>1</top_attach>
+ <bottom_attach>2</bottom_attach>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <xexpand>True</xexpand>
+ <yexpand>False</yexpand>
+ <xshrink>False</xshrink>
+ <yshrink>False</yshrink>
+ <xfill>True</xfill>
+ <yfill>False</yfill>
</child>
</widget>
</widget>
</widget>
+ </widget>
- <widget>
- <class>GtkFrame</class>
- <name>frame24</name>
- <label>Classification</label>
- <label_xalign>0</label_xalign>
- <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>True</fill>
- </child>
-
- <widget>
- <class>GtkHBox</class>
- <name>hbox6</name>
- <border_width>2</border_width>
- <homogeneous>False</homogeneous>
- <spacing>4</spacing>
-
- <widget>
- <class>GtkRadioButton</class>
- <name>classification-public</name>
- <can_focus>True</can_focus>
- <label>Pu_blic</label>
- <active>True</active>
- <draw_indicator>True</draw_indicator>
- <group>classification_radio_group</group>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
- </child>
- </widget>
-
- <widget>
- <class>GtkRadioButton</class>
- <name>classification-private</name>
- <can_focus>True</can_focus>
- <label>Pri_vate</label>
- <active>False</active>
- <draw_indicator>True</draw_indicator>
- <group>classification_radio_group</group>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
- </child>
- </widget>
+ <widget>
+ <class>GtkScrolledWindow</class>
+ <name>scrolledwindow1</name>
+ <hscrollbar_policy>GTK_POLICY_NEVER</hscrollbar_policy>
+ <vscrollbar_policy>GTK_POLICY_AUTOMATIC</vscrollbar_policy>
+ <hupdate_policy>GTK_UPDATE_CONTINUOUS</hupdate_policy>
+ <vupdate_policy>GTK_UPDATE_CONTINUOUS</vupdate_policy>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
- <widget>
- <class>GtkRadioButton</class>
- <name>classification-confidential</name>
- <can_focus>True</can_focus>
- <label>_Confidential</label>
- <active>False</active>
- <draw_indicator>True</draw_indicator>
- <group>classification_radio_group</group>
- <child>
- <padding>0</padding>
- <expand>False</expand>
- <fill>False</fill>
- </child>
- </widget>
- </widget>
+ <widget>
+ <class>GtkText</class>
+ <name>description</name>
+ <height>80</height>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text></text>
</widget>
+ </widget>
+
+ <widget>
+ <class>GtkFrame</class>
+ <name>frame23</name>
+ <label>Progress</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
<widget>
<class>GtkHBox</class>
- <name>hbox2</name>
+ <name>hbox3</name>
+ <border_width>4</border_width>
<homogeneous>False</homogeneous>
- <spacing>2</spacing>
- <child>
- <padding>0</padding>
- <expand>True</expand>
- <fill>True</fill>
- </child>
+ <spacing>4</spacing>
<widget>
- <class>GtkButton</class>
- <name>contacts-button</name>
- <can_focus>True</can_focus>
+ <class>GtkLabel</class>
+ <name>label7</name>
+ <label>_Status:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <default_focus_target>status</default_focus_target>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
-
- <widget>
- <class>GtkLabel</class>
- <name>label16</name>
- <label>_Contacts...</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0.5</xalign>
- <yalign>0.5</yalign>
- <xpad>4</xpad>
- <ypad>0</ypad>
- </widget>
</widget>
<widget>
- <class>GtkEntry</class>
- <name>contacts</name>
+ <class>GtkOptionMenu</class>
+ <name>status</name>
<can_focus>True</can_focus>
- <editable>True</editable>
- <text_visible>True</text_visible>
- <text_max_length>0</text_max_length>
- <text></text>
+ <items>Not Started
+In Progress
+Completed
+Cancelled
+</items>
+ <initial_choice>0</initial_choice>
<child>
<padding>0</padding>
- <expand>True</expand>
- <fill>True</fill>
+ <expand>False</expand>
+ <fill>False</fill>
</child>
</widget>
<widget>
- <class>GtkButton</class>
- <name>categories-button</name>
+ <class>GtkLabel</class>
+ <name>label8</name>
+ <label>_Priority:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <default_focus_target>priority</default_focus_target>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkOptionMenu</class>
+ <name>priority</name>
<can_focus>True</can_focus>
+ <items>High
+Normal
+Low
+Undefined
+</items>
+ <initial_choice>0</initial_choice>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
+ </widget>
- <widget>
- <class>GtkLabel</class>
- <name>label17</name>
- <label>Ca_tegories...</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0.5</xalign>
- <yalign>0.5</yalign>
- <xpad>4</xpad>
- <ypad>0</ypad>
- </widget>
+ <widget>
+ <class>GtkLabel</class>
+ <name>label9</name>
+ <label>% Comp_lete:</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>0</xpad>
+ <ypad>0</ypad>
+ <default_focus_target>percent-complete</default_focus_target>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
</widget>
<widget>
- <class>GtkEntry</class>
- <name>categories</name>
+ <class>GtkSpinButton</class>
+ <name>percent-complete</name>
+ <width>60</width>
<can_focus>True</can_focus>
- <editable>True</editable>
- <text_visible>True</text_visible>
- <text_max_length>0</text_max_length>
- <text></text>
+ <climb_rate>1</climb_rate>
+ <digits>0</digits>
+ <numeric>False</numeric>
+ <update_policy>GTK_UPDATE_ALWAYS</update_policy>
+ <snap>False</snap>
+ <wrap>False</wrap>
+ <value>0</value>
+ <lower>0</lower>
+ <upper>100</upper>
+ <step>10</step>
+ <page>10</page>
+ <page_size>10</page_size>
<child>
<padding>0</padding>
- <expand>True</expand>
- <fill>True</fill>
+ <expand>False</expand>
+ <fill>False</fill>
</child>
</widget>
</widget>
</widget>
<widget>
- <class>GtkLabel</class>
- <child_name>Notebook:tab</child_name>
- <name>label1</name>
- <label>Task</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0.5</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
+ <class>GtkFrame</class>
+ <name>frame24</name>
+ <label>Classification</label>
+ <label_xalign>0</label_xalign>
+ <shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>True</fill>
+ </child>
+
+ <widget>
+ <class>GtkHBox</class>
+ <name>hbox6</name>
+ <border_width>2</border_width>
+ <homogeneous>False</homogeneous>
+ <spacing>4</spacing>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>classification-public</name>
+ <can_focus>True</can_focus>
+ <label>Pu_blic</label>
+ <active>True</active>
+ <draw_indicator>True</draw_indicator>
+ <group>classification_radio_group</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>classification-private</name>
+ <can_focus>True</can_focus>
+ <label>Pri_vate</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>classification_radio_group</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+
+ <widget>
+ <class>GtkRadioButton</class>
+ <name>classification-confidential</name>
+ <can_focus>True</can_focus>
+ <label>_Confidential</label>
+ <active>False</active>
+ <draw_indicator>True</draw_indicator>
+ <group>classification_radio_group</group>
+ <child>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
+ </child>
+ </widget>
+ </widget>
</widget>
<widget>
- <class>GtkTable</class>
- <name>table4</name>
- <border_width>4</border_width>
- <rows>2</rows>
- <columns>2</columns>
+ <class>GtkHBox</class>
+ <name>hbox2</name>
<homogeneous>False</homogeneous>
- <row_spacing>2</row_spacing>
- <column_spacing>4</column_spacing>
+ <spacing>2</spacing>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
<widget>
- <class>GtkLabel</class>
- <name>label12</name>
- <label>Date Completed:</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
+ <class>GtkButton</class>
+ <name>contacts-button</name>
+ <can_focus>True</can_focus>
+ <relief>GTK_RELIEF_NORMAL</relief>
<child>
- <left_attach>0</left_attach>
- <right_attach>1</right_attach>
- <top_attach>0</top_attach>
- <bottom_attach>1</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>False</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
</child>
- </widget>
- <widget>
- <class>GtkLabel</class>
- <name>label14</name>
- <label>URL:</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <child>
- <left_attach>0</left_attach>
- <right_attach>1</right_attach>
- <top_attach>1</top_attach>
- <bottom_attach>2</bottom_attach>
- <xpad>0</xpad>
+ <widget>
+ <class>GtkLabel</class>
+ <name>label16</name>
+ <label>_Contacts...</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>4</xpad>
<ypad>0</ypad>
- <xexpand>False</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
- </child>
+ </widget>
</widget>
<widget>
<class>GtkEntry</class>
- <name>url</name>
+ <name>contacts</name>
<can_focus>True</can_focus>
<editable>True</editable>
<text_visible>True</text_visible>
<text_max_length>0</text_max_length>
<text></text>
<child>
- <left_attach>1</left_attach>
- <right_attach>2</right_attach>
- <top_attach>1</top_attach>
- <bottom_attach>2</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>True</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
</child>
</widget>
<widget>
- <class>Custom</class>
- <name>completed-date</name>
- <creation_function>task_editor_create_date_edit</creation_function>
- <int1>0</int1>
- <int2>0</int2>
- <last_modification_time>Sun, 10 Sep 2000 17:34:07 GMT</last_modification_time>
+ <class>GtkButton</class>
+ <name>categories-button</name>
+ <can_focus>True</can_focus>
+ <relief>GTK_RELIEF_NORMAL</relief>
<child>
- <left_attach>1</left_attach>
- <right_attach>2</right_attach>
- <top_attach>0</top_attach>
- <bottom_attach>1</bottom_attach>
- <xpad>0</xpad>
- <ypad>0</ypad>
- <xexpand>True</xexpand>
- <yexpand>False</yexpand>
- <xshrink>False</xshrink>
- <yshrink>False</yshrink>
- <xfill>True</xfill>
- <yfill>False</yfill>
+ <padding>0</padding>
+ <expand>False</expand>
+ <fill>False</fill>
</child>
+
+ <widget>
+ <class>GtkLabel</class>
+ <name>label17</name>
+ <label>Ca_tegories...</label>
+ <justify>GTK_JUSTIFY_CENTER</justify>
+ <wrap>False</wrap>
+ <xalign>0.5</xalign>
+ <yalign>0.5</yalign>
+ <xpad>4</xpad>
+ <ypad>0</ypad>
+ </widget>
</widget>
- </widget>
- <widget>
- <class>GtkLabel</class>
- <child_name>Notebook:tab</child_name>
- <name>label2</name>
- <label>Details</label>
- <justify>GTK_JUSTIFY_CENTER</justify>
- <wrap>False</wrap>
- <xalign>0.5</xalign>
- <yalign>0.5</yalign>
- <xpad>0</xpad>
- <ypad>0</ypad>
+ <widget>
+ <class>GtkEntry</class>
+ <name>categories</name>
+ <can_focus>True</can_focus>
+ <editable>True</editable>
+ <text_visible>True</text_visible>
+ <text_max_length>0</text_max_length>
+ <text></text>
+ <child>
+ <padding>0</padding>
+ <expand>True</expand>
+ <fill>True</fill>
+ </child>
+ </widget>
</widget>
</widget>
</widget>
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index b10382a3ea..b19c7ff310 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -803,11 +803,11 @@ e_day_view_init (EDayView *day_view)
gtk_drag_dest_set (day_view->top_canvas,
GTK_DEST_DEFAULT_ALL,
target_table, n_targets,
- GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);
gtk_drag_dest_set (day_view->main_canvas,
GTK_DEST_DEFAULT_ALL,
target_table, n_targets,
- GDK_ACTION_COPY | GDK_ACTION_MOVE);
+ GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_ASK);
}
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index c06b568d9d..96270c04aa 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -379,7 +379,6 @@ e_week_view_init (EWeekView *week_view)
2, 3, 1, 2, 0, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_widget_show (week_view->vscrollbar);
-
/* Create the cursors. */
week_view->normal_cursor = gdk_cursor_new (GDK_LEFT_PTR);
week_view->move_cursor = gdk_cursor_new (GDK_FLEUR);
diff --git a/calendar/gui/event-editor.c b/calendar/gui/event-editor.c
index 242ef67226..c96c94dadd 100644
--- a/calendar/gui/event-editor.c
+++ b/calendar/gui/event-editor.c
@@ -1656,7 +1656,7 @@ fill_reminder_widgets (EventEditor *ee)
/* Add it to the clist */
append_reminder (ee, ca, EXISTING_ALARM);
}
- cal_component_free_alarm_uids (alarms);
+ cal_obj_uid_list_free (alarms);
}
/* Fills in the recurrence widgets with the values from the calendar component.