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,
126 != G_ALERTALTERNATE) {
132 main_window_cursor_wait(summaryview->mainwin);
133 gtk_cmclist_freeze(GTK_CMCLIST(summaryview->ctree));
134 folder_item_update_freeze();
137 item = summaryview->folder_item;
139 STATUSBAR_PUSH(mainwin, _("Creating meeting..."));
141 for (cur = msglist; cur; cur = cur->next) {
142 MsgInfo *msginfo = procmsg_msginfo_get_full_info((MsgInfo *)cur->data);
143 VCalEvent *event = NULL;
146 if (MSG_IS_ENCRYPTED(msginfo->flags)) {
147 fp = procmime_get_first_encrypted_text_content(msginfo);
149 fp = procmime_get_first_text_content(msginfo);
154 time_t t = time(NULL);
157 gchar *orgname = NULL;
158 gchar *summary = g_strdup(msginfo->subject ? msginfo->subject:_("no subject"));
159 gchar *description = file_read_stream_to_str(fp);
160 gchar *dtstart = g_strdup(icaltime_as_ical_string(icaltime_from_timet_with_zone(t, FALSE, NULL)));
161 gchar *dtend = g_strdup(icaltime_as_ical_string(icaltime_from_timet_with_zone(t2, FALSE, NULL)));
163 gchar *tzid = g_strdup("UTC");
165 gint method = ICAL_METHOD_REQUEST;
167 PrefsAccount *account = NULL;
171 if (item && item->prefs && item->prefs->enable_default_account)
172 account = account_find_from_id(item->prefs->default_account);
175 account = account_get_cur_account();
180 org = g_strdup(account->address);
182 uid = prefs_account_generate_msgid(account);
184 event = vcal_manager_new_event(uid,
185 org, NULL, NULL/*location*/, summary, description,
186 dtstart, dtend, recur, tzid, url, method, sequence,
187 ICAL_VTODO_COMPONENT);
190 /* hack to get default hours */
191 g_free(event->dtstart);
192 g_free(event->dtend);
193 event->dtstart = NULL;
196 vcal_meeting_create(event);
197 vcal_manager_free_event(event);
211 procmsg_msginfo_free(&msginfo);
214 statusbar_progress_all(0,0,0);
215 STATUSBAR_POP(mainwin);
217 folder_item_update_thaw();
218 gtk_cmclist_thaw(GTK_CMCLIST(summaryview->ctree));
219 main_window_cursor_normal(summaryview->mainwin);
220 g_slist_free(msglist);
223 static gchar *get_tmpfile(VCalViewer *vcalviewer)
225 gchar *tmpfile = NULL;
227 if (!vcalviewer->tmpfile) {
228 tmpfile = procmime_get_tmp_file_name(vcalviewer->mimeinfo);
229 debug_print("creating %s\n", tmpfile);
231 if (procmime_get_part(tmpfile, vcalviewer->mimeinfo) < 0) {
232 g_warning("Can't get mimepart file");
236 vcalviewer->tmpfile = tmpfile;
239 return vcalviewer->tmpfile;
242 static GtkWidget *vcal_viewer_get_widget(MimeViewer *_mimeviewer)
244 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
246 debug_print("vcal_viewer_get_widget\n");
247 gtk_widget_show_all(vcalviewer->scrolledwin);
248 return vcalviewer->scrolledwin;
251 static void vcal_viewer_clear_viewer(MimeViewer *_mimeviewer)
253 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
255 debug_print("vcal_viewer_clear_viewer\n");
257 g_free(vcalviewer->file);
258 vcalviewer->file = NULL;
259 if (vcalviewer->tmpfile) {
260 debug_print("unlinking %s\n", vcalviewer->tmpfile);
261 g_unlink(vcalviewer->tmpfile);
262 g_free(vcalviewer->tmpfile);
263 vcalviewer->tmpfile = NULL;
265 vcalviewer->mimeinfo = NULL;
268 static VCalEvent *vcalviewer_get_component(const gchar *file, const gchar *charset)
270 gchar *compstr = NULL;
271 VCalEvent *event = NULL;
277 g_return_val_if_fail(file != NULL, NULL);
279 if ((fp = g_fopen(file, "rb")) == NULL) {
280 FILE_OP_ERROR(file, "g_fopen");
284 array = g_byte_array_new();
286 while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
287 if (n_read < sizeof(buf) && ferror(fp))
289 g_byte_array_append(array, (guchar *)buf, n_read);
293 FILE_OP_ERROR("file stream", "fread");
294 g_byte_array_free(array, TRUE);
300 g_byte_array_append(array, (guchar *)buf, 1);
301 compstr = (gchar *)array->data;
302 g_byte_array_free(array, FALSE);
307 event = vcal_get_event_from_ical(compstr, charset);
314 #define GTK_LABEL_SET_TEXT_TRIMMED(label, text) { \
315 gchar *tmplbl = strretchomp(g_strdup(text)); \
316 gtk_label_set_text(label, tmplbl); \
320 static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, icalproperty_method method);
322 static void vcalviewer_reset(VCalViewer *vcalviewer)
324 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
325 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
326 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), "-");
327 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
328 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
329 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
330 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
331 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
332 g_free(vcalviewer->url);
333 vcalviewer->url = NULL;
334 gtk_widget_hide(vcalviewer->uribtn);
335 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_CANCEL);
338 static void vcalviewer_show_error(VCalViewer *vcalviewer, const gchar *msg)
340 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), msg);
343 static void vcalviewer_hide_error(VCalViewer *vcalviewer)
345 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
348 static void vcalviewer_show_unavailable(VCalViewer *vcalviewer, gboolean visi)
351 gtk_widget_show_all(vcalviewer->unavail_box);
353 gtk_widget_hide(vcalviewer->unavail_box);
356 static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, icalproperty_method method)
360 gtk_widget_hide(vcalviewer->reedit);
361 gtk_widget_hide(vcalviewer->cancel);
362 gtk_widget_hide(vcalviewer->answer);
363 gtk_widget_hide(vcalviewer->button);
365 for (i = 0; i < 3; i++)
366 gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(vcalviewer->answer), 0);
368 vcalviewer_show_unavailable(vcalviewer, FALSE);
370 if (method == ICAL_METHOD_REQUEST && event && !event->rec_occurrence) {
371 PrefsAccount *account = vcal_manager_get_account_from_event(event);
374 account = vcal_manager_get_account_from_event(vcalviewer->event);
376 if (!account && event) {
377 account = account_get_default();
378 vcal_manager_update_answer(event, account->address,
380 ICAL_PARTSTAT_NEEDSACTION,
381 ICAL_CUTYPE_INDIVIDUAL);
384 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Accept"));
385 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Tentatively accept"));
386 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Decline"));
387 gtk_widget_set_sensitive(vcalviewer->answer, TRUE);
388 gtk_widget_set_sensitive(vcalviewer->button, TRUE);
389 gtk_widget_show(vcalviewer->answer);
390 gtk_widget_show(vcalviewer->button);
392 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), "-");
393 gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
394 gtk_widget_set_sensitive(vcalviewer->button, FALSE);
397 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), "-");
398 gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
399 gtk_widget_set_sensitive(vcalviewer->button, FALSE);
401 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
403 if (event && event->method == ICAL_METHOD_REQUEST) {
404 PrefsAccount *account = vcal_manager_get_account_from_event(event);
405 gchar *internal_ifb = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
406 "vcalendar", G_DIR_SEPARATOR_S,
407 "internal.ifb", NULL);
408 gchar *myfb = file_read_to_str(internal_ifb);
409 g_free(internal_ifb);
411 icalparameter_partstat answer =
412 vcal_manager_get_reply_for_attendee(event, account->address);
414 if (answer == ICAL_PARTSTAT_ACCEPTED)
415 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
416 if (answer == ICAL_PARTSTAT_TENTATIVE)
417 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 1);
418 if (answer == ICAL_PARTSTAT_DECLINED)
419 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 2);
420 if (event->dtstart && event->dtend && myfb && *myfb
421 && answer != ICAL_PARTSTAT_ACCEPTED
422 && answer != ICAL_PARTSTAT_TENTATIVE) {
423 if (!attendee_available(NULL, event->dtstart, event->dtend, myfb))
424 vcalviewer_show_unavailable(vcalviewer, TRUE);
430 g_free(vcalviewer->url);
431 if (event && event->url && *(event->url)) {
432 vcalviewer->url = g_strdup(event->url);
433 gtk_widget_show(vcalviewer->uribtn);
435 vcalviewer->url = NULL;
436 gtk_widget_hide(vcalviewer->uribtn);
440 static FolderItem *vcalendar_get_current_item(void)
442 MainWindow *mainwin = mainwindow_get_mainwindow();
443 FolderItem *item = NULL;
444 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
447 item = mainwin->summaryview->folder_item;
448 if (item->folder == folder)
451 return folder->inbox;
457 void vcalviewer_display_event (VCalViewer *vcalviewer, VCalEvent *event)
460 gchar *attendees = NULL;
461 gboolean mine = FALSE;
463 gboolean save_evt = FALSE;
464 FolderItem *item = vcalendar_get_current_item();
471 if (event->type == ICAL_VTODO_COMPONENT) {
473 label = g_strjoin(" ", _("You have a Todo item."),
474 _("Details follow:"), NULL);
475 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
477 } else if (event->method == ICAL_METHOD_REQUEST) {
479 if (account_find_from_address(event->organizer, FALSE)) {
480 label = g_strjoin(" ", _("You have created a meeting."),
481 _("Details follow:"), NULL);
482 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
485 label = g_strjoin(" ", _("You have been invited to a meeting."),
486 _("Details follow:"), NULL);
487 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
490 } else if (event->method == ICAL_METHOD_CANCEL) {
492 label = g_strjoin(" ",
493 _("A meeting to which you had been invited has been cancelled."),
494 _("Details follow:"), NULL);
495 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
497 vcalendar_refresh_folder_contents(item);
498 } else if (event->method == ICAL_METHOD_REPLY) {
499 /* don't change label */
502 label = g_strjoin(" ", _("You have been forwarded an appointment."),
503 _("Details follow:"), NULL);
504 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
510 if (event->orgname && *(event->orgname)
511 && event->organizer && *(event->organizer)) {
512 gchar *addr = g_strconcat(event->orgname, " <", event->organizer, ">", NULL);
513 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
515 } else if (event->organizer && *(event->organizer)) {
516 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), event->organizer);
518 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
522 if (event->location && *(event->location)) {
523 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), event->location);
525 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), "-");
529 if (event->summary && *(event->summary)) {
530 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), event->summary);
532 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
536 if (event->description && *(event->description)) {
537 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), event->description);
539 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
543 g_free(vcalviewer->url);
544 if (event->url && *(event->url)) {
545 vcalviewer->url = g_strdup(event->url);
546 gtk_widget_show(vcalviewer->uribtn);
548 vcalviewer->url = NULL;
549 gtk_widget_hide(vcalviewer->uribtn);
553 if (event->start && *(event->start)) {
554 if (event->recur && *(event->recur)) {
555 gchar *tmp = g_strdup_printf(g_strconcat("%s <span weight=\"bold\">",
556 _("(this event recurs)"),"</span>", NULL),
558 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
559 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
561 } else if (event->rec_occurrence) {
562 gchar *tmp = g_strdup_printf(g_strconcat("%s <span weight=\"bold\">",
563 _("(this event is part of a recurring event)"),
566 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
567 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
570 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), event->start);
573 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
577 if (event->end && *(event->end)) {
578 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), event->end);
580 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
584 attendees = g_strdup("");
585 for (list = vcal_manager_get_answers_emails(event);
586 list && list->data; list = list->next) {
587 gchar *attendee = (gchar *)list->data;
588 gchar *name = vcal_manager_get_attendee_name(event, attendee);
589 gchar *ename = g_markup_printf_escaped("%s", name?name:"");
590 gchar *eatt = g_markup_printf_escaped("%s", attendee);
591 icalparameter_partstat acode = vcal_manager_get_reply_for_attendee(event, attendee);
592 gchar *answer = vcal_manager_get_reply_text_for_attendee(event, attendee);
593 gchar *type = vcal_manager_get_cutype_text_for_attendee(event, attendee);
596 tmp = g_strdup_printf(
597 "%s%s<%s> (%s, <span%s>%s</span>)",
598 (ename && *(ename))?ename:"",
599 (ename && *(ename))?" ":"",
600 (eatt && *(eatt))?eatt:"",
601 (type && *(type))?type:"",
602 (acode != ICAL_PARTSTAT_ACCEPTED ? " foreground=\"red\"":""),
603 (answer && *(answer))?answer:"");
604 e_len = strlen(attendees);
607 attendees = g_realloc(attendees, e_len+n_len+2);
608 *(attendees+e_len) = '\n';
609 strcpy(attendees+e_len+1, tmp);
611 attendees = g_realloc(attendees, e_len+n_len+1);
612 strcpy(attendees, tmp);
622 if (attendees && *(attendees)) {
623 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), attendees);
625 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
628 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->attendees), TRUE);
632 if (event->type != ICAL_VTODO_COMPONENT)
633 vcalviewer_answer_set_choices(vcalviewer, event, event->method);
635 vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_PUBLISH);
637 vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_REPLY);
638 gtk_widget_show(vcalviewer->reedit);
639 gtk_widget_show(vcalviewer->cancel);
642 /* save if cancelled */
644 vcal_manager_save_event(event, TRUE);
647 gchar *vcalviewer_get_uid_from_mimeinfo(MimeInfo *mimeinfo)
649 gchar *tmpfile = procmime_get_tmp_file_name(mimeinfo);
650 const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
651 gchar *compstr = NULL;
653 VCalEvent *event = NULL;
655 if (procmime_get_part(tmpfile, mimeinfo) < 0) {
656 g_warning("Can't get mimepart file");
662 charset = CS_WINDOWS_1252;
664 if (!strcasecmp(charset, CS_ISO_8859_1))
665 charset = CS_WINDOWS_1252;
667 compstr = file_read_to_str(tmpfile);
669 event = vcal_get_event_from_ical(compstr, charset);
671 res = g_strdup(event->uid);
673 vcal_manager_free_event(event);
675 debug_print("got uid: %s\n", res);
680 static void vcalviewer_get_request_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo, gboolean is_todo)
682 VCalEvent *saved_event = NULL;
683 const gchar *saveme = procmime_mimeinfo_get_parameter(mimeinfo, "vcalsave");
685 if (!vcalviewer->event)
688 /* see if we have it registered and more recent */
689 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
690 if (saved_event && saved_event->sequence >= vcalviewer->event->sequence) {
691 saved_event->method = vcalviewer->event->method;
692 vcalviewer_display_event(vcalviewer, saved_event);
693 vcal_manager_free_event(saved_event);
695 } else if (saved_event) {
696 vcal_manager_free_event(saved_event);
699 /* load it and register it */
701 if (!saveme || strcmp(saveme,"no"))
702 vcal_manager_save_event(vcalviewer->event, FALSE);
704 vcalviewer_display_event(vcalviewer, vcalviewer->event);
707 static void vcalviewer_get_reply_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
709 VCalEvent *saved_event = NULL;
710 gchar *attendee = NULL, *label = NULL;
711 Answer *answer = NULL;
713 if (!vcalviewer->event)
716 if (!vcalviewer->event->answers || g_slist_length(vcalviewer->event->answers) > 1) {
717 g_warning("strange, no answers or more than one");
720 if (vcalviewer->event->answers) {
721 answer = (Answer *)vcalviewer->event->answers->data;
722 attendee = g_strdup(answer->attendee);
727 label = g_strjoin(" ",
728 _("You have received an answer to an unknown meeting proposal."),
729 _("Details follow:"), NULL);
730 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
732 label = g_strdup_printf(_("You have received an answer to a meeting proposal.\n"
733 "%s has %s the invitation whose details follow:"),
734 attendee, vcal_manager_answer_get_text(answer->answer));
735 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
740 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
741 if (saved_event && answer) {
742 vcal_manager_update_answer(saved_event,
743 answer->attendee, answer->name, answer->answer, answer->cutype);
744 vcal_manager_save_event(saved_event, TRUE);
745 saved_event->method = vcalviewer->event->method;
746 vcalviewer_display_event(vcalviewer, saved_event);
747 vcal_manager_free_event(saved_event);
751 if (vcalviewer->event->organizer) {
752 if (vcalviewer->event->orgname) {
753 gchar *addr = g_strconcat(vcalviewer->event->orgname, " <",
754 vcalviewer->event->organizer, ">", NULL);
755 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
758 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who),
759 vcalviewer->event->organizer);
762 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
765 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location),
766 vcalviewer->event->location?vcalviewer->event->location:"-");
768 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary),
769 vcalviewer->event->summary?vcalviewer->event->summary:"-");
771 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description),
772 vcalviewer->event->description?vcalviewer->event->description:"-");
774 g_free(vcalviewer->url);
775 if (vcalviewer->event->url) {
776 vcalviewer->url = g_strdup(vcalviewer->event->url);
777 gtk_widget_show(vcalviewer->uribtn);
779 vcalviewer->url = NULL;
780 gtk_widget_hide(vcalviewer->uribtn);
783 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start),
784 vcalviewer->event->start?vcalviewer->event->start:"-");
785 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end),
786 vcalviewer->event->end?vcalviewer->event->end:"-");
788 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
790 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REPLY);
793 static void vcalviewer_get_event(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
795 gchar *tmpfile = get_tmpfile(vcalviewer);
796 const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
799 charset = CS_WINDOWS_1252;
801 if (!strcasecmp(charset, CS_ISO_8859_1))
802 charset = CS_WINDOWS_1252;
804 if (vcalviewer->event) {
805 vcal_manager_free_event(vcalviewer->event);
806 vcalviewer->event = NULL;
810 vcalviewer_reset(vcalviewer);
811 vcalviewer_show_error(vcalviewer, _("Error - could not get the calendar MIME part."));
815 vcalviewer->event = vcalviewer_get_component(tmpfile, charset);
816 if (!vcalviewer->event) {
817 vcalviewer_reset(vcalviewer);
818 vcalviewer_show_error(vcalviewer, _("Error - no calendar part found."));
822 if (vcalviewer->event->type == ICAL_VTODO_COMPONENT) {
823 vcalviewer_get_request_values(vcalviewer, mimeinfo, TRUE);
824 } else if (vcalviewer->event->method == ICAL_METHOD_REQUEST ||
825 vcalviewer->event->method == ICAL_METHOD_PUBLISH ||
826 vcalviewer->event->method == ICAL_METHOD_CANCEL) {
827 vcalviewer_get_request_values(vcalviewer, mimeinfo, FALSE);
828 } else if (vcalviewer->event->method == ICAL_METHOD_REPLY) {
829 vcalviewer_get_reply_values(vcalviewer, mimeinfo);
831 vcalviewer_reset(vcalviewer);
832 vcalviewer_show_error(vcalviewer, _("Error - Unknown calendar component type."));
836 static VCalViewer *s_vcalviewer = NULL;
838 static void vcal_viewer_show_mimepart(MimeViewer *_mimeviewer, const gchar *file, MimeInfo *mimeinfo)
840 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
841 GtkAllocation allocation;
845 s_vcalviewer = vcalviewer;
847 if (mimeinfo == NULL) {
848 vcal_viewer_clear_viewer(_mimeviewer);
852 debug_print("vcal_viewer_show_mimepart : %s\n", file);
854 vcal_viewer_clear_viewer(_mimeviewer);
855 gtk_widget_show_all(vcalviewer->scrolledwin);
856 g_free(vcalviewer->file);
857 vcalviewer->file = g_strdup(file);
858 vcalviewer->mimeinfo = mimeinfo;
859 vcalviewer_hide_error(vcalviewer);
860 vcalviewer_get_event(vcalviewer, mimeinfo);
862 gtk_widget_get_allocation(vcalviewer->scrolledwin, &allocation);
863 gtk_widget_set_size_request(vcalviewer->description,
864 allocation.width - 200, -1);
865 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->location), TRUE);
866 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->summary), TRUE);
867 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->description), TRUE);
868 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
870 if (prefs_common_get_prefs()->textfont) {
871 PangoFontDescription *font_desc;
873 font_desc = pango_font_description_from_string
874 (prefs_common_get_prefs()->textfont);
876 gtk_widget_modify_font(
877 vcalviewer->description, font_desc);
878 pango_font_description_free(font_desc);
884 void vcalviewer_reload(FolderItem *item)
887 MainWindow *mainwin = mainwindow_get_mainwindow();
888 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
890 folder_item_scan(item);
891 if (mainwin && mainwin->summaryview->folder_item) {
892 FolderItem *cur = mainwin->summaryview->folder_item;
893 if (cur->folder == folder)
894 folder_item_scan(cur);
896 if (mainwin && mainwin->summaryview->folder_item == item) {
897 debug_print("reload: %p, %p\n", (MimeViewer *)s_vcalviewer, s_vcalviewer->mimeinfo);
898 summary_redisplay_msg(mainwin->summaryview);
903 static void vcal_viewer_destroy_viewer(MimeViewer *_mimeviewer)
905 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
907 debug_print("vcal_viewer_destroy_viewer\n");
909 if (s_vcalviewer == vcalviewer)
911 vcal_viewer_clear_viewer(_mimeviewer);
915 static gboolean vcalviewer_reedit_cb(GtkButton *widget, gpointer data)
917 VCalViewer *vcalviewer = (VCalViewer *)data;
918 gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
919 VCalEvent *event = NULL;
921 s_vcalviewer = vcalviewer;
922 /* see if we have it registered and more recent */
923 event = vcal_manager_load_event(uid);
924 vcal_meeting_create(event);
925 vcal_manager_free_event(event);
929 static gboolean vcalviewer_uribtn_cb(GtkButton *widget, gpointer data)
931 VCalViewer *vcalviewer = (VCalViewer *)data;
934 open_uri(vcalviewer->url, prefs_common_get_uri_cmd());
939 void vcalendar_refresh_folder_contents(FolderItem *item)
941 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
942 if (folder && item->folder == folder) {
943 MainWindow *mainwin = mainwindow_get_mainwindow();
944 folder_item_scan(item);
945 if (mainwin->summaryview->folder_item == item) {
946 summary_show(mainwin->summaryview, item);
951 static void send_cancel_notify_toggled_cb(GtkToggleButton *button, gboolean *data)
953 *data = gtk_toggle_button_get_active(button);
956 void vcalendar_cancel_meeting(FolderItem *item, const gchar *uid)
958 VCalEvent *event = NULL;
959 VCalMeeting *meet = NULL;
962 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
963 gboolean redisp = FALSE;
964 GtkWidget *send_notify_chkbtn = gtk_check_button_new_with_label(_("Send a notification to the attendees"));
965 gboolean send_notify = TRUE;
967 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(send_notify_chkbtn), TRUE);
968 gtk_widget_show(send_notify_chkbtn);
969 g_signal_connect(G_OBJECT(send_notify_chkbtn), "toggled",
970 G_CALLBACK(send_cancel_notify_toggled_cb),
973 val = alertpanel_full(_("Cancel meeting"),
974 _("Are you sure you want to cancel this meeting?"),
975 GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_FIRST, FALSE,
976 send_notify_chkbtn, ALERT_WARNING);
978 if (val != G_ALERTALTERNATE)
981 event = vcal_manager_load_event(uid);
984 event->method = ICAL_METHOD_CANCEL;
987 MainWindow *mainwin = mainwindow_get_mainwindow();
988 if (mainwin->summaryview->folder_item == item) {
990 summary_show(mainwin->summaryview, NULL);
995 meet = vcal_meeting_create_hidden(event);
996 if (!vcal_meeting_send(meet)) {
997 event->method = ICAL_METHOD_REQUEST;
998 vcal_manager_save_event(event, TRUE);
999 vcal_manager_free_event(event);
1001 folder_item_scan(item);
1003 if (folder && redisp) {
1004 MainWindow *mainwin = mainwindow_get_mainwindow();
1005 summary_show(mainwin->summaryview, item);
1011 vcal_manager_save_event(event, TRUE);
1013 file = vcal_manager_get_event_file(event->uid);
1015 vcal_manager_free_event(event);
1018 folder_item_scan(item);
1019 if (folder && redisp) {
1020 MainWindow *mainwin = mainwindow_get_mainwindow();
1021 summary_show(mainwin->summaryview, item);
1027 static gboolean vcalviewer_cancel_cb(GtkButton *widget, gpointer data)
1029 VCalViewer *vcalviewer = (VCalViewer *)data;
1030 FolderItem *item = vcalendar_get_current_item();
1031 gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
1032 vcalendar_cancel_meeting(item, uid);
1036 static gboolean vcalviewer_action_cb(GtkButton *widget, gpointer data)
1038 VCalViewer *vcalviewer = (VCalViewer *)data;
1039 gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(vcalviewer->answer));
1040 icalparameter_partstat reply[3] = {ICAL_PARTSTAT_ACCEPTED, ICAL_PARTSTAT_TENTATIVE, ICAL_PARTSTAT_DECLINED};
1041 PrefsAccount *account = NULL;
1042 VCalEvent *saved_event = NULL, *event = NULL;
1043 debug_print("index chosen %d\n", index);
1045 if (index < 0 || index > 2) {
1049 s_vcalviewer = vcalviewer;
1051 if (!vcalviewer->event) {
1052 g_warning("can't get event");
1056 /* see if we have it registered and more recent */
1057 event = vcalviewer->event;
1058 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
1059 if (saved_event && saved_event->sequence >= vcalviewer->event->sequence) {
1060 saved_event->method = vcalviewer->event->method;
1061 event = saved_event;
1062 } else if (saved_event) {
1063 vcal_manager_free_event(saved_event);
1066 account = vcal_manager_get_account_from_event(event);
1069 AlertValue val = alertpanel_full(_("No account found"),
1070 _("You have no account matching any attendee.\n"
1071 "Do you want to reply anyway?"),
1072 GTK_STOCK_CANCEL, _("Reply anyway"), NULL,
1073 ALERTFOCUS_SECOND, FALSE, NULL, ALERT_QUESTION);
1074 if (val == G_ALERTALTERNATE) {
1075 account = account_get_default();
1076 vcal_manager_update_answer(event, account->address,
1078 ICAL_PARTSTAT_NEEDSACTION,
1079 ICAL_CUTYPE_INDIVIDUAL);
1082 vcal_manager_free_event(saved_event);
1087 vcal_manager_update_answer(event, account->address, account->name, reply[index], 0);
1089 if (event->organizer && *(event->organizer) &&
1090 !vcal_manager_reply(account, event)) {
1091 g_warning("couldn't send reply");
1093 debug_print("no organizer, not sending answer\n");
1096 vcal_manager_save_event(event, TRUE);
1098 vcalviewer_display_event(vcalviewer, event);
1100 vcal_manager_free_event(saved_event);
1104 #define TABLE_ADD_LINE(label_text, widget) { \
1105 gchar *tmpstr = g_strdup_printf("<span weight=\"bold\">%s</span>",\
1107 GtkWidget *label = gtk_label_new(tmpstr); \
1109 gtk_label_set_use_markup (GTK_LABEL (label), TRUE); \
1110 gtk_misc_set_alignment (GTK_MISC(label), 1, 0); \
1111 gtk_table_attach (GTK_TABLE (vcalviewer->table), \
1112 label, 0, 1, i, i+1, \
1113 GTK_FILL, GTK_FILL, 6, 6); \
1114 gtk_table_attach (GTK_TABLE (vcalviewer->table), \
1115 widget, 1, 2, i, i+1, \
1116 GTK_FILL, GTK_FILL, 6, 6); \
1117 if (GTK_IS_LABEL(widget)) { \
1118 gtk_label_set_use_markup(GTK_LABEL (widget), TRUE); \
1119 gtk_misc_set_alignment (GTK_MISC(widget),0, 0); \
1120 gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); \
1125 static gchar *vcal_viewer_get_selection(MimeViewer *_viewer)
1127 VCalViewer *viewer = (VCalViewer *)_viewer;
1128 if (viewer->summary == NULL)
1130 if (gtk_label_get_text(GTK_LABEL(viewer->description))
1131 && *(gtk_label_get_text(GTK_LABEL(viewer->description))) > 2) {
1133 if (gtk_label_get_selection_bounds(GTK_LABEL(viewer->description),
1135 gchar *tmp = g_strdup(gtk_label_get_text(
1136 GTK_LABEL(viewer->description))+start);
1137 tmp[end-start] = '\0';
1140 return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->description)));
1143 else if (gtk_label_get_text(GTK_LABEL(viewer->summary))
1144 && *(gtk_label_get_text(GTK_LABEL(viewer->summary))) > 2)
1145 return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->summary)));
1151 static gboolean vcal_viewer_scroll_page(MimeViewer *_viewer, gboolean up)
1153 VCalViewer *viewer = (VCalViewer *)_viewer;
1154 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
1155 GTK_SCROLLED_WINDOW(viewer->scrolledwin));
1157 return gtkutils_scroll_page(viewer->table, vadj, up);
1160 static void vcal_viewer_scroll_one_line(MimeViewer *_viewer, gboolean up)
1162 VCalViewer *viewer = (VCalViewer *)_viewer;
1163 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
1164 GTK_SCROLLED_WINDOW(viewer->scrolledwin));
1166 gtkutils_scroll_one_line(viewer->table, vadj, up);
1169 MimeViewer *vcal_viewer_create(void)
1171 VCalViewer *vcalviewer;
1173 GtkWidget *hbox = NULL, *vbox = NULL;
1174 GtkWidget *warning_img;
1175 GtkWidget *warning_label;
1177 debug_print("Creating vcal view...\n");
1178 vcalviewer = g_new0(VCalViewer, 1);
1179 vcalviewer->mimeviewer.factory = &vcal_viewer_factory;
1181 vcalviewer->mimeviewer.get_widget = vcal_viewer_get_widget;
1182 vcalviewer->mimeviewer.show_mimepart = vcal_viewer_show_mimepart;
1183 vcalviewer->mimeviewer.clear_viewer = vcal_viewer_clear_viewer;
1184 vcalviewer->mimeviewer.destroy_viewer = vcal_viewer_destroy_viewer;
1185 vcalviewer->mimeviewer.get_selection = vcal_viewer_get_selection;
1186 vcalviewer->mimeviewer.scroll_page = vcal_viewer_scroll_page;
1187 vcalviewer->mimeviewer.scroll_one_line = vcal_viewer_scroll_one_line;
1189 vcalviewer->table = gtk_table_new(8, 2, FALSE);
1190 vcalviewer->type = gtk_label_new("meeting");
1191 vcalviewer->who = gtk_label_new("who");
1192 vcalviewer->start = gtk_label_new("start");
1193 vcalviewer->end = gtk_label_new("end");
1194 vcalviewer->location = gtk_label_new("location");
1195 vcalviewer->summary = gtk_label_new("summary");
1196 vcalviewer->description = gtk_label_new("description");
1197 vcalviewer->attendees = gtk_label_new("attendees");
1199 vcalviewer->answer = gtk_combo_box_text_new();
1200 vcalviewer->url = NULL;
1201 vcalviewer->button = gtk_button_new_with_label(_("Answer"));
1202 vcalviewer->reedit = gtk_button_new_with_label(_("Edit meeting..."));
1203 vcalviewer->cancel = gtk_button_new_with_label(_("Cancel meeting..."));
1204 vcalviewer->uribtn = gtk_button_new_with_label(_("Launch website"));
1205 vcalviewer->unavail_box = gtk_hbox_new(FALSE, 6);
1206 warning_img = gtk_image_new_from_stock
1207 (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
1208 warning_label = gtk_label_new(_("You are already busy at this time."));
1210 gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_img, FALSE, FALSE, 0);
1211 gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_label, FALSE, FALSE, 0);
1213 hbox = gtk_hbox_new(FALSE, 6);
1214 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->answer, FALSE, FALSE, 0);
1215 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->button, FALSE, FALSE, 0);
1216 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->reedit, FALSE, FALSE, 0);
1217 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->cancel, FALSE, FALSE, 0);
1218 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->uribtn, FALSE, FALSE, 0);
1220 vbox = gtk_vbox_new(FALSE, 6);
1221 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1222 gtk_box_pack_start(GTK_BOX(vbox), vcalviewer->unavail_box, FALSE, FALSE, 0);
1224 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REQUEST);
1226 gtk_label_set_selectable(GTK_LABEL(vcalviewer->type), TRUE);
1227 gtk_label_set_selectable(GTK_LABEL(vcalviewer->who), TRUE);
1228 gtk_label_set_selectable(GTK_LABEL(vcalviewer->start), TRUE);
1229 gtk_label_set_selectable(GTK_LABEL(vcalviewer->end), TRUE);
1230 gtk_label_set_selectable(GTK_LABEL(vcalviewer->location), TRUE);
1231 gtk_label_set_selectable(GTK_LABEL(vcalviewer->summary), TRUE);
1232 gtk_label_set_selectable(GTK_LABEL(vcalviewer->description), TRUE);
1233 gtk_label_set_selectable(GTK_LABEL(vcalviewer->attendees), TRUE);
1235 g_signal_connect(G_OBJECT(vcalviewer->button), "clicked",
1236 G_CALLBACK(vcalviewer_action_cb), vcalviewer);
1238 g_signal_connect(G_OBJECT(vcalviewer->reedit), "clicked",
1239 G_CALLBACK(vcalviewer_reedit_cb), vcalviewer);
1241 g_signal_connect(G_OBJECT(vcalviewer->cancel), "clicked",
1242 G_CALLBACK(vcalviewer_cancel_cb), vcalviewer);
1244 g_signal_connect(G_OBJECT(vcalviewer->uribtn), "clicked",
1245 G_CALLBACK(vcalviewer_uribtn_cb), vcalviewer);
1247 TABLE_ADD_LINE(_("Event:"), vcalviewer->type);
1248 TABLE_ADD_LINE(_("Organizer:"), vcalviewer->who);
1249 TABLE_ADD_LINE(_("Location:"), vcalviewer->location);
1250 TABLE_ADD_LINE(_("Summary:"), vcalviewer->summary);
1251 TABLE_ADD_LINE(_("Starting:"), vcalviewer->start);
1252 TABLE_ADD_LINE(_("Ending:"), vcalviewer->end);
1253 TABLE_ADD_LINE(_("Description:"), vcalviewer->description);
1254 TABLE_ADD_LINE(_("Attendees:"), vcalviewer->attendees);
1255 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
1256 TABLE_ADD_LINE(_("Action:"), vbox);
1258 vcalviewer->scrolledwin = gtk_scrolled_window_new(NULL, NULL);
1259 gtk_scrolled_window_add_with_viewport(
1260 GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
1262 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
1264 GTK_POLICY_AUTOMATIC);
1266 gtk_widget_show_all(vcalviewer->scrolledwin);
1267 return (MimeViewer *) vcalviewer;
1270 static gchar *content_types[] =
1271 {"text/calendar", NULL};
1273 MimeViewerFactory vcal_viewer_factory =
1280 static gint alert_timeout_tag = 0;
1281 static gint scan_timeout_tag = 0;
1283 static gboolean vcal_webcal_check(gpointer data)
1285 Folder *root = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
1287 if (prefs_common_get_prefs()->work_offline)
1290 manual_update = FALSE;
1291 folderview_check_new(root);
1292 manual_update = TRUE;
1296 static guint context_menu_id = 0;
1297 static guint main_menu_id = 0;
1299 void vcalendar_init(void)
1301 MainWindow *mainwin = mainwindow_get_mainwindow();
1302 Folder *folder = NULL;
1303 gchar *directory = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
1306 if (!is_dir_exist(directory) && make_dir (directory) != 0) {
1315 mimeview_register_viewer_factory(&vcal_viewer_factory);
1316 folder_register_class(vcal_folder_get_class());
1318 folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
1320 START_TIMING("creating folder");
1321 folder = folder_new(vcal_folder_get_class(), PLUGIN_NAME, NULL);
1322 folder->klass->create_tree(folder);
1324 folder_scan_tree(folder, TRUE);
1328 if (!folder->inbox) {
1329 folder->klass->create_tree(folder);
1330 folder_scan_tree(folder, TRUE);
1332 if (folder->klass->scan_required(folder, folder->inbox)) {
1333 START_TIMING("scanning folder");
1334 folder_item_scan(folder->inbox);
1338 vcal_folder_gtk_init();
1340 alert_timeout_tag = g_timeout_add(60*1000,
1341 (GSourceFunc)vcal_meeting_alert_check,
1343 scan_timeout_tag = g_timeout_add(3600*1000,
1344 (GSourceFunc)vcal_webcal_check,
1346 if (prefs_common_get_prefs()->enable_color) {
1347 gtkut_convert_int_to_gdk_color(prefs_common_get_prefs()->color[COL_URI],
1351 gtk_action_group_add_actions(mainwin->action_group, vcalendar_main_menu,
1352 1, (gpointer)mainwin);
1353 MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/Message", "CreateMeeting",
1354 "Message/CreateMeeting", GTK_UI_MANAGER_MENUITEM,
1356 MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menus/SummaryViewPopup", "CreateMeeting",
1357 "Message/CreateMeeting", GTK_UI_MANAGER_MENUITEM,
1362 void vcalendar_done(void)
1364 MainWindow *mainwin = mainwindow_get_mainwindow();
1365 FolderView *folderview = NULL;
1366 FolderItem *fitem = NULL;
1368 icalmemory_free_ring();
1370 vcal_folder_free_data();
1372 if (mainwin == NULL)
1375 folderview = mainwin->folderview;
1376 fitem = folderview->summaryview->folder_item;
1379 fitem->folder->klass == vcal_folder_get_class()) {
1380 folderview_unselect(folderview);
1381 summary_clear_all(folderview->summaryview);
1382 if (fitem->folder->klass->item_closed)
1383 fitem->folder->klass->item_closed(fitem);
1386 mimeview_unregister_viewer_factory(&vcal_viewer_factory);
1387 folder_unregister_class(vcal_folder_get_class());
1388 vcal_folder_gtk_done();
1390 g_source_remove(alert_timeout_tag);
1391 alert_timeout_tag = 0;
1392 g_source_remove(scan_timeout_tag);
1393 scan_timeout_tag = 0;
1395 MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/CreateMeeting", main_menu_id);
1397 MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/CreateMeeting", context_menu_id);
1398 context_menu_id = 0;