/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) version 3. * * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the program; if not, see * * * Authors: * Federico Mena-Quintero * Miguel de Icaza * Seth Alves * JP Rosevear * Hans Petter Jansson * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "../calendar-config.h" #include "comp-editor-util.h" #include "alarm-dialog.h" typedef struct { GtkBuilder *builder; /* The alarm */ ECalComponentAlarm *alarm; /* The client */ ECalClient *cal_client; EClientCache *client_cache; /* Toplevel */ GtkWidget *toplevel; GtkWidget *action_combo; GtkWidget *interval_value; GtkWidget *value_units_combo; GtkWidget *relative_combo; GtkWidget *time_combo; /* Alarm repeat widgets */ GtkWidget *repeat_toggle; GtkWidget *repeat_group; GtkWidget *repeat_quantity; GtkWidget *repeat_value; GtkWidget *repeat_unit_combo; GtkWidget *option_notebook; /* Display alarm widgets */ GtkWidget *dalarm_group; GtkWidget *dalarm_message; GtkWidget *dalarm_description; /* Audio alarm widgets */ GtkWidget *aalarm_group; GtkWidget *aalarm_sound; GtkWidget *aalarm_file_chooser; /* Mail alarm widgets */ const gchar *email; GtkWidget *malarm_group; GtkWidget *malarm_address_group; GtkWidget *malarm_addresses; GtkWidget *malarm_addressbook; GtkWidget *malarm_message; GtkWidget *malarm_description; /* Procedure alarm widgets */ GtkWidget *palarm_group; GtkWidget *palarm_program; GtkWidget *palarm_args; /* Addressbook name selector */ ENameSelector *name_selector; } Dialog; static const gchar *section_name = "Send To"; /* "relative" types */ enum { BEFORE, AFTER }; /* Time units */ enum { MINUTES, HOURS, DAYS }; /* Combo box maps */ static const gint action_map[] = { E_CAL_COMPONENT_ALARM_DISPLAY, E_CAL_COMPONENT_ALARM_AUDIO, E_CAL_COMPONENT_ALARM_PROCEDURE, E_CAL_COMPONENT_ALARM_EMAIL, -1 }; static const gchar *action_map_cap[] = { CAL_STATIC_CAPABILITY_NO_DISPLAY_ALARMS, CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS, CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS, CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS }; static const gint value_map[] = { MINUTES, HOURS, DAYS, -1 }; static const gint relative_map[] = { BEFORE, AFTER, -1 }; static const gint time_map[] = { E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START, E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END, -1 }; enum duration_units { DUR_MINUTES, DUR_HOURS, DUR_DAYS }; static const gint duration_units_map[] = { DUR_MINUTES, DUR_HOURS, DUR_DAYS, -1 }; static void populate_widgets_from_alarm (Dialog *dialog); static void action_changed_cb (GtkWidget *action_combo, gpointer data); /* Fills the widgets with default values */ static void clear_widgets (Dialog *dialog) { /* Sane defaults */ e_dialog_combo_box_set (dialog->action_combo, E_CAL_COMPONENT_ALARM_DISPLAY, action_map); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->interval_value), 15); e_dialog_combo_box_set (dialog->value_units_combo, MINUTES, value_map); e_dialog_combo_box_set (dialog->relative_combo, BEFORE, relative_map); e_dialog_combo_box_set (dialog->time_combo, E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START, time_map); gtk_widget_set_sensitive (dialog->repeat_group, FALSE); gtk_widget_set_sensitive (dialog->dalarm_group, FALSE); gtk_widget_set_sensitive (dialog->aalarm_group, FALSE); gtk_widget_set_sensitive (dialog->malarm_group, FALSE); gtk_notebook_set_current_page (GTK_NOTEBOOK (dialog->option_notebook), 0); } static void populate_relative_time_combobox_widget (GtkWidget *combobox, ECalClient *cal_client, const gint *map, gint prop) { GtkTreeModel *model; GtkTreeIter iter; gboolean valid; gboolean alarm_after_start; gint i; alarm_after_start = !e_client_check_capability ( E_CLIENT (cal_client), CAL_STATIC_CAPABILITY_NO_ALARM_AFTER_START); model = gtk_combo_box_get_model (GTK_COMBO_BOX (combobox)); valid = gtk_tree_model_get_iter_first (model, &iter); for (i = 0; valid && map[i] != -1; i++) { gtk_list_store_set ( GTK_LIST_STORE (model), &iter, 1, alarm_after_start ? TRUE : (map[i] == prop ? FALSE : TRUE), -1); valid = gtk_tree_model_iter_next (model, &iter); } } /* fill_widgets handler for the alarm page */ static void alarm_to_dialog (Dialog *dialog) { GtkTreeModel *model; GtkTreeIter iter; gboolean valid; gboolean repeat; ECalComponentAlarmAction action; gchar *email; gint i; /* Clean the page */ clear_widgets (dialog); /* Alarm types */ model = gtk_combo_box_get_model (GTK_COMBO_BOX (dialog->action_combo)); valid = gtk_tree_model_get_iter_first (model, &iter); for (i = 0; valid && action_map[i] != -1; i++) { gtk_list_store_set ( GTK_LIST_STORE (model), &iter, 1, !e_client_check_capability (E_CLIENT (dialog->cal_client), action_map_cap[i]), -1); valid = gtk_tree_model_iter_next (model, &iter); } populate_relative_time_combobox_widget (dialog->relative_combo, dialog->cal_client, relative_map, AFTER); populate_relative_time_combobox_widget ( dialog->time_combo, dialog->cal_client, time_map, E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END); /* * If the client doesn't support set alarm description, disable the related widgets */ if (e_client_check_capability (E_CLIENT (dialog->cal_client), CAL_STATIC_CAPABILITY_NO_ALARM_DESCRIPTION)) { gtk_widget_hide (dialog->dalarm_group); gtk_widget_hide (dialog->dalarm_message); gtk_widget_hide (dialog->dalarm_description); } /* Set a default address if possible */ if (!e_client_check_capability (E_CLIENT (dialog->cal_client), CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS) && !e_cal_component_alarm_has_attendees (dialog->alarm) && e_client_get_backend_property_sync (E_CLIENT (dialog->cal_client), CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS, &email, NULL, NULL)) { ECalComponentAttendee *a; GSList attendee_list; a = g_new0 (ECalComponentAttendee, 1); a->value = email; a->cutype = ICAL_CUTYPE_INDIVIDUAL; a->status = ICAL_PARTSTAT_NEEDSACTION; a->role = ICAL_ROLE_REQPARTICIPANT; attendee_list.data = a; attendee_list.next = NULL; e_cal_component_alarm_set_attendee_list (dialog->alarm, &attendee_list); g_free (email); g_free (a); } /* If we can repeat */ repeat = !e_client_check_capability (E_CLIENT (dialog->cal_client), CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT); gtk_widget_set_sensitive (dialog->repeat_toggle, repeat); /* if we are editing a exiting alarm */ e_cal_component_alarm_get_action (dialog->alarm, &action); if (action) populate_widgets_from_alarm (dialog); } static void alarm_to_repeat_widgets (Dialog *dialog, ECalComponentAlarm *alarm) { ECalComponentAlarmRepeat repeat; e_cal_component_alarm_get_repeat (dialog->alarm, &repeat); if (repeat.repetitions) { gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (dialog->repeat_toggle), TRUE); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->repeat_quantity), repeat.repetitions); } else return; if (repeat.duration.minutes) { e_dialog_combo_box_set (dialog->repeat_unit_combo, DUR_MINUTES, duration_units_map); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->repeat_value), repeat.duration.minutes); } if (repeat.duration.hours) { e_dialog_combo_box_set (dialog->repeat_unit_combo, DUR_HOURS, duration_units_map); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->repeat_value), repeat.duration.hours); } if (repeat.duration.days) { e_dialog_combo_box_set (dialog->repeat_unit_combo, DUR_DAYS, duration_units_map); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->repeat_value), repeat.duration.days); } } static void repeat_widgets_to_alarm (Dialog *dialog, ECalComponentAlarm *alarm) { ECalComponentAlarmRepeat repeat; if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->repeat_toggle))) { repeat.repetitions = 0; e_cal_component_alarm_set_repeat (alarm, repeat); return; } repeat.repetitions = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON (dialog->repeat_quantity)); memset (&repeat.duration, 0, sizeof (repeat.duration)); switch (e_dialog_combo_box_get (dialog->repeat_unit_combo, duration_units_map)) { case DUR_MINUTES: repeat.duration.minutes = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON (dialog->repeat_value)); break; case DUR_HOURS: repeat.duration.hours = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON (dialog->repeat_value)); break; case DUR_DAYS: repeat.duration.days = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON (dialog->repeat_value)); break; default: g_return_if_reached (); } e_cal_component_alarm_set_repeat (alarm, repeat); } /* Fills the audio alarm data with the values from the widgets */ static void aalarm_widgets_to_alarm (Dialog *dialog, ECalComponentAlarm *alarm) { gchar *url; icalattach *attach; if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->aalarm_sound))) return; url = gtk_file_chooser_get_uri ( GTK_FILE_CHOOSER (dialog->aalarm_file_chooser)); attach = icalattach_new_from_url (url ? url : ""); g_free (url); e_cal_component_alarm_set_attach (alarm, attach); icalattach_unref (attach); } /* Fills the widgets with audio alarm data */ static void alarm_to_aalarm_widgets (Dialog *dialog, ECalComponentAlarm *alarm) { const gchar *url; icalattach *attach; e_cal_component_alarm_get_attach (alarm, (&attach)); url = icalattach_get_url (attach); icalattach_unref (attach); if (!(url && *url)) return; gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (dialog->aalarm_sound), TRUE); gtk_file_chooser_set_uri ( GTK_FILE_CHOOSER (dialog->aalarm_file_chooser), url); } /* Fills the widgets with display alarm data */ static void alarm_to_dalarm_widgets (Dialog *dialog, ECalComponentAlarm *alarm) { ECalComponentText description; GtkTextBuffer *text_buffer; e_cal_component_alarm_get_description (alarm, &description); if (description.value) { gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON (dialog->dalarm_message), TRUE); text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->dalarm_description)); gtk_text_buffer_set_text (text_buffer, description.value, -1); } } /* Fills the display alarm data with the values from the widgets */ static void dalarm_widgets_to_alarm (Dialog *dialog, ECalComponentAlarm *alarm) { gchar *str; ECalComponentText description; GtkTextBuffer *text_buffer; GtkTextIter text_iter_start, text_iter_end; icalcomponent *icalcomp; icalproperty *icalprop; if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->dalarm_message))) return; text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->dalarm_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); description.value = str; description.altrep = NULL; e_cal_component_alarm_set_description (alarm, &description); g_free (str); /* remove the X-EVOLUTION-NEEDS-DESCRIPTION property, so that * we don't re-set the alarm's description */ icalcomp = e_cal_component_alarm_get_icalcomponent (alarm); icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); while (icalprop) { const gchar *x_name; x_name = icalproperty_get_x_name (icalprop); if (!strcmp (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION")) { icalcomponent_remove_property (icalcomp, icalprop); break; } icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); } } /* Fills the mail alarm data with the values from the widgets */ static void malarm_widgets_to_alarm (Dialog *dialog, ECalComponentAlarm *alarm) { gchar *str; ECalComponentText description; GSList *attendee_list = NULL; GtkTextBuffer *text_buffer; GtkTextIter text_iter_start, text_iter_end; ENameSelectorModel *name_selector_model; EDestinationStore *destination_store; GList *destinations; icalcomponent *icalcomp; icalproperty *icalprop; GList *l; /* Attendees */ name_selector_model = e_name_selector_peek_model (dialog->name_selector); e_name_selector_model_peek_section (name_selector_model, section_name, NULL, &destination_store); destinations = e_destination_store_list_destinations (destination_store); for (l = destinations; l; l = g_list_next (l)) { EDestination *dest; ECalComponentAttendee *a; dest = l->data; a = g_new0 (ECalComponentAttendee, 1); a->value = e_destination_get_email (dest); a->cn = e_destination_get_name (dest); a->cutype = ICAL_CUTYPE_INDIVIDUAL; a->status = ICAL_PARTSTAT_NEEDSACTION; a->role = ICAL_ROLE_REQPARTICIPANT; attendee_list = g_slist_append (attendee_list, a); } e_cal_component_alarm_set_attendee_list (alarm, attendee_list); e_cal_component_free_attendee_list (attendee_list); g_list_free (destinations); if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->malarm_message))) return; /* Description */ text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->malarm_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); description.value = str; description.altrep = NULL; e_cal_component_alarm_set_description (alarm, &description); g_free (str); /* remove the X-EVOLUTION-NEEDS-DESCRIPTION property, so that * we don't re-set the alarm's description */ icalcomp = e_cal_component_alarm_get_icalcomponent (alarm); icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); while (icalprop) { const gchar *x_name; x_name = icalproperty_get_x_name (icalprop); if (!strcmp (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION")) { icalcomponent_remove_property (icalcomp, icalprop); break; } icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); } } /* Fills the widgets from mail alarm data */ static void alarm_to_malarm_widgets (Dialog *dialog, ECalComponentAlarm *alarm) { ENameSelectorModel *name_selector_model; EDestinationStore *destination_store; ECalComponentText description; GtkTextBuffer *text_buffer; GSList *attendee_list, *l; gint len; /* Attendees */ name_selector_model = e_name_selector_peek_model (dialog->name_selector); e_name_selector_model_peek_section (name_selector_model, section_name, NULL, &destination_store); e_cal_component_alarm_get_attendee_list (alarm, &attendee_list); len = g_slist_length (attendee_list); if (len > 0) { for (l = attendee_list; l; l = g_slist_next (l)) { ECalComponentAttendee *a = l->data; EDestination *dest; dest = e_destination_new (); if (a->cn != NULL && *a->cn) e_destination_set_name (dest, a->cn); if (a->value != NULL && *a->value) { if (!strncasecmp (a->value, "MAILTO:", 7)) e_destination_set_email (dest, a->value + 7); else e_destination_set_email (dest, a->value); } e_destination_store_append_destination (destination_store, dest); g_object_unref (dest); } e_cal_component_free_attendee_list (attendee_list); } /* Description */ e_cal_component_alarm_get_description (alarm, &description); if (description.value) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->malarm_message), TRUE); text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->malarm_description)); gtk_text_buffer_set_text (text_buffer, description.value, -1); } } /* Fills the widgets from procedure alarm data */ static void alarm_to_palarm_widgets (Dialog *dialog, ECalComponentAlarm *alarm) { ECalComponentText description; GtkEntry *entry; const gchar *url; icalattach *attach; e_cal_component_alarm_get_attach (alarm, (&attach)); url = icalattach_get_url (attach); icalattach_unref (attach); if (!(url && *url)) return; entry = GTK_ENTRY (dialog->palarm_program); gtk_entry_set_text (entry, url); entry = GTK_ENTRY (dialog->palarm_args); e_cal_component_alarm_get_description (alarm, &description); gtk_entry_set_text (entry, description.value); } /* Fills the procedure alarm data with the values from the widgets */ static void palarm_widgets_to_alarm (Dialog *dialog, ECalComponentAlarm *alarm) { icalattach *attach; ECalComponentText description; icalcomponent *icalcomp; icalproperty *icalprop; const gchar *text; text = gtk_entry_get_text (GTK_ENTRY (dialog->palarm_program)); attach = icalattach_new_from_url ((text != NULL) ? text : ""); e_cal_component_alarm_set_attach (alarm, attach); icalattach_unref (attach); text = gtk_entry_get_text (GTK_ENTRY (dialog->palarm_args)); description.value = text; description.altrep = NULL; e_cal_component_alarm_set_description (alarm, &description); /* remove the X-EVOLUTION-NEEDS-DESCRIPTION property, so that * we don't re-set the alarm's description */ icalcomp = e_cal_component_alarm_get_icalcomponent (alarm); icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY); while (icalprop) { const gchar *x_name; x_name = icalproperty_get_x_name (icalprop); if (!strcmp (x_name, "X-EVOLUTION-NEEDS-DESCRIPTION")) { icalcomponent_remove_property (icalcomp, icalprop); break; } icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY); } } static void populate_widgets_from_alarm (Dialog *dialog) { ECalComponentAlarmTrigger *trigger; ECalComponentAlarmAction *action; action = g_new0 (ECalComponentAlarmAction, 1); e_cal_component_alarm_get_action (dialog->alarm, action); g_return_if_fail (action != NULL); trigger = g_new0 (ECalComponentAlarmTrigger, 1); e_cal_component_alarm_get_trigger (dialog->alarm, trigger); g_return_if_fail (trigger != NULL); if (*action == E_CAL_COMPONENT_ALARM_NONE) return; gtk_window_set_title (GTK_WINDOW (dialog->toplevel),_("Edit Reminder")); /* Alarm Types */ switch (trigger->type) { case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START: e_dialog_combo_box_set (dialog->time_combo, E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START, time_map); break; case E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END: e_dialog_combo_box_set (dialog->time_combo, E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END, time_map); break; default: g_warning ("%s: Unexpected alarm type (%d)", G_STRLOC, trigger->type); } switch (trigger->u.rel_duration.is_neg) { case 1: e_dialog_combo_box_set (dialog->relative_combo, BEFORE, relative_map); break; case 0: e_dialog_combo_box_set (dialog->relative_combo, AFTER, relative_map); break; } if (trigger->u.rel_duration.days) { e_dialog_combo_box_set (dialog->value_units_combo, DAYS, value_map); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->interval_value), trigger->u.rel_duration.days); } else if (trigger->u.rel_duration.hours) { e_dialog_combo_box_set (dialog->value_units_combo, HOURS, value_map); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->interval_value), trigger->u.rel_duration.hours); } else if (trigger->u.rel_duration.minutes) { e_dialog_combo_box_set (dialog->value_units_combo, MINUTES, value_map); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->interval_value), trigger->u.rel_duration.minutes); } else { e_dialog_combo_box_set (dialog->value_units_combo, MINUTES, value_map); gtk_spin_button_set_value ( GTK_SPIN_BUTTON (dialog->interval_value), 0); } /* Repeat options */ alarm_to_repeat_widgets (dialog, dialog->alarm); /* Alarm options */ e_dialog_combo_box_set (dialog->action_combo, *action, action_map); action_changed_cb (dialog->action_combo, dialog); switch (*action) { case E_CAL_COMPONENT_ALARM_AUDIO: alarm_to_aalarm_widgets (dialog, dialog->alarm); break; case E_CAL_COMPONENT_ALARM_DISPLAY: alarm_to_dalarm_widgets (dialog, dialog->alarm); break; case E_CAL_COMPONENT_ALARM_EMAIL: alarm_to_malarm_widgets (dialog, dialog->alarm); break; case E_CAL_COMPONENT_ALARM_PROCEDURE: alarm_to_palarm_widgets (dialog, dialog->alarm); break; default: g_warning ("%s: Unexpected alarm action (%d)", G_STRLOC, *action); } } /* fill_component handler for the alarm page */ static void dialog_to_alarm (Dialog *dialog) { ECalComponentAlarmTrigger trigger; ECalComponentAlarmAction action; /* Fill out the alarm */ memset (&trigger, 0, sizeof (ECalComponentAlarmTrigger)); trigger.type = e_dialog_combo_box_get (dialog->time_combo, time_map); if (e_dialog_combo_box_get (dialog->relative_combo, relative_map) == BEFORE) trigger.u.rel_duration.is_neg = 1; else trigger.u.rel_duration.is_neg = 0; switch (e_dialog_combo_box_get (dialog->value_units_combo, value_map)) { case MINUTES: trigger.u.rel_duration.minutes = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON (dialog->interval_value)); break; case HOURS: trigger.u.rel_duration.hours = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON (dialog->interval_value)); break; case DAYS: trigger.u.rel_duration.days = gtk_spin_button_get_value_as_int ( GTK_SPIN_BUTTON (dialog->interval_value)); break; default: g_return_if_reached (); } e_cal_component_alarm_set_trigger (dialog->alarm, trigger); action = e_dialog_combo_box_get (dialog->action_combo, action_map); e_cal_component_alarm_set_action (dialog->alarm, action); /* Repeat stuff */ repeat_widgets_to_alarm (dialog, dialog->alarm); /* Options */ switch (action) { case E_CAL_COMPONENT_ALARM_NONE: g_return_if_reached (); break; case E_CAL_COMPONENT_ALARM_AUDIO: aalarm_widgets_to_alarm (dialog, dialog->alarm); break; case E_CAL_COMPONENT_ALARM_DISPLAY: dalarm_widgets_to_alarm (dialog, dialog->alarm); break; case E_CAL_COMPONENT_ALARM_EMAIL: malarm_widgets_to_alarm (dialog, dialog->alarm); break; case E_CAL_COMPONENT_ALARM_PROCEDURE: palarm_widgets_to_alarm (dialog, dialog->alarm); break; case E_CAL_COMPONENT_ALARM_UNKNOWN: break; default: g_return_if_reached (); } } static void build_combobox_widget (GtkWidget *combobox, const gchar *actions[]) { GtkComboBox *combo = GTK_COMBO_BOX (combobox); GtkCellRenderer *cell; GtkListStore *store; gint i; g_return_val_if_fail (combo != NULL, FALSE); g_return_val_if_fail (GTK_IS_COMBO_BOX (combo), FALSE); store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_BOOLEAN); gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store)); g_object_unref (store); gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo)); cell = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE); gtk_cell_layout_set_attributes ( GTK_CELL_LAYOUT (combo), cell, "text", 0, "sensitive", 1, NULL); for (i = 0; actions[i] != NULL; i++) { GtkTreeIter iter; gtk_list_store_append (store, &iter); gtk_list_store_set ( store, &iter, 0, _(actions[i]), 1, TRUE, -1); } } /* Gets the widgets from the XML file and returns TRUE if they are all available. */ static gboolean get_widgets (Dialog *dialog) { dialog->toplevel = e_builder_get_widget (dialog->builder, "alarm-dialog"); if (!dialog->toplevel) return FALSE; dialog->action_combo = e_builder_get_widget (dialog->builder, "action-combobox"); dialog->interval_value = e_builder_get_widget (dialog->builder, "interval-value"); dialog->value_units_combo = e_builder_get_widget (dialog->builder, "value-units-combobox"); dialog->relative_combo = e_builder_get_widget (dialog->builder, "relative-combobox"); dialog->time_combo = e_builder_get_widget (dialog->builder, "time-combobox"); dialog->repeat_toggle = e_builder_get_widget (dialog->builder, "repeat-toggle"); dialog->repeat_group = e_builder_get_widget (dialog->builder, "repeat-group"); dialog->repeat_quantity = e_builder_get_widget (dialog->builder, "repeat-quantity"); dialog->repeat_value = e_builder_get_widget (dialog->builder, "repeat-value"); dialog->repeat_unit_combo = e_builder_get_widget (dialog->builder, "repeat-unit-combobox"); dialog->option_notebook = e_builder_get_widget (dialog->builder, "option-notebook"); dialog->dalarm_group = e_builder_get_widget (dialog->builder, "dalarm-group"); dialog->dalarm_message = e_builder_get_widget (dialog->builder, "dalarm-message"); dialog->dalarm_description = e_builder_get_widget (dialog->builder, "dalarm-description"); dialog->aalarm_group = e_builder_get_widget (dialog->builder, "aalarm-group"); dialog->aalarm_sound = e_builder_get_widget (dialog->builder, "aalarm-sound"); dialog->aalarm_file_chooser = e_builder_get_widget (dialog->builder, "aalarm-file-chooser"); dialog->malarm_group = e_builder_get_widget (dialog->builder, "malarm-group"); dialog->malarm_address_group = e_builder_get_widget (dialog->builder, "malarm-address-group"); dialog->malarm_addressbook = e_builder_get_widget (dialog->builder, "malarm-addressbook"); dialog->malarm_message = e_builder_get_widget (dialog->builder, "malarm-message"); dialog->malarm_description = e_builder_get_widget (dialog->builder, "malarm-description"); dialog->palarm_group = e_builder_get_widget (dialog->builder, "palarm-group"); dialog->palarm_program = e_builder_get_widget (dialog->builder, "palarm-program"); dialog->palarm_args = e_builder_get_widget (dialog->builder, "palarm-args"); if (dialog->action_combo) { const gchar *actions[] = { N_("Pop up an alert"), N_("Play a sound"), N_("Run a program"), N_("Send an email"), NULL }; build_combobox_widget (dialog->action_combo, actions); } if (dialog->relative_combo) { const gchar *actions[] = { N_("before"), N_("after"), NULL }; build_combobox_widget (dialog->relative_combo, actions); } if (dialog->time_combo) { const gchar *actions[] = { N_("start of appointment"), N_("end of appointment"), NULL }; build_combobox_widget (dialog->time_combo, actions); } return (dialog->action_combo && dialog->interval_value && dialog->value_units_combo && dialog->relative_combo && dialog->time_combo && dialog->repeat_toggle && dialog->repeat_group && dialog->repeat_quantity && dialog->repeat_value && dialog->repeat_unit_combo && dialog->option_notebook && dialog->dalarm_group && dialog->dalarm_message && dialog->dalarm_description && dialog->aalarm_group && dialog->aalarm_sound && dialog->aalarm_file_chooser && dialog->malarm_group && dialog->malarm_address_group && dialog->malarm_addressbook && dialog->malarm_message && dialog->malarm_description && dialog->palarm_group && dialog->palarm_program && dialog->palarm_args); } static void addressbook_clicked_cb (GtkWidget *widget, Dialog *dialog) { e_name_selector_show_dialog (dialog->name_selector, dialog->toplevel); } static void addressbook_response_cb (GtkWidget *widget, gint response, gpointer data) { Dialog *dialog = data; ENameSelectorDialog *name_selector_dialog; name_selector_dialog = e_name_selector_peek_dialog (dialog->name_selector); gtk_widget_hide (GTK_WIDGET (name_selector_dialog)); } static gboolean setup_select_names (Dialog *dialog) { ENameSelectorModel *name_selector_model; ENameSelectorDialog *name_selector_dialog; dialog->name_selector = e_name_selector_new (dialog->client_cache); e_name_selector_load_books (dialog->name_selector); name_selector_model = e_name_selector_peek_model (dialog->name_selector); e_name_selector_model_add_section (name_selector_model, section_name, section_name, NULL); dialog->malarm_addresses = GTK_WIDGET (e_name_selector_peek_section_entry (dialog->name_selector, section_name)); gtk_widget_show (dialog->malarm_addresses); gtk_box_pack_end (GTK_BOX (dialog->malarm_address_group), dialog->malarm_addresses, TRUE, TRUE, 0); g_signal_connect ( dialog->malarm_addressbook, "clicked", G_CALLBACK (addressbook_clicked_cb), dialog); name_selector_dialog = e_name_selector_peek_dialog (dialog->name_selector); g_signal_connect ( name_selector_dialog, "response", G_CALLBACK (addressbook_response_cb), dialog); return TRUE; } /* Callback used when the repeat toggle button is toggled. We sensitize the * repeat group options as appropriate. */ static void repeat_toggle_toggled_cb (GtkToggleButton *toggle, gpointer data) { Dialog *dialog = data; gboolean active; active = gtk_toggle_button_get_active (toggle); gtk_widget_set_sensitive (dialog->repeat_group, active); } static void check_custom_sound (Dialog *dialog) { gchar *str, *dir; gboolean sens; str = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER (dialog->aalarm_file_chooser)); if (str && *str) { dir = g_path_get_dirname (str); if (dir && *dir) { calendar_config_set_dir_path (dir); } } sens = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->aalarm_sound)) ? str && *str : TRUE; gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog->toplevel), GTK_RESPONSE_OK, sens); g_free (str); } static void aalarm_sound_toggled_cb (GtkToggleButton *toggle, gpointer data) { Dialog *dialog = data; gboolean active; active = gtk_toggle_button_get_active (toggle); gtk_widget_set_sensitive (dialog->aalarm_group, active); check_custom_sound (dialog); } static void aalarm_attach_changed_cb (GtkWidget *widget, gpointer data) { Dialog *dialog = data; check_custom_sound (dialog); } static void check_custom_message (Dialog *dialog) { gchar *str; GtkTextBuffer *text_buffer; GtkTextIter text_iter_start, text_iter_end; gboolean sens; text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->dalarm_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); sens = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->dalarm_message)) ? str && *str : TRUE; gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog->toplevel), GTK_RESPONSE_OK, sens); g_free (str); } static void dalarm_message_toggled_cb (GtkToggleButton *toggle, gpointer data) { Dialog *dialog = data; gboolean active; active = gtk_toggle_button_get_active (toggle); gtk_widget_set_sensitive (dialog->dalarm_group, active); check_custom_message (dialog); } static void dalarm_description_changed_cb (GtkWidget *widget, gpointer data) { Dialog *dialog = data; check_custom_message (dialog); } static void check_custom_program (Dialog *dialog) { GtkEntry *entry; const gchar *text; gboolean sensitive; entry = GTK_ENTRY (dialog->palarm_program); text = gtk_entry_get_text (entry); sensitive = (text != NULL && *text != '\0'); gtk_dialog_set_response_sensitive ( GTK_DIALOG (dialog->toplevel), GTK_RESPONSE_OK, sensitive); } static void palarm_program_changed_cb (GtkWidget *widget, gpointer data) { Dialog *dialog = data; check_custom_program (dialog); } static void check_custom_email (Dialog *dialog) { gchar *str; GtkTextBuffer *text_buffer; GtkTextIter text_iter_start, text_iter_end; ENameSelectorModel *name_selector_model; EDestinationStore *destination_store; GList *destinations; gboolean sens; name_selector_model = e_name_selector_peek_model (dialog->name_selector); e_name_selector_model_peek_section (name_selector_model, section_name, NULL, &destination_store); destinations = e_destination_store_list_destinations (destination_store); text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->malarm_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); sens = (destinations != NULL) && (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->malarm_message)) ? str && *str : TRUE); gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog->toplevel), GTK_RESPONSE_OK, sens); g_list_free (destinations); } static void malarm_addresses_changed_cb (GtkWidget *editable, gpointer data) { Dialog *dialog = data; check_custom_email (dialog); } static void malarm_message_toggled_cb (GtkToggleButton *toggle, gpointer data) { Dialog *dialog = data; gboolean active; active = gtk_toggle_button_get_active (toggle); gtk_widget_set_sensitive (dialog->malarm_group, active); check_custom_email (dialog); } static void malarm_description_changed_cb (GtkWidget *widget, gpointer data) { Dialog *dialog = data; check_custom_email (dialog); } static void action_changed_cb (GtkWidget *action_combo, gpointer data) { Dialog *dialog = data; gchar *dir; ECalComponentAlarmAction action; gint page = 0, i; action = e_dialog_combo_box_get (dialog->action_combo, action_map); for (i = 0; action_map[i] != -1; i++) { if (action == action_map[i]) { page = i; break; } } gtk_notebook_set_current_page ( GTK_NOTEBOOK (dialog->option_notebook), page); switch (action) { case E_CAL_COMPONENT_ALARM_AUDIO: dir = calendar_config_get_dir_path (); if (dir && *dir) gtk_file_chooser_set_current_folder ( GTK_FILE_CHOOSER (dialog->aalarm_file_chooser), dir); g_free (dir); check_custom_sound (dialog); break; case E_CAL_COMPONENT_ALARM_DISPLAY: check_custom_message (dialog); break; case E_CAL_COMPONENT_ALARM_EMAIL: check_custom_email (dialog); break; case E_CAL_COMPONENT_ALARM_PROCEDURE: check_custom_program (dialog); break; default: g_return_if_reached (); return; } } /* Hooks the widget signals */ static void init_widgets (Dialog *dialog) { GtkTextBuffer *text_buffer; g_signal_connect ( dialog->action_combo, "changed", G_CALLBACK (action_changed_cb), dialog); g_signal_connect ( dialog->repeat_toggle, "toggled", G_CALLBACK (repeat_toggle_toggled_cb), dialog); /* Handle custom sounds */ g_signal_connect ( dialog->aalarm_sound, "toggled", G_CALLBACK (aalarm_sound_toggled_cb), dialog); g_signal_connect ( dialog->aalarm_file_chooser, "selection-changed", G_CALLBACK (aalarm_attach_changed_cb), dialog); /* Handle custom messages */ g_signal_connect ( dialog->dalarm_message, "toggled", G_CALLBACK (dalarm_message_toggled_cb), dialog); text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->dalarm_description)); g_signal_connect ( text_buffer, "changed", G_CALLBACK (dalarm_description_changed_cb), dialog); /* Handle program */ g_signal_connect ( dialog->palarm_program, "changed", G_CALLBACK (palarm_program_changed_cb), dialog); /* Handle custom email */ g_signal_connect ( dialog->malarm_message, "toggled", G_CALLBACK (malarm_message_toggled_cb), dialog); text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dialog->malarm_description)); g_signal_connect ( text_buffer, "changed", G_CALLBACK (malarm_description_changed_cb), dialog); g_signal_connect ( dialog->malarm_addresses, "changed", G_CALLBACK (malarm_addresses_changed_cb), dialog); } gboolean alarm_dialog_run (GtkWidget *parent, EClientCache *client_cache, ECalClient *cal_client, ECalComponentAlarm *alarm) { Dialog dialog; GtkWidget *container; gint response_id; g_return_val_if_fail (E_IS_CLIENT_CACHE (client_cache), FALSE); g_return_val_if_fail (alarm != NULL, FALSE); dialog.alarm = alarm; dialog.cal_client = cal_client; dialog.client_cache = client_cache; dialog.builder = gtk_builder_new (); e_load_ui_builder_definition (dialog.builder, "alarm-dialog.ui"); if (!get_widgets (&dialog)) { g_object_unref (dialog.builder); return FALSE; } if (!setup_select_names (&dialog)) { g_object_unref (dialog.builder); return FALSE; } init_widgets (&dialog); alarm_to_dialog (&dialog); gtk_widget_ensure_style (dialog.toplevel); container = gtk_dialog_get_action_area (GTK_DIALOG (dialog.toplevel)); gtk_container_set_border_width (GTK_CONTAINER (container), 12); container = gtk_dialog_get_content_area (GTK_DIALOG (dialog.toplevel)); gtk_container_set_border_width (GTK_CONTAINER (container), 0); gtk_window_set_icon_name ( GTK_WINDOW (dialog.toplevel), "x-office-calendar"); gtk_window_set_transient_for ( GTK_WINDOW (dialog.toplevel), GTK_WINDOW (parent)); response_id = gtk_dialog_run (GTK_DIALOG (dialog.toplevel)); if (response_id == GTK_RESPONSE_OK) dialog_to_alarm (&dialog); if (dialog.name_selector) { e_name_selector_cancel_loading (dialog.name_selector); g_object_unref (dialog.name_selector); } gtk_widget_destroy (dialog.toplevel); g_object_unref (dialog.builder); return response_id == GTK_RESPONSE_OK ? TRUE : FALSE; }