Make it possible to disable Reminders for Tasks
[evolution.git] / src / calendar / gui / e-comp-editor-task.c
blob11076daf6239660b1fadcbf9f7cb03208e0da2a1
1 /*
2 * Copyright (C) 2015 Red Hat, Inc. (www.redhat.com)
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #include "evolution-config.h"
20 #include <glib/gi18n-lib.h>
21 #include <gtk/gtk.h>
23 #include <e-util/e-util.h>
25 #include "calendar-config.h"
26 #include "comp-util.h"
27 #include "e-comp-editor.h"
28 #include "e-comp-editor-page.h"
29 #include "e-comp-editor-page-attachments.h"
30 #include "e-comp-editor-page-general.h"
31 #include "e-comp-editor-page-recurrence.h"
32 #include "e-comp-editor-page-reminders.h"
33 #include "e-comp-editor-property-part.h"
34 #include "e-comp-editor-property-parts.h"
36 #include "e-comp-editor-task.h"
38 struct _ECompEditorTaskPrivate {
39 ECompEditorPage *page_general;
40 ECompEditorPage *recurrence_page;
41 ECompEditorPage *reminders_page;
42 ECompEditorPropertyPart *categories;
43 ECompEditorPropertyPart *dtstart;
44 ECompEditorPropertyPart *due_date;
45 ECompEditorPropertyPart *completed_date;
46 ECompEditorPropertyPart *percentcomplete;
47 ECompEditorPropertyPart *status;
48 ECompEditorPropertyPart *timezone;
50 gpointer in_the_past_alert;
51 gpointer insensitive_info_alert;
54 G_DEFINE_TYPE (ECompEditorTask, e_comp_editor_task, E_TYPE_COMP_EDITOR)
56 static icaltimezone *
57 ece_task_get_timezone_from_property (ECompEditor *comp_editor,
58 icalproperty *property)
60 ECalClient *client;
61 icalparameter *param;
62 icaltimezone *zone = NULL;
63 const gchar *tzid;
65 g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL);
67 if (!property)
68 return NULL;
70 param = icalproperty_get_first_parameter (property, ICAL_TZID_PARAMETER);
71 if (!param)
72 return NULL;
74 tzid = icalparameter_get_tzid (param);
75 if (!tzid || !*tzid)
76 return NULL;
78 if (g_ascii_strcasecmp (tzid, "UTC") == 0)
79 return icaltimezone_get_utc_timezone ();
81 client = e_comp_editor_get_source_client (comp_editor);
82 /* It should be already fetched for the UI, thus this should be non-blocking. */
83 if (client && e_cal_client_get_timezone_sync (client, tzid, &zone, NULL, NULL) && zone)
84 return zone;
86 zone = icaltimezone_get_builtin_timezone_from_tzid (tzid);
87 if (!zone)
88 zone = icaltimezone_get_builtin_timezone (tzid);
90 return zone;
93 static void
94 ece_task_update_timezone (ECompEditorTask *task_editor,
95 gboolean *force_allday)
97 const gint properties[] = {
98 ICAL_DTSTART_PROPERTY,
99 ICAL_DUE_PROPERTY,
100 ICAL_COMPLETED_PROPERTY
102 ECompEditor *comp_editor;
103 icalcomponent *component;
104 icaltimezone *zone = NULL;
105 gint ii;
107 g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor));
109 if (force_allday)
110 *force_allday = FALSE;
112 comp_editor = E_COMP_EDITOR (task_editor);
114 component = e_comp_editor_get_component (comp_editor);
115 if (!component)
116 return;
118 for (ii = 0; !zone && ii < G_N_ELEMENTS (properties); ii++) {
119 struct icaltimetype dt;
120 if (icalcomponent_get_first_property (component, properties[ii])) {
121 dt = icalcomponent_get_dtstart (component);
122 if (icaltime_is_valid_time (dt)) {
123 if (force_allday && dt.is_date)
124 *force_allday = TRUE;
126 if (icaltime_is_utc (dt))
127 zone = icaltimezone_get_utc_timezone ();
128 else
129 zone = ece_task_get_timezone_from_property (comp_editor,
130 icalcomponent_get_first_property (component, properties[ii]));
135 if (zone) {
136 GtkWidget *edit_widget;
138 edit_widget = e_comp_editor_property_part_get_edit_widget (task_editor->priv->timezone);
140 e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (edit_widget), zone);
142 if (zone != calendar_config_get_icaltimezone ()) {
143 /* Show timezone part */
144 GtkAction *action;
146 action = e_comp_editor_get_action (comp_editor, "view-timezone");
147 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
152 static void
153 ece_task_notify_source_client_cb (GObject *object,
154 GParamSpec *param,
155 gpointer user_data)
157 g_return_if_fail (E_IS_COMP_EDITOR_TASK (object));
159 ece_task_update_timezone (E_COMP_EDITOR_TASK (object), NULL);
162 static void
163 ece_task_notify_target_client_cb (GObject *object,
164 GParamSpec *param,
165 gpointer user_data)
167 ECompEditorTask *task_editor;
168 ECompEditor *comp_editor;
169 ECalClient *cal_client;
170 GtkWidget *edit_widget;
171 GtkAction *action;
172 gboolean date_only;
173 gboolean was_allday;
174 gboolean can_recur;
175 gboolean can_reminders;
177 g_return_if_fail (E_IS_COMP_EDITOR_TASK (object));
179 task_editor = E_COMP_EDITOR_TASK (object);
180 comp_editor = E_COMP_EDITOR (task_editor);
181 cal_client = e_comp_editor_get_target_client (comp_editor);
183 action = e_comp_editor_get_action (comp_editor, "all-day-task");
184 was_allday = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
186 date_only = !cal_client || e_client_check_capability (E_CLIENT (cal_client), CAL_STATIC_CAPABILITY_TASK_DATE_ONLY);
188 e_comp_editor_property_part_datetime_set_date_only (E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->dtstart), date_only);
189 e_comp_editor_property_part_datetime_set_date_only (E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->due_date), date_only);
190 e_comp_editor_property_part_datetime_set_date_only (E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->completed_date), date_only);
192 edit_widget = e_comp_editor_property_part_get_edit_widget (task_editor->priv->timezone);
193 gtk_widget_set_sensitive (edit_widget, !date_only);
195 action = e_comp_editor_get_action (comp_editor, "view-timezone");
196 gtk_action_set_sensitive (action, !date_only);
198 action = e_comp_editor_get_action (comp_editor, "all-day-task");
199 gtk_action_set_visible (action, !date_only);
201 if (was_allday) {
202 action = e_comp_editor_get_action (comp_editor, "all-day-task");
203 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
206 can_reminders = !cal_client || !e_client_check_capability (E_CLIENT (cal_client), CAL_STATIC_CAPABILITY_TASK_NO_ALARM);
207 gtk_widget_set_visible (GTK_WIDGET (task_editor->priv->reminders_page), can_reminders);
209 can_recur = !cal_client || e_client_check_capability (E_CLIENT (cal_client), CAL_STATIC_CAPABILITY_TASK_CAN_RECUR);
210 gtk_widget_set_visible (GTK_WIDGET (task_editor->priv->recurrence_page), can_recur);
213 static void
214 ece_task_check_dates_in_the_past (ECompEditorTask *task_editor)
216 guint32 flags;
218 g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor));
220 flags = e_comp_editor_get_flags (E_COMP_EDITOR (task_editor));
222 if (task_editor->priv->in_the_past_alert)
223 e_alert_response (task_editor->priv->in_the_past_alert, GTK_RESPONSE_OK);
225 if ((flags & E_COMP_EDITOR_FLAG_IS_NEW) != 0) {
226 GString *message = NULL;
227 struct icaltimetype dtstart_itt, due_date_itt;
229 dtstart_itt = e_comp_editor_property_part_datetime_get_value (
230 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->dtstart));
231 due_date_itt = e_comp_editor_property_part_datetime_get_value (
232 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->due_date));
234 if (cal_comp_util_compare_time_with_today (dtstart_itt) < 0)
235 message = g_string_new (_("Task’s start date is in the past"));
237 if (cal_comp_util_compare_time_with_today (due_date_itt) < 0) {
238 if (message)
239 g_string_append (message, "\n");
240 else
241 message = g_string_new ("");
243 g_string_append (message, _("Task’s due date is in the past"));
246 if (message) {
247 EAlert *alert;
249 alert = e_comp_editor_add_warning (E_COMP_EDITOR (task_editor), message->str, NULL);
251 task_editor->priv->in_the_past_alert = alert;
253 if (alert)
254 g_object_add_weak_pointer (G_OBJECT (alert), &task_editor->priv->in_the_past_alert);
256 g_string_free (message, TRUE);
257 g_clear_object (&alert);
262 static void
263 ece_task_dtstart_changed_cb (EDateEdit *date_edit,
264 ECompEditorTask *task_editor)
266 ECompEditor *comp_editor;
268 g_return_if_fail (E_IS_DATE_EDIT (date_edit));
269 g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor));
271 comp_editor = E_COMP_EDITOR (task_editor);
273 if (e_comp_editor_get_updating (comp_editor))
274 return;
276 e_comp_editor_set_updating (comp_editor, TRUE);
278 e_comp_editor_ensure_start_before_end (E_COMP_EDITOR (task_editor),
279 task_editor->priv->dtstart, task_editor->priv->due_date,
280 TRUE);
282 e_comp_editor_set_updating (comp_editor, FALSE);
284 ece_task_check_dates_in_the_past (task_editor);
287 static void
288 ece_task_due_date_changed_cb (EDateEdit *date_edit,
289 ECompEditorTask *task_editor)
291 ECompEditor *comp_editor;
293 g_return_if_fail (E_IS_DATE_EDIT (date_edit));
294 g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor));
296 comp_editor = E_COMP_EDITOR (task_editor);
298 if (e_comp_editor_get_updating (comp_editor))
299 return;
301 e_comp_editor_set_updating (comp_editor, TRUE);
303 e_comp_editor_ensure_start_before_end (E_COMP_EDITOR (task_editor),
304 task_editor->priv->dtstart, task_editor->priv->due_date,
305 FALSE);
307 e_comp_editor_set_updating (comp_editor, FALSE);
309 ece_task_check_dates_in_the_past (task_editor);
312 static void
313 ece_task_completed_date_changed_cb (EDateEdit *date_edit,
314 ECompEditorTask *task_editor)
316 GtkSpinButton *percent_spin;
317 ECompEditor *comp_editor;
318 struct icaltimetype itt;
319 gint status;
321 g_return_if_fail (E_IS_DATE_EDIT (date_edit));
322 g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor));
324 comp_editor = E_COMP_EDITOR (task_editor);
326 if (e_comp_editor_get_updating (comp_editor))
327 return;
329 e_comp_editor_set_updating (comp_editor, TRUE);
331 status = e_comp_editor_property_part_picker_with_map_get_selected (
332 E_COMP_EDITOR_PROPERTY_PART_PICKER_WITH_MAP (task_editor->priv->status));
333 itt = e_comp_editor_property_part_datetime_get_value (
334 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->completed_date));
335 percent_spin = GTK_SPIN_BUTTON (e_comp_editor_property_part_get_edit_widget (task_editor->priv->percentcomplete));
337 if (icaltime_is_null_time (itt)) {
338 if (status == ICAL_STATUS_COMPLETED) {
339 e_comp_editor_property_part_picker_with_map_set_selected (
340 E_COMP_EDITOR_PROPERTY_PART_PICKER_WITH_MAP (task_editor->priv->status),
341 ICAL_STATUS_NONE);
343 gtk_spin_button_set_value (percent_spin, 0);
345 } else {
346 if (status != ICAL_STATUS_COMPLETED) {
347 e_comp_editor_property_part_picker_with_map_set_selected (
348 E_COMP_EDITOR_PROPERTY_PART_PICKER_WITH_MAP (task_editor->priv->status),
349 ICAL_STATUS_COMPLETED);
352 gtk_spin_button_set_value (percent_spin, 100);
355 e_comp_editor_set_updating (comp_editor, FALSE);
358 static void
359 ece_task_status_changed_cb (GtkComboBox *combo_box,
360 ECompEditorTask *task_editor)
362 ECompEditor *comp_editor;
363 GtkSpinButton *percent_spin;
364 EDateEdit *completed_date;
365 gint status;
367 g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
368 g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor));
370 comp_editor = E_COMP_EDITOR (task_editor);
372 if (e_comp_editor_get_updating (comp_editor))
373 return;
375 e_comp_editor_set_updating (comp_editor, TRUE);
377 percent_spin = GTK_SPIN_BUTTON (e_comp_editor_property_part_get_edit_widget (task_editor->priv->percentcomplete));
378 completed_date = E_DATE_EDIT (e_comp_editor_property_part_get_edit_widget (task_editor->priv->completed_date));
379 status = e_comp_editor_property_part_picker_with_map_get_selected (
380 E_COMP_EDITOR_PROPERTY_PART_PICKER_WITH_MAP (task_editor->priv->status));
382 if (status == ICAL_STATUS_NONE) {
383 gtk_spin_button_set_value (percent_spin, 0);
384 e_date_edit_set_time (completed_date, (time_t) -1);
385 } else if (status == ICAL_STATUS_INPROCESS) {
386 gint percent_complete = gtk_spin_button_get_value_as_int (percent_spin);
388 if (percent_complete <= 0 || percent_complete >= 100)
389 gtk_spin_button_set_value (percent_spin, 50);
391 e_date_edit_set_time (completed_date, (time_t) -1);
392 } else if (status == ICAL_STATUS_COMPLETED) {
393 gtk_spin_button_set_value (percent_spin, 100);
394 e_date_edit_set_time (completed_date, time (NULL));
397 e_comp_editor_set_updating (comp_editor, FALSE);
400 static void
401 ece_task_percentcomplete_value_changed_cb (GtkSpinButton *spin_button,
402 ECompEditorTask *task_editor)
404 ECompEditor *comp_editor;
405 GtkSpinButton *percent_spin;
406 EDateEdit *completed_date;
407 gint status, percent;
408 time_t ctime;
410 g_return_if_fail (GTK_IS_SPIN_BUTTON (spin_button));
411 g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor));
413 comp_editor = E_COMP_EDITOR (task_editor);
415 if (e_comp_editor_get_updating (comp_editor))
416 return;
418 e_comp_editor_set_updating (comp_editor, TRUE);
420 percent_spin = GTK_SPIN_BUTTON (e_comp_editor_property_part_get_edit_widget (task_editor->priv->percentcomplete));
421 completed_date = E_DATE_EDIT (e_comp_editor_property_part_get_edit_widget (task_editor->priv->completed_date));
423 percent = gtk_spin_button_get_value_as_int (percent_spin);
424 if (percent == 100) {
425 ctime = time (NULL);
426 status = ICAL_STATUS_COMPLETED;
427 } else {
428 ctime = (time_t) -1;
430 if (percent == 0)
431 status = ICAL_STATUS_NONE;
432 else
433 status = ICAL_STATUS_INPROCESS;
436 e_comp_editor_property_part_picker_with_map_set_selected (
437 E_COMP_EDITOR_PROPERTY_PART_PICKER_WITH_MAP (task_editor->priv->status), status);
438 e_date_edit_set_time (completed_date, ctime);
440 e_comp_editor_set_updating (comp_editor, FALSE);
443 static void
444 ece_task_sensitize_widgets (ECompEditor *comp_editor,
445 gboolean force_insensitive)
447 ECompEditorTask *task_editor;
448 GtkAction *action;
449 gboolean is_organizer;
450 guint32 flags;
452 g_return_if_fail (E_IS_COMP_EDITOR_TASK (comp_editor));
454 E_COMP_EDITOR_CLASS (e_comp_editor_task_parent_class)->sensitize_widgets (comp_editor, force_insensitive);
456 flags = e_comp_editor_get_flags (comp_editor);
457 is_organizer = (flags & (E_COMP_EDITOR_FLAG_IS_NEW | E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER)) != 0;
458 task_editor = E_COMP_EDITOR_TASK (comp_editor);
460 action = e_comp_editor_get_action (comp_editor, "all-day-task");
461 gtk_action_set_sensitive (action, !force_insensitive && is_organizer);
463 if (task_editor->priv->insensitive_info_alert)
464 e_alert_response (task_editor->priv->insensitive_info_alert, GTK_RESPONSE_OK);
466 if (force_insensitive || !is_organizer) {
467 ECalClient *client;
468 const gchar *message = NULL;
470 client = e_comp_editor_get_target_client (comp_editor);
471 if (!client)
472 message = _("Task cannot be edited, because the selected task list could not be opened");
473 else if (e_client_is_readonly (E_CLIENT (client)))
474 message = _("Task cannot be edited, because the selected task list is read only");
475 else if (!is_organizer)
476 message = _("Task cannot be fully edited, because you are not the organizer");
478 if (message) {
479 EAlert *alert;
481 alert = e_comp_editor_add_information (comp_editor, message, NULL);
483 task_editor->priv->insensitive_info_alert = alert;
485 if (alert)
486 g_object_add_weak_pointer (G_OBJECT (alert), &task_editor->priv->insensitive_info_alert);
488 g_clear_object (&alert);
492 ece_task_check_dates_in_the_past (task_editor);
495 static void
496 ece_task_fill_widgets (ECompEditor *comp_editor,
497 icalcomponent *component)
499 gboolean force_allday = FALSE;
501 g_return_if_fail (E_IS_COMP_EDITOR_TASK (comp_editor));
502 g_return_if_fail (component != NULL);
504 E_COMP_EDITOR_CLASS (e_comp_editor_task_parent_class)->fill_widgets (comp_editor, component);
506 ece_task_update_timezone (E_COMP_EDITOR_TASK (comp_editor), &force_allday);
508 if (force_allday) {
509 GtkAction *action;
511 action = e_comp_editor_get_action (comp_editor, "all-day-task");
512 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
516 static gboolean
517 ece_task_fill_component (ECompEditor *comp_editor,
518 icalcomponent *component)
520 ECompEditorTask *task_editor;
521 struct icaltimetype itt;
523 g_return_val_if_fail (E_IS_COMP_EDITOR_TASK (comp_editor), FALSE);
525 task_editor = E_COMP_EDITOR_TASK (comp_editor);
527 if (!e_comp_editor_property_part_datetime_check_validity (
528 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->dtstart), NULL, NULL)) {
530 e_comp_editor_set_validation_error (comp_editor,
531 task_editor->priv->page_general,
532 e_comp_editor_property_part_get_edit_widget (task_editor->priv->dtstart),
533 _("Start date is not a valid date"));
535 return FALSE;
538 if (e_cal_util_component_has_recurrences (component)) {
539 struct icaltimetype dtstart;
541 dtstart = e_comp_editor_property_part_datetime_get_value (E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->dtstart));
543 if (icaltime_is_null_time (dtstart) || !icaltime_is_valid_time (dtstart)) {
544 e_comp_editor_set_validation_error (comp_editor,
545 task_editor->priv->page_general,
546 e_comp_editor_property_part_get_edit_widget (task_editor->priv->dtstart),
547 _("Start date is required for recurring tasks"));
549 return FALSE;
553 if (!e_comp_editor_property_part_datetime_check_validity (
554 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->due_date), NULL, NULL)) {
556 e_comp_editor_set_validation_error (comp_editor,
557 task_editor->priv->page_general,
558 e_comp_editor_property_part_get_edit_widget (task_editor->priv->due_date),
559 _("Due date is not a valid date"));
561 return FALSE;
564 if (!e_comp_editor_property_part_datetime_check_validity (
565 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->completed_date), NULL, NULL)) {
567 e_comp_editor_set_validation_error (comp_editor,
568 task_editor->priv->page_general,
569 e_comp_editor_property_part_get_edit_widget (task_editor->priv->completed_date),
570 _("Completed date is not a valid date"));
572 return FALSE;
575 itt = e_comp_editor_property_part_datetime_get_value (
576 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->completed_date));
577 if (cal_comp_util_compare_time_with_today (itt) > 0) {
578 e_comp_editor_set_validation_error (comp_editor,
579 task_editor->priv->page_general,
580 e_comp_editor_property_part_get_edit_widget (task_editor->priv->completed_date),
581 _("Completed date cannot be in the future"));
583 return FALSE;
586 if (!E_COMP_EDITOR_CLASS (e_comp_editor_task_parent_class)->fill_component (comp_editor, component))
587 return FALSE;
589 if (e_cal_util_component_has_recurrences (component)) {
590 ECalClient *cal_client;
592 cal_client = e_comp_editor_get_source_client (comp_editor);
593 if (!cal_client)
594 cal_client = e_comp_editor_get_target_client (comp_editor);
596 if (cal_client) {
597 if ((e_comp_editor_get_flags (comp_editor) & E_COMP_EDITOR_FLAG_IS_NEW) != 0) {
598 e_cal_util_init_recur_task_sync (component, cal_client, NULL, NULL);
599 } else if (icalcomponent_get_first_property (component, ICAL_COMPLETED_PROPERTY)) {
600 e_cal_util_mark_task_complete_sync (component, (time_t) -1, cal_client, NULL, NULL);
601 } else if (!icalcomponent_get_first_property (component, ICAL_DUE_PROPERTY)) {
602 e_cal_util_init_recur_task_sync (component, cal_client, NULL, NULL);
607 return TRUE;
610 static void
611 ece_task_setup_ui (ECompEditorTask *task_editor)
613 const gchar *ui =
614 "<ui>"
615 " <menubar action='main-menu'>"
616 " <menu action='view-menu'>"
617 " <placeholder name='parts'>"
618 " <menuitem action='view-timezone'/>"
619 " <menuitem action='view-categories'/>"
620 " </placeholder>"
621 " </menu>"
622 " <menu action='options-menu'>"
623 " <placeholder name='toggles'>"
624 " <menuitem action='all-day-task'/>"
625 " </placeholder>"
626 " </menu>"
627 " </menubar>"
628 " <toolbar name='main-toolbar'>"
629 " <placeholder name='content'>\n"
630 " <toolitem action='all-day-task'/>\n"
631 " </placeholder>"
632 " </toolbar>"
633 "</ui>";
635 const GtkToggleActionEntry view_actions[] = {
636 { "view-categories",
637 NULL,
638 N_("_Categories"),
639 NULL,
640 N_("Toggles whether to display categories"),
641 NULL,
642 FALSE },
644 { "view-timezone",
645 "stock_timezone",
646 N_("Time _Zone"),
647 NULL,
648 N_("Toggles whether the time zone is displayed"),
649 NULL,
650 FALSE },
652 { "all-day-task",
653 "stock_new-24h-appointment",
654 N_("All _Day Task"),
655 NULL,
656 N_("Toggles whether to have All Day Task"),
657 NULL,
658 FALSE }
661 ECompEditor *comp_editor;
662 GSettings *settings;
663 GtkUIManager *ui_manager;
664 GtkAction *action;
665 GtkActionGroup *action_group;
666 GtkWidget *edit_widget;
667 GError *error = NULL;
669 g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor));
671 comp_editor = E_COMP_EDITOR (task_editor);
672 settings = e_comp_editor_get_settings (comp_editor);
673 ui_manager = e_comp_editor_get_ui_manager (comp_editor);
674 action_group = e_comp_editor_get_action_group (comp_editor, "individual");
676 gtk_action_group_add_toggle_actions (action_group,
677 view_actions, G_N_ELEMENTS (view_actions), task_editor);
679 gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
681 e_plugin_ui_register_manager (ui_manager, "org.gnome.evolution.task-editor", task_editor);
682 e_plugin_ui_enable_manager (ui_manager, "org.gnome.evolution.task-editor");
684 if (error) {
685 g_critical ("%s: %s", G_STRFUNC, error->message);
686 g_error_free (error);
689 action = e_comp_editor_get_action (comp_editor, "view-timezone");
690 e_binding_bind_property (
691 task_editor->priv->timezone, "visible",
692 action, "active",
693 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
694 g_settings_bind (
695 settings, "editor-show-timezone",
696 action, "active",
697 G_SETTINGS_BIND_DEFAULT);
699 action = e_comp_editor_get_action (comp_editor, "view-categories");
700 e_binding_bind_property (
701 task_editor->priv->categories, "visible",
702 action, "active",
703 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
704 g_settings_bind (
705 settings, "editor-show-categories",
706 action, "active",
707 G_SETTINGS_BIND_DEFAULT);
709 action = e_comp_editor_get_action (comp_editor, "all-day-task");
711 edit_widget = e_comp_editor_property_part_get_edit_widget (task_editor->priv->dtstart);
712 e_binding_bind_property (
713 action, "active",
714 edit_widget, "show-time",
715 G_BINDING_INVERT_BOOLEAN | G_BINDING_BIDIRECTIONAL);
717 edit_widget = e_comp_editor_property_part_get_edit_widget (task_editor->priv->due_date);
718 e_binding_bind_property (
719 action, "active",
720 edit_widget, "show-time",
721 G_BINDING_INVERT_BOOLEAN);
723 edit_widget = e_comp_editor_property_part_get_edit_widget (task_editor->priv->completed_date);
724 e_binding_bind_property (
725 action, "active",
726 edit_widget, "show-time",
727 G_BINDING_INVERT_BOOLEAN);
730 static void
731 e_comp_editor_task_constructed (GObject *object)
733 ECompEditorTask *task_editor;
734 ECompEditor *comp_editor;
735 ECompEditorPage *page;
736 ECompEditorPropertyPart *part, *summary;
737 EFocusTracker *focus_tracker;
738 GtkWidget *edit_widget;
740 G_OBJECT_CLASS (e_comp_editor_task_parent_class)->constructed (object);
742 task_editor = E_COMP_EDITOR_TASK (object);
743 comp_editor = E_COMP_EDITOR (task_editor);
744 focus_tracker = e_comp_editor_get_focus_tracker (comp_editor);
746 page = e_comp_editor_page_general_new (comp_editor,
747 _("_List:"), E_SOURCE_EXTENSION_TASK_LIST,
748 NULL, FALSE, 3);
750 part = e_comp_editor_property_part_summary_new (focus_tracker);
751 e_comp_editor_page_add_property_part (page, part, 0, 2, 4, 1);
752 summary = part;
754 part = e_comp_editor_property_part_dtstart_new (C_("ECompEditor", "Sta_rt date:"), TRUE, TRUE);
755 e_comp_editor_page_add_property_part (page, part, 0, 3, 2, 1);
756 task_editor->priv->dtstart = part;
758 edit_widget = e_comp_editor_property_part_get_edit_widget (part);
759 g_signal_connect (edit_widget, "changed", G_CALLBACK (ece_task_dtstart_changed_cb), task_editor);
761 part = e_comp_editor_property_part_status_new ();
762 e_comp_editor_page_add_property_part (page, part, 2, 3, 2, 1);
763 task_editor->priv->status = part;
765 edit_widget = e_comp_editor_property_part_get_edit_widget (part);
766 g_signal_connect (edit_widget, "changed", G_CALLBACK (ece_task_status_changed_cb), task_editor);
768 part = e_comp_editor_property_part_due_new (TRUE, TRUE);
769 e_comp_editor_page_add_property_part (page, part, 0, 4, 2, 1);
770 task_editor->priv->due_date = part;
772 edit_widget = e_comp_editor_property_part_get_edit_widget (part);
773 g_signal_connect (edit_widget, "changed", G_CALLBACK (ece_task_due_date_changed_cb), task_editor);
775 part = e_comp_editor_property_part_priority_new ();
776 e_comp_editor_page_add_property_part (page, part, 2, 4, 2, 1);
778 part = e_comp_editor_property_part_completed_new (TRUE, TRUE);
779 e_comp_editor_page_add_property_part (page, part, 0, 5, 2, 1);
780 task_editor->priv->completed_date = part;
782 edit_widget = e_comp_editor_property_part_get_edit_widget (part);
783 g_signal_connect (edit_widget, "changed", G_CALLBACK (ece_task_completed_date_changed_cb), task_editor);
785 part = e_comp_editor_property_part_percentcomplete_new ();
786 e_comp_editor_page_add_property_part (page, part, 2, 5, 2, 1);
787 task_editor->priv->percentcomplete = part;
789 edit_widget = e_comp_editor_property_part_get_edit_widget (part);
790 g_signal_connect (edit_widget, "value-changed", G_CALLBACK (ece_task_percentcomplete_value_changed_cb), task_editor);
792 part = e_comp_editor_property_part_url_new (focus_tracker);
793 e_comp_editor_page_add_property_part (page, part, 0, 6, 2, 1);
795 edit_widget = e_comp_editor_property_part_get_edit_widget (part);
796 gtk_widget_set_hexpand (edit_widget, TRUE);
798 part = e_comp_editor_property_part_classification_new ();
799 e_comp_editor_page_add_property_part (page, part, 2, 6, 2, 1);
801 part = e_comp_editor_property_part_timezone_new ();
802 e_comp_editor_page_add_property_part (page, part, 0, 7, 4, 1);
803 task_editor->priv->timezone = part;
805 part = e_comp_editor_property_part_categories_new (focus_tracker);
806 e_comp_editor_page_add_property_part (page, part, 0, 8, 4, 1);
807 task_editor->priv->categories = part;
809 part = e_comp_editor_property_part_description_new (focus_tracker);
810 e_comp_editor_page_add_property_part (page, part, 0, 9, 4, 1);
812 e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "General"), page);
813 task_editor->priv->page_general = page;
815 edit_widget = e_comp_editor_property_part_get_edit_widget (task_editor->priv->timezone);
816 e_comp_editor_property_part_datetime_attach_timezone_entry (
817 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->dtstart),
818 E_TIMEZONE_ENTRY (edit_widget));
819 e_comp_editor_property_part_datetime_attach_timezone_entry (
820 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->due_date),
821 E_TIMEZONE_ENTRY (edit_widget));
822 e_comp_editor_property_part_datetime_attach_timezone_entry (
823 E_COMP_EDITOR_PROPERTY_PART_DATETIME (task_editor->priv->completed_date),
824 E_TIMEZONE_ENTRY (edit_widget));
826 e_comp_editor_set_time_parts (comp_editor, task_editor->priv->dtstart, task_editor->priv->due_date);
828 page = e_comp_editor_page_reminders_new (comp_editor);
829 e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "Reminders"), page);
830 task_editor->priv->reminders_page = page;
832 page = e_comp_editor_page_recurrence_new (comp_editor);
833 e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "Recurrence"), page);
834 task_editor->priv->recurrence_page = page;
836 page = e_comp_editor_page_attachments_new (comp_editor);
837 e_comp_editor_add_page (comp_editor, C_("ECompEditorPage", "Attachments"), page);
839 ece_task_setup_ui (task_editor);
841 edit_widget = e_comp_editor_property_part_get_edit_widget (summary);
842 e_binding_bind_property (edit_widget, "text", comp_editor, "title-suffix", 0);
843 gtk_widget_grab_focus (edit_widget);
845 g_signal_connect (comp_editor, "notify::source-client",
846 G_CALLBACK (ece_task_notify_source_client_cb), NULL);
847 g_signal_connect (comp_editor, "notify::target-client",
848 G_CALLBACK (ece_task_notify_target_client_cb), NULL);
851 static void
852 e_comp_editor_task_init (ECompEditorTask *task_editor)
854 task_editor->priv = G_TYPE_INSTANCE_GET_PRIVATE (task_editor, E_TYPE_COMP_EDITOR_TASK, ECompEditorTaskPrivate);
857 static void
858 e_comp_editor_task_class_init (ECompEditorTaskClass *klass)
860 GObjectClass *object_class;
861 ECompEditorClass *comp_editor_class;
863 g_type_class_add_private (klass, sizeof (ECompEditorTaskPrivate));
865 object_class = G_OBJECT_CLASS (klass);
866 object_class->constructed = e_comp_editor_task_constructed;
868 comp_editor_class = E_COMP_EDITOR_CLASS (klass);
869 comp_editor_class->help_section = "tasks-usage";
870 comp_editor_class->title_format_with_attendees = _("Assigned Task — %s");
871 comp_editor_class->title_format_without_attendees = _("Task — %s");
872 comp_editor_class->icon_name = "stock_task";
873 comp_editor_class->sensitize_widgets = ece_task_sensitize_widgets;
874 comp_editor_class->fill_widgets = ece_task_fill_widgets;
875 comp_editor_class->fill_component = ece_task_fill_component;