/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* Evolution calendar - Alarm page of the calendar component dialogs * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * * Authors: Federico Mena-Quintero * Miguel de Icaza * Seth Alves * JP Rosevear * Hans Petter Jansson * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "e-util/e-dialog-widgets.h" #include #include #include "e-util/e-dialog-widgets.h" #include "e-util/e-icon-factory.h" #include "e-util/e-util-private.h" #include "alarm-dialog.h" #include "alarm-list-dialog.h" typedef struct { /* Glade XML data */ GladeXML *xml; /* The client */ ECal *ecal; /* The list store */ EAlarmList *list_store; /* Toplevel */ GtkWidget *toplevel; GtkWidget *list; GtkWidget *add; GtkWidget *edit; GtkWidget *delete; GtkWidget *box; } Dialog; /* Gets the widgets from the XML file and returns TRUE if they are all available. */ static gboolean get_widgets (Dialog *dialog) { #define GW(name) glade_xml_get_widget (dialog->xml, name) dialog->toplevel = GW ("alarm-list-dialog"); if (!dialog->toplevel) return FALSE; dialog->box = GW ("vbox53"); dialog->list = GW ("list"); dialog->add = GW ("add"); dialog->edit = GW ("edit"); dialog->delete = GW ("delete"); #undef GW return (dialog->list && dialog->add && dialog->edit && dialog->delete); } static void sensitize_buttons (Dialog *dialog) { GtkTreeSelection *selection; GtkTreeIter iter; gboolean have_selected, read_only = FALSE; GError *error = NULL; if (!e_cal_is_read_only (dialog->ecal, &read_only, &error)) { if (error->code != E_CALENDAR_STATUS_BUSY) read_only = TRUE; g_error_free (error); } selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->list)); have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter); if ((e_cal_get_one_alarm_only (dialog->ecal) && have_selected) || read_only) gtk_widget_set_sensitive (dialog->add, FALSE); else gtk_widget_set_sensitive (dialog->add, TRUE); gtk_widget_set_sensitive (dialog->delete, have_selected && !read_only); gtk_widget_set_sensitive (dialog->edit, have_selected && !read_only); } /* Callback used for the "add reminder" button */ static void add_clicked_cb (GtkButton *button, gpointer data) { Dialog *dialog = data; ECalComponentAlarm *alarm; GtkTreeView *view; GtkTreeIter iter; icalcomponent *icalcomp; icalproperty *icalprop; view = GTK_TREE_VIEW (dialog->list); alarm = e_cal_component_alarm_new (); icalcomp = e_cal_component_alarm_get_icalcomponent (alarm); icalprop = icalproperty_new_x ("1"); icalproperty_set_x_name (icalprop, "X-EVOLUTION-NEEDS-DESCRIPTION"); icalcomponent_add_property (icalcomp, icalprop); if (alarm_dialog_run (dialog->toplevel, dialog->ecal, alarm)) { e_alarm_list_append (dialog->list_store, &iter, alarm); gtk_tree_selection_select_iter (gtk_tree_view_get_selection (view), &iter); } else { e_cal_component_alarm_free (alarm); } sensitize_buttons (dialog); } /* Callback used for the "edit reminder" button */ static void edit_clicked_cb (GtkButton *button, gpointer data) { Dialog *dialog = data; GtkTreeSelection *selection; GtkTreeIter iter; GtkTreePath *path; ECalComponentAlarm *alarm; GtkTreeView *view; view = GTK_TREE_VIEW (dialog->list); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->list)); if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) { g_warning ("Could not get a selection to delete."); return; } alarm = (ECalComponentAlarm *)e_alarm_list_get_alarm (dialog->list_store, &iter); path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->list_store), &iter); if (alarm_dialog_run (dialog->toplevel, dialog->ecal, alarm)) { gtk_tree_selection_select_iter (gtk_tree_view_get_selection (view), &iter); gtk_tree_model_row_changed (GTK_TREE_MODEL (dialog->list_store), path, &iter); } } /* Callback used for the "delete reminder" button */ static void delete_clicked_cb (GtkButton *button, gpointer data) { Dialog *dialog = data; GtkTreeSelection *selection; GtkTreeIter iter; GtkTreePath *path; gboolean valid_iter; selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->list)); if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) { g_warning ("Could not get a selection to delete."); return; } path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->list_store), &iter); e_alarm_list_remove (dialog->list_store, &iter); /* Select closest item after removal */ valid_iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->list_store), &iter, path); if (!valid_iter) { gtk_tree_path_prev (path); valid_iter = gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->list_store), &iter, path); } if (valid_iter) gtk_tree_selection_select_iter (selection, &iter); sensitize_buttons (dialog); gtk_tree_path_free (path); } static void selection_changed_cb (GtkTreeSelection *selection, gpointer data) { Dialog *dialog = data; sensitize_buttons (dialog); } void alarm_list_dialog_set_client (GtkWidget *dlg_box, ECal *client) { Dialog *dialog; if (!dlg_box) return; dialog = g_object_get_data (G_OBJECT (dlg_box), "dialog"); if (dialog) { dialog->ecal = client; sensitize_buttons (dialog); } } /* Hooks the widget signals */ static void init_widgets (Dialog *dialog) { GtkTreeViewColumn *column; GtkCellRenderer *cell_renderer; /* View */ gtk_tree_view_set_model (GTK_TREE_VIEW (dialog->list), GTK_TREE_MODEL (dialog->list_store)); column = gtk_tree_view_column_new (); gtk_tree_view_column_set_title (column, _("Action/Trigger")); cell_renderer = GTK_CELL_RENDERER (gtk_cell_renderer_text_new ()); gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); gtk_tree_view_column_add_attribute (column, cell_renderer, "text", E_ALARM_LIST_COLUMN_DESCRIPTION); gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->list), column); /* Reminder buttons */ g_signal_connect (dialog->add, "clicked", G_CALLBACK (add_clicked_cb), dialog); g_signal_connect (dialog->delete, "clicked", G_CALLBACK (delete_clicked_cb), dialog); g_signal_connect (dialog->edit, "clicked", G_CALLBACK (edit_clicked_cb), dialog); g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->list)), "changed", G_CALLBACK (selection_changed_cb), dialog); } gboolean alarm_list_dialog_run (GtkWidget *parent, ECal *ecal, EAlarmList *list_store) { Dialog dialog; int response_id; GList *icon_list; char *gladefile; dialog.ecal = ecal; dialog.list_store = list_store; gladefile = g_build_filename (EVOLUTION_GLADEDIR, "alarm-list-dialog.glade", NULL); dialog.xml = glade_xml_new (gladefile, NULL, NULL); g_free (gladefile); if (!dialog.xml) { g_message (G_STRLOC ": Could not load the Glade XML file!"); return FALSE; } if (!get_widgets (&dialog)) { g_object_unref(dialog.xml); return FALSE; } init_widgets (&dialog); sensitize_buttons (&dialog); gtk_widget_ensure_style (dialog.toplevel); gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog.toplevel)->vbox), 0); gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog.toplevel)->action_area), 12); icon_list = e_icon_factory_get_icon_list ("x-office-calendar"); if (icon_list) { gtk_window_set_icon_list (GTK_WINDOW (dialog.toplevel), icon_list); g_list_foreach (icon_list, (GFunc) g_object_unref, NULL); g_list_free (icon_list); } gtk_window_set_transient_for (GTK_WINDOW (dialog.toplevel), GTK_WINDOW (parent)); response_id = gtk_dialog_run (GTK_DIALOG (dialog.toplevel)); gtk_widget_hide (dialog.toplevel); gtk_widget_destroy (dialog.toplevel); g_object_unref (dialog.xml); return response_id == GTK_RESPONSE_OK ? TRUE : FALSE; } GtkWidget * alarm_list_dialog_peek (ECal *ecal, EAlarmList *list_store) { Dialog *dialog; char *gladefile; dialog = (Dialog *)g_new (Dialog, 1); dialog->ecal = ecal; dialog->list_store = list_store; gladefile = g_build_filename (EVOLUTION_GLADEDIR, "alarm-list-dialog.glade", NULL); dialog->xml = glade_xml_new (gladefile, NULL, NULL); g_free (gladefile); if (!dialog->xml) { g_message (G_STRLOC ": Could not load the Glade XML file!"); return NULL; } if (!get_widgets (dialog)) { g_object_unref(dialog->xml); return NULL; } init_widgets (dialog); sensitize_buttons (dialog); g_object_unref (dialog->xml); /* Free the other stuff when the parent really gets destroyed. */ g_object_set_data_full (G_OBJECT (dialog->box), "toplevel", dialog->toplevel, (GDestroyNotify) gtk_widget_destroy); g_object_set_data_full (G_OBJECT (dialog->box), "dialog", dialog, g_free); return dialog->box; }