No issues found
1 /*
2 * Evolution calendar - Event editor dialog
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 * Miguel de Icaza <miguel@ximian.com>
20 * Federico Mena-Quintero <federico@ximian.com>
21 * Seth Alves <alves@hungry.com>
22 *
23 *
24 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
25 *
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31
32 #include <string.h>
33 #include <glib/gi18n.h>
34
35 #include <misc/e-dateedit.h>
36 #include <e-util/e-plugin-ui.h>
37 #include <e-util/e-util-private.h>
38 #include <e-util/e-ui-manager.h>
39
40 #include "event-page.h"
41 #include "recurrence-page.h"
42 #include "schedule-page.h"
43 #include "cancel-comp.h"
44 #include "event-editor.h"
45
46 #define EVENT_EDITOR_GET_PRIVATE(obj) \
47 (G_TYPE_INSTANCE_GET_PRIVATE \
48 ((obj), TYPE_EVENT_EDITOR, EventEditorPrivate))
49
50 struct _EventEditorPrivate {
51 EventPage *event_page;
52 RecurrencePage *recur_page;
53 GtkWidget *recur_window;
54 SchedulePage *sched_page;
55 GtkWidget *sched_window;
56
57 EMeetingStore *model;
58 gboolean meeting_shown;
59 gboolean updating;
60 };
61
62 /* Extends the UI definition in CompEditor */
63 static const gchar *ui =
64 "<ui>"
65 " <menubar action='main-menu'>"
66 " <menu action='view-menu'>"
67 " <menuitem action='view-type'/>"
68 " <menuitem action='view-status'/>"
69 " <menuitem action='view-role'/>"
70 " <menuitem action='view-rsvp'/>"
71 " <separator/>"
72 " <menuitem action='view-time-zone'/>"
73 " <menuitem action='view-categories'/>"
74 " </menu>"
75 " <menu action='insert-menu'>"
76 " <menuitem action='send-options'/>"
77 " </menu>"
78 " <menu action='options-menu'>"
79 " <menuitem action='alarms'/>"
80 " <menuitem action='show-time-busy'/>"
81 " <menuitem action='recurrence'/>"
82 " <menuitem action='all-day-event'/>"
83 " <menuitem action='free-busy'/>"
84 " <menu action='classification-menu'>"
85 " <menuitem action='classify-public'/>"
86 " <menuitem action='classify-private'/>"
87 " <menuitem action='classify-confidential'/>"
88 " </menu>"
89 " </menu>"
90 " </menubar>"
91 " <toolbar name='main-toolbar'>"
92 " <placeholder name='content'>\n"
93 "#if !EXPRESS\n"
94 " <toolitem action='alarms'/>\n"
95 "#endif\n"
96 " <toolitem action='show-time-busy'/>\n"
97 "#if !EXPRESS\n"
98 " <toolitem action='recurrence'/>\n"
99 "#endif\n"
100 " <toolitem action='all-day-event'/>\n"
101 "#if !EXPRESS\n"
102 " <toolitem action='free-busy'/>\n"
103 "#endif\n"
104 " </placeholder>"
105 " </toolbar>"
106 "</ui>";
107
108 static void event_editor_edit_comp (CompEditor *editor,
109 ECalComponent *comp);
110 static gboolean event_editor_send_comp (CompEditor *editor,
111 ECalComponentItipMethod method,
112 gboolean strip_alarms);
113
114 G_DEFINE_TYPE (EventEditor, event_editor, TYPE_COMP_EDITOR)
115
116 static void
117 create_schedule_page (CompEditor *editor)
118 {
119 EventEditorPrivate *priv;
120 ENameSelector *name_selector;
121 CompEditorPage *page;
122 GtkWidget *content_area;
123
124 priv = EVENT_EDITOR_GET_PRIVATE (editor);
125
126 priv->sched_window = gtk_dialog_new_with_buttons (
127 _("Free/Busy"), GTK_WINDOW (editor), GTK_DIALOG_DESTROY_WITH_PARENT,
128 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
129
130 content_area =
131 gtk_dialog_get_content_area (GTK_DIALOG (priv->sched_window));
132
133 g_signal_connect (
134 priv->sched_window, "response",
135 G_CALLBACK (gtk_widget_hide), NULL);
136 g_signal_connect (
137 priv->sched_window, "delete-event",
138 G_CALLBACK (gtk_widget_hide_on_delete), NULL);
139
140 priv->sched_page = schedule_page_new (priv->model, editor);
141 page = COMP_EDITOR_PAGE (priv->sched_page);
142 gtk_container_add (
143 GTK_CONTAINER (content_area),
144 comp_editor_page_get_widget (page));
145
146 name_selector = event_page_get_name_selector (priv->event_page);
147 schedule_page_set_name_selector (priv->sched_page, name_selector);
148
149 comp_editor_append_page (editor, page, NULL, FALSE);
150 schedule_page_update_free_busy (priv->sched_page);
151
152 gtk_widget_show_all (priv->sched_window);
153 }
154
155 static void
156 action_alarms_cb (GtkAction *action,
157 EventEditor *editor)
158 {
159 event_page_show_alarm (editor->priv->event_page);
160 }
161
162 static void
163 action_all_day_event_cb (GtkToggleAction *action,
164 EventEditor *editor)
165 {
166 gboolean active;
167 GtkAction *action_show_busy;
168 CompEditor *comp_editor = COMP_EDITOR (editor);
169
170 active = gtk_toggle_action_get_active (action);
171 event_page_set_all_day_event (editor->priv->event_page, active);
172
173 action_show_busy = comp_editor_get_action (comp_editor, "show-time-busy");
174 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action_show_busy), !active);
175 event_page_set_show_time_busy (editor->priv->event_page, !active);
176 }
177
178 static void
179 action_free_busy_cb (GtkAction *action,
180 EventEditor *editor)
181 {
182 if (editor->priv->sched_window == NULL)
183 create_schedule_page (COMP_EDITOR (editor));
184 else
185 gtk_window_present (GTK_WINDOW (editor->priv->sched_window));
186 }
187
188 static void
189 action_recurrence_cb (GtkAction *action,
190 EventEditor *editor)
191 {
192 gtk_widget_show (editor->priv->recur_window);
193 }
194
195 static void
196 action_send_options_cb (GtkAction *action,
197 EventEditor *editor)
198 {
199 event_page_send_options_clicked_cb (editor->priv->event_page);
200 }
201
202 static void
203 action_show_time_busy_cb (GtkToggleAction *action,
204 EventEditor *editor)
205 {
206 gboolean active;
207
208 active = gtk_toggle_action_get_active (action);
209 event_page_set_show_time_busy (editor->priv->event_page, active);
210 }
211
212 static GtkActionEntry editable_entries[] = {
213
214 { "alarms",
215 "appointment-soon",
216 N_("_Reminders"),
217 NULL,
218 N_("Set or unset reminders for this event"),
219 G_CALLBACK (action_alarms_cb) },
220 };
221
222 static GtkToggleActionEntry editable_toggle_entries[] = {
223
224 { "show-time-busy",
225 GTK_STOCK_DIALOG_ERROR,
226 N_("Show Time as _Busy"),
227 NULL,
228 N_("Toggles whether to show time as busy"),
229 G_CALLBACK (action_show_time_busy_cb),
230 FALSE }
231 };
232
233 static GtkActionEntry event_entries[] = {
234
235 { "recurrence",
236 "stock_task-recurring",
237 N_("_Recurrence"),
238 NULL,
239 N_("Make this a recurring event"),
240 G_CALLBACK (action_recurrence_cb) },
241
242 { "send-options",
243 NULL,
244 N_("Send Options"),
245 NULL,
246 N_("Insert advanced send options"),
247 G_CALLBACK (action_send_options_cb) }
248 };
249
250 static GtkToggleActionEntry event_toggle_entries[] = {
251
252 { "all-day-event",
253 "stock_new-24h-appointment",
254 N_("All _Day Event"),
255 NULL,
256 N_("Toggles whether to have All Day Event"),
257 G_CALLBACK (action_all_day_event_cb),
258 FALSE },
259 };
260
261 static GtkActionEntry meeting_entries[] = {
262
263 { "free-busy",
264 "query-free-busy",
265 N_("_Free/Busy"),
266 NULL,
267 N_("Query free / busy information for the attendees"),
268 G_CALLBACK (action_free_busy_cb) }
269 };
270
271 static void
272 event_editor_model_changed_cb (EventEditor *ee)
273 {
274 if (!ee->priv->updating) {
275 comp_editor_set_changed (COMP_EDITOR (ee), TRUE);
276 comp_editor_set_needs_send (COMP_EDITOR (ee), TRUE);
277 }
278 }
279
280 static GObject *
281 event_editor_constructor (GType type,
282 guint n_construct_properties,
283 GObjectConstructParam *construct_properties)
284 {
285 GObject *object;
286 CompEditor *editor;
287 CompEditorFlags flags;
288 CompEditorPage *page;
289 EventEditorPrivate *priv;
290 GtkActionGroup *action_group;
291 GtkWidget *content_area;
292 EShell *shell;
293 ECalClient *client;
294 gboolean is_meeting;
295 GtkWidget *alarm_page;
296 GtkWidget *attendee_page;
297
298 /* Chain up to parent's constructor() method. */
299 object = G_OBJECT_CLASS (event_editor_parent_class)->constructor (
300 type, n_construct_properties, construct_properties);
301
302 editor = COMP_EDITOR (object);
303 priv = EVENT_EDITOR_GET_PRIVATE (object);
304
305 shell = comp_editor_get_shell (editor);
306
307 client = comp_editor_get_client (editor);
308 flags = comp_editor_get_flags (editor);
309 action_group = comp_editor_get_action_group (editor, "coordinated");
310
311 is_meeting = flags & COMP_EDITOR_MEETING;
312
313 gtk_action_group_set_visible (action_group, is_meeting);
314
315 priv->event_page = event_page_new (priv->model, editor);
316 comp_editor_append_page (
317 editor, COMP_EDITOR_PAGE (priv->event_page),
318 _("Appointment"), TRUE);
319
320 priv->recur_window = gtk_dialog_new_with_buttons (
321 _("Recurrence"), GTK_WINDOW (editor), GTK_DIALOG_MODAL,
322 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
323 g_signal_connect (
324 priv->recur_window, "response",
325 G_CALLBACK (gtk_widget_hide), NULL);
326 g_signal_connect (
327 priv->recur_window, "delete-event",
328 G_CALLBACK (gtk_widget_hide_on_delete), NULL);
329
330 content_area =
331 gtk_dialog_get_content_area (GTK_DIALOG (priv->recur_window));
332
333 priv->recur_page = recurrence_page_new (priv->model, editor);
334 page = COMP_EDITOR_PAGE (priv->recur_page);
335 if (!e_shell_get_express_mode (shell)) {
336 gtk_container_add (
337 GTK_CONTAINER (content_area),
338 comp_editor_page_get_widget (page));
339 gtk_widget_show_all (gtk_bin_get_child (GTK_BIN (priv->recur_window)));
340 comp_editor_append_page (editor, page, NULL, FALSE);
341 } else {
342 comp_editor_append_page (editor, page, _("Recurrence"), TRUE);
343 }
344
345 if (e_shell_get_express_mode (shell)) {
346 ENameSelector *name_selector;
347
348 priv->sched_page = schedule_page_new (priv->model, editor);
349 page = COMP_EDITOR_PAGE (priv->sched_page);
350
351 name_selector = event_page_get_name_selector (priv->event_page);
352 schedule_page_set_name_selector (priv->sched_page, name_selector);
353
354 comp_editor_append_page (editor, page, _("Free/Busy"), TRUE);
355 schedule_page_update_free_busy (priv->sched_page);
356
357 g_object_bind_property (
358 action_group, "visible",
359 comp_editor_page_get_widget (page), "visible",
360 G_BINDING_SYNC_CREATE);
361
362 /* Alarm page */
363 alarm_page = event_page_get_alarm_page (priv->event_page);
364 comp_editor_append_widget (editor, alarm_page, _("Reminder"), TRUE);
365 g_object_unref (alarm_page);
366 }
367
368 if (is_meeting) {
369
370 if (e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS))
371 event_page_show_options (priv->event_page);
372
373 comp_editor_set_group_item (editor, TRUE);
374 if (!((flags & COMP_EDITOR_USER_ORG) ||
375 (flags & COMP_EDITOR_DELEGATE) ||
376 (flags & COMP_EDITOR_NEW_ITEM))) {
377 GtkAction *action;
378
379 action = comp_editor_get_action (editor, "free-busy");
380 gtk_action_set_visible (action, FALSE);
381 }
382
383 event_page_set_meeting (priv->event_page, TRUE);
384 priv->meeting_shown = TRUE;
385
386 if (e_shell_get_express_mode (shell)) {
387 attendee_page = event_page_get_attendee_page (priv->event_page);
388 comp_editor_append_widget (editor, attendee_page, _("Attendees"), TRUE);
389 g_object_unref (attendee_page);
390 }
391 }
392
393 return object;
394 }
395
396 static void
397 event_editor_dispose (GObject *object)
398 {
399 EventEditorPrivate *priv;
400
401 priv = EVENT_EDITOR_GET_PRIVATE (object);
402
403 if (priv->event_page) {
404 g_object_unref (priv->event_page);
405 priv->event_page = NULL;
406 }
407
408 if (priv->recur_page) {
409 g_object_unref (priv->recur_page);
410 priv->recur_page = NULL;
411 }
412
413 if (priv->sched_page) {
414 g_object_unref (priv->sched_page);
415 priv->sched_page = NULL;
416 }
417
418 if (priv->model) {
419 g_signal_handlers_disconnect_by_func (
420 priv->model, event_editor_model_changed_cb, object);
421 g_object_unref (priv->model);
422 priv->model = NULL;
423 }
424
425 /* Chain up to parent's dispose() method. */
426 G_OBJECT_CLASS (event_editor_parent_class)->dispose (object);
427 }
428
429 static void
430 event_editor_constructed (GObject *object)
431 {
432 EventEditorPrivate *priv;
433
434 priv = EVENT_EDITOR_GET_PRIVATE (object);
435
436 g_object_bind_property (
437 object, "client",
438 priv->model, "client",
439 G_BINDING_SYNC_CREATE);
440
441 /* Chain up to parent's constructed() method. */
442 G_OBJECT_CLASS (event_editor_parent_class)->constructed (object);
443 }
444
445 static void
446 event_editor_show_categories (CompEditor *editor,
447 gboolean visible)
448 {
449 EventEditorPrivate *priv;
450
451 priv = EVENT_EDITOR_GET_PRIVATE (editor);
452
453 event_page_set_show_categories (priv->event_page, visible);
454 }
455
456 static void
457 event_editor_show_role (CompEditor *editor,
458 gboolean visible)
459 {
460 EventEditorPrivate *priv;
461
462 priv = EVENT_EDITOR_GET_PRIVATE (editor);
463
464 event_page_set_view_role (priv->event_page, visible);
465 }
466
467 static void
468 event_editor_show_rsvp (CompEditor *editor,
469 gboolean visible)
470 {
471 EventEditorPrivate *priv;
472
473 priv = EVENT_EDITOR_GET_PRIVATE (editor);
474
475 event_page_set_view_rsvp (priv->event_page, visible);
476 }
477
478 static void
479 event_editor_show_status (CompEditor *editor,
480 gboolean visible)
481 {
482 EventEditorPrivate *priv;
483
484 priv = EVENT_EDITOR_GET_PRIVATE (editor);
485
486 event_page_set_view_status (priv->event_page, visible);
487 }
488
489 static void
490 event_editor_show_time_zone (CompEditor *editor,
491 gboolean visible)
492 {
493 EventEditorPrivate *priv;
494
495 priv = EVENT_EDITOR_GET_PRIVATE (editor);
496
497 event_page_set_show_timezone (priv->event_page, visible);
498 }
499
500 static void
501 event_editor_show_type (CompEditor *editor,
502 gboolean visible)
503 {
504 EventEditorPrivate *priv;
505
506 priv = EVENT_EDITOR_GET_PRIVATE (editor);
507
508 event_page_set_view_type (priv->event_page, visible);
509 }
510
511 static void
512 event_editor_class_init (EventEditorClass *class)
513 {
514 GObjectClass *object_class;
515 CompEditorClass *editor_class;
516
517 g_type_class_add_private (class, sizeof (EventEditorPrivate));
518
519 object_class = G_OBJECT_CLASS (class);
520 object_class->constructor = event_editor_constructor;
521 object_class->dispose = event_editor_dispose;
522 object_class->constructed = event_editor_constructed;
523
524 editor_class = COMP_EDITOR_CLASS (class);
525 editor_class->help_section = "calendar-usage-add-appointment";
526 editor_class->edit_comp = event_editor_edit_comp;
527 editor_class->send_comp = event_editor_send_comp;
528 editor_class->show_categories = event_editor_show_categories;
529 editor_class->show_role = event_editor_show_role;
530 editor_class->show_rsvp = event_editor_show_rsvp;
531 editor_class->show_status = event_editor_show_status;;
532 editor_class->show_time_zone = event_editor_show_time_zone;
533 editor_class->show_type = event_editor_show_type;
534 }
535
536 static void
537 event_editor_init (EventEditor *ee)
538 {
539 CompEditor *editor = COMP_EDITOR (ee);
540 GtkUIManager *ui_manager;
541 GtkActionGroup *action_group;
542 GtkAction *action;
543 const gchar *id;
544 GError *error = NULL;
545
546 ee->priv = EVENT_EDITOR_GET_PRIVATE (ee);
547 ee->priv->model = E_MEETING_STORE (e_meeting_store_new ());
548 ee->priv->meeting_shown = TRUE;
549 ee->priv->updating = FALSE;
550
551 action_group = comp_editor_get_action_group (editor, "individual");
552 gtk_action_group_add_actions (
553 action_group, event_entries,
554 G_N_ELEMENTS (event_entries), ee);
555 gtk_action_group_add_toggle_actions (
556 action_group, event_toggle_entries,
557 G_N_ELEMENTS (event_toggle_entries), ee);
558
559 action_group = comp_editor_get_action_group (editor, "editable");
560 gtk_action_group_add_actions (
561 action_group, editable_entries,
562 G_N_ELEMENTS (editable_entries), ee);
563 gtk_action_group_add_toggle_actions (
564 action_group, editable_toggle_entries,
565 G_N_ELEMENTS (editable_toggle_entries), ee);
566
567 action_group = comp_editor_get_action_group (editor, "coordinated");
568 gtk_action_group_add_actions (
569 action_group, meeting_entries,
570 G_N_ELEMENTS (meeting_entries), ee);
571
572 ui_manager = comp_editor_get_ui_manager (editor);
573 e_ui_manager_add_ui_from_string (E_UI_MANAGER (ui_manager), ui, &error);
574
575 id = "org.gnome.evolution.event-editor";
576 e_plugin_ui_register_manager (ui_manager, id, ee);
577 e_plugin_ui_enable_manager (ui_manager, id);
578
579 if (error != NULL) {
580 g_critical ("%s: %s", G_STRFUNC, error->message);
581 g_error_free (error);
582 }
583
584 action = comp_editor_get_action (editor, "print");
585 gtk_action_set_tooltip (action, _("Print this event"));
586
587 /* Hide send options. */
588 action = comp_editor_get_action (editor, "send-options");
589 gtk_action_set_visible (action, FALSE);
590
591 g_signal_connect_swapped (
592 ee->priv->model, "row_changed",
593 G_CALLBACK (event_editor_model_changed_cb), ee);
594 g_signal_connect_swapped (
595 ee->priv->model, "row_inserted",
596 G_CALLBACK (event_editor_model_changed_cb), ee);
597 g_signal_connect_swapped (
598 ee->priv->model, "row_deleted",
599 G_CALLBACK (event_editor_model_changed_cb), ee);
600 }
601
602 static void
603 event_editor_edit_comp (CompEditor *editor,
604 ECalComponent *comp)
605 {
606 EventEditorPrivate *priv;
607 ECalComponentOrganizer organizer;
608 gboolean delegate;
609 ECalComponentDateTime dtstart, dtend;
610 ECalClient *client;
611 GSList *attendees = NULL;
612 ESourceRegistry *registry;
613 EShell *shell;
614
615 priv = EVENT_EDITOR_GET_PRIVATE (editor);
616
617 priv->updating = TRUE;
618 delegate = (comp_editor_get_flags (COMP_EDITOR (editor)) & COMP_EDITOR_DELEGATE);
619
620 if (priv->sched_page) {
621 e_cal_component_get_dtstart (comp, &dtstart);
622 e_cal_component_get_dtend (comp, &dtend);
623
624 schedule_page_set_meeting_time (priv->sched_page, dtstart.value, dtend.value);
625
626 e_cal_component_free_datetime (&dtstart);
627 e_cal_component_free_datetime (&dtend);
628 }
629
630 if (COMP_EDITOR_CLASS (event_editor_parent_class)->edit_comp)
631 COMP_EDITOR_CLASS (event_editor_parent_class)->edit_comp (editor, comp);
632
633 shell = comp_editor_get_shell (editor);
634 client = comp_editor_get_client (editor);
635
636 registry = e_shell_get_registry (shell);
637
638 /* Get meeting related stuff */
639 e_cal_component_get_organizer (comp, &organizer);
640 e_cal_component_get_attendee_list (comp, &attendees);
641
642 /* Set up the attendees */
643 if (attendees != NULL) {
644 GSList *l;
645 gint row;
646 gchar *user_email;
647
648 user_email = itip_get_comp_attendee (
649 registry, comp, client);
650
651 if (!priv->meeting_shown) {
652 GtkAction *action;
653
654 action = comp_editor_get_action (editor, "free-busy");
655 gtk_action_set_visible (action, TRUE);
656 }
657
658 if (!(delegate && e_client_check_capability (
659 E_CLIENT (client), CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY))) {
660 event_page_remove_all_attendees (priv->event_page);
661
662 for (l = attendees; l != NULL; l = l->next) {
663 ECalComponentAttendee *ca = l->data;
664 EMeetingAttendee *ia;
665 gboolean addresses_match;
666
667 addresses_match = g_str_equal (
668 user_email,
669 itip_strip_mailto (ca->value));
670
671 if (delegate && !addresses_match)
672 continue;
673
674 ia = E_MEETING_ATTENDEE (
675 e_meeting_attendee_new_from_e_cal_component_attendee (ca));
676
677 /* If we aren't the organizer or the attendee
678 * is just delegated, don't allow editing. */
679 if (!comp_editor_get_user_org (editor) ||
680 e_meeting_attendee_is_set_delto (ia))
681 e_meeting_attendee_set_edit_level (
682 ia, E_MEETING_ATTENDEE_EDIT_NONE);
683
684 comp_editor_page_add_attendee (
685 COMP_EDITOR_PAGE (priv->event_page), ia);
686
687 g_object_unref (ia);
688 }
689
690 /* If we aren't the organizer we can still change our own status */
691 if (!comp_editor_get_user_org (editor)) {
692 EMeetingAttendee *ia;
693
694 ia = e_meeting_store_find_self (priv->model, &row);
695 if (ia != NULL)
696 e_meeting_attendee_set_edit_level (
697 ia, E_MEETING_ATTENDEE_EDIT_STATUS);
698 } else if (e_cal_client_check_organizer_must_attend (client)) {
699 EMeetingAttendee *ia;
700
701 ia = e_meeting_store_find_attendee (
702 priv->model, organizer.value, &row);
703 if (ia != NULL)
704 e_meeting_attendee_set_edit_level (
705 ia, E_MEETING_ATTENDEE_EDIT_NONE);
706 }
707 }
708
709 event_page_set_meeting (priv->event_page, TRUE);
710 priv->meeting_shown = TRUE;
711 g_free (user_email);
712 }
713 e_cal_component_free_attendee_list (attendees);
714
715 comp_editor_set_needs_send (
716 editor, priv->meeting_shown && (itip_organizer_is_user (
717 registry, comp, client) || itip_sentby_is_user (registry,
718 comp, client)));
719
720 priv->updating = FALSE;
721 }
722
723 static gboolean
724 event_editor_send_comp (CompEditor *editor,
725 ECalComponentItipMethod method,
726 gboolean strip_alarms)
727 {
728 EventEditorPrivate *priv;
729 EShell *shell;
730 ESourceRegistry *registry;
731 ECalComponent *comp = NULL;
732
733 priv = EVENT_EDITOR_GET_PRIVATE (editor);
734
735 /* Don't cancel more than once or when just publishing */
736 if (method == E_CAL_COMPONENT_METHOD_PUBLISH ||
737 method == E_CAL_COMPONENT_METHOD_CANCEL)
738 goto parent;
739
740 shell = comp_editor_get_shell (editor);
741 registry = e_shell_get_registry (shell);
742
743 comp = event_page_get_cancel_comp (priv->event_page);
744 if (comp != NULL) {
745 ECalClient *client;
746 gboolean result;
747
748 client = e_meeting_store_get_client (priv->model);
749 result = itip_send_comp (
750 registry, E_CAL_COMPONENT_METHOD_CANCEL, comp,
751 client, NULL, NULL, NULL, strip_alarms, FALSE);
752 g_object_unref (comp);
753
754 if (!result)
755 return result;
756 }
757
758 parent:
759 if (COMP_EDITOR_CLASS (event_editor_parent_class)->send_comp)
760 return COMP_EDITOR_CLASS (event_editor_parent_class)->
761 send_comp (editor, method, strip_alarms);
762
763 return FALSE;
764 }
765
766 /**
767 * event_editor_new:
768 * @client: a ECalClient
769 *
770 * Creates a new event editor dialog.
771 *
772 * Return value: A newly-created event editor dialog, or NULL if the event
773 * editor could not be created.
774 **/
775 CompEditor *
776 event_editor_new (ECalClient *client,
777 EShell *shell,
778 CompEditorFlags flags)
779 {
780 g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
781 g_return_val_if_fail (E_IS_SHELL (shell), NULL);
782
783 return g_object_new (
784 TYPE_EVENT_EDITOR,
785 "client", client, "flags", flags, "shell", shell, NULL);
786 }
787
788 void
789 event_editor_show_meeting (EventEditor *ee)
790 {
791 CompEditor *editor;
792 CompEditorFlags flags;
793
794 g_return_if_fail (IS_EVENT_EDITOR (ee));
795
796 editor = COMP_EDITOR (ee);
797 flags = comp_editor_get_flags (editor);
798
799 event_page_set_meeting (ee->priv->event_page, TRUE);
800 if (!ee->priv->meeting_shown) {
801 GtkAction *action;
802
803 action = comp_editor_get_action (editor, "free-busy");
804 gtk_action_set_visible (action, TRUE);
805
806 ee->priv->meeting_shown = TRUE;
807
808 comp_editor_set_changed (editor, FALSE);
809 comp_editor_set_needs_send (editor, TRUE);
810 }
811
812 if (!(flags & COMP_EDITOR_NEW_ITEM) && !(flags & COMP_EDITOR_USER_ORG))
813 gtk_drag_dest_unset (GTK_WIDGET (editor));
814 }