1 /*
2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2018 Colin Leroy and the Claws Mail team
4 *
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.
9 *
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.
14 *
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.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #include "claws-features.h"
23 #endif
24
25 #include <stddef.h>
26 #include <glib.h>
27 #include <glib/gi18n.h>
28
29 #include <libical/ical.h>
30 #include <gtk/gtk.h>
31
32 #if USE_PTHREAD
33 #include "pthread.h"
34 #endif
35
36 #include "folder.h"
37 #include "folder_item_prefs.h"
38 #include "mimeview.h"
39 #include "file-utils.h"
40 #include "utils.h"
41 #include "vcalendar.h"
42 #include "vcal_manager.h"
43 #include "vcal_folder.h"
44 #include "vcal_meeting_gtk.h"
45 #include "vcal_interface.h"
46 #include "prefs_account.h"
47 #include "prefs_common.h"
48 #include "menu.h"
49 #include "account.h"
50 #include "codeconv.h"
51 #include "xml.h"
52 #include "xmlprops.h"
53 #include "alertpanel.h"
54 #include "vcal_prefs.h"
55 #include "statusbar.h"
56 #include "timing.h"
57 #include "inc.h"
58
59 MimeViewerFactory vcal_viewer_factory;
60
61 static void create_meeting_from_message_cb_ui(GtkAction *action, gpointer data);
62
63 static GdkColor uri_color = {
64 (gulong)0,
65 (gushort)0,
66 (gushort)0,
67 (gushort)0
68 };
69
70 struct _VCalViewer
71 {
72 MimeViewer mimeviewer;
73
74 gchar *file;
75 MimeInfo *mimeinfo;
76 gchar *tmpfile;
77 VCalEvent *event;
78
79 GtkWidget *scrolledwin;
80 GtkWidget *table;
81 GtkWidget *type;
82 GtkWidget *who;
83 GtkWidget *start;
84 GtkWidget *end;
85 GtkWidget *location;
86 GtkWidget *summary;
87 GtkWidget *description;
88 gchar *url;
89 GtkWidget *answer;
90 GtkWidget *button;
91 GtkWidget *reedit;
92 GtkWidget *cancel;
93 GtkWidget *uribtn;
94 GtkWidget *attendees;
95 GtkWidget *unavail_box;
96 };
97
98 static GtkActionEntry vcalendar_main_menu[] = {{
99 "Message/CreateMeeting",
100 NULL, N_("Create meeting from message..."), NULL, NULL, G_CALLBACK(create_meeting_from_message_cb_ui)
101 }};
102
create_meeting_from_message_cb_ui(GtkAction * action,gpointer data)103 static void create_meeting_from_message_cb_ui(GtkAction *action, gpointer data)
104 {
105 MainWindow *mainwin = mainwindow_get_mainwindow();
106 SummaryView *summaryview = mainwin->summaryview;
107 GSList *msglist = summary_get_selected_msg_list(summaryview);
108 FolderItem *item = NULL;
109 GSList *cur;
110 gchar *msg;
111 gint total=0;
112
113 if (summary_is_locked(summaryview) || !msglist) {
114 if (msglist)
115 g_slist_free(msglist);
116 return;
117 }
118 total = g_slist_length(msglist);
119
120 msg = g_strdup_printf(_("You are about to create %d "
121 "meetings, one by one. Do you "
122 "want to continue?"),
123 total);
124 if (total > 9
125 && alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, GTK_STOCK_YES, NULL,
126 ALERTFOCUS_SECOND)
127 != G_ALERTALTERNATE) {
128 g_free(msg);
129 return;
130 }
131 g_free(msg);
132
133 main_window_cursor_wait(summaryview->mainwin);
134 gtk_cmclist_freeze(GTK_CMCLIST(summaryview->ctree));
135 folder_item_update_freeze();
136 inc_lock();
137
138 item = summaryview->folder_item;
139
140 STATUSBAR_PUSH(mainwin, _("Creating meeting..."));
141
142 for (cur = msglist; cur; cur = cur->next) {
143 MsgInfo *msginfo = procmsg_msginfo_get_full_info((MsgInfo *)cur->data);
144 VCalEvent *event = NULL;
145 FILE *fp = NULL;
146
147 if (MSG_IS_ENCRYPTED(msginfo->flags)) {
148 fp = procmime_get_first_encrypted_text_content(msginfo);
149 } else {
150 fp = procmime_get_first_text_content(msginfo);
151 }
152
153 if (fp) {
154 gchar *uid;
155 time_t t = time(NULL);
156 time_t t2 = t+3600;
157 gchar *org = NULL;
158 gchar *orgname = NULL;
159 gchar *summary = g_strdup(msginfo->subject ? msginfo->subject:_("no subject"));
160 gchar *description = file_read_stream_to_str(fp);
161 gchar *dtstart = g_strdup(icaltime_as_ical_string(icaltime_from_timet_with_zone(t, FALSE, NULL)));
162 gchar *dtend = g_strdup(icaltime_as_ical_string(icaltime_from_timet_with_zone(t2, FALSE, NULL)));
163 gchar *recur = NULL;
164 gchar *tzid = g_strdup("UTC");
165 gchar *url = NULL;
166 gint method = ICAL_METHOD_REQUEST;
167 gint sequence = 1;
168 PrefsAccount *account = NULL;
169
170 claws_fclose(fp);
171
172 if (item && item->prefs && item->prefs->enable_default_account)
173 account = account_find_from_id(item->prefs->default_account);
174
175 if (!account)
176 account = account_get_cur_account();
177
178 if (!account)
179 goto bail;
180
181 org = g_strdup(account->address);
182
183 uid = prefs_account_generate_msgid(account);
184
185 event = vcal_manager_new_event(uid,
186 org, NULL, NULL/*location*/, summary, description,
187 dtstart, dtend, recur, tzid, url, method, sequence,
188 ICAL_VTODO_COMPONENT);
189 g_free(uid);
190
191 /* hack to get default hours */
192 g_free(event->dtstart);
193 g_free(event->dtend);
194 event->dtstart = NULL;
195 event->dtend = NULL;
196
197 vcal_meeting_create(event);
198 vcal_manager_free_event(event);
199
200 bail:
201 g_free(org);
202 g_free(orgname);
203 g_free(summary);
204 g_free(description);
205 g_free(dtstart);
206 g_free(dtend);
207 g_free(recur);
208 g_free(tzid);
209 g_free(url);
210 }
211
212 procmsg_msginfo_free(&msginfo);
213 }
214
215 statusbar_progress_all(0,0,0);
216 STATUSBAR_POP(mainwin);
217 inc_unlock();
218 folder_item_update_thaw();
219 gtk_cmclist_thaw(GTK_CMCLIST(summaryview->ctree));
220 main_window_cursor_normal(summaryview->mainwin);
221 g_slist_free(msglist);
222 }
223
get_tmpfile(VCalViewer * vcalviewer)224 static gchar *get_tmpfile(VCalViewer *vcalviewer)
225 {
226 gchar *tmpfile = NULL;
227
228 if (!vcalviewer->tmpfile) {
229 tmpfile = procmime_get_tmp_file_name(vcalviewer->mimeinfo);
230 debug_print("creating %s\n", tmpfile);
231
232 if (procmime_get_part(tmpfile, vcalviewer->mimeinfo) < 0) {
233 g_warning("Can't get mimepart file");
234 g_free(tmpfile);
235 return NULL;
236 }
237 vcalviewer->tmpfile = tmpfile;
238 }
239
240 return vcalviewer->tmpfile;
241 }
242
vcal_viewer_get_widget(MimeViewer * _mimeviewer)243 static GtkWidget *vcal_viewer_get_widget(MimeViewer *_mimeviewer)
244 {
245 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
246
247 debug_print("vcal_viewer_get_widget\n");
248 gtk_widget_show_all(vcalviewer->scrolledwin);
249 return vcalviewer->scrolledwin;
250 }
251
vcal_viewer_clear_viewer(MimeViewer * _mimeviewer)252 static void vcal_viewer_clear_viewer(MimeViewer *_mimeviewer)
253 {
254 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
255
256 debug_print("vcal_viewer_clear_viewer\n");
257
258 g_free(vcalviewer->file);
259 vcalviewer->file = NULL;
260 if (vcalviewer->tmpfile) {
261 debug_print("unlinking %s\n", vcalviewer->tmpfile);
262 g_unlink(vcalviewer->tmpfile);
263 g_free(vcalviewer->tmpfile);
264 vcalviewer->tmpfile = NULL;
265 }
266 vcalviewer->mimeinfo = NULL;
267 }
268
vcalviewer_get_component(const gchar * file,const gchar * charset)269 static VCalEvent *vcalviewer_get_component(const gchar *file, const gchar *charset)
270 {
271 gchar *compstr = NULL;
272 VCalEvent *event = NULL;
273 FILE *fp;
274 GByteArray *array;
275 gchar buf[BUFSIZ];
276 gint n_read;
277
278 g_return_val_if_fail(file != NULL, NULL);
279
280 if ((fp = claws_fopen(file, "rb")) == NULL) {
281 FILE_OP_ERROR(file, "claws_fopen");
282 return NULL;
283 }
284
285 array = g_byte_array_new();
286
287 while ((n_read = claws_fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
288 if (n_read < sizeof(buf) && claws_ferror(fp))
289 break;
290 g_byte_array_append(array, (guchar *)buf, n_read);
291 }
292
293 if (claws_ferror(fp)) {
294 FILE_OP_ERROR("file stream", "claws_fread");
295 g_byte_array_free(array, TRUE);
296 claws_fclose(fp);
297 return NULL;
298 }
299
300 buf[0] = '\0';
301 g_byte_array_append(array, (guchar *)buf, 1);
302 compstr = (gchar *)array->data;
303 g_byte_array_free(array, FALSE);
304
305 claws_fclose(fp);
306
307 if (compstr) {
308 event = vcal_get_event_from_ical(compstr, charset);
309 g_free(compstr);
310 }
311
312 return event;
313 }
314
315 #define GTK_LABEL_SET_TEXT_TRIMMED(label, text) { \
316 gchar *tmplbl = strretchomp(g_strdup(text)); \
317 gtk_label_set_text(label, tmplbl); \
318 g_free(tmplbl); \
319 }
320
321 static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, icalproperty_method method);
322
vcalviewer_reset(VCalViewer * vcalviewer)323 static void vcalviewer_reset(VCalViewer *vcalviewer)
324 {
325 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
326 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
327 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), "-");
328 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
329 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
330 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
331 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
332 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
333 g_free(vcalviewer->url);
334 vcalviewer->url = NULL;
335 gtk_widget_hide(vcalviewer->uribtn);
336 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_CANCEL);
337 }
338
vcalviewer_show_error(VCalViewer * vcalviewer,const gchar * msg)339 static void vcalviewer_show_error(VCalViewer *vcalviewer, const gchar *msg)
340 {
341 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), msg);
342 }
343
vcalviewer_hide_error(VCalViewer * vcalviewer)344 static void vcalviewer_hide_error(VCalViewer *vcalviewer)
345 {
346 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
347 }
348
vcalviewer_show_unavailable(VCalViewer * vcalviewer,gboolean visi)349 static void vcalviewer_show_unavailable(VCalViewer *vcalviewer, gboolean visi)
350 {
351 if (visi)
352 gtk_widget_show_all(vcalviewer->unavail_box);
353 else
354 gtk_widget_hide(vcalviewer->unavail_box);
355 }
356
vcalviewer_answer_set_choices(VCalViewer * vcalviewer,VCalEvent * event,icalproperty_method method)357 static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, icalproperty_method method)
358 {
359 int i = 0;
360
361 gtk_widget_hide(vcalviewer->reedit);
362 gtk_widget_hide(vcalviewer->cancel);
363 gtk_widget_hide(vcalviewer->answer);
364 gtk_widget_hide(vcalviewer->button);
365
366 for (i = 0; i < 3; i++)
367 gtk_combo_box_text_remove(GTK_COMBO_BOX_TEXT(vcalviewer->answer), 0);
368
369 vcalviewer_show_unavailable(vcalviewer, FALSE);
370
371 if (method == ICAL_METHOD_REQUEST && event && !event->rec_occurrence) {
372 PrefsAccount *account = vcal_manager_get_account_from_event(event);
373
374 if (!account)
375 account = vcal_manager_get_account_from_event(vcalviewer->event);
376
377 if (!account && event) {
378 account = account_get_default();
379 vcal_manager_update_answer(event, account->address,
380 account->name,
381 ICAL_PARTSTAT_NEEDSACTION,
382 ICAL_CUTYPE_INDIVIDUAL);
383 }
384 if (account) {
385 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Accept"));
386 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Tentatively accept"));
387 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), _("Decline"));
388 gtk_widget_set_sensitive(vcalviewer->answer, TRUE);
389 gtk_widget_set_sensitive(vcalviewer->button, TRUE);
390 gtk_widget_show(vcalviewer->answer);
391 gtk_widget_show(vcalviewer->button);
392 } else {
393 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), "-");
394 gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
395 gtk_widget_set_sensitive(vcalviewer->button, FALSE);
396 }
397 } else {
398 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(vcalviewer->answer), "-");
399 gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
400 gtk_widget_set_sensitive(vcalviewer->button, FALSE);
401 }
402 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
403
404 if (event && event->method == ICAL_METHOD_REQUEST) {
405 PrefsAccount *account = vcal_manager_get_account_from_event(event);
406 gchar *internal_ifb = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
407 "vcalendar", G_DIR_SEPARATOR_S,
408 "internal.ifb", NULL);
409 gchar *myfb = file_read_to_str(internal_ifb);
410 g_free(internal_ifb);
411 if (account) {
412 icalparameter_partstat answer =
413 vcal_manager_get_reply_for_attendee(event, account->address);
414
415 if (answer == ICAL_PARTSTAT_ACCEPTED)
416 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
417 if (answer == ICAL_PARTSTAT_TENTATIVE)
418 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 1);
419 if (answer == ICAL_PARTSTAT_DECLINED)
420 gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 2);
421 if (event->dtstart && event->dtend && myfb && *myfb
422 && answer != ICAL_PARTSTAT_ACCEPTED
423 && answer != ICAL_PARTSTAT_TENTATIVE) {
424 if (!attendee_available(NULL, event->dtstart, event->dtend, myfb))
425 vcalviewer_show_unavailable(vcalviewer, TRUE);
426 }
427 }
428 g_free(myfb);
429 }
430
431 g_free(vcalviewer->url);
432 if (event && event->url && *(event->url)) {
433 vcalviewer->url = g_strdup(event->url);
434 gtk_widget_show(vcalviewer->uribtn);
435 } else {
436 vcalviewer->url = NULL;
437 gtk_widget_hide(vcalviewer->uribtn);
438 }
439 }
440
vcalendar_get_current_item(void)441 static FolderItem *vcalendar_get_current_item(void)
442 {
443 MainWindow *mainwin = mainwindow_get_mainwindow();
444 FolderItem *item = NULL;
445 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
446
447 if (mainwin) {
448 item = mainwin->summaryview->folder_item;
449 if (item == NULL)
450 return NULL;
451 if (item->folder == folder)
452 return item;
453 else
454 return folder->inbox;
455 } else {
456 return NULL;
457 }
458 }
459
vcalviewer_display_event(VCalViewer * vcalviewer,VCalEvent * event)460 void vcalviewer_display_event (VCalViewer *vcalviewer, VCalEvent *event)
461 {
462 GSList *list = NULL;
463 gchar *attendees = NULL;
464 gboolean mine = FALSE;
465 gchar *label = NULL;
466 gboolean save_evt = FALSE;
467 FolderItem *item = vcalendar_get_current_item();
468 if (!event)
469 return;
470 if (!vcalviewer)
471 return;
472
473 /* general */
474 if (event->type == ICAL_VTODO_COMPONENT) {
475
476 label = g_strjoin(" ", _("You have a Todo item."),
477 _("Details follow:"), NULL);
478 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
479
480 } else if (event->method == ICAL_METHOD_REQUEST) {
481
482 if (account_find_from_address(event->organizer, FALSE)) {
483 label = g_strjoin(" ", _("You have created a meeting."),
484 _("Details follow:"), NULL);
485 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
486 mine = TRUE;
487 } else {
488 label = g_strjoin(" ", _("You have been invited to a meeting."),
489 _("Details follow:"), NULL);
490 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
491 }
492
493 } else if (event->method == ICAL_METHOD_CANCEL) {
494
495 label = g_strjoin(" ",
496 _("A meeting to which you had been invited has been cancelled."),
497 _("Details follow:"), NULL);
498 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
499 save_evt = TRUE;
500 vcalendar_refresh_folder_contents(item);
501 } else if (event->method == ICAL_METHOD_REPLY) {
502 /* don't change label */
503 } else {
504
505 label = g_strjoin(" ", _("You have been forwarded an appointment."),
506 _("Details follow:"), NULL);
507 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
508 }
509
510 g_free(label);
511
512 /* organizer */
513 if (event->orgname && *(event->orgname)
514 && event->organizer && *(event->organizer)) {
515 gchar *addr = g_strconcat(event->orgname, " <", event->organizer, ">", NULL);
516 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
517 g_free(addr);
518 } else if (event->organizer && *(event->organizer)) {
519 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), event->organizer);
520 } else {
521 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
522 }
523
524 /* location */
525 if (event->location && *(event->location)) {
526 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), event->location);
527 } else {
528 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location), "-");
529 }
530
531 /* summary */
532 if (event->summary && *(event->summary)) {
533 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), event->summary);
534 } else {
535 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
536 }
537
538 /* description */
539 if (event->description && *(event->description)) {
540 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), event->description);
541 } else {
542 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
543 }
544
545 /* url */
546 g_free(vcalviewer->url);
547 if (event->url && *(event->url)) {
548 vcalviewer->url = g_strdup(event->url);
549 gtk_widget_show(vcalviewer->uribtn);
550 } else {
551 vcalviewer->url = NULL;
552 gtk_widget_hide(vcalviewer->uribtn);
553 }
554
555 /* start */
556 if (event->start && *(event->start)) {
557 if (event->recur && *(event->recur)) {
558 gchar *tmp = g_strdup_printf(g_strconcat("%s <span weight=\"bold\">",
559 _("(this event recurs)"),"</span>", NULL),
560 event->start);
561 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
562 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
563 g_free(tmp);
564 } else if (event->rec_occurrence) {
565 gchar *tmp = g_strdup_printf(g_strconcat("%s <span weight=\"bold\">",
566 _("(this event is part of a recurring event)"),
567 "</span>", NULL),
568 event->start);
569 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
570 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
571 g_free(tmp);
572 } else {
573 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), event->start);
574 }
575 } else {
576 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
577 }
578
579 /* end */
580 if (event->end && *(event->end)) {
581 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), event->end);
582 } else {
583 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
584 }
585
586 /* attendees */
587 attendees = g_strdup("");
588 for (list = vcal_manager_get_answers_emails(event);
589 list && list->data; list = list->next) {
590 gchar *attendee = (gchar *)list->data;
591 gchar *name = vcal_manager_get_attendee_name(event, attendee);
592 gchar *ename = g_markup_printf_escaped("%s", name?name:"");
593 gchar *eatt = g_markup_printf_escaped("%s", attendee);
594 icalparameter_partstat acode = vcal_manager_get_reply_for_attendee(event, attendee);
595 gchar *answer = vcal_manager_get_reply_text_for_attendee(event, attendee);
596 gchar *type = vcal_manager_get_cutype_text_for_attendee(event, attendee);
597 gchar *tmp = NULL;
598 gint e_len, n_len;
599 tmp = g_strdup_printf(
600 "%s%s<%s> (%s, <span%s>%s</span>)",
601 (ename && *(ename))?ename:"",
602 (ename && *(ename))?" ":"",
603 (eatt && *(eatt))?eatt:"",
604 (type && *(type))?type:"",
605 (acode != ICAL_PARTSTAT_ACCEPTED ? " foreground=\"red\"":""),
606 (answer && *(answer))?answer:"");
607 e_len = strlen(attendees);
608 n_len = strlen(tmp);
609 if (e_len) {
610 attendees = g_realloc(attendees, e_len+n_len+2);
611 *(attendees+e_len) = '\n';
612 strcpy(attendees+e_len+1, tmp);
613 } else {
614 attendees = g_realloc(attendees, e_len+n_len+1);
615 strcpy(attendees, tmp);
616 }
617 g_free(tmp);
618 g_free(answer);
619 g_free(type);
620 g_free(name);
621 g_free(ename);
622 g_free(eatt);
623 }
624
625 if (attendees && *(attendees)) {
626 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), attendees);
627 } else {
628 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
629 }
630 g_free(attendees);
631 gtk_label_set_use_markup(GTK_LABEL(vcalviewer->attendees), TRUE);
632
633 /* buttons */
634 if (!mine)
635 if (event->type != ICAL_VTODO_COMPONENT)
636 vcalviewer_answer_set_choices(vcalviewer, event, event->method);
637 else
638 vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_PUBLISH);
639 else {
640 vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_REPLY);
641 gtk_widget_show(vcalviewer->reedit);
642 gtk_widget_show(vcalviewer->cancel);
643 }
644
645 /* save if cancelled */
646 if (save_evt)
647 vcal_manager_save_event(event, TRUE);
648 }
649
vcalviewer_get_uid_from_mimeinfo(MimeInfo * mimeinfo)650 gchar *vcalviewer_get_uid_from_mimeinfo(MimeInfo *mimeinfo)
651 {
652 gchar *compstr = NULL;
653 gchar *res = NULL;
654 VCalEvent *event = NULL;
655
656 compstr = procmime_get_part_as_string(mimeinfo, TRUE);
657
658 event = vcal_get_event_from_ical(compstr, NULL);
659 if (event)
660 res = g_strdup(event->uid);
661
662 vcal_manager_free_event(event);
663
664 debug_print("got uid: %s\n", res);
665 return res;
666
667 }
668
vcalviewer_get_request_values(VCalViewer * vcalviewer,MimeInfo * mimeinfo,gboolean is_todo)669 static void vcalviewer_get_request_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo, gboolean is_todo)
670 {
671 VCalEvent *saved_event = NULL;
672 const gchar *saveme = procmime_mimeinfo_get_parameter(mimeinfo, "vcalsave");
673
674 if (!vcalviewer->event)
675 return;
676
677 /* see if we have it registered and more recent */
678 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
679 if (saved_event && saved_event->sequence >= vcalviewer->event->sequence) {
680 saved_event->method = vcalviewer->event->method;
681 vcalviewer_display_event(vcalviewer, saved_event);
682 vcal_manager_free_event(saved_event);
683 return;
684 } else if (saved_event) {
685 vcal_manager_free_event(saved_event);
686 }
687
688 /* load it and register it */
689
690 if (!saveme || strcmp(saveme,"no"))
691 vcal_manager_save_event(vcalviewer->event, FALSE);
692
693 vcalviewer_display_event(vcalviewer, vcalviewer->event);
694 }
695
vcalviewer_get_reply_values(VCalViewer * vcalviewer,MimeInfo * mimeinfo)696 static void vcalviewer_get_reply_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
697 {
698 VCalEvent *saved_event = NULL;
699 gchar *attendee = NULL, *label = NULL;
700 Answer *answer = NULL;
701
702 if (!vcalviewer->event)
703 return;
704
705 if (!vcalviewer->event->answers || g_slist_length(vcalviewer->event->answers) > 1) {
706 g_warning("strange, no answers or more than one");
707 }
708
709 if (vcalviewer->event->answers) {
710 answer = (Answer *)vcalviewer->event->answers->data;
711 attendee = g_strdup(answer->attendee);
712 }
713
714
715 if (!answer) {
716 label = g_strjoin(" ",
717 _("You have received an answer to an unknown meeting proposal."),
718 _("Details follow:"), NULL);
719 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
720 } else {
721 label = g_strdup_printf(_("You have received an answer to a meeting proposal.\n"
722 "%s has %s the invitation whose details follow:"),
723 attendee, vcal_manager_answer_get_text(answer->answer));
724 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
725 g_free(attendee);
726 }
727 g_free(label);
728
729 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
730 if (saved_event && answer) {
731 vcal_manager_update_answer(saved_event,
732 answer->attendee, answer->name, answer->answer, answer->cutype);
733 vcal_manager_save_event(saved_event, TRUE);
734 saved_event->method = vcalviewer->event->method;
735 vcalviewer_display_event(vcalviewer, saved_event);
736 vcal_manager_free_event(saved_event);
737 return;
738 }
739
740 if (vcalviewer->event->organizer) {
741 if (vcalviewer->event->orgname) {
742 gchar *addr = g_strconcat(vcalviewer->event->orgname, " <",
743 vcalviewer->event->organizer, ">", NULL);
744 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
745 g_free(addr);
746 } else {
747 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who),
748 vcalviewer->event->organizer);
749 }
750 } else {
751 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
752 }
753
754 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->location),
755 vcalviewer->event->location?vcalviewer->event->location:"-");
756
757 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary),
758 vcalviewer->event->summary?vcalviewer->event->summary:"-");
759
760 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description),
761 vcalviewer->event->description?vcalviewer->event->description:"-");
762
763 g_free(vcalviewer->url);
764 if (vcalviewer->event->url) {
765 vcalviewer->url = g_strdup(vcalviewer->event->url);
766 gtk_widget_show(vcalviewer->uribtn);
767 } else {
768 vcalviewer->url = NULL;
769 gtk_widget_hide(vcalviewer->uribtn);
770 }
771
772 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start),
773 vcalviewer->event->start?vcalviewer->event->start:"-");
774 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end),
775 vcalviewer->event->end?vcalviewer->event->end:"-");
776
777 GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
778
779 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REPLY);
780 }
781
vcalviewer_get_event(VCalViewer * vcalviewer,MimeInfo * mimeinfo)782 static void vcalviewer_get_event(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
783 {
784 gchar *tmpfile = get_tmpfile(vcalviewer);
785 const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
786
787 if (!charset)
788 charset = CS_WINDOWS_1252;
789
790 if (!strcasecmp(charset, CS_ISO_8859_1))
791 charset = CS_WINDOWS_1252;
792
793 if (vcalviewer->event) {
794 vcal_manager_free_event(vcalviewer->event);
795 vcalviewer->event = NULL;
796 }
797
798 if (!tmpfile) {
799 vcalviewer_reset(vcalviewer);
800 vcalviewer_show_error(vcalviewer, _("Error - could not get the calendar MIME part."));
801 return;
802 }
803
804 vcalviewer->event = vcalviewer_get_component(tmpfile, charset);
805 if (!vcalviewer->event) {
806 vcalviewer_reset(vcalviewer);
807 vcalviewer_show_error(vcalviewer, _("Error - no calendar part found."));
808 return;
809 }
810
811 if (vcalviewer->event->type == ICAL_VTODO_COMPONENT) {
812 vcalviewer_get_request_values(vcalviewer, mimeinfo, TRUE);
813 } else if (vcalviewer->event->method == ICAL_METHOD_REQUEST ||
814 vcalviewer->event->method == ICAL_METHOD_PUBLISH ||
815 vcalviewer->event->method == ICAL_METHOD_CANCEL) {
816 vcalviewer_get_request_values(vcalviewer, mimeinfo, FALSE);
817 } else if (vcalviewer->event->method == ICAL_METHOD_REPLY) {
818 vcalviewer_get_reply_values(vcalviewer, mimeinfo);
819 } else {
820 vcalviewer_reset(vcalviewer);
821 vcalviewer_show_error(vcalviewer, _("Error - Unknown calendar component type."));
822 }
823 }
824
825 static VCalViewer *s_vcalviewer = NULL;
826
vcal_viewer_show_mimepart(MimeViewer * _mimeviewer,const gchar * file,MimeInfo * mimeinfo)827 static void vcal_viewer_show_mimepart(MimeViewer *_mimeviewer, const gchar *file, MimeInfo *mimeinfo)
828 {
829 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
830 GtkAllocation allocation;
831
832 START_TIMING("");
833
834 s_vcalviewer = vcalviewer;
835
836 if (mimeinfo == NULL) {
837 vcal_viewer_clear_viewer(_mimeviewer);
838 END_TIMING();
839 return;
840 }
841 debug_print("vcal_viewer_show_mimepart : %s\n", file);
842
843 vcal_viewer_clear_viewer(_mimeviewer);
844 gtk_widget_show_all(vcalviewer->scrolledwin);
845 g_free(vcalviewer->file);
846 vcalviewer->file = g_strdup(file);
847 vcalviewer->mimeinfo = mimeinfo;
848 vcalviewer_hide_error(vcalviewer);
849 vcalviewer_get_event(vcalviewer, mimeinfo);
850 GTK_EVENTS_FLUSH();
851 gtk_widget_get_allocation(vcalviewer->scrolledwin, &allocation);
852 gtk_widget_set_size_request(vcalviewer->description,
853 allocation.width - 200, -1);
854 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->location), TRUE);
855 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->summary), TRUE);
856 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->description), TRUE);
857 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
858
859 if (prefs_common_get_prefs()->textfont) {
860 PangoFontDescription *font_desc;
861
862 font_desc = pango_font_description_from_string
863 (prefs_common_get_prefs()->textfont);
864 if (font_desc) {
865 gtk_widget_modify_font(
866 vcalviewer->description, font_desc);
867 pango_font_description_free(font_desc);
868 }
869 }
870 END_TIMING();
871 }
872
vcalviewer_reload(FolderItem * item)873 void vcalviewer_reload(FolderItem *item)
874 {
875 if (s_vcalviewer) {
876 MainWindow *mainwin = mainwindow_get_mainwindow();
877 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
878
879 folder_item_scan(item);
880 if (mainwin && mainwin->summaryview->folder_item) {
881 FolderItem *cur = mainwin->summaryview->folder_item;
882 if (cur->folder == folder)
883 folder_item_scan(cur);
884 }
885 if (mainwin && mainwin->summaryview->folder_item == item) {
886 debug_print("reload: %p, %p\n", (MimeViewer *)s_vcalviewer, s_vcalviewer->mimeinfo);
887 summary_redisplay_msg(mainwin->summaryview);
888 }
889 }
890 }
891
vcal_viewer_destroy_viewer(MimeViewer * _mimeviewer)892 static void vcal_viewer_destroy_viewer(MimeViewer *_mimeviewer)
893 {
894 VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
895
896 debug_print("vcal_viewer_destroy_viewer\n");
897
898 if (s_vcalviewer == vcalviewer)
899 s_vcalviewer = NULL;
900 vcal_viewer_clear_viewer(_mimeviewer);
901 g_free(vcalviewer);
902 }
903
vcalviewer_reedit_cb(GtkButton * widget,gpointer data)904 static gboolean vcalviewer_reedit_cb(GtkButton *widget, gpointer data)
905 {
906 VCalViewer *vcalviewer = (VCalViewer *)data;
907 gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
908 VCalEvent *event = NULL;
909
910 s_vcalviewer = vcalviewer;
911 /* see if we have it registered and more recent */
912 event = vcal_manager_load_event(uid);
913 vcal_meeting_create(event);
914 vcal_manager_free_event(event);
915 return TRUE;
916 }
917
vcalviewer_uribtn_cb(GtkButton * widget,gpointer data)918 static gboolean vcalviewer_uribtn_cb(GtkButton *widget, gpointer data)
919 {
920 VCalViewer *vcalviewer = (VCalViewer *)data;
921
922 if (vcalviewer->url)
923 open_uri(vcalviewer->url, prefs_common_get_uri_cmd());
924
925 return TRUE;
926 }
927
vcalendar_refresh_folder_contents(FolderItem * item)928 void vcalendar_refresh_folder_contents(FolderItem *item)
929 {
930 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
931 if (folder && item->folder == folder) {
932 MainWindow *mainwin = mainwindow_get_mainwindow();
933 folder_item_scan(item);
934 if (mainwin->summaryview->folder_item == item) {
935 summary_show(mainwin->summaryview, item, FALSE);
936 }
937 }
938 }
939
send_cancel_notify_toggled_cb(GtkToggleButton * button,gboolean * data)940 static void send_cancel_notify_toggled_cb(GtkToggleButton *button, gboolean *data)
941 {
942 *data = gtk_toggle_button_get_active(button);
943 }
944
vcalendar_cancel_meeting(FolderItem * item,const gchar * uid)945 void vcalendar_cancel_meeting(FolderItem *item, const gchar *uid)
946 {
947 VCalEvent *event = NULL;
948 VCalMeeting *meet = NULL;
949 gchar *file = NULL;
950 gint val = 0;
951 Folder *folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
952 gboolean redisp = FALSE;
953 GtkWidget *send_notify_chkbtn = gtk_check_button_new_with_label(_("Send a notification to the attendees"));
954 gboolean send_notify = TRUE;
955
956 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(send_notify_chkbtn), TRUE);
957 gtk_widget_show(send_notify_chkbtn);
958 g_signal_connect(G_OBJECT(send_notify_chkbtn), "toggled",
959 G_CALLBACK(send_cancel_notify_toggled_cb),
960 &send_notify);
961
962 val = alertpanel_full(_("Cancel meeting"),
963 _("Are you sure you want to cancel this meeting?"),
964 GTK_STOCK_NO, GTK_STOCK_YES, NULL, ALERTFOCUS_FIRST, FALSE,
965 send_notify_chkbtn, ALERT_WARNING);
966
967 if (val != G_ALERTALTERNATE)
968 return;
969
970 event = vcal_manager_load_event(uid);
971 if (!event)
972 return;
973 event->method = ICAL_METHOD_CANCEL;
974
975 if (folder) {
976 MainWindow *mainwin = mainwindow_get_mainwindow();
977 if (mainwin->summaryview->folder_item == item) {
978 redisp = TRUE;
979 summary_show(mainwin->summaryview, NULL, FALSE);
980 }
981 }
982
983 if (send_notify) {
984 meet = vcal_meeting_create_hidden(event);
985 if (!vcal_meeting_send(meet)) {
986 event->method = ICAL_METHOD_REQUEST;
987 vcal_manager_save_event(event, TRUE);
988 vcal_manager_free_event(event);
989 if (folder)
990 folder_item_scan(item);
991
992 if (folder && redisp) {
993 MainWindow *mainwin = mainwindow_get_mainwindow();
994 summary_show(mainwin->summaryview, item, FALSE);
995 }
996 return;
997 }
998 }
999
1000 vcal_manager_save_event(event, TRUE);
1001
1002 file = vcal_manager_get_event_file(event->uid);
1003 g_unlink(file);
1004 vcal_manager_free_event(event);
1005 g_free(file);
1006 if (folder)
1007 folder_item_scan(item);
1008 if (folder && redisp) {
1009 MainWindow *mainwin = mainwindow_get_mainwindow();
1010 summary_show(mainwin->summaryview, item, FALSE);
1011 }
1012
1013 return;
1014 }
1015
vcalviewer_cancel_cb(GtkButton * widget,gpointer data)1016 static gboolean vcalviewer_cancel_cb(GtkButton *widget, gpointer data)
1017 {
1018 VCalViewer *vcalviewer = (VCalViewer *)data;
1019 FolderItem *item = vcalendar_get_current_item();
1020 gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
1021 vcalendar_cancel_meeting(item, uid);
1022 return TRUE;
1023 }
1024
vcalviewer_action_cb(GtkButton * widget,gpointer data)1025 static gboolean vcalviewer_action_cb(GtkButton *widget, gpointer data)
1026 {
1027 VCalViewer *vcalviewer = (VCalViewer *)data;
1028 gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(vcalviewer->answer));
1029 icalparameter_partstat reply[3] = {ICAL_PARTSTAT_ACCEPTED, ICAL_PARTSTAT_TENTATIVE, ICAL_PARTSTAT_DECLINED};
1030 PrefsAccount *account = NULL;
1031 VCalEvent *saved_event = NULL, *event = NULL;
1032 debug_print("index chosen %d\n", index);
1033
1034 if (index < 0 || index > 2) {
1035 return TRUE;
1036 }
1037
1038 s_vcalviewer = vcalviewer;
1039
1040 if (!vcalviewer->event) {
1041 g_warning("can't get event");
1042 return TRUE;
1043 }
1044
1045 /* see if we have it registered and more recent */
1046 event = vcalviewer->event;
1047 saved_event = vcal_manager_load_event(vcalviewer->event->uid);
1048 if (saved_event && saved_event->sequence >= vcalviewer->event->sequence) {
1049 saved_event->method = vcalviewer->event->method;
1050 event = saved_event;
1051 } else if (saved_event) {
1052 vcal_manager_free_event(saved_event);
1053 saved_event = NULL;
1054 }
1055 account = vcal_manager_get_account_from_event(event);
1056
1057 if (!account) {
1058 AlertValue val = alertpanel_full(_("No account found"),
1059 _("You have no account matching any attendee.\n"
1060 "Do you want to reply anyway?"),
1061 GTK_STOCK_CANCEL, _("Reply anyway"), NULL,
1062 ALERTFOCUS_SECOND, FALSE, NULL, ALERT_QUESTION);
1063 if (val == G_ALERTALTERNATE) {
1064 account = account_get_default();
1065 vcal_manager_update_answer(event, account->address,
1066 account->name,
1067 ICAL_PARTSTAT_NEEDSACTION,
1068 ICAL_CUTYPE_INDIVIDUAL);
1069 } else {
1070 if (saved_event)
1071 vcal_manager_free_event(saved_event);
1072 return TRUE;
1073 }
1074 }
1075
1076 vcal_manager_update_answer(event, account->address, account->name, reply[index], 0);
1077
1078 if (event->organizer && *(event->organizer) &&
1079 !vcal_manager_reply(account, event)) {
1080 g_warning("couldn't send reply");
1081 } else {
1082 debug_print("no organizer, not sending answer\n");
1083 }
1084
1085 vcal_manager_save_event(event, TRUE);
1086
1087 vcalviewer_display_event(vcalviewer, event);
1088 if (saved_event)
1089 vcal_manager_free_event(saved_event);
1090 return TRUE;
1091 };
1092
1093 #define TABLE_ADD_LINE(label_text, widget) { \
1094 gchar *tmpstr = g_strdup_printf("<span weight=\"bold\">%s</span>",\
1095 label_text); \
1096 GtkWidget *label = gtk_label_new(tmpstr); \
1097 g_free(tmpstr); \
1098 gtk_label_set_use_markup (GTK_LABEL (label), TRUE); \
1099 gtk_misc_set_alignment (GTK_MISC(label), 1, 0); \
1100 gtk_table_attach (GTK_TABLE (vcalviewer->table), \
1101 label, 0, 1, i, i+1, \
1102 GTK_FILL, GTK_FILL, 6, 6); \
1103 gtk_table_attach (GTK_TABLE (vcalviewer->table), \
1104 widget, 1, 2, i, i+1, \
1105 GTK_FILL, GTK_FILL, 6, 6); \
1106 if (GTK_IS_LABEL(widget)) { \
1107 gtk_label_set_use_markup(GTK_LABEL (widget), TRUE); \
1108 gtk_misc_set_alignment (GTK_MISC(widget),0, 0); \
1109 gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); \
1110 } \
1111 i++; \
1112 }
1113
vcal_viewer_get_selection(MimeViewer * _viewer)1114 static gchar *vcal_viewer_get_selection(MimeViewer *_viewer)
1115 {
1116 VCalViewer *viewer = (VCalViewer *)_viewer;
1117 if (viewer->summary == NULL)
1118 return NULL;
1119 if (gtk_label_get_text(GTK_LABEL(viewer->description))
1120 && *(gtk_label_get_text(GTK_LABEL(viewer->description))) > 2) {
1121 gint start, end;
1122 if (gtk_label_get_selection_bounds(GTK_LABEL(viewer->description),
1123 &start, &end)) {
1124 gchar *tmp = g_strdup(gtk_label_get_text(
1125 GTK_LABEL(viewer->description))+start);
1126 tmp[end-start] = '\0';
1127 return tmp;
1128 } else {
1129 return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->description)));
1130 }
1131 }
1132 else if (gtk_label_get_text(GTK_LABEL(viewer->summary))
1133 && *(gtk_label_get_text(GTK_LABEL(viewer->summary))) > 2)
1134 return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->summary)));
1135 else
1136 return NULL;
1137 }
1138
1139
vcal_viewer_scroll_page(MimeViewer * _viewer,gboolean up)1140 static gboolean vcal_viewer_scroll_page(MimeViewer *_viewer, gboolean up)
1141 {
1142 VCalViewer *viewer = (VCalViewer *)_viewer;
1143 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
1144 GTK_SCROLLED_WINDOW(viewer->scrolledwin));
1145
1146 return gtkutils_scroll_page(viewer->table, vadj, up);
1147 }
1148
vcal_viewer_scroll_one_line(MimeViewer * _viewer,gboolean up)1149 static void vcal_viewer_scroll_one_line(MimeViewer *_viewer, gboolean up)
1150 {
1151 VCalViewer *viewer = (VCalViewer *)_viewer;
1152 GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
1153 GTK_SCROLLED_WINDOW(viewer->scrolledwin));
1154
1155 gtkutils_scroll_one_line(viewer->table, vadj, up);
1156 }
1157
vcal_viewer_create(void)1158 MimeViewer *vcal_viewer_create(void)
1159 {
1160 VCalViewer *vcalviewer;
1161 int i = 0;
1162 GtkWidget *hbox = NULL, *vbox = NULL;
1163 GtkWidget *warning_img;
1164 GtkWidget *warning_label;
1165
1166 debug_print("Creating vcal view...\n");
1167 vcalviewer = g_new0(VCalViewer, 1);
1168 vcalviewer->mimeviewer.factory = &vcal_viewer_factory;
1169
1170 vcalviewer->mimeviewer.get_widget = vcal_viewer_get_widget;
1171 vcalviewer->mimeviewer.show_mimepart = vcal_viewer_show_mimepart;
1172 vcalviewer->mimeviewer.clear_viewer = vcal_viewer_clear_viewer;
1173 vcalviewer->mimeviewer.destroy_viewer = vcal_viewer_destroy_viewer;
1174 vcalviewer->mimeviewer.get_selection = vcal_viewer_get_selection;
1175 vcalviewer->mimeviewer.scroll_page = vcal_viewer_scroll_page;
1176 vcalviewer->mimeviewer.scroll_one_line = vcal_viewer_scroll_one_line;
1177
1178 vcalviewer->table = gtk_table_new(8, 2, FALSE);
1179 vcalviewer->type = gtk_label_new("meeting");
1180 vcalviewer->who = gtk_label_new("who");
1181 vcalviewer->start = gtk_label_new("start");
1182 vcalviewer->end = gtk_label_new("end");
1183 vcalviewer->location = gtk_label_new("location");
1184 vcalviewer->summary = gtk_label_new("summary");
1185 vcalviewer->description = gtk_label_new("description");
1186 vcalviewer->attendees = gtk_label_new("attendees");
1187
1188 vcalviewer->answer = gtk_combo_box_text_new();
1189 vcalviewer->url = NULL;
1190 vcalviewer->button = gtk_button_new_with_label(_("Answer"));
1191 vcalviewer->reedit = gtk_button_new_with_label(_("Edit meeting..."));
1192 vcalviewer->cancel = gtk_button_new_with_label(_("Cancel meeting..."));
1193 vcalviewer->uribtn = gtk_button_new_with_label(_("Launch website"));
1194 vcalviewer->unavail_box = gtk_hbox_new(FALSE, 6);
1195 warning_img = gtk_image_new_from_stock
1196 (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
1197 warning_label = gtk_label_new(_("You are already busy at this time."));
1198
1199 gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_img, FALSE, FALSE, 0);
1200 gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_label, FALSE, FALSE, 0);
1201
1202 hbox = gtk_hbox_new(FALSE, 6);
1203 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->answer, FALSE, FALSE, 0);
1204 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->button, FALSE, FALSE, 0);
1205 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->reedit, FALSE, FALSE, 0);
1206 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->cancel, FALSE, FALSE, 0);
1207 gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->uribtn, FALSE, FALSE, 0);
1208
1209 vbox = gtk_vbox_new(FALSE, 6);
1210 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1211 gtk_box_pack_start(GTK_BOX(vbox), vcalviewer->unavail_box, FALSE, FALSE, 0);
1212
1213 vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REQUEST);
1214
1215 gtk_label_set_selectable(GTK_LABEL(vcalviewer->type), TRUE);
1216 gtk_label_set_selectable(GTK_LABEL(vcalviewer->who), TRUE);
1217 gtk_label_set_selectable(GTK_LABEL(vcalviewer->start), TRUE);
1218 gtk_label_set_selectable(GTK_LABEL(vcalviewer->end), TRUE);
1219 gtk_label_set_selectable(GTK_LABEL(vcalviewer->location), TRUE);
1220 gtk_label_set_selectable(GTK_LABEL(vcalviewer->summary), TRUE);
1221 gtk_label_set_selectable(GTK_LABEL(vcalviewer->description), TRUE);
1222 gtk_label_set_selectable(GTK_LABEL(vcalviewer->attendees), TRUE);
1223
1224 g_signal_connect(G_OBJECT(vcalviewer->button), "clicked",
1225 G_CALLBACK(vcalviewer_action_cb), vcalviewer);
1226
1227 g_signal_connect(G_OBJECT(vcalviewer->reedit), "clicked",
1228 G_CALLBACK(vcalviewer_reedit_cb), vcalviewer);
1229
1230 g_signal_connect(G_OBJECT(vcalviewer->cancel), "clicked",
1231 G_CALLBACK(vcalviewer_cancel_cb), vcalviewer);
1232
1233 g_signal_connect(G_OBJECT(vcalviewer->uribtn), "clicked",
1234 G_CALLBACK(vcalviewer_uribtn_cb), vcalviewer);
1235
1236 TABLE_ADD_LINE(_("Event:"), vcalviewer->type);
1237 TABLE_ADD_LINE(_("Organizer:"), vcalviewer->who);
1238 TABLE_ADD_LINE(_("Location:"), vcalviewer->location);
1239 TABLE_ADD_LINE(_("Summary:"), vcalviewer->summary);
1240 TABLE_ADD_LINE(_("Starting:"), vcalviewer->start);
1241 TABLE_ADD_LINE(_("Ending:"), vcalviewer->end);
1242 TABLE_ADD_LINE(_("Description:"), vcalviewer->description);
1243 TABLE_ADD_LINE(_("Attendees:"), vcalviewer->attendees);
1244 gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
1245 TABLE_ADD_LINE(_("Action:"), vbox);
1246
1247 vcalviewer->scrolledwin = gtk_scrolled_window_new(NULL, NULL);
1248 gtk_scrolled_window_add_with_viewport(
1249 GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
1250 vcalviewer->table);
1251 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
1252 GTK_POLICY_NEVER,
1253 GTK_POLICY_AUTOMATIC);
1254
1255 gtk_widget_show_all(vcalviewer->scrolledwin);
1256 return (MimeViewer *) vcalviewer;
1257 }
1258
1259 static gchar *content_types[] =
1260 {"text/calendar", NULL};
1261
1262 MimeViewerFactory vcal_viewer_factory =
1263 {
1264 content_types,
1265 0,
1266 vcal_viewer_create,
1267 };
1268
1269 static gint alert_timeout_tag = 0;
1270 static gint scan_timeout_tag = 0;
1271
vcal_webcal_check(gpointer data)1272 static gboolean vcal_webcal_check(gpointer data)
1273 {
1274 Folder *root = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
1275
1276 if (prefs_common_get_prefs()->work_offline)
1277 return TRUE;
1278
1279 manual_update = FALSE;
1280 folderview_check_new(root);
1281 manual_update = TRUE;
1282 return TRUE;
1283 }
1284
1285 static guint context_menu_id = 0;
1286 static guint main_menu_id = 0;
1287
vcalendar_init(void)1288 void vcalendar_init(void)
1289 {
1290 MainWindow *mainwin = mainwindow_get_mainwindow();
1291 Folder *folder = NULL;
1292 gchar *directory = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
1293 "vcalendar", NULL);
1294 START_TIMING("");
1295 if (!is_dir_exist(directory) && make_dir (directory) != 0) {
1296 g_free(directory);
1297 return;
1298 }
1299
1300 g_free(directory);
1301
1302 vcal_prefs_init();
1303
1304 mimeview_register_viewer_factory(&vcal_viewer_factory);
1305 folder_register_class(vcal_folder_get_class());
1306
1307 folder = folder_find_from_name (PLUGIN_NAME, vcal_folder_get_class());
1308 if (!folder) {
1309 START_TIMING("creating folder");
1310 folder = folder_new(vcal_folder_get_class(), PLUGIN_NAME, NULL);
1311 folder->klass->create_tree(folder);
1312 folder_add(folder);
1313 folder_scan_tree(folder, TRUE);
1314 END_TIMING();
1315 }
1316
1317 if (!folder->inbox) {
1318 folder->klass->create_tree(folder);
1319 folder_scan_tree(folder, TRUE);
1320 }
1321 if (folder->klass->scan_required(folder, folder->inbox)) {
1322 START_TIMING("scanning folder");
1323 folder_item_scan(folder->inbox);
1324 END_TIMING();
1325 }
1326
1327 vcal_folder_gtk_init();
1328
1329 alert_timeout_tag = g_timeout_add(60*1000,
1330 (GSourceFunc)vcal_meeting_alert_check,
1331 (gpointer)NULL);
1332 scan_timeout_tag = g_timeout_add(3600*1000,
1333 (GSourceFunc)vcal_webcal_check,
1334 (gpointer)NULL);
1335 if (prefs_common_get_prefs()->enable_color) {
1336 gtkut_convert_int_to_gdk_color(prefs_common_get_prefs()->color[COL_URI],
1337 &uri_color);
1338 }
1339
1340 gtk_action_group_add_actions(mainwin->action_group, vcalendar_main_menu,
1341 1, (gpointer)mainwin);
1342 MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menu/Message", "CreateMeeting",
1343 "Message/CreateMeeting", GTK_UI_MANAGER_MENUITEM,
1344 main_menu_id)
1345 MENUITEM_ADDUI_ID_MANAGER(mainwin->ui_manager, "/Menus/SummaryViewPopup", "CreateMeeting",
1346 "Message/CreateMeeting", GTK_UI_MANAGER_MENUITEM,
1347 context_menu_id)
1348 END_TIMING();
1349 }
1350
vcalendar_done(void)1351 void vcalendar_done(void)
1352 {
1353 MainWindow *mainwin = mainwindow_get_mainwindow();
1354 FolderView *folderview = NULL;
1355 FolderItem *fitem = NULL;
1356
1357 icalmemory_free_ring();
1358
1359 vcal_folder_free_data();
1360
1361 if (mainwin == NULL)
1362 return;
1363
1364 folderview = mainwin->folderview;
1365 fitem = folderview->summaryview->folder_item;
1366
1367 if (fitem &&
1368 fitem->folder->klass == vcal_folder_get_class()) {
1369 folderview_unselect(folderview);
1370 summary_clear_all(folderview->summaryview);
1371 if (fitem->folder->klass->item_closed)
1372 fitem->folder->klass->item_closed(fitem);
1373 }
1374
1375 mimeview_unregister_viewer_factory(&vcal_viewer_factory);
1376 folder_unregister_class(vcal_folder_get_class());
1377 vcal_folder_gtk_done();
1378 vcal_prefs_done();
1379 g_source_remove(alert_timeout_tag);
1380 alert_timeout_tag = 0;
1381 g_source_remove(scan_timeout_tag);
1382 scan_timeout_tag = 0;
1383
1384 MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/CreateMeeting", main_menu_id);
1385 main_menu_id = 0;
1386 MENUITEM_REMUI_MANAGER(mainwin->ui_manager,mainwin->action_group, "Message/CreateMeeting", context_menu_id);
1387 context_menu_id = 0;
1388 }
1389