No issues found
1 /*
2 * Evolution calendar - Alarm page of the calendar component dialogs
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with the program; if not, see <http://www.gnu.org/licenses/>
16 *
17 *
18 * Authors:
19 * Federico Mena-Quintero <federico@ximian.com>
20 * Miguel de Icaza <miguel@ximian.com>
21 * Seth Alves <alves@hungry.com>
22 * JP Rosevear <jpr@ximian.com>
23 * Hans Petter Jansson <hpj@ximian.com>
24 *
25 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
26 *
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33 #include <string.h>
34 #include <gtk/gtk.h>
35 #include <glib/gi18n.h>
36
37 #include "e-util/e-util.h"
38 #include "e-util/e-util-private.h"
39 #include "alarm-dialog.h"
40 #include "alarm-list-dialog.h"
41
42 typedef struct {
43 GtkBuilder *builder;
44 ESourceRegistry *registry;
45
46 /* The client */
47 ECalClient *cal_client;
48
49 /* The list store */
50 EAlarmList *list_store;
51
52 /* Toplevel */
53 GtkWidget *toplevel;
54
55 GtkWidget *list;
56 GtkWidget *add;
57 GtkWidget *edit;
58 GtkWidget *delete;
59 GtkWidget *box;
60
61 } Dialog;
62
63 /* Gets the widgets from the XML file and returns TRUE if they are all available. */
64 static gboolean
65 get_widgets (Dialog *dialog)
66 {
67 #define GW(name) e_builder_get_widget (dialog->builder, name)
68
69 dialog->toplevel = GW ("alarm-list-dialog");
70 if (!dialog->toplevel)
71 return FALSE;
72
73 dialog->box = GW ("vbox53");
74 dialog->list = GW ("list");
75 dialog->add = GW ("add");
76 dialog->edit = GW ("edit");
77 dialog->delete = GW ("delete");
78
79 #undef GW
80
81 return (dialog->list
82 && dialog->add
83 && dialog->edit
84 && dialog->delete);
85 }
86
87 static void
88 sensitize_buttons (Dialog *dialog)
89 {
90 GtkTreeSelection *selection;
91 GtkTreeIter iter;
92 gboolean have_selected, read_only = FALSE;
93
94 read_only = e_client_is_readonly (E_CLIENT (dialog->cal_client));
95
96 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->list));
97 have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
98
99 if ((e_cal_client_check_one_alarm_only (dialog->cal_client) &&have_selected) || read_only)
100 gtk_widget_set_sensitive (dialog->add, FALSE);
101 else
102 gtk_widget_set_sensitive (dialog->add, TRUE);
103 gtk_widget_set_sensitive (dialog->delete, have_selected && !read_only);
104 gtk_widget_set_sensitive (dialog->edit, have_selected && !read_only);
105 }
106
107 /* Callback used for the "add reminder" button */
108 static void
109 add_clicked_cb (GtkButton *button,
110 gpointer data)
111 {
112 Dialog *dialog = data;
113 ECalComponentAlarm *alarm;
114 GtkTreeView *view;
115 GtkTreeIter iter;
116 icalcomponent *icalcomp;
117 icalproperty *icalprop;
118
119 view = GTK_TREE_VIEW (dialog->list);
120
121 alarm = e_cal_component_alarm_new ();
122
123 icalcomp = e_cal_component_alarm_get_icalcomponent (alarm);
124 icalprop = icalproperty_new_x ("1");
125 icalproperty_set_x_name (icalprop, "X-EVOLUTION-NEEDS-DESCRIPTION");
126 icalcomponent_add_property (icalcomp, icalprop);
127
128 if (alarm_dialog_run (dialog->toplevel, dialog->registry, dialog->cal_client, alarm)) {
129 e_alarm_list_append (dialog->list_store, &iter, alarm);
130 gtk_tree_selection_select_iter (gtk_tree_view_get_selection (view), &iter);
131 } else {
132 e_cal_component_alarm_free (alarm);
133 }
134
135 sensitize_buttons (dialog);
136 }
137
138 /* Callback used for the "edit reminder" button */
139 static void
140 edit_clicked_cb (GtkButton *button,
141 gpointer data)
142 {
143 Dialog *dialog = data;
144 GtkTreeSelection *selection;
145 GtkTreeIter iter;
146 GtkTreePath *path;
147 ECalComponentAlarm *alarm;
148 GtkTreeView *view;
149
150 view = GTK_TREE_VIEW (dialog->list);
151
152 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->list));
153 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
154 g_warning ("Could not get a selection to edit.");
155 return;
156 }
157
158 alarm = (ECalComponentAlarm *) e_alarm_list_get_alarm (dialog->list_store, &iter);
159 path = gtk_tree_model_get_path (GTK_TREE_MODEL (dialog->list_store), &iter);
160
161 if (alarm_dialog_run (dialog->toplevel, dialog->registry, dialog->cal_client, alarm)) {
162 gtk_tree_selection_select_iter (gtk_tree_view_get_selection (view), &iter);
163 gtk_tree_model_row_changed (GTK_TREE_MODEL (dialog->list_store), path, &iter);
164 }
165 }
166
167 /* Callback used for the "delete reminder" button */
168 static void
169 delete_clicked_cb (GtkButton *button,
170 gpointer data)
171 {
172 Dialog *dialog = data;
173 GtkTreeSelection *selection;
174 GtkTreeModel *model;
175 GtkTreeIter iter;
176 GtkTreePath *path;
177 gboolean valid_iter;
178
179 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->list));
180 if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
181 g_warning ("Could not get a selection to delete.");
182 return;
183 }
184
185 model = GTK_TREE_MODEL (dialog->list_store);
186 path = gtk_tree_model_get_path (model, &iter);
187 e_alarm_list_remove (dialog->list_store, &iter);
188
189 /* Select closest item after removal */
190 valid_iter = gtk_tree_model_get_iter (model, &iter, path);
191 if (!valid_iter) {
192 gtk_tree_path_prev (path);
193 valid_iter = gtk_tree_model_get_iter (model, &iter, path);
194 }
195
196 if (valid_iter)
197 gtk_tree_selection_select_iter (selection, &iter);
198
199 sensitize_buttons (dialog);
200
201 gtk_tree_path_free (path);
202 }
203
204 static void
205 selection_changed_cb (GtkTreeSelection *selection,
206 gpointer data)
207 {
208 Dialog *dialog = data;
209
210 sensitize_buttons (dialog);
211 }
212
213 void
214 alarm_list_dialog_set_client (GtkWidget *dlg_box,
215 ECalClient *cal_client)
216 {
217 Dialog *dialog;
218
219 if (!dlg_box) return;
220
221 dialog = g_object_get_data (G_OBJECT (dlg_box), "dialog");
222 if (dialog) {
223 dialog->cal_client = cal_client;
224 sensitize_buttons (dialog);
225 }
226 }
227
228 /* Hooks the widget signals */
229 static void
230 init_widgets (Dialog *dialog)
231 {
232 GtkTreeViewColumn *column;
233 GtkCellRenderer *cell_renderer;
234
235 /* View */
236 gtk_tree_view_set_model (
237 GTK_TREE_VIEW (dialog->list),
238 GTK_TREE_MODEL (dialog->list_store));
239
240 column = gtk_tree_view_column_new ();
241 gtk_tree_view_column_set_title (column, _("Action/Trigger"));
242 cell_renderer = GTK_CELL_RENDERER (gtk_cell_renderer_text_new ());
243 gtk_tree_view_column_pack_start (column, cell_renderer, TRUE);
244 gtk_tree_view_column_add_attribute (
245 column, cell_renderer,
246 "text", E_ALARM_LIST_COLUMN_DESCRIPTION);
247 gtk_tree_view_append_column (GTK_TREE_VIEW (dialog->list), column);
248
249 /* Reminder buttons */
250 g_signal_connect (
251 dialog->add, "clicked",
252 G_CALLBACK (add_clicked_cb), dialog);
253 g_signal_connect (
254 dialog->delete, "clicked",
255 G_CALLBACK (delete_clicked_cb), dialog);
256 g_signal_connect (
257 dialog->edit, "clicked",
258 G_CALLBACK (edit_clicked_cb), dialog);
259
260 g_signal_connect (
261 gtk_tree_view_get_selection (GTK_TREE_VIEW (dialog->list)),
262 "changed", G_CALLBACK (selection_changed_cb), dialog);
263 }
264
265 gboolean
266 alarm_list_dialog_run (GtkWidget *parent,
267 ESourceRegistry *registry,
268 ECalClient *cal_client,
269 EAlarmList *list_store)
270 {
271 Dialog dialog;
272 GtkWidget *container;
273 gint response_id;
274
275 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
276
277 dialog.registry = registry;
278 dialog.cal_client = cal_client;
279 dialog.list_store = list_store;
280
281 dialog.builder = gtk_builder_new ();
282 e_load_ui_builder_definition (dialog.builder, "alarm-list-dialog.ui");
283
284 if (!get_widgets (&dialog)) {
285 g_object_unref (dialog.builder);
286 return FALSE;
287 }
288
289 init_widgets (&dialog);
290
291 sensitize_buttons (&dialog);
292
293 gtk_widget_ensure_style (dialog.toplevel);
294
295 container = gtk_dialog_get_action_area (GTK_DIALOG (dialog.toplevel));
296 gtk_container_set_border_width (GTK_CONTAINER (container), 12);
297
298 container = gtk_dialog_get_content_area (GTK_DIALOG (dialog.toplevel));
299 gtk_container_set_border_width (GTK_CONTAINER (container), 0);
300
301 gtk_window_set_icon_name (
302 GTK_WINDOW (dialog.toplevel), "x-office-calendar");
303
304 gtk_window_set_transient_for (
305 GTK_WINDOW (dialog.toplevel),
306 GTK_WINDOW (parent));
307
308 response_id = gtk_dialog_run (GTK_DIALOG (dialog.toplevel));
309 gtk_widget_hide (dialog.toplevel);
310
311 gtk_widget_destroy (dialog.toplevel);
312 g_object_unref (dialog.builder);
313
314 return response_id == GTK_RESPONSE_OK ? TRUE : FALSE;
315 }
316
317 GtkWidget *
318 alarm_list_dialog_peek (ESourceRegistry *registry,
319 ECalClient *cal_client,
320 EAlarmList *list_store)
321 {
322 Dialog *dialog;
323
324 dialog = (Dialog *) g_new (Dialog, 1);
325 dialog->registry = registry;
326 dialog->cal_client = cal_client;
327 dialog->list_store = list_store;
328
329 dialog->builder = gtk_builder_new ();
330 e_load_ui_builder_definition (dialog->builder, "alarm-list-dialog.ui");
331
332 if (!get_widgets (dialog)) {
333 g_object_unref (dialog->builder);
334 return NULL;
335 }
336
337 init_widgets (dialog);
338
339 sensitize_buttons (dialog);
340
341 g_object_unref (dialog->builder);
342
343 /* Free the other stuff when the parent really gets destroyed. */
344 g_object_set_data_full (
345 G_OBJECT (dialog->box),
346 "toplevel", dialog->toplevel,
347 (GDestroyNotify) gtk_widget_destroy);
348 g_object_set_data_full (
349 G_OBJECT (dialog->box), "dialog",
350 dialog, (GDestroyNotify) g_free);
351
352 return dialog->box;
353 }