2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2018 Colin Leroy and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include "claws-features.h"
27 #include <glib/gi18n.h>
29 #include <libical/ical.h>
37 #include "folder_item_prefs.h"
40 #include "vcalendar.h"
41 #include "vcal_manager.h"
42 #include "vcal_folder.h"
43 #include "vcal_meeting_gtk.h"
44 #include "vcal_interface.h"
45 #include "prefs_account.h"
46 #include "prefs_common.h"
52 #include "alertpanel.h"
53 #include "vcal_prefs.h"
54 #include "statusbar.h"
58 MimeViewerFactory vcal_viewer_factory;
60 static void create_meeting_from_message_cb_ui(GtkAction *action, gpointer data);
62 static GdkColor uri_color = {
71 MimeViewer mimeviewer;
78 GtkWidget *scrolledwin;
86 GtkWidget *description;
94 GtkWidget *unavail_box;
97 static GtkActionEntry vcalendar_main_menu[] = {{
98 "Message/CreateMeeting",
99 NULL, N_("Create meeting from message..."), NULL, NULL, G_CALLBACK(create_meeting_from_message_cb_ui)
102 static void create_meeting_from_message_cb_ui(GtkAction *action, gpointer data)
104 MainWindow *mainwin = mainwindow_get_mainwindow();
105 SummaryView *summaryview = mainwin->summaryview;
106 GSList *msglist = summary_get_selected_msg_list(summaryview);
107 FolderItem *item = NULL;
112 if (summary_is_locked(summaryview) || !msglist) {
114 g_slist_free(msglist);
117 total = g_slist_length(msglist);
119 msg = g_strdup_printf(_("You are about to create %d "
120 "meetings, one by one. Do you "
121 "want to continue?"),
124 && alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, "+" GTK_STOCK_YES, NULL)
125 != G_ALERTALTERNATE) {
131 main_window_cursor_wait(summaryview->mainwin);
132 gtk_cmclist_freeze(GTK_CMCLIST(summaryview->ctree));
133 folder_item_update_freeze();
136 item = summaryview->folder_item;
138 STATUSBAR_PUSH(mainwin, _("Creating meeting..."));
140 for (cur = msglist; cur; cur = cur->next) {
141 MsgInfo *msginfo = procmsg_msginfo_get_full_info((MsgInfo *)cur->data);
142 VCalEvent *event = NULL;
145 if (MSG_IS_ENCRYPTED(msginfo->flags)) {
146 fp = procmime_get_first_encrypted_text_content(msginfo);
148 fp = procmime_get_first_text_content(msginfo);
153 time_t t = time(NULL);
156 gchar *orgname = NULL;
157 gchar *summary = g_strdup(msginfo->subject ? msginfo->subject:_("no subject"));
158 gchar *description = file_read_stream_to_str(fp);
159 gchar *dtstart = g_strdup(icaltime_as_ical_string(icaltime_from_timet_with_zone(t, FALSE, NULL)));
160 gchar *dtend = g_strdup(icaltime_as_ical_string(icaltime_from_timet_with_zone(t2, FALSE, NULL)));
162 gchar *tzid = g_strdup("UTC");
164 gint method = ICAL_METHOD_REQUEST;
166 PrefsAccount *account = NULL;
170 if (item && item->prefs && item->prefs->enable_default_account)
171 account = account_find_from_id(item->prefs->default_account);
174 account = account_get_cur_account();
179 org = g_strdup(account->address);
181 uid = prefs_account_generate_msgid(account);
183 event = vcal_manager_new_event(uid,
184 org, NULL, NULL/*location*/, summary, description,
185 dtstart, dtend, recur, tzid, url, method, sequence,
186 ICAL_VTODO_COMPONENT);
189 /* hack to get default hours */
190 g_free(event->dtstart);
191 g_free(event->dtend);
192 event->dtstart = NULL;
195 vcal_meeting_create(event);
196 vcal_manager_free_event(event);
210 procmsg_msginfo_free(&msginfo);
213 statusbar_progress_all(0,0,0);
214 STATUSBAR_POP(mainwin);
216 folder_item_update_thaw();
217 gtk_cmclist_thaw(GTK_CMCLIST(summaryview->ctree));
218 main_window_cursor_normal(summaryview->mainwin);
219 g_slist_free(msglist);
222 static gchar *get_tmpfile(VCalViewer *vcalviewer)
224 gchar *tmpfile = NULL;
226 if (!vcalviewer->tmpfile) {
227 tmpfile = procmime_get_tmp_file_name(vcalviewer->mimeinfo);
228 debug_print("creating %s\n", tmpfile);
230 if (procmime_get_part(tmpfile, vcalviewer->mimeinfo) < 0) {
231 g_warning("Can't get mimepart file");
235 vcalviewer->tmpfile = tmpfile;
238 return vcalviewer->tmpfile;
241 static GtkWidget *vcal_viewer_get_widget(MimeViewer *_mimeviewer)
243 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
245 debug_print("vcal_viewer_get_widget\n");
246 gtk_widget_show_all(vcalviewer->scrolledwin);
247 return vcalviewer->scrolledwin;
250 static void vcal_viewer_clear_viewer(MimeViewer *_mimeviewer)
252 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
254 debug_print("vcal_viewer_clear_viewer\n");
256 g_free(vcalviewer->file);
257 vcalviewer->file = NULL;
258 if (vcalviewer->tmpfile) {
259 debug_print("unlinking %s\n", vcalviewer->tmpfile);
260 g_unlink(vcalviewer->tmpfile);
261 g_free(vcalviewer->tmpfile);
262 vcalviewer->tmpfile = NULL;
264 vcalviewer->mimeinfo = NULL;
267 static VCalEvent *vcalviewer_get_component(const gchar *file, const gchar *charset)
269 gchar *compstr = NULL;
270 VCalEvent *event = NULL;
276 g_return_val_if_fail(file != NULL, NULL);
278 if ((fp = g_fopen(file, "rb")) == NULL) {
279 FILE_OP_ERROR(file, "g_fopen");
283 array = g_byte_array_new();
285 while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
286 if (n_read < sizeof(buf) && ferror(fp))
288 g_byte_array_append(array, (guchar *)buf, n_read);
292 FILE_OP_ERROR("file stream", "fread");
293 g_byte_array_free(array, TRUE);
299 g_byte_array_append(array, (guchar *)buf, 1);
300 compstr = (gchar *)array->data;
301 g_byte_array_free(array, FALSE);
306 event = vcal_get_event_from_ical(compstr, charset);
313 #define GTK_LABEL_SET_TEXT_TRIMMED(label, text) { \
314 gchar *tmplbl = strretchomp(g_strdup(text)); \
315 gtk_label_set_text(label, tmplbl); \
319 static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, icalproperty_method method);
321 static void vcalviewer_reset(VCalViewer *vcalviewer)
323 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
324 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
325 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), "-");
326 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
327 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
328 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
329 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
330 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
331 g_free(vcalviewer->url);
332 vcalviewer->url = NULL;
333 gtk_widget_hide(vcalviewer->uribtn);
334 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_CANCEL);
337 static void vcalviewer_show_error(VCalViewer *vcalviewer, const gchar *msg)
339 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), msg);
342 static void vcalviewer_hide_error(VCalViewer *vcalviewer)
344 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
347 static void vcalviewer_show_unavailable(VCalViewer *vcalviewer, gboolean visi)
350 gtk_widget_show_all(vcalviewer->unavail_box);
352 gtk_widget_hide(vcalviewer->unavail_box);
355 static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, icalproperty_method method)
359 gtk_widget_hide(vcalviewer->reedit);
360 gtk_widget_hide(vcalviewer->cancel);
361 gtk_widget_hide(vcalviewer->answer);
362 gtk_widget_hide(vcalviewer->button);
364 for (i = 0; i < 3; i++)
365 gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(vcalviewer->answer), 0);
367 vcalviewer_show_unavailable(vcalviewer, FALSE);
369 if (method == ICAL_METHOD_REQUEST && event && !event->rec_occurrence) {
370 PrefsAccount *account = vcal_manager_get_account_from_event(event);
373 account = vcal_manager_get_account_from_event(vcalviewer->event);
375 if (!account && event) {
376 account = account_get_default();
377 vcal_manager_update_answer(event, account->address,
379 ICAL_PARTSTAT_NEEDSACTION,
380 ICAL_CUTYPE_INDIVIDUAL);
383 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Accept"));
384 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Tentatively accept"));
385 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Decline"));
386 gtk_widget_set_sensitive(vcalviewer->answer, TRUE);
387 gtk_widget_set_sensitive(vcalviewer->button, TRUE);
388 gtk_widget_show(vcalviewer->answer);
389 gtk_widget_show(vcalviewer->button);
391 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), "-");
392 gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
393 gtk_widget_set_sensitive(vcalviewer->button, FALSE);
396 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), "-");
397 gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
398 gtk_widget_set_sensitive(vcalviewer->button, FALSE);
400 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
402 if (event && event->method == ICAL_METHOD_REQUEST) {
403 PrefsAccount *account = vcal_manager_get_account_from_event(event);
404 gchar *internal_ifb = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
405 "vcalendar", G_DIR_SEPARATOR_S,
406 "internal.ifb", NULL);
407 gchar *myfb = file_read_to_str(internal_ifb);
408 g_free(internal_ifb);
410 icalparameter_partstat answer =
411 vcal_manager_get_reply_for_attendee(event, account->address);
413 if (answer == ICAL_PARTSTAT_ACCEPTED)
414 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
415 if (answer == ICAL_PARTSTAT_TENTATIVE)
416 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 1);
417 if (answer == ICAL_PARTSTAT_DECLINED)
418 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 2);
419 if (event->dtstart && event->dtend && myfb && *myfb
420 && answer != ICAL_PARTSTAT_ACCEPTED
421 && answer != ICAL_PARTSTAT_TENTATIVE) {
422 if (!attendee_available(NULL, event->dtstart, event->dtend, myfb))
423 vcalviewer_show_unavailable(vcalviewer, TRUE);
429 g_free(vcalviewer->url);
430 if (event && event->url && *(event->url)) {
431 vcalviewer->url = g_strdup(event->url);
432 gtk_widget_show(vcalviewer->uribtn);
434 vcalviewer->url = NULL;
435 gtk_widget_hide(vcalviewer->uribtn);
439 static FolderItem *vcalendar_get_current_item(void)
441 MainWindow *mainwin = mainwindow_get_mainwindow();
442 FolderItem *item = NULL;
443 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
446 item = mainwin->summaryview->folder_item;
447 if (item->folder == folder)
450 return folder->inbox;
456 void vcalviewer_display_event (VCalViewer *vcalviewer, VCalEvent *event)
459 gchar *attendees = NULL;
460 gboolean mine = FALSE;
462 gboolean save_evt = FALSE;
463 FolderItem *item = vcalendar_get_current_item();
470 if (event->type == ICAL_VTODO_COMPONENT) {
472 label = g_strjoin(" ", _("You have a Todo item."),
473 _("Details follow:"), NULL);
474 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
476 } else if (event->method == ICAL_METHOD_REQUEST) {
478 if (account_find_from_address(event->organizer, FALSE)) {
479 label = g_strjoin(" ", _("You have created a meeting."),
480 _("Details follow:"), NULL);
481 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
484 label = g_strjoin(" ", _("You have been invited to a meeting."),
485 _("Details follow:"), NULL);
486 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
489 } else if (event->method == ICAL_METHOD_CANCEL) {
491 label = g_strjoin(" ",
492 _("A meeting to which you had been invited has been cancelled."),
493 _("Details follow:"), NULL);
494 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
496 vcalendar_refresh_folder_contents(item);
497 } else if (event->method == ICAL_METHOD_REPLY) {
498 /* don't change label */
501 label = g_strjoin(" ", _("You have been forwarded an appointment."),
502 _("Details follow:"), NULL);
503 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
509 if (event->orgname && *(event->orgname)
510 && event->organizer && *(event->organizer)) {
511 gchar *addr = g_strconcat(event->orgname, " <", event->organizer, ">", NULL);
512 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
514 } else if (event->organizer && *(event->organizer)) {
515 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), event->organizer);
517 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
521 if (event->location && *(event->location)) {
522 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), event->location);
524 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), "-");
528 if (event->summary && *(event->summary)) {
529 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), event->summary);
531 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
535 if (event->description && *(event->description)) {
536 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), event->description);
538 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
542 g_free(vcalviewer->url);
543 if (event->url && *(event->url)) {
544 vcalviewer->url = g_strdup(event->url);
545 gtk_widget_show(vcalviewer->uribtn);
547 vcalviewer->url = NULL;
548 gtk_widget_hide(vcalviewer->uribtn);
552 if (event->start && *(event->start)) {
553 if (event->recur && *(event->recur)) {
554 gchar *tmp = g_strdup_printf(g_strconcat("%s <span weight=\"bold\">",
555 _("(this event recurs)"),"</span>", NULL),
557 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
558 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
560 } else if (event->rec_occurrence) {
561 gchar *tmp = g_strdup_printf(g_strconcat("%s <span weight=\"bold\">",
562 _("(this event is part of a recurring event)"),
565 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
566 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
569 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), event->start);
572 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
576 if (event->end && *(event->end)) {
577 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), event->end);
579 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
583 attendees = g_strdup("");
584 for (list = vcal_manager_get_answers_emails(event);
585 list && list->data; list = list->next) {
586 gchar *attendee = (gchar *)list->data;
587 gchar *name = vcal_manager_get_attendee_name(event, attendee);
588 gchar *ename = g_markup_printf_escaped("%s", name?name:"");
589 gchar *eatt = g_markup_printf_escaped("%s", attendee);
590 icalparameter_partstat acode = vcal_manager_get_reply_for_attendee(event, attendee);
591 gchar *answer = vcal_manager_get_reply_text_for_attendee(event, attendee);
592 gchar *type = vcal_manager_get_cutype_text_for_attendee(event, attendee);
595 tmp = g_strdup_printf(
596 "%s%s<%s> (%s, <span%s>%s</span>)",
597 (ename && *(ename))?ename:"",
598 (ename && *(ename))?" ":"",
599 (eatt && *(eatt))?eatt:"",
600 (type && *(type))?type:"",
601 (acode != ICAL_PARTSTAT_ACCEPTED ? " foreground=\"red\"":""),
602 (answer && *(answer))?answer:"");
603 e_len = strlen(attendees);
606 attendees = g_realloc(attendees, e_len+n_len+2);
607 *(attendees+e_len) = '\n';
608 strcpy(attendees+e_len+1, tmp);
610 attendees = g_realloc(attendees, e_len+n_len+1);
611 strcpy(attendees, tmp);
621 if (attendees && *(attendees)) {
622 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), attendees);
624 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
627 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->attendees), TRUE);
631 if (event->type != ICAL_VTODO_COMPONENT)
632 vcalviewer_answer_set_choices(vcalviewer, event, event->method);
634 vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_PUBLISH);
636 vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_REPLY);
637 gtk_widget_show(vcalviewer->reedit);
638 gtk_widget_show(vcalviewer->cancel);
641 /* save if cancelled */
643 vcal_manager_save_event(event, TRUE);
646 gchar *vcalviewer_get_uid_from_mimeinfo(MimeInfo *mimeinfo)
648 gchar *tmpfile = procmime_get_tmp_file_name(mimeinfo);
649 const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
650 gchar *compstr = NULL;
652 VCalEvent *event = NULL;
655 charset = CS_WINDOWS_1252;
657 if (!strcasecmp(charset, CS_ISO_8859_1))
658 charset = CS_WINDOWS_1252;
660 if (procmime_get_part(tmpfile, mimeinfo) < 0) {
661 g_warning("Can't get mimepart file");
666 compstr = file_read_to_str(tmpfile);
668 event = vcal_get_event_from_ical(compstr, charset);
670 res = g_strdup(event->uid);
672 vcal_manager_free_event(event);
674 debug_print("got uid: %s\n", res);
679 static void vcalviewer_get_request_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo, gboolean is_todo)
681 VCalEvent *saved_event = NULL;
682 const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
683 const gchar *saveme = procmime_mimeinfo_get_parameter(mimeinfo, "vcalsave");
685 if (!vcalviewer->event)
689 charset = CS_WINDOWS_1252;
691 if (!strcasecmp(charset, CS_ISO_8859_1))
692 charset = CS_WINDOWS_1252;
694 /* see if we have it registered and more recent */
695 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
696 if (saved_event && saved_event->sequence >= vcalviewer->event->sequence) {
697 charset = CS_INTERNAL;
698 saved_event->method = vcalviewer->event->method;
699 vcalviewer_display_event(vcalviewer, saved_event);
700 vcal_manager_free_event(saved_event);
702 } else if (saved_event) {
703 vcal_manager_free_event(saved_event);
706 /* load it and register it */
708 if (!saveme || strcmp(saveme,"no"))
709 vcal_manager_save_event(vcalviewer->event, FALSE);
711 vcalviewer_display_event(vcalviewer, vcalviewer->event);
714 static void vcalviewer_get_reply_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
716 const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
717 VCalEvent *saved_event = NULL;
718 gchar *attendee = NULL, *label = NULL;
719 Answer *answer = NULL;
721 if (!vcalviewer->event)
725 charset = CS_WINDOWS_1252;
727 if (!strcasecmp(charset, CS_ISO_8859_1))
728 charset = CS_WINDOWS_1252;
730 if (!vcalviewer->event->answers || g_slist_length(vcalviewer->event->answers) > 1) {
731 g_warning("strange, no answers or more than one");
734 if (vcalviewer->event->answers) {
735 answer = (Answer *)vcalviewer->event->answers->data;
736 attendee = g_strdup(answer->attendee);
741 label = g_strjoin(" ",
742 _("You have received an answer to an unknown meeting proposal."),
743 _("Details follow:"), NULL);
744 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
746 label = g_strdup_printf(_("You have received an answer to a meeting proposal.\n"
747 "%s has %s the invitation whose details follow:"),
748 attendee, vcal_manager_answer_get_text(answer->answer));
749 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
754 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
755 if (saved_event && answer) {
756 vcal_manager_update_answer(saved_event,
757 answer->attendee, answer->name, answer->answer, answer->cutype);
758 vcal_manager_save_event(saved_event, TRUE);
759 saved_event->method = vcalviewer->event->method;
760 vcalviewer_display_event(vcalviewer, saved_event);
761 vcal_manager_free_event(saved_event);
765 if (vcalviewer->event->organizer) {
766 if (vcalviewer->event->orgname) {
767 gchar *addr = g_strconcat(vcalviewer->event->orgname, " <",
768 vcalviewer->event->organizer, ">", NULL);
769 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
772 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who),
773 vcalviewer->event->organizer);
776 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
779 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location),
780 vcalviewer->event->location?vcalviewer->event->location:"-");
782 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary),
783 vcalviewer->event->summary?vcalviewer->event->summary:"-");
785 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description),
786 vcalviewer->event->description?vcalviewer->event->description:"-");
788 g_free(vcalviewer->url);
789 if (vcalviewer->event->url) {
790 vcalviewer->url = g_strdup(vcalviewer->event->url);
791 gtk_widget_show(vcalviewer->uribtn);
793 vcalviewer->url = NULL;
794 gtk_widget_hide(vcalviewer->uribtn);
797 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start),
798 vcalviewer->event->start?vcalviewer->event->start:"-");
799 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end),
800 vcalviewer->event->end?vcalviewer->event->end:"-");
802 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
804 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REPLY);
807 static void vcalviewer_get_event(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
809 gchar *tmpfile = get_tmpfile(vcalviewer);
810 const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
813 charset = CS_WINDOWS_1252;
815 if (!strcasecmp(charset, CS_ISO_8859_1))
816 charset = CS_WINDOWS_1252;
818 if (vcalviewer->event) {
819 vcal_manager_free_event(vcalviewer->event);
820 vcalviewer->event = NULL;
824 vcalviewer_reset(vcalviewer);
825 vcalviewer_show_error(vcalviewer, _("Error - could not get the calendar MIME part."));
829 vcalviewer->event = vcalviewer_get_component(tmpfile, charset);
830 if (!vcalviewer->event) {
831 vcalviewer_reset(vcalviewer);
832 vcalviewer_show_error(vcalviewer, _("Error - no calendar part found."));
836 if (vcalviewer->event->type == ICAL_VTODO_COMPONENT) {
837 vcalviewer_get_request_values(vcalviewer, mimeinfo, TRUE);
838 } else if (vcalviewer->event->method == ICAL_METHOD_REQUEST ||
839 vcalviewer->event->method == ICAL_METHOD_PUBLISH ||
840 vcalviewer->event->method == ICAL_METHOD_CANCEL) {
841 vcalviewer_get_request_values(vcalviewer, mimeinfo, FALSE);
842 } else if (vcalviewer->event->method == ICAL_METHOD_REPLY) {
843 vcalviewer_get_reply_values(vcalviewer, mimeinfo);
845 vcalviewer_reset(vcalviewer);
846 vcalviewer_show_error(vcalviewer, _("Error - Unknown calendar component type."));
850 static VCalViewer *s_vcalviewer = NULL;
852 static void vcal_viewer_show_mimepart(MimeViewer *_mimeviewer, const gchar *file, MimeInfo *mimeinfo)
854 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
855 GtkAllocation allocation;
859 s_vcalviewer = vcalviewer;
861 if (mimeinfo == NULL) {
862 vcal_viewer_clear_viewer(_mimeviewer);
866 debug_print("vcal_viewer_show_mimepart : %s\n", file);
868 vcal_viewer_clear_viewer(_mimeviewer);
869 gtk_widget_show_all(vcalviewer->scrolledwin);
870 g_free(vcalviewer->file);
871 vcalviewer->file = g_strdup(file);
872 vcalviewer->mimeinfo = mimeinfo;
873 vcalviewer_hide_error(vcalviewer);
874 vcalviewer_get_event(vcalviewer, mimeinfo);
876 gtk_widget_get_allocation(vcalviewer->scrolledwin, &allocation);
877 gtk_widget_set_size_request(vcalviewer->description,
878 allocation.width - 200, -1);
879 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->location), TRUE);
880 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->summary), TRUE);
881 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->description), TRUE);
882 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
884 if (prefs_common_get_prefs()->textfont) {
885 PangoFontDescription *font_desc;
887 font_desc = pango_font_description_from_string
888 (prefs_common_get_prefs()->textfont);
890 gtk_widget_modify_font(
891 vcalviewer->description, font_desc);
892 pango_font_description_free(font_desc);
898 void vcalviewer_reload(FolderItem *item)
901 MainWindow *mainwin = mainwindow_get_mainwindow();
902 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
904 folder_item_scan(item);
905 if (mainwin && mainwin->summaryview->folder_item) {
906 FolderItem *cur = mainwin->summaryview->folder_item;
907 if (cur->folder == folder)
908 folder_item_scan(cur);
910 if (mainwin && mainwin->summaryview->folder_item == item) {
911 debug_print("reload: %p, %p\n", (MimeViewer *)s_vcalviewer, s_vcalviewer->mimeinfo);
912 summary_redisplay_msg(mainwin->summaryview);
917 static void vcal_viewer_destroy_viewer(MimeViewer *_mimeviewer)
919 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
921 debug_print("vcal_viewer_destroy_viewer\n");
923 if (s_vcalviewer == vcalviewer)
925 vcal_viewer_clear_viewer(_mimeviewer);
929 static gboolean vcalviewer_reedit_cb(GtkButton *widget, gpointer data)
931 VCalViewer *vcalviewer = (VCalViewer *)data;
932 gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
933 VCalEvent *event = NULL;
935 s_vcalviewer = vcalviewer;
936 /* see if we have it registered and more recent */
937 event = vcal_manager_load_event(uid);
938 vcal_meeting_create(event);
939 vcal_manager_free_event(event);
943 static gboolean vcalviewer_uribtn_cb(GtkButton *widget, gpointer data)
945 VCalViewer *vcalviewer = (VCalViewer *)data;
948 open_uri(vcalviewer->url, prefs_common_get_uri_cmd());
953 void vcalendar_refresh_folder_contents(FolderItem *item)
955 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
956 if (folder && item->folder == folder) {
957 MainWindow *mainwin = mainwindow_get_mainwindow();
958 folder_item_scan(item);
959 if (mainwin->summaryview->folder_item == item) {
960 summary_show(mainwin->summaryview, item);
965 static void send_cancel_notify_toggled_cb(GtkToggleButton *button, gboolean *data)
967 *data = gtk_toggle_button_get_active(button);
970 void vcalendar_cancel_meeting(FolderItem *item, const gchar *uid)
972 VCalEvent *event = NULL;
973 VCalMeeting *meet = NULL;
976 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
977 gboolean redisp = FALSE;
978 GtkWidget *send_notify_chkbtn = gtk_check_button_new_with_label(_("Send a notification to the attendees"));
979 gboolean send_notify = TRUE;
981 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(send_notify_chkbtn), TRUE);
982 gtk_widget_show(send_notify_chkbtn);
983 g_signal_connect(G_OBJECT(send_notify_chkbtn), "toggled",
984 G_CALLBACK(send_cancel_notify_toggled_cb),
987 val = alertpanel_full(_("Cancel meeting"),
988 _("Are you sure you want to cancel this meeting?"),
989 GTK_STOCK_NO, GTK_STOCK_YES, NULL, FALSE,
990 send_notify_chkbtn, ALERT_WARNING, G_ALERTDEFAULT);
992 if (val != G_ALERTALTERNATE)
995 event = vcal_manager_load_event(uid);
998 event->method = ICAL_METHOD_CANCEL;
1001 MainWindow *mainwin = mainwindow_get_mainwindow();
1002 if (mainwin->summaryview->folder_item == item) {
1004 summary_show(mainwin->summaryview, NULL);
1009 meet = vcal_meeting_create_hidden(event);
1010 if (!vcal_meeting_send(meet)) {
1011 event->method = ICAL_METHOD_REQUEST;
1012 vcal_manager_save_event(event, TRUE);
1013 vcal_manager_free_event(event);
1015 folder_item_scan(item);
1017 if (folder && redisp) {
1018 MainWindow *mainwin = mainwindow_get_mainwindow();
1019 summary_show(mainwin->summaryview, item);
1025 vcal_manager_save_event(event, TRUE);
1027 file = vcal_manager_get_event_file(event->uid);
1029 vcal_manager_free_event(event);
1032 folder_item_scan(item);
1033 if (folder && redisp) {
1034 MainWindow *mainwin = mainwindow_get_mainwindow();
1035 summary_show(mainwin->summaryview, item);
1041 static gboolean vcalviewer_cancel_cb(GtkButton *widget, gpointer data)
1043 VCalViewer *vcalviewer = (VCalViewer *)data;
1044 FolderItem *item = vcalendar_get_current_item();
1045 gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
1046 vcalendar_cancel_meeting(item, uid);
1050 static gboolean vcalviewer_action_cb(GtkButton *widget, gpointer data)
1052 VCalViewer *vcalviewer = (VCalViewer *)data;
1053 gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(vcalviewer->answer));
1054 icalparameter_partstat reply[3] = {ICAL_PARTSTAT_ACCEPTED, ICAL_PARTSTAT_TENTATIVE, ICAL_PARTSTAT_DECLINED};
1055 PrefsAccount *account = NULL;
1056 VCalEvent *saved_event = NULL, *event = NULL;
1057 debug_print("index chosen %d\n", index);
1059 if (index < 0 || index > 2) {
1063 s_vcalviewer = vcalviewer;
1065 if (!vcalviewer->event) {
1066 g_warning("can't get event");
1070 /* see if we have it registered and more recent */
1071 event = vcalviewer->event;
1072 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
1073 if (saved_event && saved_event->sequence >= vcalviewer->event->sequence) {
1074 saved_event->method = vcalviewer->event->method;
1075 event = saved_event;
1076 } else if (saved_event) {
1077 vcal_manager_free_event(saved_event);
1080 account = vcal_manager_get_account_from_event(event);
1083 AlertValue val = alertpanel_full(_("No account found"),
1084 _("You have no account matching any attendee.\n"
1085 "Do you want to reply anyway?"),
1086 GTK_STOCK_CANCEL, g_strconcat("+", _("Reply anyway"), NULL),
1087 NULL, FALSE, NULL, ALERT_QUESTION, G_ALERTDEFAULT);
1088 if (val == G_ALERTALTERNATE) {
1089 account = account_get_default();
1090 vcal_manager_update_answer(event, account->address,
1092 ICAL_PARTSTAT_NEEDSACTION,
1093 ICAL_CUTYPE_INDIVIDUAL);
1096 vcal_manager_free_event(saved_event);
1101 vcal_manager_update_answer(event, account->address, account->name, reply[index], 0);
1103 if (event->organizer && *(event->organizer) &&
1104 !vcal_manager_reply(account, event)) {
1105 g_warning("couldn't send reply");
1107 debug_print("no organizer, not sending answer\n");
1110 vcal_manager_save_event(event, TRUE);
1112 vcalviewer_display_event(vcalviewer, event);
1114 vcal_manager_free_event(saved_event);
1118 #define TABLE_ADD_LINE(label_text, widget) { \
1119 gchar *tmpstr = g_strdup_printf("<span weight=\"bold\">%s</span>",\
1121 GtkWidget *label = gtk_label_new(tmpstr); \
1123 gtk_label_set_use_markup (GTK_LABEL (label), TRUE); \
1124 gtk_misc_set_alignment (GTK_MISC(label), 1, 0); \
1125 gtk_table_attach (GTK_TABLE (vcalviewer->table), \
1126 label, 0, 1, i, i+1, \
1127 GTK_FILL, GTK_FILL, 6, 6); \
1128 gtk_table_attach (GTK_TABLE (vcalviewer->table), \
1129 widget, 1, 2, i, i+1, \
1130 GTK_FILL, GTK_FILL, 6, 6); \
1131 if (GTK_IS_LABEL(widget)) { \
1132 gtk_label_set_use_markup(GTK_LABEL (widget), TRUE); \
1133 gtk_misc_set_alignment (GTK_MISC(widget),0, 0); \
1134 gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); \
1139 static gchar *vcal_viewer_get_selection(MimeViewer *_viewer)
1141 VCalViewer *viewer = (VCalViewer *)_viewer;
1142 if (viewer->summary == NULL)
1144 if (gtk_label_get_text(GTK_LABEL(viewer->description))
1145 && *(gtk_label_get_text(GTK_LABEL(viewer->description))) > 2) {
1147 if (gtk_label_get_selection_bounds(GTK_LABEL(viewer->description),
1149 gchar *tmp = g_strdup(gtk_label_get_text(
1150 GTK_LABEL(viewer->description))+start);
1151 tmp[end-start] = '\0';
1154 return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->description)));
1157 else if (gtk_label_get_text(GTK_LABEL(viewer->summary))
1158 && *(gtk_label_get_text(GTK_LABEL(viewer->summary))) > 2)
1159 return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->summary)));
1165 static gboolean vcal_viewer_scroll_page(MimeViewer *_viewer, gboolean up)
1167 VCalViewer *viewer = (VCalViewer *)_viewer;
1168 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
1169 GTK_SCROLLED_WINDOW(viewer->scrolledwin));
1171 return gtkutils_scroll_page(viewer->table, vadj, up);
1174 static void vcal_viewer_scroll_one_line(MimeViewer *_viewer, gboolean up)
1176 VCalViewer *viewer = (VCalViewer *)_viewer;
1177 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
1178 GTK_SCROLLED_WINDOW(viewer->scrolledwin));
1180 gtkutils_scroll_one_line(viewer->table, vadj, up);
1183 MimeViewer *vcal_viewer_create(void)
1185 VCalViewer *vcalviewer;
1187 GtkWidget *hbox = NULL, *vbox = NULL;
1188 GtkWidget *warning_img;
1189 GtkWidget *warning_label;
1191 debug_print("Creating vcal view...\n");
1192 vcalviewer = g_new0(VCalViewer, 1);
1193 vcalviewer->mimeviewer.factory = &vcal_viewer_factory;
1195 vcalviewer->mimeviewer.get_widget = vcal_viewer_get_widget;
1196 vcalviewer->mimeviewer.show_mimepart = vcal_viewer_show_mimepart;
1197 vcalviewer->mimeviewer.clear_viewer = vcal_viewer_clear_viewer;
1198 vcalviewer->mimeviewer.destroy_viewer = vcal_viewer_destroy_viewer;
1199 vcalviewer->mimeviewer.get_selection = vcal_viewer_get_selection;
1200 vcalviewer->mimeviewer.scroll_page = vcal_viewer_scroll_page;
1201 vcalviewer->mimeviewer.scroll_one_line = vcal_viewer_scroll_one_line;
1203 vcalviewer->table = gtk_table_new(8, 2, FALSE);
1204 vcalviewer->type = gtk_label_new("meeting");
1205 vcalviewer->who = gtk_label_new("who");
1206 vcalviewer->start = gtk_label_new("start");
1207 vcalviewer->end = gtk_label_new("end");
1208 vcalviewer->location = gtk_label_new("location");
1209 vcalviewer->summary = gtk_label_new("summary");
1210 vcalviewer->description = gtk_label_new("description");
1211 vcalviewer->attendees = gtk_label_new("attendees");
1213 vcalviewer->answer = gtk_combo_box_text_new();
1214 vcalviewer->url = NULL;
1215 vcalviewer->button = gtk_button_new_with_label(_("Answer"));
1216 vcalviewer->reedit = gtk_button_new_with_label(_("Edit meeting..."));
1217 vcalviewer->cancel = gtk_button_new_with_label(_("Cancel meeting..."));
1218 vcalviewer->uribtn = gtk_button_new_with_label(_("Launch website"));
1219 vcalviewer->unavail_box = gtk_hbox_new(FALSE, 6);
1220 warning_img = gtk_image_new_from_stock
1221 (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
1222 warning_label = gtk_label_new(_("You are already busy at this time."));
1224 gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_img, FALSE, FALSE, 0);
1225 gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_label, FALSE, FALSE, 0);
1227 hbox = gtk_hbox_new(FALSE, 6);
1228 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->answer, FALSE, FALSE, 0);
1229 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->button, FALSE, FALSE, 0);
1230 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->reedit, FALSE, FALSE, 0);
1231 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->cancel, FALSE, FALSE, 0);
1232 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->uribtn, FALSE, FALSE, 0);
1234 vbox = gtk_vbox_new(FALSE, 6);
1235 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1236 gtk_box_pack_start(GTK_BOX(vbox), vcalviewer->unavail_box, FALSE, FALSE, 0);
1238 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REQUEST);
1240 gtk_label_set_selectable(GTK_LABEL(vcalviewer->type), TRUE);
1241 gtk_label_set_selectable(GTK_LABEL(vcalviewer->who), TRUE);
1242 gtk_label_set_selectable(GTK_LABEL(vcalviewer->start), TRUE);
1243 gtk_label_set_selectable(GTK_LABEL(vcalviewer->end), TRUE);
1244 gtk_label_set_selectable(GTK_LABEL(vcalviewer->location), TRUE);
1245 gtk_label_set_selectable(GTK_LABEL(vcalviewer->summary), TRUE);
1246 gtk_label_set_selectable(GTK_LABEL(vcalviewer->description), TRUE);
1247 gtk_label_set_selectable(GTK_LABEL(vcalviewer->attendees), TRUE);
1249 g_signal_connect(G_OBJECT(vcalviewer->button), "clicked",
1250 G_CALLBACK(vcalviewer_action_cb), vcalviewer);
1252 g_signal_connect(G_OBJECT(vcalviewer->reedit), "clicked",
1253 G_CALLBACK(vcalviewer_reedit_cb), vcalviewer);
1255 g_signal_connect(G_OBJECT(vcalviewer->cancel), "clicked",
1256 G_CALLBACK(vcalviewer_cancel_cb), vcalviewer);
1258 g_signal_connect(G_OBJECT(vcalviewer->uribtn), "clicked",
1259 G_CALLBACK(vcalviewer_uribtn_cb), vcalviewer);
1261 TABLE_ADD_LINE(_("Event:"), vcalviewer->type);
1262 TABLE_ADD_LINE(_("Organizer:"), vcalviewer->who);
1263 TABLE_ADD_LINE(_("Location:"), vcalviewer->location);
1264 TABLE_ADD_LINE(_("Summary:"), vcalviewer->summary);
1265 TABLE_ADD_LINE(_("Starting:"), vcalviewer->start);
1266 TABLE_ADD_LINE(_("Ending:"), vcalviewer->end);
1267 TABLE_ADD_LINE(_("Description:"), vcalviewer->description);
1268 TABLE_ADD_LINE(_("Attendees:"), vcalviewer->attendees);
1269 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
1270 TABLE_ADD_LINE(_("Action:"), vbox);
1272 vcalviewer->scrolledwin = gtk_scrolled_window_new(NULL, NULL);
1273 gtk_scrolled_window_add_with_viewport(
1274 GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
1276 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
1278 GTK_POLICY_AUTOMATIC);
1280 gtk_widget_show_all(vcalviewer->scrolledwin);
1281 return (MimeViewer *) vcalviewer;
1284 static gchar *content_types[] =
1285 {"text/calendar", NULL};
1287 MimeViewerFactory vcal_viewer_factory =
1294 static gint alert_timeout_tag = 0;
1295 static gint scan_timeout_tag = 0;
1297 static gboolean vcal_webcal_check(gpointer data)
1299 Folder *root = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
1301 if (prefs_common_get_prefs()->work_offline)
1304 manual_update = FALSE;
1305 folderview_check_new(root);
1306 manual_update = TRUE;
1310 static guint context_menu_id = 0;
1311 static guint main_menu_id = 0;
1313 void vcalendar_init(void)
1315 MainWindow *mainwin = mainwindow_get_mainwindow();
1316 Folder *folder = NULL;
1317 gchar *directory = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
1320 if (!is_dir_exist(directory) && make_dir (directory) != 0) {
1329 mimeview_register_viewer_factory(&vcal_viewer_factory);
1330 folder_register_class(vcal_folder_get_class());
1332 folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
1334 START_TIMING("creating folder");
1335 folder = folder_new(vcal_folder_get_class(), PLUGIN_NAME, NULL);
1336 folder->klass->create_tree(folder);
1338 folder_scan_tree(folder, TRUE);
1342 if (!folder->inbox) {
1343 folder->klass->create_tree(folder);
1344 folder_scan_tree(folder, TRUE);
1346 if (folder->klass->scan_required(folder, folder->inbox)) {
1347 START_TIMING("scanning folder");
1348 folder_item_scan(folder->inbox);
1352 vcal_folder_gtk_init();
1354 alert_timeout_tag = g_timeout_add(60*1000,
1355 (GSourceFunc)vcal_meeting_alert_check,
1357 scan_timeout_tag = g_timeout_add(3600*1000,
1358 (GSourceFunc)vcal_webcal_check,
1360 if (prefs_common_get_prefs()->enable_color) {
1361 gtkut_convert_int_to_gdk_color(prefs_common_get_prefs()->color[COL_URI],
1365 gtk_action_group_add_actions(mainwin->action_group, vcalendar_main_menu,
1366 1, (gpointer)mainwin);
1367 MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/Message", "CreateMeeting",
1368 "Message/CreateMeeting", GTK_UI_MANAGER_MENUITEM,
1370 MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menus/SummaryViewPopup", "CreateMeeting",
1371 "Message/CreateMeeting", GTK_UI_MANAGER_MENUITEM,
1376 void vcalendar_done(void)
1378 MainWindow *mainwin = mainwindow_get_mainwindow();
1379 FolderView *folderview = NULL;
1380 FolderItem *fitem = NULL;
1382 icalmemory_free_ring();
1384 vcal_folder_free_data();
1386 if (mainwin == NULL)
1389 folderview = mainwin->folderview;
1390 fitem = folderview->summaryview->folder_item;
1393 fitem->folder->klass == vcal_folder_get_class()) {
1394 folderview_unselect(folderview);
1395 summary_clear_all(folderview->summaryview);
1396 if (fitem->folder->klass->item_closed)
1397 fitem->folder->klass->item_closed(fitem);
1400 mimeview_unregister_viewer_factory(&vcal_viewer_factory);
1401 folder_unregister_class(vcal_folder_get_class());
1402 vcal_folder_gtk_done();
1404 g_source_remove(alert_timeout_tag);
1405 alert_timeout_tag = 0;
1406 g_source_remove(scan_timeout_tag);
1407 scan_timeout_tag = 0;
1409 MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/CreateMeeting", main_menu_id);
1411 MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/CreateMeeting", context_menu_id);
1412 context_menu_id = 0;