aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/dialogs/event-page.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/dialogs/event-page.c')
-rw-r--r--calendar/gui/dialogs/event-page.c1967
1 files changed, 0 insertions, 1967 deletions
diff --git a/calendar/gui/dialogs/event-page.c b/calendar/gui/dialogs/event-page.c
deleted file mode 100644
index d0a4283366..0000000000
--- a/calendar/gui/dialogs/event-page.c
+++ /dev/null
@@ -1,1967 +0,0 @@
-/* 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 version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * 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 <string.h>
-#include <gtk/gtksignal.h>
-#include <gtk/gtktextview.h>
-#include <gtk/gtktogglebutton.h>
-#include <gtk/gtkmessagedialog.h>
-#include <libgnome/gnome-i18n.h>
-#include <glade/glade.h>
-#include <gal/widgets/e-categories.h>
-#include <libedataserverui/e-source-option-menu.h>
-#include "common/authentication.h"
-#include "e-util/e-categories-config.h"
-#include "e-util/e-dialog-widgets.h"
-#include "widgets/misc/e-dateedit.h"
-#include <libecal/e-cal-time-util.h>
-#include "../calendar-config.h"
-#include "../e-timezone-entry.h"
-#include "comp-editor.h"
-#include "comp-editor-util.h"
-#include "../e-alarm-list.h"
-#include "alarm-list-dialog.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 *summary_label;
- GtkWidget *location;
- GtkWidget *location_label;
-
- GtkWidget *start_time;
- GtkWidget *end_time;
- GtkWidget *start_timezone;
- GtkWidget *end_timezone;
- GtkWidget *all_day_event;
-
- GtkWidget *description;
-
- GtkWidget *classification;
-
- GtkWidget *show_time_as_busy;
-
- GtkWidget *alarm;
- GtkWidget *alarm_time;
- GtkWidget *alarm_warning;
- GtkWidget *alarm_custom;
-
- GtkWidget *categories_btn;
- GtkWidget *categories;
-
- GtkWidget *source_selector;
-
- EAlarmList *alarm_list_store;
-
- gboolean updating;
-
- char *old_summary;
- CalUnits alarm_units;
- int alarm_interval;
-
- /* This is TRUE if both the start & end timezone are the same. If the
- start timezone is then changed, we updated the end timezone to the
- same value, since 99% of events start and end in one timezone. */
- gboolean sync_timezones;
-};
-
-
-
-static void event_page_finalize (GObject *object);
-
-static GtkWidget *event_page_get_widget (CompEditorPage *page);
-static void event_page_focus_main_widget (CompEditorPage *page);
-static gboolean event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp);
-static gboolean event_page_fill_component (CompEditorPage *page, ECalComponent *comp);
-static gboolean event_page_fill_timezones (CompEditorPage *page, GHashTable *timezones);
-static void event_page_set_summary (CompEditorPage *page, const char *summary);
-static void event_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates);
-
-G_DEFINE_TYPE (EventPage, event_page, TYPE_COMP_EDITOR_PAGE);
-
-/* Class initialization function for the event page */
-static void
-event_page_class_init (EventPageClass *class)
-{
- CompEditorPageClass *editor_page_class;
- GObjectClass *object_class;
-
- editor_page_class = (CompEditorPageClass *) class;
- object_class = (GObjectClass *) class;
-
- editor_page_class->get_widget = event_page_get_widget;
- editor_page_class->focus_main_widget = event_page_focus_main_widget;
- editor_page_class->fill_widgets = event_page_fill_widgets;
- editor_page_class->fill_component = event_page_fill_component;
- editor_page_class->fill_timezones = event_page_fill_timezones;
- editor_page_class->set_summary = event_page_set_summary;
- editor_page_class->set_dates = event_page_set_dates;
-
- object_class->finalize = event_page_finalize;
-}
-
-/* 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->summary_label = NULL;
- priv->location = NULL;
- priv->location_label = NULL;
- priv->start_time = NULL;
- priv->end_time = NULL;
- priv->start_timezone = NULL;
- priv->end_timezone = NULL;
- priv->all_day_event = NULL;
- priv->description = NULL;
- priv->classification = NULL;
- priv->show_time_as_busy = NULL;
- priv->alarm = NULL;
- priv->alarm_time = NULL;
- priv->alarm_custom = NULL;
- priv->categories_btn = NULL;
- priv->categories = NULL;
-
- priv->alarm_interval = -1;
-
- priv->updating = FALSE;
- priv->sync_timezones = FALSE;
-}
-
-/* Destroy handler for the event page */
-static void
-event_page_finalize (GObject *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->main)
- gtk_widget_unref (priv->main);
-
- if (priv->xml) {
- g_object_unref (priv->xml);
- priv->xml = NULL;
- }
-
- if (priv->alarm_list_store) {
- g_object_unref (priv->alarm_list_store);
- priv->alarm_list_store = NULL;
- }
-
- g_free (priv->old_summary);
-
- g_free (priv);
- epage->priv = NULL;
-
- if (G_OBJECT_CLASS (event_page_parent_class)->finalize)
- (* G_OBJECT_CLASS (event_page_parent_class)->finalize) (object);
-}
-
-
-
-static const int classification_map[] = {
- E_CAL_COMPONENT_CLASS_PUBLIC,
- E_CAL_COMPONENT_CLASS_PRIVATE,
- E_CAL_COMPONENT_CLASS_CONFIDENTIAL,
- -1
-};
-
-enum {
- ALARM_15_MINUTES,
- ALARM_1_HOUR,
- ALARM_1_DAY,
- ALARM_USER_TIME
-};
-
-static const int alarm_map[] = {
- ALARM_15_MINUTES,
- ALARM_1_HOUR,
- ALARM_1_DAY,
- ALARM_USER_TIME,
- -1
-};
-
-/* get_widget handler for the event page */
-static GtkWidget *
-event_page_get_widget (CompEditorPage *page)
-{
- EventPage *epage;
- EventPagePrivate *priv;
-
- epage = EVENT_PAGE (page);
- priv = epage->priv;
-
- return priv->main;
-}
-
-/* focus_main_widget handler for the event page */
-static void
-event_page_focus_main_widget (CompEditorPage *page)
-{
- EventPage *epage;
- EventPagePrivate *priv;
-
- epage = EVENT_PAGE (page);
- priv = epage->priv;
-
- gtk_widget_grab_focus (priv->summary);
-}
-
-/* Sets the 'All Day Event' flag to the given value (without emitting signals),
- * and shows or hides the widgets as appropriate. */
-static void
-set_all_day (EventPage *epage, gboolean all_day)
-{
- EventPagePrivate *priv;
-
- priv = epage->priv;
-
- 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);
-
- /* DATE values do not have timezones, so we hide the fields. */
- if (all_day) {
- gtk_widget_hide (priv->start_timezone);
- gtk_widget_hide (priv->end_timezone);
- } else {
- gtk_widget_show (priv->start_timezone);
- gtk_widget_show (priv->end_timezone);
- }
-}
-
-static void
-update_time (EventPage *epage, ECalComponentDateTime *start_date, ECalComponentDateTime *end_date)
-{
- EventPagePrivate *priv;
- struct icaltimetype *start_tt, *end_tt, implied_tt;
- icaltimezone *start_zone = NULL, *end_zone = NULL;
- gboolean all_day_event;
-
- priv = epage->priv;
-
- /* Note that if we are creating a new event, the timezones may not be
- on the server, so we try to get the builtin timezone with the TZID
- first. */
- start_zone = icaltimezone_get_builtin_timezone_from_tzid (start_date->tzid);
- if (!start_zone) {
- /* FIXME: Handle error better. */
- if (!e_cal_get_timezone (COMP_EDITOR_PAGE (epage)->client,
- start_date->tzid, &start_zone, NULL)) {
- g_warning ("Couldn't get timezone from server: %s",
- start_date->tzid ? start_date->tzid : "");
- }
- }
-
- end_zone = icaltimezone_get_builtin_timezone_from_tzid (end_date->tzid);
- if (!end_zone) {
- if (!e_cal_get_timezone (COMP_EDITOR_PAGE (epage)->client,
- end_date->tzid, &end_zone, NULL)) {
- /* FIXME: Handle error better. */
- g_warning ("Couldn't get timezone from server: %s",
- end_date->tzid ? end_date->tzid : "");
- }
- }
-
- /* If both times are DATE values, we set the 'All Day Event' checkbox.
- Also, if DTEND is after DTSTART, we subtract 1 day from it. */
- all_day_event = FALSE;
- start_tt = start_date->value;
- end_tt = end_date->value;
- if (!end_tt && start_tt->is_date) {
- end_tt = &implied_tt;
- *end_tt = *start_tt;
- icaltime_adjust (end_tt, 1, 0, 0, 0);
- }
-
- if (start_tt->is_date && end_tt->is_date) {
- all_day_event = TRUE;
- if (icaltime_compare_date_only (*end_tt, *start_tt) > 0) {
- icaltime_adjust (end_tt, -1, 0, 0, 0);
- }
- }
-
- set_all_day (epage, all_day_event);
-
- /* If it is an all day event, we set both timezones to the current
- timezone, so that if the user toggles the 'All Day Event' checkbox
- the event uses the current timezone rather than none at all. */
- if (all_day_event)
- start_zone = end_zone = calendar_config_get_icaltimezone ();
-
- gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time),
- epage);
- g_signal_handlers_block_matched (priv->end_time, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
-
- e_date_edit_set_date (E_DATE_EDIT (priv->start_time), start_tt->year,
- start_tt->month, start_tt->day);
- e_date_edit_set_time_of_day (E_DATE_EDIT (priv->start_time),
- start_tt->hour, start_tt->minute);
-
- e_date_edit_set_date (E_DATE_EDIT (priv->end_time), end_tt->year,
- end_tt->month, end_tt->day);
- e_date_edit_set_time_of_day (E_DATE_EDIT (priv->end_time),
- end_tt->hour, end_tt->minute);
-
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time),
- epage);
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time),
- epage);
-
- /* Set the timezones, and set sync_timezones to TRUE if both timezones
- are the same. */
- gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_timezone),
- epage);
- g_signal_handlers_block_matched (priv->end_timezone, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
-
- e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->start_timezone),
- start_zone);
- e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->end_timezone),
- end_zone);
-
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_timezone),
- epage);
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_timezone),
- epage);
-
- priv->sync_timezones = (start_zone == end_zone) ? TRUE : FALSE;
-
-}
-
-/* Fills the widgets with default values */
-static void
-clear_widgets (EventPage *epage)
-{
- EventPagePrivate *priv;
-
- priv = epage->priv;
-
- /* Summary, description */
- e_dialog_editable_set (priv->summary, NULL);
- e_dialog_editable_set (priv->location, NULL);
- gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->description)), "", 0);
-
- /* Start and end times */
- gtk_signal_handler_block_by_data (GTK_OBJECT (priv->start_time),
- epage);
- g_signal_handlers_block_matched (priv->end_time, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
-
- e_date_edit_set_time (E_DATE_EDIT (priv->start_time), 0);
- e_date_edit_set_time (E_DATE_EDIT (priv->end_time), 0);
-
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time),
- epage);
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time),
- epage);
-
- set_all_day (epage, FALSE);
-
- /* Classification */
- e_dialog_option_menu_set (priv->classification, E_CAL_COMPONENT_CLASS_PRIVATE, classification_map);
-
- /* Show Time As (Transparency) */
- e_dialog_toggle_set (priv->show_time_as_busy, TRUE);
-
- /* Alarm */
- e_dialog_toggle_set (priv->alarm, FALSE);
- e_dialog_option_menu_set (priv->alarm_time, ALARM_15_MINUTES, alarm_map);
-
- /* Categories */
- e_dialog_editable_set (priv->categories, NULL);
-}
-
-static gboolean
-is_custom_alarm (ECalComponentAlarm *ca, char *old_summary, CalUnits user_units, int user_interval, int *alarm_type)
-{
- ECalComponentAlarmTrigger trigger;
- ECalComponentAlarmRepeat repeat;
- ECalComponentAlarmAction action;
- ECalComponentText desc;
- icalcomponent *icalcomp;
- icalproperty *icalprop;
- icalattach *attach;
- gboolean needs_desc = FALSE;
-
- e_cal_component_alarm_get_action (ca, &action);
- if (action != E_CAL_COMPONENT_ALARM_DISPLAY)
- return TRUE;
-
- e_cal_component_alarm_get_attach (ca, &attach);
- if (attach)
- return TRUE;
-
- icalcomp = e_cal_component_alarm_get_icalcomponent (ca);
- icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
- while (icalprop) {
- const char *x_name;
-
- x_name = icalproperty_get_x_name (icalprop);
- if (!strcmp (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION"))
- needs_desc = TRUE;
-
- icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
- }
-
- if (!needs_desc) {
- e_cal_component_alarm_get_description (ca, &desc);
- if (!desc.value || !old_summary || strcmp (desc.value, old_summary))
- return TRUE;
- }
-
- e_cal_component_alarm_get_repeat (ca, &repeat);
- if (repeat.repetitions != 0)
- return TRUE;
-
- if (e_cal_component_alarm_has_attendees (ca))
- return TRUE;
-
- e_cal_component_alarm_get_trigger (ca, &trigger);
- if (trigger.type != E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START)
- return TRUE;
-
- if (trigger.u.rel_duration.is_neg != 1)
- return TRUE;
-
- if (trigger.u.rel_duration.weeks != 0)
- return TRUE;
-
- if (trigger.u.rel_duration.seconds != 0)
- return TRUE;
-
- if (trigger.u.rel_duration.days == 1
- && trigger.u.rel_duration.hours == 0
- && trigger.u.rel_duration.minutes == 0) {
- if (alarm_type)
- *alarm_type = ALARM_1_DAY;
- return FALSE;
- }
-
- if (trigger.u.rel_duration.days == 0
- && trigger.u.rel_duration.hours == 1
- && trigger.u.rel_duration.minutes == 0) {
- if (alarm_type)
- *alarm_type = ALARM_1_HOUR;
- return FALSE;
- }
-
- if (trigger.u.rel_duration.days == 0
- && trigger.u.rel_duration.hours == 0
- && trigger.u.rel_duration.minutes == 15) {
- if (alarm_type)
- *alarm_type = ALARM_15_MINUTES;
- return FALSE;
- }
-
- if (user_interval != -1) {
- switch (user_units) {
- case CAL_DAYS:
- if (trigger.u.rel_duration.days == user_interval
- && trigger.u.rel_duration.hours == 0
- && trigger.u.rel_duration.minutes == 0) {
- if (alarm_type)
- *alarm_type = ALARM_USER_TIME;
- return FALSE;
- }
- break;
-
- case CAL_HOURS:
- if (trigger.u.rel_duration.days == 0
- && trigger.u.rel_duration.hours == user_interval
- && trigger.u.rel_duration.minutes == 0) {
- if (alarm_type)
- *alarm_type = ALARM_USER_TIME;
- return FALSE;
- }
- break;
-
- case CAL_MINUTES:
- if (trigger.u.rel_duration.days == 0
- && trigger.u.rel_duration.hours == 0
- && trigger.u.rel_duration.minutes == user_interval) {
- if (alarm_type)
- *alarm_type = ALARM_USER_TIME;
- return FALSE;
- }
- break;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-is_custom_alarm_uid_list (ECalComponent *comp, GList *alarms, char *old_summary, CalUnits user_units, int user_interval, int *alarm_type)
-{
- ECalComponentAlarm *ca;
- gboolean result;
-
- if (g_list_length (alarms) > 1)
- return TRUE;
-
- ca = e_cal_component_get_alarm (comp, alarms->data);
- result = is_custom_alarm (ca, old_summary, user_units, user_interval, alarm_type);
- e_cal_component_alarm_free (ca);
-
- return result;
-}
-
-static gboolean
-is_custom_alarm_store (EAlarmList *alarm_list_store, char *old_summary, CalUnits user_units, int user_interval, int *alarm_type)
-{
- const ECalComponentAlarm *alarm;
- GtkTreeModel *model;
- GtkTreeIter iter;
- gboolean valid_iter;
-
- model = GTK_TREE_MODEL (alarm_list_store);
-
- valid_iter = gtk_tree_model_get_iter_first (model, &iter);
- if (!valid_iter)
- return FALSE;
-
- alarm = e_alarm_list_get_alarm (alarm_list_store, &iter);
- if (is_custom_alarm ((ECalComponentAlarm *)alarm, old_summary, user_units, user_interval, alarm_type))
- return TRUE;
-
- valid_iter = gtk_tree_model_iter_next (model, &iter);
- if (valid_iter)
- return TRUE;
-
- return FALSE;
-}
-
-static void
-sensitize_widgets (EventPage *epage)
-{
- gboolean read_only, custom, alarm;
- EventPagePrivate *priv;
-
- priv = epage->priv;
-
- if (!e_cal_is_read_only (COMP_EDITOR_PAGE (epage)->client, &read_only, NULL))
- read_only = TRUE;
-
- custom = is_custom_alarm_store (priv->alarm_list_store, priv->old_summary, priv->alarm_units, priv->alarm_interval, NULL);
- alarm = e_dialog_toggle_get (priv->alarm);
-
- gtk_widget_set_sensitive (priv->summary_label, !read_only);
- gtk_entry_set_editable (GTK_ENTRY (priv->summary), !read_only);
- gtk_widget_set_sensitive (priv->location_label, !read_only);
- gtk_entry_set_editable (GTK_ENTRY (priv->location), !read_only);
- gtk_widget_set_sensitive (priv->start_time, !read_only);
- gtk_widget_set_sensitive (priv->start_timezone, !read_only);
- gtk_widget_set_sensitive (priv->end_time, !read_only);
- gtk_widget_set_sensitive (priv->end_timezone, !read_only);
- gtk_widget_set_sensitive (priv->all_day_event, !read_only);
- gtk_widget_set_sensitive (priv->description, !read_only);
- gtk_widget_set_sensitive (priv->classification, !read_only);
- gtk_widget_set_sensitive (priv->show_time_as_busy, !read_only);
- gtk_widget_set_sensitive (priv->alarm, !read_only);
- gtk_widget_set_sensitive (priv->alarm_time, !read_only && !custom && alarm);
- gtk_widget_set_sensitive (priv->alarm_custom, !read_only && alarm);
- if (custom)
- gtk_widget_show (priv->alarm_warning);
- else
- gtk_widget_hide (priv->alarm_warning);
- gtk_widget_set_sensitive (priv->categories_btn, !read_only);
- gtk_entry_set_editable (GTK_ENTRY (priv->categories), !read_only);
-}
-
-/* fill_widgets handler for the event page */
-static gboolean
-event_page_fill_widgets (CompEditorPage *page, ECalComponent *comp)
-{
- EventPage *epage;
- EventPagePrivate *priv;
- ECalComponentText text;
- ECalComponentClassification cl;
- ECalComponentTransparency transparency;
- ECalComponentDateTime start_date, end_date;
- const char *location;
- const char *categories;
- ESource *source;
- GSList *l;
- gboolean validated = TRUE;
-
- g_return_val_if_fail (page->client != NULL, FALSE);
-
- epage = EVENT_PAGE (page);
- priv = epage->priv;
-
- /* Don't send off changes during this time */
- priv->updating = TRUE;
-
- /* Clean the page */
- clear_widgets (epage);
-
- /* Summary, location, description(s) */
-
- e_cal_component_get_summary (comp, &text);
- e_dialog_editable_set (priv->summary, text.value);
- priv->old_summary = g_strdup (text.value);
-
- e_cal_component_get_location (comp, &location);
- e_dialog_editable_set (priv->location, location);
-
- e_cal_component_get_description_list (comp, &l);
- if (l && l->data) {
- ECalComponentText *dtext;
-
- dtext = l->data;
- gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->description)),
- dtext->value ? dtext->value : "", -1);
- }
- e_cal_component_free_text_list (l);
-
- /* Start and end times */
-
- e_cal_component_get_dtstart (comp, &start_date);
- e_cal_component_get_dtend (comp, &end_date);
- if (!start_date.value) {
- comp_editor_page_display_validation_error (page, _("Event with no start date"), priv->start_time);
- validated = FALSE;
- } else if (!end_date.value) {
- comp_editor_page_display_validation_error (page, _("Event with no end date"), priv->end_time);
- validated = FALSE;
- } else
- update_time (epage, &start_date, &end_date);
-
- e_cal_component_free_datetime (&start_date);
- e_cal_component_free_datetime (&end_date);
-
- /* Classification */
- e_cal_component_get_classification (comp, &cl);
-
- switch (cl) {
- case E_CAL_COMPONENT_CLASS_PUBLIC:
- case E_CAL_COMPONENT_CLASS_PRIVATE:
- case E_CAL_COMPONENT_CLASS_CONFIDENTIAL:
- break;
- default:
- cl = E_CAL_COMPONENT_CLASS_PUBLIC;
- break;
- }
- e_dialog_option_menu_set (priv->classification, cl, classification_map);
-
- /* Show Time As (Transparency) */
- e_cal_component_get_transparency (comp, &transparency);
- switch (transparency) {
- case E_CAL_COMPONENT_TRANSP_TRANSPARENT:
- e_dialog_toggle_set (priv->show_time_as_busy, FALSE);
- break;
-
- default:
- e_dialog_toggle_set (priv->show_time_as_busy, TRUE);
- break;
- }
- if (e_cal_get_static_capability (page->client, CAL_STATIC_CAPABILITY_NO_TRANSPARENCY))
- gtk_widget_hide (priv->show_time_as_busy);
- else
- gtk_widget_show (priv->show_time_as_busy);
-
- /* Alarms */
- g_signal_handlers_block_matched (priv->alarm, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
- if (e_cal_component_has_alarms (comp)) {
- GList *alarms, *l;
- int alarm_type;
-
- e_dialog_toggle_set (priv->alarm, TRUE);
-
- alarms = e_cal_component_get_alarm_uids (comp);
- if (!is_custom_alarm_uid_list (comp, alarms, priv->old_summary, priv->alarm_units, priv->alarm_interval, &alarm_type))
- e_dialog_option_menu_set (priv->alarm_time, alarm_type, alarm_map);
-
- for (l = alarms; l != NULL; l = l->next) {
- ECalComponentAlarm *ca;
-
- ca = e_cal_component_get_alarm (comp, l->data);
- e_alarm_list_append (priv->alarm_list_store, NULL, ca);
- e_cal_component_alarm_free (ca);
- }
-
- cal_obj_uid_list_free (alarms);
- } else {
- e_dialog_toggle_set (priv->alarm, FALSE);
- e_dialog_option_menu_set (priv->alarm_time, priv->alarm_interval == -1 ? ALARM_15_MINUTES : ALARM_USER_TIME, alarm_map);
- }
- g_signal_handlers_unblock_matched (priv->alarm, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
-
- /* Categories */
- e_cal_component_get_categories (comp, &categories);
- e_dialog_editable_set (priv->categories, categories);
-
- /* Source */
- source = e_cal_get_source (page->client);
- e_source_option_menu_select (E_SOURCE_OPTION_MENU (priv->source_selector), source);
-
- priv->updating = FALSE;
-
- sensitize_widgets (epage);
-
- return validated;
-}
-
-/* fill_component handler for the event page */
-static gboolean
-event_page_fill_component (CompEditorPage *page, ECalComponent *comp)
-{
- EventPage *epage;
- EventPagePrivate *priv;
- ECalComponentDateTime start_date, end_date;
- struct icaltimetype start_tt, end_tt;
- gboolean all_day_event, start_date_set, end_date_set, busy;
- char *cat, *str;
- ECalComponentClassification classif;
- GtkTextBuffer *text_buffer;
- GtkTextIter text_iter_start, text_iter_end;
-
- epage = EVENT_PAGE (page);
- priv = epage->priv;
- text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->description));
-
- /* Summary */
-
- str = e_dialog_editable_get (priv->summary);
- if (!str || strlen (str) == 0)
- e_cal_component_set_summary (comp, NULL);
- else {
- ECalComponentText text;
-
- text.value = str;
- text.altrep = NULL;
-
- e_cal_component_set_summary (comp, &text);
- }
-
- if (str)
- g_free (str);
-
- /* Location */
-
- str = e_dialog_editable_get (priv->location);
- if (!str || strlen (str) == 0)
- e_cal_component_set_location (comp, NULL);
- else
- e_cal_component_set_location (comp, str);
-
- if (str)
- g_free (str);
-
- /* Description */
-
- gtk_text_buffer_get_start_iter (text_buffer, &text_iter_start);
- gtk_text_buffer_get_end_iter (text_buffer, &text_iter_end);
- str = gtk_text_buffer_get_text (text_buffer, &text_iter_start, &text_iter_end, FALSE);
-
- if (!str || strlen (str) == 0)
- e_cal_component_set_description_list (comp, NULL);
- else {
- GSList l;
- ECalComponentText text;
-
- text.value = str;
- text.altrep = NULL;
- l.data = &text;
- l.next = NULL;
-
- e_cal_component_set_description_list (comp, &l);
- }
-
- if (str)
- g_free (str);
-
- /* Dates */
-
- start_tt = icaltime_null_time ();
- start_date.value = &start_tt;
- start_date.tzid = NULL;
-
- end_tt = icaltime_null_time ();
- end_date.value = &end_tt;
- end_date.tzid = NULL;
-
- if (!e_date_edit_date_is_valid (E_DATE_EDIT (priv->start_time))) {
- comp_editor_page_display_validation_error (page, _("Start date is wrong"), priv->start_time);
- return FALSE;
- }
- start_date_set = e_date_edit_get_date (E_DATE_EDIT (priv->start_time),
- &start_tt.year,
- &start_tt.month,
- &start_tt.day);
- g_assert (start_date_set);
-
- if (!e_date_edit_date_is_valid (E_DATE_EDIT (priv->end_time))) {
- comp_editor_page_display_validation_error (page, _("End date is wrong"), priv->end_time);
- return FALSE;
- }
- end_date_set = e_date_edit_get_date (E_DATE_EDIT (priv->end_time),
- &end_tt.year,
- &end_tt.month,
- &end_tt.day);
- g_assert (end_date_set);
-
- /* If the all_day toggle is set, we use DATE values for DTSTART and
- DTEND. If not, we fetch the hour & minute from the widgets. */
- all_day_event = e_dialog_toggle_get (priv->all_day_event);
-
- if (all_day_event) {
- start_tt.is_date = TRUE;
- end_tt.is_date = TRUE;
-
- /* We have to add 1 day to DTEND, as it is not inclusive. */
- icaltime_adjust (&end_tt, 1, 0, 0, 0);
- } else {
- icaltimezone *start_zone, *end_zone;
-
- if (!e_date_edit_time_is_valid (E_DATE_EDIT (priv->start_time))) {
- comp_editor_page_display_validation_error (page, _("Start time is wrong"), priv->start_time);
- return FALSE;
- }
- e_date_edit_get_time_of_day (E_DATE_EDIT (priv->start_time),
- &start_tt.hour,
- &start_tt.minute);
- if (!e_date_edit_time_is_valid (E_DATE_EDIT (priv->end_time))) {
- comp_editor_page_display_validation_error (page, _("End time is wrong"), priv->end_time);
- return FALSE;
- }
- e_date_edit_get_time_of_day (E_DATE_EDIT (priv->end_time),
- &end_tt.hour,
- &end_tt.minute);
- start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone));
- start_date.tzid = icaltimezone_get_tzid (start_zone);
- end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone));
- end_date.tzid = icaltimezone_get_tzid (end_zone);
- }
-
- e_cal_component_set_dtstart (comp, &start_date);
- e_cal_component_set_dtend (comp, &end_date);
-
-
- /* Categories */
-
- cat = e_dialog_editable_get (priv->categories);
- str = comp_editor_strip_categories (cat);
- if (cat)
- g_free (cat);
-
- e_cal_component_set_categories (comp, str);
-
- if (str)
- g_free (str);
-
- /* Classification */
- classif = e_dialog_option_menu_get (priv->classification, classification_map);
- e_cal_component_set_classification (comp, classif);
-
- /* Show Time As (Transparency) */
- busy = e_dialog_toggle_get (priv->show_time_as_busy);
- e_cal_component_set_transparency (comp, busy ? E_CAL_COMPONENT_TRANSP_OPAQUE : E_CAL_COMPONENT_TRANSP_TRANSPARENT);
-
- /* Alarm */
- e_cal_component_remove_all_alarms (comp);
- if (e_dialog_toggle_get (priv->alarm)) {
- if (is_custom_alarm_store (priv->alarm_list_store, priv->old_summary, priv->alarm_units, priv->alarm_interval, NULL)) {
- GtkTreeModel *model;
- GtkTreeIter iter;
- gboolean valid_iter;
-
- model = GTK_TREE_MODEL (priv->alarm_list_store);
-
- for (valid_iter = gtk_tree_model_get_iter_first (model, &iter); valid_iter;
- valid_iter = gtk_tree_model_iter_next (model, &iter)) {
- ECalComponentAlarm *alarm, *alarm_copy;
- icalcomponent *icalcomp;
- icalproperty *icalprop;
-
- alarm = (ECalComponentAlarm *) e_alarm_list_get_alarm (priv->alarm_list_store, &iter);
- g_assert (alarm != NULL);
-
- /* We set the description of the alarm if it's got
- * the X-EVOLUTION-NEEDS-DESCRIPTION property.
- */
- icalcomp = e_cal_component_alarm_get_icalcomponent (alarm);
- icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
- while (icalprop) {
- const char *x_name;
- ECalComponentText summary;
-
- x_name = icalproperty_get_x_name (icalprop);
- if (!strcmp (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION")) {
- e_cal_component_get_summary (comp, &summary);
- e_cal_component_alarm_set_description (alarm, &summary);
-
- icalcomponent_remove_property (icalcomp, icalprop);
- break;
- }
-
- icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
- }
-
- /* We clone the alarm to maintain the invariant that the alarm
- * structures in the list did *not* come from the component.
- */
-
- alarm_copy = e_cal_component_alarm_clone (alarm);
- e_cal_component_add_alarm (comp, alarm_copy);
- e_cal_component_alarm_free (alarm_copy);
- }
- } else {
- ECalComponentAlarm *ca;
- ECalComponentText summary;
- ECalComponentAlarmTrigger trigger;
- int alarm_type;
-
- ca = e_cal_component_alarm_new ();
-
- e_cal_component_get_summary (comp, &summary);
- e_cal_component_alarm_set_description (ca, &summary);
-
- e_cal_component_alarm_set_action (ca, E_CAL_COMPONENT_ALARM_DISPLAY);
-
- memset (&trigger, 0, sizeof (ECalComponentAlarmTrigger));
- trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
- trigger.u.rel_duration.is_neg = 1;
-
- alarm_type = e_dialog_option_menu_get (priv->alarm_time, alarm_map);
- switch (alarm_type) {
- case ALARM_15_MINUTES:
- trigger.u.rel_duration.minutes = 15;
- break;
-
- case ALARM_1_HOUR:
- trigger.u.rel_duration.hours = 1;
- break;
-
- case ALARM_1_DAY:
- trigger.u.rel_duration.days = 1;
- break;
-
- case ALARM_USER_TIME:
- switch (calendar_config_get_default_reminder_units ()) {
- case CAL_DAYS:
- trigger.u.rel_duration.days = priv->alarm_interval;
- break;
-
- case CAL_HOURS:
- trigger.u.rel_duration.hours = priv->alarm_interval;
- break;
-
- case CAL_MINUTES:
- trigger.u.rel_duration.minutes = priv->alarm_interval;
- break;
- }
- break;
-
- default:
- break;
- }
- e_cal_component_alarm_set_trigger (ca, trigger);
-
- e_cal_component_add_alarm (comp, ca);
- }
- }
-
- return TRUE;
-}
-
-/* fill_timezones handler for the event page */
-static gboolean
-event_page_fill_timezones (CompEditorPage *page, GHashTable *timezones)
-{
- EventPage *epage;
- EventPagePrivate *priv;
- icaltimezone *zone;
-
- epage = EVENT_PAGE (page);
- priv = epage->priv;
-
- /* add start date timezone */
- zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone));
- if (zone) {
- if (!g_hash_table_lookup (timezones, icaltimezone_get_tzid (zone)))
- g_hash_table_insert (timezones, icaltimezone_get_tzid (zone), zone);
- }
-
- /* add end date timezone */
- zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone));
- if (zone) {
- if (!g_hash_table_lookup (timezones, icaltimezone_get_tzid (zone)))
- g_hash_table_insert (timezones, icaltimezone_get_tzid (zone), zone);
- }
-
- return TRUE;
-}
-
-/* set_summary handler for the event page */
-static void
-event_page_set_summary (CompEditorPage *page, const char *summary)
-{
- /* nothing */
-}
-
-static void
-event_page_set_dates (CompEditorPage *page, CompEditorPageDates *dates)
-{
- update_time (EVENT_PAGE (page), dates->start, dates->end);
-}
-
-
-
-/* Gets the widgets from the XML file and returns if they are all available. */
-static gboolean
-get_widgets (EventPage *epage)
-{
- CompEditorPage *page = COMP_EDITOR_PAGE (epage);
- EventPagePrivate *priv;
- GSList *accel_groups;
- GtkWidget *toplevel;
-
- priv = epage->priv;
-
-#define GW(name) glade_xml_get_widget (priv->xml, name)
-
- priv->main = GW ("event-page");
- if (!priv->main)
- return FALSE;
-
- /* Get the GtkAccelGroup from the toplevel window, so we can install
- it when the notebook page is mapped. */
- toplevel = gtk_widget_get_toplevel (priv->main);
- accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
- if (accel_groups) {
- page->accel_group = accel_groups->data;
- gtk_accel_group_ref (page->accel_group);
- }
-
- gtk_widget_ref (priv->main);
- gtk_container_remove (GTK_CONTAINER (priv->main->parent), priv->main);
-
- priv->summary = GW ("summary");
- priv->summary_label = GW ("summary-label");
- priv->location = GW ("location");
- priv->location_label = GW ("location-label");
-
- /* Glade's visibility flag doesn't seem to work for custom widgets */
- priv->start_time = GW ("start-time");
- gtk_widget_show (priv->start_time);
- priv->end_time = GW ("end-time");
- gtk_widget_show (priv->end_time);
-
- priv->start_timezone = GW ("start-timezone");
- priv->end_timezone = GW ("end-timezone");
- priv->all_day_event = GW ("all-day-event");
-
- priv->description = GW ("description");
-
- priv->classification = GW ("classification");
-
- priv->show_time_as_busy = GW ("show-time-as-busy");
-
- priv->alarm = GW ("alarm");
- priv->alarm_time = GW ("alarm-time");
- priv->alarm_warning = GW ("alarm-warning");
- priv->alarm_custom = GW ("alarm-custom");
-
- priv->categories_btn = GW ("categories-button");
- priv->categories = GW ("categories");
-
- priv->source_selector = GW ("source");
-
-#undef GW
-
- return (priv->summary
- && priv->location
- && priv->start_time
- && priv->end_time
- && priv->start_timezone
- && priv->end_timezone
- && priv->all_day_event
- && priv->description
- && priv->classification
- && priv->show_time_as_busy
- && priv->alarm
- && priv->alarm_time
- && priv->alarm_warning
- && priv->alarm_custom
- && 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;
- EventPagePrivate *priv;
- gchar *summary;
-
- epage = EVENT_PAGE (data);
- priv = epage->priv;
-
- if (priv->updating)
- return;
-
- summary = e_dialog_editable_get (GTK_WIDGET (editable));
- comp_editor_page_notify_summary_changed (COMP_EDITOR_PAGE (epage),
- summary);
- g_free (summary);
-}
-
-
-/* Note that this assumes that the start_tt and end_tt passed to it are the
- dates visible to the user. For DATE values, we have to add 1 day to the
- end_tt before emitting the signal. */
-static void
-notify_dates_changed (EventPage *epage, struct icaltimetype *start_tt,
- struct icaltimetype *end_tt)
-{
- EventPagePrivate *priv;
- CompEditorPageDates dates;
- ECalComponentDateTime start_dt, end_dt;
- gboolean all_day_event;
- icaltimezone *start_zone = NULL, *end_zone = NULL;
-
- priv = epage->priv;
-
- all_day_event = e_dialog_toggle_get (priv->all_day_event);
-
- start_dt.value = start_tt;
- end_dt.value = end_tt;
-
- if (all_day_event) {
- /* The actual DTEND is 1 day after the displayed date for
- DATE values. */
- icaltime_adjust (end_tt, 1, 0, 0, 0);
- } else {
- start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone));
- end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone));
- }
-
- start_dt.tzid = start_zone ? icaltimezone_get_tzid (start_zone) : NULL;
- end_dt.tzid = end_zone ? icaltimezone_get_tzid (end_zone) : NULL;
-
- dates.start = &start_dt;
- dates.end = &end_dt;
-
- dates.due = NULL;
- dates.complete = NULL;
-
- comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (epage),
- &dates);
-}
-
-
-static gboolean
-check_start_before_end (struct icaltimetype *start_tt,
- icaltimezone *start_zone,
- struct icaltimetype *end_tt,
- icaltimezone *end_zone,
- gboolean adjust_end_time)
-{
- struct icaltimetype end_tt_copy;
- int cmp;
-
- /* Convert the end time to the same timezone as the start time. */
- end_tt_copy = *end_tt;
- icaltimezone_convert_time (&end_tt_copy, end_zone, start_zone);
-
- /* Now check if the start time is after the end time. If it is,
- we need to modify one of the times. */
- cmp = icaltime_compare (*start_tt, end_tt_copy);
- if (cmp > 0) {
- if (adjust_end_time) {
- /* Modify the end time, to be the start + 1 hour. */
- *end_tt = *start_tt;
- icaltime_adjust (end_tt, 0, 1, 0, 0);
- icaltimezone_convert_time (end_tt, start_zone,
- end_zone);
- } else {
- /* Modify the start time, to be the end - 1 hour. */
- *start_tt = *end_tt;
- icaltime_adjust (start_tt, 0, -1, 0, 0);
- icaltimezone_convert_time (start_tt, end_zone,
- start_zone);
- }
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/*
- * This is called whenever the start or end dates or timezones is changed.
- * It makes sure that the start date < end date. It also emits the notification
- * signals so the other event editor pages update their labels etc.
- *
- * If adjust_end_time is TRUE, if the start time < end time it will adjust
- * the end time. If FALSE it will adjust the start time. If the user sets the
- * start or end time, the other time is adjusted to make it valid.
- */
-static void
-times_updated (EventPage *epage, gboolean adjust_end_time)
-{
- EventPagePrivate *priv;
- struct icaltimetype start_tt = icaltime_null_time();
- struct icaltimetype end_tt = icaltime_null_time();
- gboolean date_set, all_day_event;
- gboolean set_start_date = FALSE, set_end_date = FALSE;
- icaltimezone *start_zone, *end_zone;
-
- priv = epage->priv;
-
- if (priv->updating)
- return;
-
- /* Fetch the start and end times and timezones from the widgets. */
- all_day_event = e_dialog_toggle_get (priv->all_day_event);
-
- date_set = e_date_edit_get_date (E_DATE_EDIT (priv->start_time),
- &start_tt.year,
- &start_tt.month,
- &start_tt.day);
- g_assert (date_set);
-
- date_set = e_date_edit_get_date (E_DATE_EDIT (priv->end_time),
- &end_tt.year,
- &end_tt.month,
- &end_tt.day);
- g_assert (date_set);
-
- if (all_day_event) {
- /* All Day Events are simple. We just compare the dates and if
- start > end we copy one of them to the other. */
- int cmp = icaltime_compare_date_only (start_tt, end_tt);
- if (cmp > 0) {
- if (adjust_end_time) {
- end_tt = start_tt;
- set_end_date = TRUE;
- } else {
- start_tt = end_tt;
- set_start_date = TRUE;
- }
- }
-
- start_tt.is_date = TRUE;
- end_tt.is_date = TRUE;
- } else {
- /* For DATE-TIME events, we have to convert to the same
- timezone before comparing. */
- e_date_edit_get_time_of_day (E_DATE_EDIT (priv->start_time),
- &start_tt.hour,
- &start_tt.minute);
- e_date_edit_get_time_of_day (E_DATE_EDIT (priv->end_time),
- &end_tt.hour,
- &end_tt.minute);
-
- start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone));
- end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone));
-
- if (check_start_before_end (&start_tt, start_zone,
- &end_tt, end_zone,
- adjust_end_time)) {
- if (adjust_end_time)
- set_end_date = TRUE;
- else
- set_start_date = TRUE;
- }
- }
-
-
- if (set_start_date) {
- g_signal_handlers_block_matched (priv->start_time, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
- e_date_edit_set_date (E_DATE_EDIT (priv->start_time),
- start_tt.year, start_tt.month,
- start_tt.day);
- e_date_edit_set_time_of_day (E_DATE_EDIT (priv->start_time),
- start_tt.hour, start_tt.minute);
- g_signal_handlers_unblock_matched (priv->start_time, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
- }
-
- if (set_end_date) {
- g_signal_handlers_block_matched (priv->end_time, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
- e_date_edit_set_date (E_DATE_EDIT (priv->end_time),
- end_tt.year, end_tt.month, end_tt.day);
- e_date_edit_set_time_of_day (E_DATE_EDIT (priv->end_time),
- end_tt.hour, end_tt.minute);
- g_signal_handlers_unblock_matched (priv->end_time, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, epage);
- }
-
- /* Notify upstream */
- notify_dates_changed (epage, &start_tt, &end_tt);
-}
-
-/* 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 (GtkWidget *dedit, gpointer data)
-{
- EventPage *epage;
-
- epage = EVENT_PAGE (data);
-
- times_updated (epage, dedit == epage->priv->start_time);
-}
-
-
-/* Callback used when the start timezone is changed. If sync_timezones is set,
- * we set the end timezone to the same value. It also updates the start time
- * labels on the other notebook pages.
- */
-static void
-start_timezone_changed_cb (GtkWidget *widget, gpointer data)
-{
- EventPage *epage;
- EventPagePrivate *priv;
- icaltimezone *zone;
-
- epage = EVENT_PAGE (data);
- priv = epage->priv;
-
- if (priv->sync_timezones) {
- zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone));
- priv->updating = TRUE;
- e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (priv->end_timezone), zone);
- priv->updating = FALSE;
- }
-
- times_updated (epage, TRUE);
-}
-
-
-/* Callback used when the end timezone is changed. It checks if the end
- * timezone is the same as the start timezone and sets sync_timezones if so.
- */
-static void
-end_timezone_changed_cb (GtkWidget *widget, gpointer data)
-{
- EventPage *epage;
- EventPagePrivate *priv;
- icaltimezone *start_zone, *end_zone;
-
- epage = EVENT_PAGE (data);
- priv = epage->priv;
-
- start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone));
- end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone));
-
- priv->sync_timezones = (start_zone == end_zone) ? TRUE : FALSE;
-
- times_updated (epage, TRUE);
-}
-
-/* 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;
- gboolean all_day;
- struct icaltimetype start_tt = icaltime_null_time();
- struct icaltimetype end_tt = icaltime_null_time();
- gboolean date_set;
-
- 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 round it down to the previous day, so the
- * event times stay the same.
- *
- * When the all_day_toggle is turned off, then if the event is within
- * one day, we set the event start to the start of the working day,
- * and set the event end to one hour after it. If the event is longer
- * than one day, we set the event end to the end of the day it is on,
- * so that the actual event times remain the same.
- *
- * This may need tweaking to work well with different timezones used
- * in the event start & end.
- */
- all_day = GTK_TOGGLE_BUTTON (toggle)->active;
-
- set_all_day (epage, all_day);
-
- date_set = e_date_edit_get_date (E_DATE_EDIT (priv->start_time),
- &start_tt.year,
- &start_tt.month,
- &start_tt.day);
- e_date_edit_get_time_of_day (E_DATE_EDIT (priv->start_time),
- &start_tt.hour,
- &start_tt.minute);
- g_assert (date_set);
-
- date_set = e_date_edit_get_date (E_DATE_EDIT (priv->end_time),
- &end_tt.year,
- &end_tt.month,
- &end_tt.day);
- e_date_edit_get_time_of_day (E_DATE_EDIT (priv->end_time),
- &end_tt.hour,
- &end_tt.minute);
- g_assert (date_set);
-
- if (all_day) {
- /* Round down to the start of the day. */
- start_tt.hour = 0;
- start_tt.minute = 0;
- start_tt.second = 0;
- start_tt.is_date = TRUE;
-
- /* Round down to the start of the day, or the start of the
- previous day if it is midnight. */
- icaltime_adjust (&end_tt, 0, 0, 0, -1);
- end_tt.hour = 0;
- end_tt.minute = 0;
- end_tt.second = 0;
- end_tt.is_date = TRUE;
- } else {
- icaltimezone *start_zone, *end_zone;
-
- if (end_tt.year == start_tt.year
- && end_tt.month == start_tt.month
- && end_tt.day == start_tt.day) {
- /* The event is within one day, so we set the event
- start to the start of the working day, and the end
- to one hour later. */
- start_tt.hour = calendar_config_get_day_start_hour ();
- start_tt.minute = calendar_config_get_day_start_minute ();
- start_tt.second = 0;
-
- end_tt = start_tt;
- icaltime_adjust (&end_tt, 0, 1, 0, 0);
- } else {
- /* The event is longer than 1 day, so we keep exactly
- the same times, just using DATE-TIME rather than
- DATE. */
- icaltime_adjust (&end_tt, 1, 0, 0, 0);
- }
-
- /* Make sure that end > start using the timezones. */
- start_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->start_timezone));
- end_zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->end_timezone));
- check_start_before_end (&start_tt, start_zone,
- &end_tt, end_zone,
- TRUE);
- }
-
- 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_date (E_DATE_EDIT (priv->start_time), start_tt.year,
- start_tt.month, start_tt.day);
- e_date_edit_set_time_of_day (E_DATE_EDIT (priv->start_time),
- start_tt.hour, start_tt.minute);
-
- e_date_edit_set_date (E_DATE_EDIT (priv->end_time), end_tt.year,
- end_tt.month, end_tt.day);
- e_date_edit_set_time_of_day (E_DATE_EDIT (priv->end_time),
- end_tt.hour, end_tt.minute);
-
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->start_time),
- epage);
- gtk_signal_handler_unblock_by_data (GTK_OBJECT (priv->end_time),
- epage);
-
- /* Notify upstream */
- notify_dates_changed (epage, &start_tt, &end_tt);
-}
-
-/* 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;
- GtkWidget *entry;
-
- epage = EVENT_PAGE (data);
- priv = epage->priv;
-
- entry = priv->categories;
- e_categories_config_open_dialog_for_entry (GTK_ENTRY (entry));
-}
-
-/* This is called when any field is changed; it notifies upstream. */
-static void
-field_changed_cb (GtkWidget *widget, gpointer data)
-{
- EventPage *epage;
- EventPagePrivate *priv;
-
- epage = EVENT_PAGE (data);
- priv = epage->priv;
-
- if (!priv->updating)
- comp_editor_page_notify_changed (COMP_EDITOR_PAGE (epage));
-}
-
-static void
-source_changed_cb (GtkWidget *widget, ESource *source, gpointer data)
-{
- EventPage *epage;
- EventPagePrivate *priv;
-
- epage = EVENT_PAGE (data);
- priv = epage->priv;
-
- if (!priv->updating) {
- ECal *client;
-
- client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_EVENT);
- if (!client || !e_cal_open (client, FALSE, NULL)) {
- GtkWidget *dialog;
-
- if (client)
- g_object_unref (client);
-
- e_source_option_menu_select (E_SOURCE_OPTION_MENU (priv->source_selector),
- e_cal_get_source (COMP_EDITOR_PAGE (epage)->client));
-
- dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
- GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
- _("Unable to open the calendar '%s'."),
- e_source_peek_name (source));
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- } else {
- icaltimezone *zone;
-
- zone = calendar_config_get_icaltimezone ();
- e_cal_set_default_timezone (client, zone, NULL);
-
- comp_editor_notify_client_changed (
- COMP_EDITOR (gtk_widget_get_toplevel (priv->main)),
- client);
- sensitize_widgets (epage);
- }
- }
-}
-
-static void
-alarm_changed_cb (GtkWidget *widget, gpointer data)
-{
- EventPage *epage;
- EventPagePrivate *priv;
-
- epage = EVENT_PAGE (data);
- priv = epage->priv;
-
- if (e_dialog_toggle_get (priv->alarm)) {
- ECalComponentAlarm *ca;
- ECalComponentAlarmTrigger trigger;
- icalcomponent *icalcomp;
- icalproperty *icalprop;
- int alarm_type;
-
- ca = e_cal_component_alarm_new ();
-
- e_cal_component_alarm_set_action (ca, E_CAL_COMPONENT_ALARM_DISPLAY);
-
- memset (&trigger, 0, sizeof (ECalComponentAlarmTrigger));
- trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
- trigger.u.rel_duration.is_neg = 1;
-
- alarm_type = e_dialog_option_menu_get (priv->alarm_time, alarm_map);
- switch (alarm_type) {
- case ALARM_15_MINUTES:
- trigger.u.rel_duration.minutes = 15;
- break;
-
- case ALARM_1_HOUR:
- trigger.u.rel_duration.hours = 1;
- break;
-
- case ALARM_1_DAY:
- trigger.u.rel_duration.days = 1;
- break;
-
- case ALARM_USER_TIME:
- switch (calendar_config_get_default_reminder_units ()) {
- case CAL_DAYS:
- trigger.u.rel_duration.days = priv->alarm_interval;
- break;
-
- case CAL_HOURS:
- trigger.u.rel_duration.hours = priv->alarm_interval;
- break;
-
- case CAL_MINUTES:
- trigger.u.rel_duration.minutes = priv->alarm_interval;
- break;
- }
- break;
-
- default:
- break;
- }
- e_cal_component_alarm_set_trigger (ca, trigger);
-
- icalcomp = e_cal_component_alarm_get_icalcomponent (ca);
- icalprop = icalproperty_new_x ("1");
- icalproperty_set_x_name (icalprop, "X-EVOLUTION-NEEDS-DESCRIPTION");
- icalcomponent_add_property (icalcomp, icalprop);
-
- e_alarm_list_append (priv->alarm_list_store, NULL, ca);
- } else {
- e_alarm_list_clear (priv->alarm_list_store);
- }
-
- sensitize_widgets (epage);
-}
-
-static void
-alarm_custom_clicked_cb (GtkWidget *widget, gpointer data)
-{
- EventPage *epage;
- EventPagePrivate *priv;
- EAlarmList *temp_list_store;
- GtkTreeModel *model;
- GtkTreeIter iter;
- gboolean valid_iter;
- GtkWidget *toplevel;
-
- epage = EVENT_PAGE (data);
- priv = epage->priv;
-
- /* Make a copy of the list store in case the user cancels */
- temp_list_store = e_alarm_list_new ();
- model = GTK_TREE_MODEL (priv->alarm_list_store);
-
- for (valid_iter = gtk_tree_model_get_iter_first (model, &iter); valid_iter;
- valid_iter = gtk_tree_model_iter_next (model, &iter)) {
- ECalComponentAlarm *alarm;
-
- alarm = (ECalComponentAlarm *) e_alarm_list_get_alarm (priv->alarm_list_store, &iter);
- g_assert (alarm != NULL);
-
- e_alarm_list_append (temp_list_store, NULL, alarm);
- }
-
- toplevel = gtk_widget_get_toplevel (priv->main);
- if (alarm_list_dialog_run (toplevel, COMP_EDITOR_PAGE (epage)->client, temp_list_store)) {
- g_object_unref (priv->alarm_list_store);
- priv->alarm_list_store = temp_list_store;
-
- comp_editor_page_notify_changed (COMP_EDITOR_PAGE (epage));
- } else {
- g_object_unref (temp_list_store);
- }
-
- /* If the user erases everything, uncheck the alarm toggle */
- valid_iter = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->alarm_list_store), &iter);
- if (!valid_iter)
- e_dialog_toggle_set (priv->alarm, FALSE);
-
- sensitize_widgets (epage);
-}
-
-/* Hooks the widget signals */
-static gboolean
-init_widgets (EventPage *epage)
-{
- EventPagePrivate *priv;
- GtkTextBuffer *text_buffer;
- icaltimezone *zone;
- char *menu_label = NULL;
-
- priv = epage->priv;
-
- /* Make sure the EDateEdit widgets use our timezones to get the
- current time. */
- e_date_edit_set_get_time_callback (E_DATE_EDIT (priv->start_time),
- (EDateEditGetTimeCallback) comp_editor_get_current_time,
- epage, NULL);
- e_date_edit_set_get_time_callback (E_DATE_EDIT (priv->end_time),
- (EDateEditGetTimeCallback) comp_editor_get_current_time,
- epage, NULL);
-
- /* Summary */
- g_signal_connect((priv->summary), "changed",
- G_CALLBACK (summary_changed_cb), epage);
-
- /* Description */
- text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->description));
-
- gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (priv->description), GTK_WRAP_WORD);
-
- /* Start and end times */
- g_signal_connect((priv->start_time), "changed",
- G_CALLBACK (date_changed_cb), epage);
- g_signal_connect((priv->end_time), "changed",
- G_CALLBACK (date_changed_cb), epage);
-
- g_signal_connect((priv->start_timezone), "changed",
- G_CALLBACK (start_timezone_changed_cb), epage);
- g_signal_connect((priv->end_timezone), "changed",
- G_CALLBACK (end_timezone_changed_cb), epage);
-
- g_signal_connect((priv->all_day_event), "toggled",
- G_CALLBACK (all_day_event_toggled_cb), epage);
-
- /* Categories button */
- g_signal_connect((priv->categories_btn), "clicked",
- G_CALLBACK (categories_clicked_cb), epage);
-
- /* Source selector */
- g_signal_connect((priv->source_selector), "source_selected",
- G_CALLBACK (source_changed_cb), epage);
-
- /* Alarms */
- priv->alarm_list_store = e_alarm_list_new ();
-
- /* Add the user defined time if necessary */
- priv->alarm_units = calendar_config_get_default_reminder_units ();
- priv->alarm_interval = calendar_config_get_default_reminder_interval ();
-
- switch (priv->alarm_units) {
- case CAL_DAYS:
- if (priv->alarm_interval != 1) {
- menu_label = g_strdup_printf (ngettext("%d day before appointment", "%d days before appointment", priv->alarm_interval), priv->alarm_interval);
- } else {
- priv->alarm_interval = -1;
- }
- break;
-
- case CAL_HOURS:
- if (priv->alarm_interval != 1) {
- menu_label = g_strdup_printf (ngettext("%d hour before appointment", "%d hours before appointment", priv->alarm_interval), priv->alarm_interval);
- } else {
- priv->alarm_interval = -1;
- }
- break;
-
- case CAL_MINUTES:
- if (priv->alarm_interval != 15) {
- menu_label = g_strdup_printf (ngettext("%d minute before appointement", "%d minutes before appointment", priv->alarm_interval), priv->alarm_interval);
- } else {
- priv->alarm_interval = -1;
- }
- break;
- }
-
- if (menu_label) {
- GtkWidget *item, *menu;
-
- item = gtk_menu_item_new_with_label (menu_label);
- gtk_widget_show (item);
- menu = gtk_option_menu_get_menu (GTK_OPTION_MENU (priv->alarm_time));
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- }
-
- g_signal_connect (priv->alarm,
- "toggled", G_CALLBACK (alarm_changed_cb),
- epage);
- g_signal_connect (priv->alarm_custom, "clicked",
- G_CALLBACK (alarm_custom_clicked_cb), epage);
-
- /* Connect the default signal handler to use to make sure we notify
- * upstream of changes to the widget values.
- */
-
- /* Belongs to priv->description */
- g_signal_connect((text_buffer), "changed",
- G_CALLBACK (field_changed_cb), epage);
-
- g_signal_connect((priv->summary), "changed",
- G_CALLBACK (field_changed_cb), epage);
- g_signal_connect((priv->location), "changed",
- G_CALLBACK (field_changed_cb), epage);
- g_signal_connect((priv->start_time), "changed",
- G_CALLBACK (field_changed_cb), epage);
- g_signal_connect((priv->end_time), "changed",
- G_CALLBACK (field_changed_cb), epage);
- g_signal_connect((priv->start_timezone), "changed",
- G_CALLBACK (field_changed_cb), epage);
- g_signal_connect((priv->end_timezone), "changed",
- G_CALLBACK (field_changed_cb), epage);
- g_signal_connect((priv->all_day_event), "toggled",
- G_CALLBACK (field_changed_cb), epage);
- g_signal_connect((priv->classification),
- "changed", G_CALLBACK (field_changed_cb),
- epage);
- g_signal_connect((priv->show_time_as_busy),
- "toggled", G_CALLBACK (field_changed_cb),
- epage);
- g_signal_connect((priv->alarm),
- "toggled", G_CALLBACK (field_changed_cb),
- epage);
- g_signal_connect((priv->alarm_time),
- "changed", G_CALLBACK (field_changed_cb),
- epage);
- g_signal_connect((priv->categories), "changed",
- G_CALLBACK (field_changed_cb), epage);
-
- /* Set the default timezone, so the timezone entry may be hidden. */
- zone = calendar_config_get_icaltimezone ();
- e_timezone_entry_set_default_timezone (E_TIMEZONE_ENTRY (priv->start_timezone), zone);
- e_timezone_entry_set_default_timezone (E_TIMEZONE_ENTRY (priv->end_timezone), zone);
-
- return TRUE;
-}
-
-
-
-/**
- * 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, 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;
- }
-
- if (!init_widgets (epage)) {
- g_message ("event_page_construct(): "
- "Could not initialize the widgets!");
- return NULL;
- }
-
- 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 = g_object_new (TYPE_EVENT_PAGE, NULL);
- if (!event_page_construct (epage)) {
- g_object_unref (epage);
- return NULL;
- }
-
- return epage;
-}
-
-GtkWidget *make_date_edit (void);
-
-GtkWidget *
-make_date_edit (void)
-{
- return comp_editor_new_date_edit (TRUE, TRUE, TRUE);
-}
-
-GtkWidget *make_timezone_entry (void);
-
-GtkWidget *
-make_timezone_entry (void)
-{
- GtkWidget *w;
-
- w = e_timezone_entry_new ();
- gtk_widget_show (w);
- return w;
-}
-
-GtkWidget *event_page_create_source_option_menu (void);
-
-GtkWidget *
-event_page_create_source_option_menu (void)
-{
- GtkWidget *menu;
- GConfClient *gconf_client;
- ESourceList *source_list;
-
- gconf_client = gconf_client_get_default ();
- source_list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/calendar/sources");
-
- menu = e_source_option_menu_new (source_list);
- g_object_unref (source_list);
-
- gtk_widget_show (menu);
- return menu;
-}