/*
* 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;
}