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
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>
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-page-schedule.h"
34 #include "e-comp-editor-property-parts.h"
35 #include "e-timezone-entry.h"
37 #include "e-comp-editor-event.h"
39 struct _ECompEditorEventPrivate
{
40 ECompEditorPage
*page_general
;
41 ECompEditorPropertyPart
*dtstart
;
42 ECompEditorPropertyPart
*dtend
;
43 ECompEditorPropertyPart
*categories
;
44 ECompEditorPropertyPart
*timezone
;
45 ECompEditorPropertyPart
*transparency
;
46 GtkWidget
*all_day_check
;
48 gpointer in_the_past_alert
;
49 gpointer insensitive_info_alert
;
52 G_DEFINE_TYPE (ECompEditorEvent
, e_comp_editor_event
, E_TYPE_COMP_EDITOR
)
55 ece_event_action_classification_cb (GtkRadioAction
*action
,
56 GtkRadioAction
*current
,
57 ECompEditorEvent
*event_editor
)
59 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor
));
61 e_comp_editor_set_changed (E_COMP_EDITOR (event_editor
), TRUE
);
65 ece_event_update_times (ECompEditorEvent
*event_editor
,
67 gboolean change_end_datetime
)
72 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor
));
73 g_return_if_fail (E_IS_DATE_EDIT (date_edit
));
75 widget
= e_date_edit_get_entry (date_edit
);
76 if (widget
&& gtk_widget_has_focus (widget
))
79 if (!e_comp_editor_get_updating (E_COMP_EDITOR (event_editor
))) {
80 e_comp_editor_ensure_start_before_end (E_COMP_EDITOR (event_editor
),
81 event_editor
->priv
->dtstart
,
82 event_editor
->priv
->dtend
,
86 flags
= e_comp_editor_get_flags (E_COMP_EDITOR (event_editor
));
88 if ((flags
& E_COMP_EDITOR_FLAG_IS_NEW
) != 0) {
89 struct icaltimetype start_tt
;
91 start_tt
= e_comp_editor_property_part_datetime_get_value (
92 E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor
->priv
->dtstart
));
94 if (cal_comp_util_compare_time_with_today (start_tt
) < 0) {
95 if (!event_editor
->priv
->in_the_past_alert
) {
98 alert
= e_comp_editor_add_warning (E_COMP_EDITOR (event_editor
),
99 _("Event’s time is in the past"), NULL
);
101 event_editor
->priv
->in_the_past_alert
= alert
;
104 g_object_add_weak_pointer (G_OBJECT (alert
), &event_editor
->priv
->in_the_past_alert
);
106 g_clear_object (&alert
);
108 } else if (event_editor
->priv
->in_the_past_alert
) {
109 e_alert_response (event_editor
->priv
->in_the_past_alert
, GTK_RESPONSE_OK
);
115 ece_event_dtstart_changed_cb (EDateEdit
*date_edit
,
116 ECompEditorEvent
*event_editor
)
118 g_return_if_fail (E_IS_DATE_EDIT (date_edit
));
119 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor
));
121 ece_event_update_times (event_editor
, date_edit
, TRUE
);
125 ece_event_dtend_changed_cb (EDateEdit
*date_edit
,
126 ECompEditorEvent
*event_editor
)
128 g_return_if_fail (E_IS_DATE_EDIT (date_edit
));
129 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor
));
131 ece_event_update_times (event_editor
, date_edit
, FALSE
);
135 ece_event_all_day_toggled_cb (ECompEditorEvent
*event_editor
)
137 GtkWidget
*edit_widget
;
139 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor
));
141 edit_widget
= e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->dtstart
);
143 ece_event_update_times (event_editor
, E_DATE_EDIT (edit_widget
), TRUE
);
145 e_comp_editor_ensure_changed (E_COMP_EDITOR (event_editor
));
149 ece_event_sensitize_widgets (ECompEditor
*comp_editor
,
150 gboolean force_insensitive
)
152 ECompEditorEvent
*event_editor
;
153 gboolean is_organizer
;
157 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (comp_editor
));
159 E_COMP_EDITOR_CLASS (e_comp_editor_event_parent_class
)->sensitize_widgets (comp_editor
, force_insensitive
);
161 flags
= e_comp_editor_get_flags (comp_editor
);
162 is_organizer
= (flags
& (E_COMP_EDITOR_FLAG_IS_NEW
| E_COMP_EDITOR_FLAG_ORGANIZER_IS_USER
)) != 0;
163 event_editor
= E_COMP_EDITOR_EVENT (comp_editor
);
165 gtk_widget_set_sensitive (event_editor
->priv
->all_day_check
, !force_insensitive
&& is_organizer
);
167 #define sensitize_part(x) G_STMT_START { \
170 widget = e_comp_editor_property_part_get_label_widget (x); \
172 gtk_widget_set_sensitive (widget, !force_insensitive && is_organizer); \
174 widget = e_comp_editor_property_part_get_edit_widget (x); \
176 gtk_widget_set_sensitive (widget, !force_insensitive && is_organizer); \
179 sensitize_part (event_editor
->priv
->dtstart
);
180 sensitize_part (event_editor
->priv
->dtend
);
181 sensitize_part (event_editor
->priv
->timezone
);
183 #undef sensitize_part
185 action
= e_comp_editor_get_action (comp_editor
, "all-day-event");
186 gtk_action_set_sensitive (action
, !force_insensitive
&& is_organizer
);
188 action
= e_comp_editor_get_action (comp_editor
, "classification-menu");
189 gtk_action_set_sensitive (action
, !force_insensitive
&& is_organizer
);
191 if (event_editor
->priv
->insensitive_info_alert
)
192 e_alert_response (event_editor
->priv
->insensitive_info_alert
, GTK_RESPONSE_OK
);
194 if (force_insensitive
|| !is_organizer
) {
196 const gchar
*message
= NULL
;
198 client
= e_comp_editor_get_target_client (comp_editor
);
200 message
= _("Event cannot be edited, because the selected calendar could not be opened");
201 else if (e_client_is_readonly (E_CLIENT (client
)))
202 message
= _("Event cannot be edited, because the selected calendar is read only");
203 else if (!is_organizer
)
204 message
= _("Event cannot be fully edited, because you are not the organizer");
209 alert
= e_comp_editor_add_information (comp_editor
, message
, NULL
);
211 event_editor
->priv
->insensitive_info_alert
= alert
;
214 g_object_add_weak_pointer (G_OBJECT (alert
), &event_editor
->priv
->insensitive_info_alert
);
216 g_clear_object (&alert
);
221 static icaltimezone
*
222 ece_event_get_timezone_from_property (ECompEditor
*comp_editor
,
223 icalproperty
*property
)
226 icalparameter
*param
;
227 icaltimezone
*zone
= NULL
;
230 g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor
), NULL
);
235 param
= icalproperty_get_first_parameter (property
, ICAL_TZID_PARAMETER
);
239 tzid
= icalparameter_get_tzid (param
);
243 if (g_ascii_strcasecmp (tzid
, "UTC") == 0)
244 return icaltimezone_get_utc_timezone ();
246 client
= e_comp_editor_get_source_client (comp_editor
);
247 /* It should be already fetched for the UI, thus this should be non-blocking. */
248 if (client
&& e_cal_client_get_timezone_sync (client
, tzid
, &zone
, NULL
, NULL
) && zone
)
251 zone
= icaltimezone_get_builtin_timezone_from_tzid (tzid
);
253 zone
= icaltimezone_get_builtin_timezone (tzid
);
259 ece_event_update_timezone (ECompEditorEvent
*event_editor
,
260 struct icaltimetype
*out_dtstart
,
261 struct icaltimetype
*out_dtend
)
263 ECompEditor
*comp_editor
;
264 struct icaltimetype dtstart
, dtend
;
265 icalcomponent
*component
;
266 icaltimezone
*zone
= NULL
;
268 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor
));
270 comp_editor
= E_COMP_EDITOR (event_editor
);
272 dtstart
= icaltime_null_time ();
273 dtend
= icaltime_null_time ();
275 component
= e_comp_editor_get_component (comp_editor
);
278 *out_dtstart
= dtstart
;
286 if (icalcomponent_get_first_property (component
, ICAL_DTSTART_PROPERTY
)) {
287 dtstart
= icalcomponent_get_dtstart (component
);
288 if (icaltime_is_valid_time (dtstart
)) {
289 if (icaltime_is_utc (dtstart
))
290 zone
= icaltimezone_get_utc_timezone ();
292 zone
= ece_event_get_timezone_from_property (comp_editor
,
293 icalcomponent_get_first_property (component
, ICAL_DTSTART_PROPERTY
));
297 if (icalcomponent_get_first_property (component
, ICAL_DTEND_PROPERTY
)) {
298 dtend
= icalcomponent_get_dtend (component
);
299 if (!zone
&& icaltime_is_valid_time (dtend
)) {
300 if (icaltime_is_utc (dtend
))
301 zone
= icaltimezone_get_utc_timezone ();
303 zone
= ece_event_get_timezone_from_property (comp_editor
,
304 icalcomponent_get_first_property (component
, ICAL_DTEND_PROPERTY
));
309 struct icaltimetype itt
;
311 itt
= icalcomponent_get_due (component
);
312 if (icaltime_is_valid_time (itt
)) {
313 if (icaltime_is_utc (itt
))
314 zone
= icaltimezone_get_utc_timezone ();
316 zone
= ece_event_get_timezone_from_property (comp_editor
,
317 icalcomponent_get_first_property (component
, ICAL_DUE_PROPERTY
));
322 GtkWidget
*edit_widget
;
324 edit_widget
= e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->timezone
);
326 e_timezone_entry_set_timezone (E_TIMEZONE_ENTRY (edit_widget
), zone
);
328 if (zone
!= calendar_config_get_icaltimezone ()) {
329 /* Show timezone part */
332 action
= e_comp_editor_get_action (comp_editor
, "view-timezone");
333 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
), TRUE
);
338 *out_dtstart
= dtstart
;
345 ece_event_fill_widgets (ECompEditor
*comp_editor
,
346 icalcomponent
*component
)
348 ECompEditorEvent
*event_editor
;
349 struct icaltimetype dtstart
, dtend
;
351 gboolean all_day_event
= FALSE
;
355 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (comp_editor
));
356 g_return_if_fail (component
!= NULL
);
358 E_COMP_EDITOR_CLASS (e_comp_editor_event_parent_class
)->fill_widgets (comp_editor
, component
);
360 event_editor
= E_COMP_EDITOR_EVENT (comp_editor
);
362 flags
= e_comp_editor_get_flags (comp_editor
);
363 dtstart
= icaltime_null_time ();
364 dtend
= icaltime_null_time ();
366 ece_event_update_timezone (event_editor
, &dtstart
, &dtend
);
368 if (icaltime_is_valid_time (dtstart
) && !icaltime_is_null_time (dtstart
) &&
369 (!icaltime_is_valid_time (dtend
) || icaltime_is_null_time (dtend
))) {
372 icaltime_adjust (&dtend
, 1, 0, 0, 0);
375 if (icaltime_is_valid_time (dtend
) && !icaltime_is_null_time (dtend
)) {
376 if (dtstart
.is_date
&& dtend
.is_date
) {
377 all_day_event
= TRUE
;
378 if (icaltime_compare_date_only (dtend
, dtstart
) > 0) {
379 icaltime_adjust (&dtend
, -1, 0, 0, 0);
383 e_comp_editor_property_part_datetime_set_value (
384 E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor
->priv
->dtend
), dtend
);
387 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (event_editor
->priv
->all_day_check
), all_day_event
);
389 prop
= icalcomponent_get_first_property (component
, ICAL_CLASS_PROPERTY
);
390 if (prop
&& icalproperty_get_class (prop
) == ICAL_CLASS_PRIVATE
)
391 action
= e_comp_editor_get_action (comp_editor
, "classify-private");
392 else if (prop
&& icalproperty_get_class (prop
) == ICAL_CLASS_CONFIDENTIAL
)
393 action
= e_comp_editor_get_action (comp_editor
, "classify-confidential");
394 else if (!(flags
& E_COMP_EDITOR_FLAG_IS_NEW
))
395 action
= e_comp_editor_get_action (comp_editor
, "classify-public");
399 settings
= e_util_ref_settings ("org.gnome.evolution.calendar");
401 if (g_settings_get_boolean (settings
, "classify-private")) {
402 action
= e_comp_editor_get_action (comp_editor
, "classify-private");
404 action
= e_comp_editor_get_action (comp_editor
, "classify-public");
407 g_object_unref (settings
);
410 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action
), TRUE
);
414 ece_event_fill_component (ECompEditor
*comp_editor
,
415 icalcomponent
*component
)
417 ECompEditorEvent
*event_editor
;
418 gboolean date_valid
, time_valid
;
419 icalproperty
*dtstart_prop
, *dtend_prop
;
421 icalproperty_class class_value
;
423 g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor
), FALSE
);
424 g_return_val_if_fail (component
!= NULL
, FALSE
);
426 if (!E_COMP_EDITOR_CLASS (e_comp_editor_event_parent_class
)->fill_component (comp_editor
, component
))
429 event_editor
= E_COMP_EDITOR_EVENT (comp_editor
);
431 if (!e_comp_editor_property_part_datetime_check_validity (
432 E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor
->priv
->dtstart
), &date_valid
, &time_valid
)) {
433 const gchar
*error_message
= NULL
;
436 error_message
= g_strdup (_("Start date is not a valid date"));
437 else if (!time_valid
)
438 error_message
= g_strdup (_("Start time is not a valid time"));
440 e_comp_editor_set_validation_error (comp_editor
, event_editor
->priv
->page_general
,
441 e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->dtstart
),
442 error_message
? error_message
: _("Unknown error"));
447 if (!e_comp_editor_property_part_datetime_check_validity (
448 E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor
->priv
->dtend
), &date_valid
, &time_valid
)) {
449 const gchar
*error_message
= NULL
;
452 error_message
= g_strdup (_("End date is not a valid date"));
453 else if (!time_valid
)
454 error_message
= g_strdup (_("End time is not a valid time"));
456 e_comp_editor_set_validation_error (comp_editor
, event_editor
->priv
->page_general
,
457 e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->dtend
),
458 error_message
? error_message
: _("Unknown error"));
463 dtstart_prop
= icalcomponent_get_first_property (component
, ICAL_DTSTART_PROPERTY
);
464 dtend_prop
= icalcomponent_get_first_property (component
, ICAL_DTEND_PROPERTY
);
466 if (dtstart_prop
&& dtend_prop
) {
467 struct icaltimetype dtstart
, dtend
;
468 gboolean set_dtstart
= FALSE
, set_dtend
= FALSE
;
470 dtstart
= icalproperty_get_dtstart (dtstart_prop
);
471 dtend
= icalproperty_get_dtend (dtend_prop
);
473 if (dtstart
.is_date
&& dtend
.is_date
) {
476 /* Add 1 day to DTEND, as it is not inclusive. */
477 icaltime_adjust (&dtend
, 1, 0, 0, 0);
480 client
= e_comp_editor_get_target_client (comp_editor
);
481 if (client
&& e_client_check_capability (E_CLIENT (client
), CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME
)) {
482 ECompEditorEvent
*event_editor
= E_COMP_EDITOR_EVENT (comp_editor
);
483 GtkWidget
*timezone_entry
;
485 dtstart
.is_date
= FALSE
;
490 dtend
.is_date
= FALSE
;
495 timezone_entry
= e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->timezone
);
497 dtstart
.zone
= e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (timezone_entry
));
499 dtstart
.zone
= icaltimezone_get_utc_timezone ();
501 dtend
.zone
= dtstart
.zone
;
509 icalproperty_set_dtstart (dtstart_prop
, dtstart
);
510 cal_comp_util_update_tzid_parameter (dtstart_prop
, dtstart
);
514 icalproperty_set_dtend (dtend_prop
, dtend
);
515 cal_comp_util_update_tzid_parameter (dtend_prop
, dtend
);
519 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (
520 e_comp_editor_get_action (comp_editor
, "classify-private"))))
521 class_value
= ICAL_CLASS_PRIVATE
;
522 else if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (
523 e_comp_editor_get_action (comp_editor
, "classify-confidential"))))
524 class_value
= ICAL_CLASS_CONFIDENTIAL
;
526 class_value
= ICAL_CLASS_PUBLIC
;
528 prop
= icalcomponent_get_first_property (component
, ICAL_CLASS_PROPERTY
);
530 icalproperty_set_class (prop
, class_value
);
532 prop
= icalproperty_new_class (class_value
);
533 icalcomponent_add_property (component
, prop
);
540 ece_event_notify_source_client_cb (GObject
*object
,
544 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (object
));
546 ece_event_update_timezone (E_COMP_EDITOR_EVENT (object
), NULL
, NULL
);
550 ece_event_setup_ui (ECompEditorEvent
*event_editor
)
554 " <menubar action='main-menu'>"
555 " <menu action='view-menu'>"
556 " <placeholder name='parts'>"
557 " <menuitem action='view-timezone'/>"
558 " <menuitem action='view-categories'/>"
561 " <menu action='options-menu'>"
562 " <placeholder name='toggles'>"
563 " <menuitem action='all-day-event'/>"
564 " <menuitem action='show-time-busy'/>"
565 " <menu action='classification-menu'>"
566 " <menuitem action='classify-public'/>"
567 " <menuitem action='classify-private'/>"
568 " <menuitem action='classify-confidential'/>"
573 " <toolbar name='main-toolbar'>"
574 " <placeholder name='content'>\n"
575 " <toolitem action='all-day-event'/>\n"
576 " <toolitem action='show-time-busy'/>\n"
581 const GtkToggleActionEntry view_actions
[] = {
586 N_("Toggles whether to display categories"),
594 N_("Toggles whether the time zone is displayed"),
599 "stock_new-24h-appointment",
600 N_("All _Day Event"),
602 N_("Toggles whether to have All Day Event"),
608 N_("Show Time as _Busy"),
610 N_("Toggles whether to show time as busy"),
615 const GtkRadioActionEntry classification_radio_entries
[] = {
621 N_("Classify as public"),
624 { "classify-private",
628 N_("Classify as private"),
629 ICAL_CLASS_PRIVATE
},
631 { "classify-confidential",
635 N_("Classify as confidential"),
636 ICAL_CLASS_CONFIDENTIAL
}
639 ECompEditor
*comp_editor
;
641 GtkUIManager
*ui_manager
;
643 GtkActionGroup
*action_group
;
645 GError
*error
= NULL
;
647 g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor
));
649 comp_editor
= E_COMP_EDITOR (event_editor
);
650 settings
= e_comp_editor_get_settings (comp_editor
);
651 ui_manager
= e_comp_editor_get_ui_manager (comp_editor
);
652 action_group
= e_comp_editor_get_action_group (comp_editor
, "individual");
654 gtk_action_group_add_toggle_actions (action_group
,
655 view_actions
, G_N_ELEMENTS (view_actions
), event_editor
);
657 gtk_action_group_add_radio_actions (
658 action_group
, classification_radio_entries
,
659 G_N_ELEMENTS (classification_radio_entries
),
661 G_CALLBACK (ece_event_action_classification_cb
), event_editor
);
663 gtk_ui_manager_add_ui_from_string (ui_manager
, ui
, -1, &error
);
665 e_plugin_ui_register_manager (ui_manager
, "org.gnome.evolution.event-editor", event_editor
);
666 e_plugin_ui_enable_manager (ui_manager
, "org.gnome.evolution.event-editor");
669 g_critical ("%s: %s", G_STRFUNC
, error
->message
);
670 g_error_free (error
);
673 action
= e_comp_editor_get_action (comp_editor
, "view-categories");
674 e_binding_bind_property (
675 event_editor
->priv
->categories
, "visible",
677 G_BINDING_SYNC_CREATE
| G_BINDING_BIDIRECTIONAL
);
679 settings
, "editor-show-categories",
681 G_SETTINGS_BIND_DEFAULT
);
683 action
= e_comp_editor_get_action (comp_editor
, "view-timezone");
684 e_binding_bind_property (
685 event_editor
->priv
->timezone
, "visible",
687 G_BINDING_SYNC_CREATE
| G_BINDING_BIDIRECTIONAL
);
689 settings
, "editor-show-timezone",
691 G_SETTINGS_BIND_DEFAULT
);
693 action
= e_comp_editor_get_action (comp_editor
, "all-day-event");
694 e_binding_bind_property (
695 event_editor
->priv
->all_day_check
, "active",
697 G_BINDING_SYNC_CREATE
| G_BINDING_BIDIRECTIONAL
);
699 widget
= e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->transparency
);
700 action
= e_comp_editor_get_action (comp_editor
, "show-time-busy");
701 e_binding_bind_property (
704 G_BINDING_SYNC_CREATE
| G_BINDING_BIDIRECTIONAL
);
708 e_comp_editor_event_constructed (GObject
*object
)
710 ECompEditor
*comp_editor
;
711 ECompEditorEvent
*event_editor
;
712 ECompEditorPage
*page
;
713 ECompEditorPropertyPart
*part
;
714 ECompEditorPropertyPart
*summary
;
715 EFocusTracker
*focus_tracker
;
718 G_OBJECT_CLASS (e_comp_editor_event_parent_class
)->constructed (object
);
720 event_editor
= E_COMP_EDITOR_EVENT (object
);
721 comp_editor
= E_COMP_EDITOR (event_editor
);
722 focus_tracker
= e_comp_editor_get_focus_tracker (comp_editor
);
724 page
= e_comp_editor_page_general_new (comp_editor
,
725 _("_Calendar:"), E_SOURCE_EXTENSION_CALENDAR
,
727 event_editor
->priv
->page_general
= page
;
729 part
= e_comp_editor_property_part_summary_new (focus_tracker
);
730 e_comp_editor_page_add_property_part (page
, part
, 0, 2, 3, 1);
733 part
= e_comp_editor_property_part_location_new (focus_tracker
);
734 e_comp_editor_page_add_property_part (page
, part
, 0, 3, 3, 1);
736 part
= e_comp_editor_property_part_dtstart_new (C_("ECompEditor", "_Start time:"), FALSE
, FALSE
);
737 e_comp_editor_page_add_property_part (page
, part
, 0, 4, 2, 1);
738 e_comp_editor_property_part_set_sensitize_handled (part
, TRUE
);
739 event_editor
->priv
->dtstart
= part
;
741 part
= e_comp_editor_property_part_dtend_new (C_("ECompEditor", "_End time:"), FALSE
, FALSE
);
742 e_comp_editor_page_add_property_part (page
, part
, 0, 5, 2, 1);
743 e_comp_editor_property_part_set_sensitize_handled (part
, TRUE
);
744 event_editor
->priv
->dtend
= part
;
746 part
= e_comp_editor_property_part_timezone_new ();
747 e_comp_editor_page_add_property_part (page
, part
, 0, 6, 3, 1);
748 e_comp_editor_property_part_set_sensitize_handled (part
, TRUE
);
749 event_editor
->priv
->timezone
= part
;
751 widget
= gtk_check_button_new_with_mnemonic (C_("ECompEditor", "All da_y event"));
752 g_object_set (G_OBJECT (widget
),
754 "halign", GTK_ALIGN_FILL
,
756 "valign", GTK_ALIGN_START
,
758 gtk_grid_attach (GTK_GRID (page
), widget
, 2, 4, 1, 1);
759 gtk_widget_show (widget
);
760 event_editor
->priv
->all_day_check
= widget
;
762 part
= e_comp_editor_property_part_transparency_new ();
763 e_comp_editor_page_add_property_part (page
, part
, 2, 5, 1, 1);
764 event_editor
->priv
->transparency
= part
;
766 widget
= e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->transparency
);
767 /* Transparency checkbox is not shown in the page, even it's packed there */
768 gtk_widget_hide (widget
);
770 part
= e_comp_editor_property_part_categories_new (focus_tracker
);
771 e_comp_editor_page_add_property_part (page
, part
, 0, 7, 3, 1);
772 event_editor
->priv
->categories
= part
;
774 part
= e_comp_editor_property_part_description_new (focus_tracker
);
775 e_comp_editor_page_add_property_part (page
, part
, 0, 8, 3, 1);
777 widget
= e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->timezone
);
778 e_comp_editor_property_part_datetime_attach_timezone_entry (
779 E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor
->priv
->dtstart
),
780 E_TIMEZONE_ENTRY (widget
));
781 e_comp_editor_property_part_datetime_attach_timezone_entry (
782 E_COMP_EDITOR_PROPERTY_PART_DATETIME (event_editor
->priv
->dtend
),
783 E_TIMEZONE_ENTRY (widget
));
785 e_comp_editor_set_time_parts (comp_editor
, event_editor
->priv
->dtstart
, event_editor
->priv
->dtend
);
787 widget
= e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->dtstart
);
788 e_binding_bind_property (
789 event_editor
->priv
->all_day_check
, "active",
791 G_BINDING_INVERT_BOOLEAN
| G_BINDING_BIDIRECTIONAL
);
792 g_signal_connect (widget
, "changed", G_CALLBACK (ece_event_dtstart_changed_cb
), event_editor
);
794 widget
= e_comp_editor_property_part_get_edit_widget (event_editor
->priv
->dtend
);
795 e_binding_bind_property (
796 event_editor
->priv
->all_day_check
, "active",
798 G_BINDING_INVERT_BOOLEAN
| G_BINDING_BIDIRECTIONAL
);
799 g_signal_connect (widget
, "changed", G_CALLBACK (ece_event_dtend_changed_cb
), event_editor
);
801 e_signal_connect_notify_swapped (event_editor
->priv
->all_day_check
, "notify::active",
802 G_CALLBACK (ece_event_all_day_toggled_cb
), event_editor
);
804 e_comp_editor_add_page (comp_editor
, C_("ECompEditorPage", "General"), page
);
806 page
= e_comp_editor_page_reminders_new (comp_editor
);
807 e_comp_editor_add_page (comp_editor
, C_("ECompEditorPage", "Reminders"), page
);
809 page
= e_comp_editor_page_recurrence_new (comp_editor
);
810 e_comp_editor_add_page (comp_editor
, C_("ECompEditorPage", "Recurrence"), page
);
812 page
= e_comp_editor_page_attachments_new (comp_editor
);
813 e_comp_editor_add_page (comp_editor
, C_("ECompEditorPage", "Attachments"), page
);
815 page
= e_comp_editor_page_schedule_new (comp_editor
,
816 e_comp_editor_page_general_get_meeting_store (
817 E_COMP_EDITOR_PAGE_GENERAL (event_editor
->priv
->page_general
)));
818 e_binding_bind_property (
819 event_editor
->priv
->page_general
, "show-attendees",
821 G_BINDING_SYNC_CREATE
);
823 e_comp_editor_add_page (comp_editor
, C_("ECompEditorPage", "Schedule"), page
);
825 ece_event_setup_ui (event_editor
);
827 widget
= e_comp_editor_property_part_get_edit_widget (summary
);
828 e_binding_bind_property (widget
, "text", comp_editor
, "title-suffix", 0);
829 /* Do this as the last thing, because some widgets can call the function as well */
830 gtk_widget_grab_focus (widget
);
832 g_signal_connect (comp_editor
, "notify::source-client",
833 G_CALLBACK (ece_event_notify_source_client_cb
), NULL
);
837 e_comp_editor_event_init (ECompEditorEvent
*event_editor
)
839 event_editor
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (event_editor
, E_TYPE_COMP_EDITOR_EVENT
, ECompEditorEventPrivate
);
843 e_comp_editor_event_class_init (ECompEditorEventClass
*klass
)
845 GObjectClass
*object_class
;
846 ECompEditorClass
*comp_editor_class
;
848 g_type_class_add_private (klass
, sizeof (ECompEditorEventPrivate
));
850 object_class
= G_OBJECT_CLASS (klass
);
851 object_class
->constructed
= e_comp_editor_event_constructed
;
853 comp_editor_class
= E_COMP_EDITOR_CLASS (klass
);
854 comp_editor_class
->help_section
= "calendar-usage-add-appointment";
855 comp_editor_class
->title_format_with_attendees
= _("Meeting — %s");
856 comp_editor_class
->title_format_without_attendees
= _("Appointment — %s");
857 comp_editor_class
->icon_name
= "appointment-new";
858 comp_editor_class
->sensitize_widgets
= ece_event_sensitize_widgets
;
859 comp_editor_class
->fill_widgets
= ece_event_fill_widgets
;
860 comp_editor_class
->fill_component
= ece_event_fill_component
;