evolution-3.6.4/modules/calendar/e-calendar-preferences.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Damon Chaplin <damon@ximian.com>
 18  *		Ettore Perazzoli <ettore@ximian.com>
 19  *		David Trowbridge <trowbrds cs colorado edu>
 20  *
 21  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 22  *
 23  */
 24 
 25 #ifdef HAVE_CONFIG_H
 26 #include <config.h>
 27 #endif
 28 
 29 #include "e-calendar-preferences.h"
 30 
 31 #include <string.h>
 32 #include <glib/gi18n.h>
 33 
 34 #include "calendar/gui/e-cal-config.h"
 35 #include "calendar/gui/e-timezone-entry.h"
 36 #include "calendar/gui/calendar-config.h"
 37 #include "widgets/misc/e-alarm-selector.h"
 38 #include "widgets/misc/e-dateedit.h"
 39 #include "e-util/e-util.h"
 40 #include "e-util/e-datetime-format.h"
 41 #include "e-util/e-dialog-widgets.h"
 42 #include "e-util/e-util-private.h"
 43 #include "shell/e-shell-utils.h"
 44 
 45 /* same is used for Birthdays & Anniversaries calendar */
 46 static const gint default_reminder_units_map[] = {
 47 	E_DURATION_MINUTES, E_DURATION_HOURS, E_DURATION_DAYS, -1
 48 };
 49 
 50 G_DEFINE_DYNAMIC_TYPE (
 51 	ECalendarPreferences,
 52 	e_calendar_preferences,
 53 	GTK_TYPE_VBOX)
 54 
 55 static gboolean
 56 transform_time_divisions_to_index (GBinding *binding,
 57                                    const GValue *source_value,
 58                                    GValue *target_value,
 59                                    gpointer not_used)
 60 {
 61 	gboolean success = TRUE;
 62 
 63 	g_return_val_if_fail (G_IS_BINDING (binding), FALSE);
 64 
 65 	switch (g_value_get_int (source_value)) {
 66 		case 60:
 67 			g_value_set_int (target_value, 0);
 68 			break;
 69 		case 30:
 70 			g_value_set_int (target_value, 1);
 71 			break;
 72 		case 15:
 73 			g_value_set_int (target_value, 2);
 74 			break;
 75 		case 10:
 76 			g_value_set_int (target_value, 3);
 77 			break;
 78 		case 5:
 79 			g_value_set_int (target_value, 4);
 80 			break;
 81 		default:
 82 			success = FALSE;
 83 	}
 84 
 85 	return success;
 86 }
 87 
 88 static gboolean
 89 transform_index_to_time_divisions (GBinding *binding,
 90                                    const GValue *source_value,
 91                                    GValue *target_value,
 92                                    gpointer not_used)
 93 {
 94 	gboolean success = TRUE;
 95 
 96 	switch (g_value_get_int (source_value)) {
 97 		case 0:
 98 			g_value_set_int (target_value, 60);
 99 			break;
100 		case 1:
101 			g_value_set_int (target_value, 30);
102 			break;
103 		case 2:
104 			g_value_set_int (target_value, 15);
105 			break;
106 		case 3:
107 			g_value_set_int (target_value, 10);
108 			break;
109 		case 4:
110 			g_value_set_int (target_value, 5);
111 			break;
112 		default:
113 			success = FALSE;
114 	}
115 
116 	return success;
117 }
118 
119 static void
120 calendar_preferences_dispose (GObject *object)
121 {
122 	ECalendarPreferences *prefs = (ECalendarPreferences *) object;
123 
124 	if (prefs->builder != NULL) {
125 		g_object_unref (prefs->builder);
126 		prefs->builder = NULL;
127 	}
128 
129 	if (prefs->registry != NULL) {
130 		g_object_unref (prefs->registry);
131 		prefs->registry = NULL;
132 	}
133 
134 	if (prefs->shell_settings != NULL) {
135 		g_object_unref (prefs->shell_settings);
136 		prefs->shell_settings = NULL;
137 	}
138 
139 	/* Chain up to parent's dispose() method. */
140 	G_OBJECT_CLASS (e_calendar_preferences_parent_class)->dispose (object);
141 }
142 
143 static void
144 e_calendar_preferences_class_init (ECalendarPreferencesClass *class)
145 {
146 	GObjectClass *object_class;
147 
148 	object_class = G_OBJECT_CLASS (class);
149 	object_class->dispose = calendar_preferences_dispose;
150 }
151 
152 static void
153 e_calendar_preferences_class_finalize (ECalendarPreferencesClass *class)
154 {
155 }
156 
157 static void
158 e_calendar_preferences_init (ECalendarPreferences *preferences)
159 {
160 }
161 
162 static GtkWidget *
163 calendar_preferences_get_config_widget (EConfig *ec,
164                                         EConfigItem *item,
165                                         GtkWidget *parent,
166                                         GtkWidget *old,
167                                         gint position,
168                                         gpointer data)
169 {
170 	ECalendarPreferences *preferences = data;
171 
172 	return e_builder_get_widget (preferences->builder, item->label);
173 }
174 
175 static void
176 update_day_second_zone_caption (ECalendarPreferences *prefs)
177 {
178 	gchar *location;
179 	const gchar *caption;
180 	icaltimezone *zone;
181 
182 	g_return_if_fail (prefs != NULL);
183 
184 	/* Translators: "None" indicates no second time zone set for a day view */
185 	caption = C_("cal-second-zone", "None");
186 
187 	location = calendar_config_get_day_second_zone ();
188 	if (location && *location) {
189 		zone = icaltimezone_get_builtin_timezone (location);
190 		if (zone && icaltimezone_get_display_name (zone)) {
191 			caption = icaltimezone_get_display_name (zone);
192 		}
193 	}
194 	g_free (location);
195 
196 	gtk_button_set_label (GTK_BUTTON (prefs->day_second_zone), caption);
197 }
198 
199 static void
200 on_set_day_second_zone (GtkWidget *item,
201                         ECalendarPreferences *prefs)
202 {
203 	if (!gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)))
204 		return;
205 
206 	calendar_config_set_day_second_zone (g_object_get_data (G_OBJECT (item), "timezone"));
207 	update_day_second_zone_caption (prefs);
208 }
209 
210 static void
211 on_select_day_second_zone (GtkWidget *item,
212                            ECalendarPreferences *prefs)
213 {
214 	g_return_if_fail (prefs != NULL);
215 
216 	calendar_config_select_day_second_zone ();
217 	update_day_second_zone_caption (prefs);
218 }
219 
220 static void
221 day_second_zone_clicked (GtkWidget *widget,
222                          ECalendarPreferences *prefs)
223 {
224 	GtkWidget *menu, *item;
225 	GSList *group = NULL, *recent_zones, *s;
226 	gchar *location;
227 	icaltimezone *zone, *second_zone = NULL;
228 
229 	menu = gtk_menu_new ();
230 
231 	location = calendar_config_get_day_second_zone ();
232 	if (location && *location)
233 		second_zone = icaltimezone_get_builtin_timezone (location);
234 	g_free (location);
235 
236 	group = NULL;
237 	item = gtk_radio_menu_item_new_with_label (group, C_("cal-second-zone", "None"));
238 	group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
239 	if (!second_zone)
240 		gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
241 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
242 	g_signal_connect (
243 		item, "toggled",
244 		G_CALLBACK (on_set_day_second_zone), prefs);
245 
246 	recent_zones = calendar_config_get_day_second_zones ();
247 	for (s = recent_zones; s != NULL; s = s->next) {
248 		zone = icaltimezone_get_builtin_timezone (s->data);
249 		if (!zone)
250 			continue;
251 
252 		item = gtk_radio_menu_item_new_with_label (group, icaltimezone_get_display_name (zone));
253 		group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (item));
254 		/* both comes from builtin, thus no problem to compare pointers */
255 		if (zone == second_zone)
256 			gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
257 		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
258 		g_object_set_data_full (G_OBJECT (item), "timezone", g_strdup (s->data), g_free);
259 		g_signal_connect (
260 			item, "toggled",
261 			G_CALLBACK (on_set_day_second_zone), prefs);
262 	}
263 	calendar_config_free_day_second_zones (recent_zones);
264 
265 	item = gtk_separator_menu_item_new ();
266 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
267 
268 	item = gtk_menu_item_new_with_label (_("Select..."));
269 	g_signal_connect (
270 		item, "activate",
271 		G_CALLBACK (on_select_day_second_zone), prefs);
272 	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
273 
274 	gtk_widget_show_all (menu);
275 
276 	gtk_menu_popup (
277 		GTK_MENU (menu), NULL, NULL, NULL, NULL,
278 		0, gtk_get_current_event_time ());
279 }
280 
281 static void
282 start_of_day_changed (GtkWidget *widget,
283                       ECalendarPreferences *prefs)
284 {
285 	gint start_hour, start_minute, end_hour, end_minute;
286 	EDateEdit *start, *end;
287 
288 	start = E_DATE_EDIT (prefs->start_of_day);
289 	end = E_DATE_EDIT (prefs->end_of_day);
290 
291 	e_date_edit_get_time_of_day (start, &start_hour, &start_minute);
292 	e_date_edit_get_time_of_day (end, &end_hour, &end_minute);
293 
294 	if ((start_hour > end_hour) || (start_hour == end_hour && start_minute > end_minute)) {
295 		if (start_hour < 23)
296 			e_date_edit_set_time_of_day (end, start_hour + 1, start_minute);
297 		else
298 			e_date_edit_set_time_of_day (end, 23, 59);
299 
300 		return;
301 	}
302 
303 	e_shell_settings_set_int (
304 		prefs->shell_settings,
305 		"cal-work-day-start-hour", start_hour);
306 	e_shell_settings_set_int (
307 		prefs->shell_settings,
308 		"cal-work-day-start-minute", start_minute);
309 }
310 
311 static void
312 end_of_day_changed (GtkWidget *widget,
313                     ECalendarPreferences *prefs)
314 {
315 	gint start_hour, start_minute, end_hour, end_minute;
316 	EDateEdit *start, *end;
317 
318 	start = E_DATE_EDIT (prefs->start_of_day);
319 	end = E_DATE_EDIT (prefs->end_of_day);
320 
321 	e_date_edit_get_time_of_day (start, &start_hour, &start_minute);
322 	e_date_edit_get_time_of_day (end, &end_hour, &end_minute);
323 
324 	if ((end_hour < start_hour) || (end_hour == start_hour && end_minute < start_minute)) {
325 		if (end_hour < 1)
326 			e_date_edit_set_time_of_day (start, 0, 0);
327 		else
328 			e_date_edit_set_time_of_day (start, end_hour - 1, end_minute);
329 
330 		return;
331 	}
332 
333 	e_shell_settings_set_int (
334 		prefs->shell_settings,
335 		"cal-work-day-end-hour", end_hour);
336 	e_shell_settings_set_int (
337 		prefs->shell_settings,
338 		"cal-work-day-end-minute", end_minute);
339 }
340 
341 static void
342 notify_with_tray_toggled (GtkToggleButton *toggle,
343                           ECalendarPreferences *prefs)
344 {
345 	GSettings *settings;
346 
347 	g_return_if_fail (toggle != NULL);
348 
349 	settings = g_settings_new ("org.gnome.evolution.calendar");
350 	g_settings_set_boolean (settings, "notify-with-tray", gtk_toggle_button_get_active (toggle));
351 	g_object_unref (settings);
352 }
353 
354 static void
355 update_system_tz_widgets (EShellSettings *shell_settings,
356                           GParamSpec *pspec,
357                           ECalendarPreferences *prefs)
358 {
359 	GtkWidget *widget;
360 	icaltimezone *zone;
361 	const gchar *display_name;
362 	gchar *text;
363 
364 	widget = e_builder_get_widget (prefs->builder, "system-tz-label");
365 	g_return_if_fail (GTK_IS_LABEL (widget));
366 
367 	zone = e_cal_util_get_system_timezone ();
368 	if (zone != NULL)
369 		display_name = gettext (icaltimezone_get_display_name (zone));
370 	else
371 		display_name = "UTC";
372 
373 	text = g_strdup_printf ("(%s)", display_name);
374 	gtk_label_set_text (GTK_LABEL (widget), text);
375 	g_free (text);
376 }
377 
378 static void
379 setup_changes (ECalendarPreferences *prefs)
380 {
381 	g_signal_connect (
382 		prefs->day_second_zone, "clicked",
383 		G_CALLBACK (day_second_zone_clicked), prefs);
384 
385 	g_signal_connect (
386 		prefs->start_of_day, "changed",
387 		G_CALLBACK (start_of_day_changed), prefs);
388 
389 	g_signal_connect (
390 		prefs->end_of_day, "changed",
391 		G_CALLBACK (end_of_day_changed), prefs);
392 
393 	g_signal_connect (
394 		prefs->notify_with_tray, "toggled",
395 		G_CALLBACK (notify_with_tray_toggled), prefs);
396 }
397 
398 static void
399 show_alarms_config (ECalendarPreferences *prefs)
400 {
401 	GSettings *settings;
402 	GtkWidget *widget;
403 
404 	widget = e_alarm_selector_new (prefs->registry);
405 	atk_object_set_name (
406 		gtk_widget_get_accessible (widget),
407 		_("Selected Calendars for Alarms"));
408 	gtk_container_add (GTK_CONTAINER (prefs->scrolled_window), widget);
409 	gtk_widget_show (widget);
410 
411 	settings = g_settings_new ("org.gnome.evolution.calendar");
412 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (prefs->notify_with_tray), g_settings_get_boolean (settings, "notify-with-tray"));
413 	g_object_unref (settings);
414 }
415 
416 /* Shows the current config settings in the dialog. */
417 static void
418 show_config (ECalendarPreferences *prefs)
419 {
420 	EShellSettings *shell_settings;
421 
422 	shell_settings = prefs->shell_settings;
423 
424 	/* Day's second zone */
425 	update_day_second_zone_caption (prefs);
426 
427 	/* Start of Day. */
428 	e_date_edit_set_time_of_day (
429 		E_DATE_EDIT (prefs->start_of_day),
430 		e_shell_settings_get_int (
431 			shell_settings, "cal-work-day-start-hour"),
432 		e_shell_settings_get_int (
433 			shell_settings, "cal-work-day-start-minute"));
434 
435 	/* End of Day. */
436 	e_date_edit_set_time_of_day (
437 		E_DATE_EDIT (prefs->end_of_day),
438 		e_shell_settings_get_int (
439 			shell_settings, "cal-work-day-end-hour"),
440 		e_shell_settings_get_int (
441 			shell_settings, "cal-work-day-end-minute"));
442 
443 	/* Alarms list */
444 	show_alarms_config (prefs);
445 }
446 
447 /* plugin meta-data */
448 static ECalConfigItem eccp_items[] = {
449 	{ E_CONFIG_BOOK,          (gchar *) "",                             (gchar *) "toplevel-notebook", calendar_preferences_get_config_widget },
450 	{ E_CONFIG_PAGE,          (gchar *) "00.general",                   (gchar *) "general",           calendar_preferences_get_config_widget },
451 	{ E_CONFIG_SECTION_TABLE, (gchar *) "00.general/00.time",           (gchar *) "time",              calendar_preferences_get_config_widget },
452 	{ E_CONFIG_SECTION_TABLE, (gchar *) "00.general/10.workWeek",       (gchar *) "workWeek",          calendar_preferences_get_config_widget },
453 	{ E_CONFIG_SECTION,       (gchar *) "00.general/20.alerts",         (gchar *) "alerts",            calendar_preferences_get_config_widget },
454 	{ E_CONFIG_PAGE,          (gchar *) "10.display",                   (gchar *) "display",           calendar_preferences_get_config_widget },
455 	{ E_CONFIG_SECTION,       (gchar *) "10.display/00.general",        (gchar *) "displayGeneral",    calendar_preferences_get_config_widget },
456 	{ E_CONFIG_SECTION,       (gchar *) "10.display/10.taskList",       (gchar *) "taskList",          calendar_preferences_get_config_widget },
457 	{ E_CONFIG_PAGE,          (gchar *) "12.tasks",                     (gchar *) "tasks-vbox",        calendar_preferences_get_config_widget },
458 	{ E_CONFIG_PAGE,          (gchar *) "15.alarms",                    (gchar *) "alarms",            calendar_preferences_get_config_widget },
459 	{ E_CONFIG_PAGE,          (gchar *) "20.freeBusy",                  (gchar *) "freebusy",          calendar_preferences_get_config_widget },
460 	{ E_CONFIG_SECTION,       (gchar *) "20.freeBusy/00.defaultServer", (gchar *) "default-freebusy-vbox",   calendar_preferences_get_config_widget },
461 };
462 
463 static void
464 eccp_free (EConfig *ec,
465            GSList *items,
466            gpointer data)
467 {
468 	g_slist_free (items);
469 }
470 
471 static void
472 calendar_preferences_construct (ECalendarPreferences *prefs,
473                                 EShell *shell)
474 {
475 	ECalConfig *ec;
476 	ECalConfigTargetPrefs *target;
477 	EShellSettings *shell_settings;
478 	gboolean locale_supports_12_hour_format;
479 	gint i;
480 	GtkWidget *toplevel;
481 	GtkWidget *widget;
482 	GtkWidget *table;
483 	GSList *l;
484 
485 	shell_settings = prefs->shell_settings;
486 
487 	locale_supports_12_hour_format =
488 		calendar_config_locale_supports_12_hour_format ();
489 
490 	/* Force 24 hour format for locales which don't support 12 hour format */
491 	if (!locale_supports_12_hour_format
492 	    && !e_shell_settings_get_boolean (shell_settings, "cal-use-24-hour-format"))
493 		e_shell_settings_set_boolean (shell_settings, "cal-use-24-hour-format", TRUE);
494 
495 	/* Make sure our custom widget classes are registered with
496 	 * GType before we load the GtkBuilder definition file. */
497 	E_TYPE_DATE_EDIT;
498 	E_TYPE_TIMEZONE_ENTRY;
499 
500 	prefs->builder = gtk_builder_new ();
501 	e_load_ui_builder_definition (prefs->builder, "e-calendar-preferences.ui");
502 
503 	/** @HookPoint-ECalConfig: Calendar Preferences Page
504 	 * @Id: org.gnome.evolution.calendar.prefs
505 	 * @Type: E_CONFIG_BOOK
506 	 * @Class: org.gnome.evolution.calendar.config:1.0
507 	 * @Target: ECalConfigTargetPrefs
508 	 *
509 	 * The mail calendar preferences page
510 	 */
511 	ec = e_cal_config_new (E_CONFIG_BOOK, "org.gnome.evolution.calendar.prefs");
512 	l = NULL;
513 	for (i = 0; i < G_N_ELEMENTS (eccp_items); i++)
514 		l = g_slist_prepend (l, &eccp_items[i]);
515 	e_config_add_items ((EConfig *) ec, l, eccp_free, prefs);
516 
517 	widget = e_builder_get_widget (prefs->builder, "use-system-tz-check");
518 	g_object_bind_property (
519 		shell_settings, "cal-use-system-timezone",
520 		widget, "active",
521 		G_BINDING_BIDIRECTIONAL |
522 		G_BINDING_SYNC_CREATE);
523 	g_signal_connect (
524 		shell_settings, "notify::cal-use-system-timezone",
525 		G_CALLBACK (update_system_tz_widgets), prefs);
526 	update_system_tz_widgets (shell_settings, NULL, prefs);
527 
528 	widget = e_builder_get_widget (prefs->builder, "timezone");
529 	g_object_bind_property (
530 		shell_settings, "cal-timezone",
531 		widget, "timezone",
532 		G_BINDING_BIDIRECTIONAL |
533 		G_BINDING_SYNC_CREATE);
534 	g_object_bind_property (
535 		shell_settings, "cal-use-system-timezone",
536 		widget, "sensitive",
537 		G_BINDING_BIDIRECTIONAL |
538 		G_BINDING_SYNC_CREATE |
539 		G_BINDING_INVERT_BOOLEAN);
540 
541 	/* General tab */
542 	prefs->day_second_zone = e_builder_get_widget (prefs->builder, "day_second_zone");
543 
544 	widget = e_builder_get_widget (prefs->builder, "sun_button");
545 	g_object_bind_property (
546 		shell_settings, "cal-working-days-sunday",
547 		widget, "active",
548 		G_BINDING_BIDIRECTIONAL |
549 		G_BINDING_SYNC_CREATE);
550 
551 	widget = e_builder_get_widget (prefs->builder, "mon_button");
552 	g_object_bind_property (
553 		shell_settings, "cal-working-days-monday",
554 		widget, "active",
555 		G_BINDING_BIDIRECTIONAL |
556 		G_BINDING_SYNC_CREATE);
557 
558 	widget = e_builder_get_widget (prefs->builder, "tue_button");
559 	g_object_bind_property (
560 		shell_settings, "cal-working-days-tuesday",
561 		widget, "active",
562 		G_BINDING_BIDIRECTIONAL |
563 		G_BINDING_SYNC_CREATE);
564 
565 	widget = e_builder_get_widget (prefs->builder, "wed_button");
566 	g_object_bind_property (
567 		shell_settings, "cal-working-days-wednesday",
568 		widget, "active",
569 		G_BINDING_BIDIRECTIONAL |
570 		G_BINDING_SYNC_CREATE);
571 
572 	widget = e_builder_get_widget (prefs->builder, "thu_button");
573 	g_object_bind_property (
574 		shell_settings, "cal-working-days-thursday",
575 		widget, "active",
576 		G_BINDING_BIDIRECTIONAL |
577 		G_BINDING_SYNC_CREATE);
578 
579 	widget = e_builder_get_widget (prefs->builder, "fri_button");
580 	g_object_bind_property (
581 		shell_settings, "cal-working-days-friday",
582 		widget, "active",
583 		G_BINDING_BIDIRECTIONAL |
584 		G_BINDING_SYNC_CREATE);
585 
586 	widget = e_builder_get_widget (prefs->builder, "sat_button");
587 	g_object_bind_property (
588 		shell_settings, "cal-working-days-saturday",
589 		widget, "active",
590 		G_BINDING_BIDIRECTIONAL |
591 		G_BINDING_SYNC_CREATE);
592 
593 	widget = e_builder_get_widget (prefs->builder, "week_start_day");
594 	g_object_bind_property (
595 		shell_settings, "cal-week-start-day",
596 		widget, "active",
597 		G_BINDING_BIDIRECTIONAL |
598 		G_BINDING_SYNC_CREATE);
599 
600 	widget = e_builder_get_widget (prefs->builder, "start_of_day");
601 	prefs->start_of_day = widget;  /* XXX delete this */
602 	if (locale_supports_12_hour_format)
603 		g_object_bind_property (
604 			shell_settings, "cal-use-24-hour-format",
605 			widget, "use-24-hour-format",
606 			G_BINDING_SYNC_CREATE);
607 
608 	widget = e_builder_get_widget (prefs->builder, "end_of_day");
609 	prefs->end_of_day = widget;  /* XXX delete this */
610 	if (locale_supports_12_hour_format)
611 		g_object_bind_property (
612 			shell_settings, "cal-use-24-hour-format",
613 			widget, "use-24-hour-format",
614 			G_BINDING_SYNC_CREATE);
615 
616 	widget = e_builder_get_widget (prefs->builder, "use_12_hour");
617 	gtk_widget_set_sensitive (widget, locale_supports_12_hour_format);
618 	g_object_bind_property (
619 		shell_settings, "cal-use-24-hour-format",
620 		widget, "active",
621 		G_BINDING_BIDIRECTIONAL |
622 		G_BINDING_SYNC_CREATE |
623 		G_BINDING_INVERT_BOOLEAN);
624 
625 	widget = e_builder_get_widget (prefs->builder, "use_24_hour");
626 	gtk_widget_set_sensitive (widget, locale_supports_12_hour_format);
627 	g_object_bind_property (
628 		shell_settings, "cal-use-24-hour-format",
629 		widget, "active",
630 		G_BINDING_BIDIRECTIONAL |
631 		G_BINDING_SYNC_CREATE);
632 
633 	widget = e_builder_get_widget (prefs->builder, "confirm_delete");
634 	g_object_bind_property (
635 		shell_settings, "cal-confirm-delete",
636 		widget, "active",
637 		G_BINDING_BIDIRECTIONAL |
638 		G_BINDING_SYNC_CREATE);
639 
640 	widget = e_builder_get_widget (prefs->builder, "default_reminder");
641 	g_object_bind_property (
642 		shell_settings, "cal-use-default-reminder",
643 		widget, "active",
644 		G_BINDING_BIDIRECTIONAL |
645 		G_BINDING_SYNC_CREATE);
646 
647 	widget = e_builder_get_widget (prefs->builder, "default_reminder_interval");
648 	g_object_bind_property (
649 		shell_settings, "cal-default-reminder-interval",
650 		widget, "value",
651 		G_BINDING_BIDIRECTIONAL |
652 		G_BINDING_SYNC_CREATE);
653 	g_object_bind_property (
654 		shell_settings, "cal-use-default-reminder",
655 		widget, "sensitive",
656 		G_BINDING_SYNC_CREATE);
657 
658 	widget = e_builder_get_widget (prefs->builder, "default_reminder_units");
659 	g_object_bind_property (
660 		shell_settings, "cal-default-reminder-units",
661 		widget, "active",
662 		G_BINDING_BIDIRECTIONAL |
663 		G_BINDING_SYNC_CREATE);
664 	g_object_bind_property (
665 		shell_settings, "cal-use-default-reminder",
666 		widget, "sensitive",
667 		G_BINDING_SYNC_CREATE);
668 
669 	widget = e_builder_get_widget (prefs->builder, "ba_reminder");
670 	g_object_bind_property (
671 		shell_settings, "cal-use-ba-reminder",
672 		widget, "active",
673 		G_BINDING_BIDIRECTIONAL |
674 		G_BINDING_SYNC_CREATE);
675 
676 	widget = e_builder_get_widget (prefs->builder, "ba_reminder_interval");
677 	g_object_bind_property (
678 		shell_settings, "cal-ba-reminder-interval",
679 		widget, "value",
680 		G_BINDING_BIDIRECTIONAL |
681 		G_BINDING_SYNC_CREATE);
682 	g_object_bind_property (
683 		shell_settings, "cal-use-ba-reminder",
684 		widget, "sensitive",
685 		G_BINDING_SYNC_CREATE);
686 
687 	widget = e_builder_get_widget (prefs->builder, "ba_reminder_units");
688 	g_object_bind_property (
689 		shell_settings, "cal-ba-reminder-units",
690 		widget, "active",
691 		G_BINDING_BIDIRECTIONAL |
692 		G_BINDING_SYNC_CREATE);
693 	g_object_bind_property (
694 		shell_settings, "cal-use-ba-reminder",
695 		widget, "sensitive",
696 		G_BINDING_SYNC_CREATE);
697 
698 	/* Display tab */
699 	widget = e_builder_get_widget (prefs->builder, "time_divisions");
700 	g_object_bind_property_full (
701 		shell_settings, "cal-time-divisions",
702 		widget, "active",
703 		G_BINDING_BIDIRECTIONAL |
704 		G_BINDING_SYNC_CREATE,
705 		transform_time_divisions_to_index,
706 		transform_index_to_time_divisions,
707 		NULL, (GDestroyNotify) NULL);
708 
709 	widget = e_builder_get_widget (prefs->builder, "show_end_times");
710 	g_object_bind_property (
711 		shell_settings, "cal-show-event-end-times",
712 		widget, "active",
713 		G_BINDING_BIDIRECTIONAL |
714 		G_BINDING_SYNC_CREATE);
715 
716 	widget = e_builder_get_widget (prefs->builder, "compress_weekend");
717 	g_object_bind_property (
718 		shell_settings, "cal-compress-weekend",
719 		widget, "active",
720 		G_BINDING_BIDIRECTIONAL |
721 		G_BINDING_SYNC_CREATE);
722 
723 	widget = e_builder_get_widget (prefs->builder, "show_week_numbers");
724 	g_object_bind_property (
725 		shell_settings, "cal-show-week-numbers",
726 		widget, "active",
727 		G_BINDING_BIDIRECTIONAL |
728 		G_BINDING_SYNC_CREATE);
729 
730 	widget = e_builder_get_widget (prefs->builder, "recur_events_italic");
731 	g_object_bind_property (
732 		shell_settings, "cal-recur-events-italic",
733 		widget, "active",
734 		G_BINDING_BIDIRECTIONAL |
735 		G_BINDING_SYNC_CREATE);
736 
737 	widget = e_builder_get_widget (prefs->builder, "month_scroll_by_week");
738 	g_object_bind_property (
739 		shell_settings, "cal-month-scroll-by-week",
740 		widget, "active",
741 		G_BINDING_BIDIRECTIONAL |
742 		G_BINDING_SYNC_CREATE);
743 
744 	widget = e_builder_get_widget (prefs->builder, "tasks_due_today_highlight");
745 	g_object_bind_property (
746 		shell_settings, "cal-tasks-highlight-due-today",
747 		widget, "active",
748 		G_BINDING_BIDIRECTIONAL |
749 		G_BINDING_SYNC_CREATE);
750 
751 	widget = e_builder_get_widget (prefs->builder, "tasks_due_today_color");
752 	g_object_bind_property_full (
753 		shell_settings, "cal-tasks-color-due-today",
754 		widget, "color",
755 		G_BINDING_BIDIRECTIONAL |
756 		G_BINDING_SYNC_CREATE,
757 		e_binding_transform_string_to_color,
758 		e_binding_transform_color_to_string,
759 		NULL, (GDestroyNotify) NULL);
760 	g_object_bind_property (
761 		shell_settings, "cal-tasks-highlight-due-today",
762 		widget, "sensitive",
763 		G_BINDING_SYNC_CREATE);
764 
765 	widget = e_builder_get_widget (prefs->builder, "tasks_overdue_highlight");
766 	g_object_bind_property (
767 		shell_settings, "cal-tasks-highlight-overdue",
768 		widget, "active",
769 		G_BINDING_BIDIRECTIONAL |
770 		G_BINDING_SYNC_CREATE);
771 
772 	widget = e_builder_get_widget (prefs->builder, "tasks_overdue_color");
773 	g_object_bind_property_full (
774 		shell_settings, "cal-tasks-color-overdue",
775 		widget, "color",
776 		G_BINDING_BIDIRECTIONAL |
777 		G_BINDING_SYNC_CREATE,
778 		e_binding_transform_string_to_color,
779 		e_binding_transform_color_to_string,
780 		(GDestroyNotify) NULL, NULL);
781 	g_object_bind_property (
782 		shell_settings, "cal-tasks-highlight-overdue",
783 		widget, "sensitive",
784 		G_BINDING_SYNC_CREATE);
785 
786 	widget = e_builder_get_widget (prefs->builder, "tasks_hide_completed");
787 	g_object_bind_property (
788 		shell_settings, "cal-hide-completed-tasks",
789 		widget, "active",
790 		G_BINDING_BIDIRECTIONAL |
791 		G_BINDING_SYNC_CREATE);
792 
793 	widget = e_builder_get_widget (prefs->builder, "tasks_hide_completed_interval");
794 	g_object_bind_property (
795 		shell_settings, "cal-hide-completed-tasks-value",
796 		widget, "value",
797 		G_BINDING_BIDIRECTIONAL |
798 		G_BINDING_SYNC_CREATE);
799 	g_object_bind_property (
800 		shell_settings, "cal-hide-completed-tasks",
801 		widget, "sensitive",
802 		G_BINDING_SYNC_CREATE);
803 
804 	widget = e_builder_get_widget (prefs->builder, "tasks_hide_completed_units");
805 	g_object_bind_property (
806 		shell_settings, "cal-hide-completed-tasks-units",
807 		widget, "active",
808 		G_BINDING_BIDIRECTIONAL |
809 		G_BINDING_SYNC_CREATE);
810 	g_object_bind_property (
811 		shell_settings, "cal-hide-completed-tasks",
812 		widget, "sensitive",
813 		G_BINDING_SYNC_CREATE);
814 
815 	/* Alarms tab */
816 	prefs->notify_with_tray = e_builder_get_widget (prefs->builder, "notify_with_tray");
817 	prefs->scrolled_window = e_builder_get_widget (prefs->builder, "calendar-source-scrolled-window");
818 
819 	/* Free/Busy tab */
820 	widget = e_builder_get_widget (prefs->builder, "template_url");
821 	g_object_bind_property (
822 		shell_settings, "cal-free-busy-template",
823 		widget, "text",
824 		G_BINDING_BIDIRECTIONAL |
825 		G_BINDING_SYNC_CREATE);
826 
827 	/* date/time format */
828 	table = e_builder_get_widget (prefs->builder, "datetime_format_table");
829 	e_datetime_format_add_setup_widget (table, 0, "calendar", "table",  DTFormatKindDateTime, _("Ti_me and date:"));
830 	e_datetime_format_add_setup_widget (table, 1, "calendar", "table",  DTFormatKindDate, _("_Date only:"));
831 
832 	/* Hide senseless preferences when running in Express mode */
833 	e_shell_hide_widgets_for_express_mode (shell, prefs->builder,
834 					       "label_second_zone",
835 					       "hbox_second_zone",
836 					       "timezone",
837 					       "timezone_label",
838 					       "hbox_use_system_timezone",
839 					       "hbox_time_divisions",
840 					       "show_end_times",
841 					       "month_scroll_by_week",
842 					       NULL);
843 
844 	/* HACK: GTK+ 2.18 and 2.20 has a GtkTable which includes
845 	 *       row/column spacing even for empty rows/columns.
846 	 *       When Evo runs in Express mode, we hide all the rows in
847 	 *       the Time section of the calendar's General preferences
848 	 *       page.  However, due to that behavior in GTK+, we get a
849 	 *       lot of extra spacing in that section.  Since we know that
850 	 *       in Express mode we only leave a single row visible, we'll
851 	 *       make the table's row spacing equal to 0 in that case. */
852 	if (e_shell_get_express_mode (shell)) {
853 		widget = e_builder_get_widget (prefs->builder, "time");
854 		gtk_table_set_row_spacings (GTK_TABLE (widget), 0);
855 	}
856 
857 	/* Hook up and add the toplevel widget */
858 
859 	target = e_cal_config_target_new_prefs (ec);
860 	e_config_set_target ((EConfig *) ec, (EConfigTarget *) target);
861 	toplevel = e_config_create_widget ((EConfig *) ec);
862 	gtk_container_add (GTK_CONTAINER (prefs), toplevel);
863 
864 	show_config (prefs);
865 	/* FIXME: weakref? */
866 	setup_changes (prefs);
867 }
868 
869 void
870 e_calendar_preferences_type_register (GTypeModule *type_module)
871 {
872 	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
873 	 *     function, so we have to wrap it with a public function in
874 	 *     order to register types from a separate compilation unit. */
875 	e_calendar_preferences_register_type (type_module);
876 }
877 
878 GtkWidget *
879 e_calendar_preferences_new (EPreferencesWindow *window)
880 {
881 	EShell *shell;
882 	ESourceRegistry *registry;
883 	EShellSettings *shell_settings;
884 	ECalendarPreferences *preferences;
885 
886 	shell = e_preferences_window_get_shell (window);
887 
888 	registry = e_shell_get_registry (shell);
889 	shell_settings = e_shell_get_shell_settings (shell);
890 
891 	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
892 
893 	preferences = g_object_new (E_TYPE_CALENDAR_PREFERENCES, NULL);
894 
895 	preferences->registry = g_object_ref (registry);
896 	preferences->shell_settings = g_object_ref (shell_settings);
897 
898 	/* FIXME Kill this function. */
899 	calendar_preferences_construct (preferences, shell);
900 
901 	return GTK_WIDGET (preferences);
902 }