/*
* Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
* Copyright (C) 1999-2007 Colin Leroy <colin@colino.net> and
* the Claws Mail team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ical.h>
#include "gettext.h"
#include <gtk/gtk.h>
#include <pthread.h>
#include "mimeview.h"
#include "utils.h"
#include "vcalendar.h"
#include "vcal_manager.h"
#include "vcal_folder.h"
#include "vcal_meeting_gtk.h"
#include "prefs_account.h"
#include "prefs_common.h"
#include "account.h"
#include "codeconv.h"
#include "xml.h"
#include "xmlprops.h"
#include "alertpanel.h"
#include "vcal_prefs.h"
#include "statusbar.h"
#include "timing.h"
MimeViewerFactory vcal_viewer_factory;
static void refresh_folder_contents(VCalViewer *vcalviewer);
static void create_meeting_from_message_cb(gpointer callback_data, guint callback_action, GtkWidget *widget);
static GdkColor uri_color = {
(gulong)0,
(gushort)0,
(gushort)0,
(gushort)0
};
struct _VCalViewer
{
MimeViewer mimeviewer;
gchar *file;
MimeInfo *mimeinfo;
gchar *tmpfile;
icalcomponent *comp;
icalcomponent *icomp;
GtkWidget *scrolledwin;
GtkWidget *table;
GtkWidget *type;
GtkWidget *who;
GtkWidget *start;
GtkWidget *end;
GtkWidget *summary;
GtkWidget *description;
gchar *url;
GtkWidget *answer;
GtkWidget *button;
GtkWidget *reedit;
GtkWidget *cancel;
GtkWidget *uribtn;
GtkWidget *attendees;
GtkWidget *unavail_box;
};
static GtkItemFactoryEntry vcalendar_main_menu = {
N_("/Message/Create meeting from message..."),
NULL,
create_meeting_from_message_cb,
0,
NULL
};
static GtkItemFactoryEntry vcalendar_context_menu = {
N_("/Create meeting from message..."),
NULL,
create_meeting_from_message_cb,
0,
NULL
};
static void create_meeting_from_message_cb(gpointer callback_data, guint callback_action, GtkWidget *widget)
{
MainWindow *mainwin = mainwindow_get_mainwindow();
SummaryView *summaryview = mainwin->summaryview;
GSList *msglist = summary_get_selected_msg_list(summaryview);
FolderItem *item = NULL;
GSList *cur;
gchar *msg;
gint curnum=0, total=0;
if (summary_is_locked(summaryview) || !msglist) {
if (msglist)
g_slist_free(msglist);
return;
}
total = g_slist_length(msglist);
msg = g_strdup_printf(_("You are about to create %d "
"meetings, one by one. Do you "
"want to continue?"),
total);
if (total > 9
&& alertpanel(_("Warning"), msg, GTK_STOCK_CANCEL, "+" GTK_STOCK_YES, NULL)
!= G_ALERTALTERNATE) {
g_free(msg);
return;
}
g_free(msg);
main_window_cursor_wait(summaryview->mainwin);
gtk_clist_freeze(GTK_CLIST(summaryview->ctree));
folder_item_update_freeze();
inc_lock();
item = summaryview->folder_item;
STATUSBAR_PUSH(mainwin, _("Creating meeting..."));
for (cur = msglist; cur; cur = cur->next) {
MsgInfo *msginfo = procmsg_msginfo_get_full_info((MsgInfo *)cur->data);
VCalEvent *event = NULL;
FILE *fp = NULL;
if (MSG_IS_ENCRYPTED(msginfo->flags)) {
fp = procmime_get_first_encrypted_text_content(msginfo);
} else {
fp = procmime_get_first_text_content(msginfo);
}
if (fp) {
gchar uid[256];
time_t t = time(NULL);
time_t t2 = t+3600;
gchar *org = NULL;
gchar *orgname = NULL;
gchar *summary = g_strdup(msginfo->subject ? msginfo->subject:_("no subject"));
gchar *description = file_read_stream_to_str(fp);
gchar *dtstart = g_strdup(icaltime_as_ical_string(icaltime_from_timet(t, FALSE)));
gchar *dtend = g_strdup(icaltime_as_ical_string(icaltime_from_timet(t2, FALSE)));
gchar *recur = NULL;
gchar *tzid = g_strdup("UTC");
gchar *url = NULL;
gint method = ICAL_METHOD_REQUEST;
gint sequence = 1;
PrefsAccount *account = NULL;
fclose(fp);
if (item && item->prefs && item->prefs->enable_default_account)
account = account_find_from_id(item->prefs->default_account);
if (!account)
account = cur_account;
if (!account)
goto bail;
org = g_strdup(account->address);
if (account->set_domain && account->domain) {
g_snprintf(uid, sizeof(uid), "%s", account->domain);
} else if (!strncmp(get_domain_name(), "localhost", strlen("localhost"))) {
g_snprintf(uid, sizeof(uid), "%s",
strchr(account->address, '@') ?
strchr(account->address, '@')+1 :
account->address);
} else {
g_snprintf(uid, sizeof(uid), "%s", "");
}
generate_msgid(uid, 255);
event = vcal_manager_new_event(uid,
org, NULL, summary, description,
dtstart, dtend, recur, tzid, url, method, sequence,
ICAL_VTODO_COMPONENT);
/* hack to get default hours */
g_free(event->dtstart);
g_free(event->dtend);
event->dtstart = NULL;
event->dtend = NULL;
vcal_meeting_create(event);
vcal_manager_free_event(event);
bail:
g_free(org);
g_free(orgname);
g_free(summary);
g_free(description);
g_free(dtstart);
g_free(dtend);
g_free(recur);
g_free(tzid);
g_free(url);
}
procmsg_msginfo_free(msginfo);
}
statusbar_progress_all(0,0,0);
STATUSBAR_POP(mainwin);
inc_unlock();
folder_item_update_thaw();
gtk_clist_thaw(GTK_CLIST(summaryview->ctree));
main_window_cursor_normal(summaryview->mainwin);
g_slist_free(msglist);
}
static gchar *get_tmpfile(VCalViewer *vcalviewer)
{
gchar *tmpfile = NULL;
if (!vcalviewer->tmpfile) {
tmpfile = procmime_get_tmp_file_name(vcalviewer->mimeinfo);
debug_print("creating %s\n", tmpfile);
if (procmime_get_part(tmpfile, vcalviewer->mimeinfo) < 0) {
g_warning("Can't get mimepart file");
g_free(tmpfile);
return NULL;
}
vcalviewer->tmpfile = tmpfile;
}
return vcalviewer->tmpfile;
}
static GtkWidget *vcal_viewer_get_widget(MimeViewer *_mimeviewer)
{
VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
debug_print("vcal_viewer_get_widget\n");
gtk_widget_show_all(vcalviewer->scrolledwin);
return vcalviewer->scrolledwin;
}
static void vcal_viewer_clear_viewer(MimeViewer *_mimeviewer)
{
VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
debug_print("vcal_viewer_clear_viewer\n");
g_free(vcalviewer->file);
vcalviewer->file = NULL;
if (vcalviewer->tmpfile) {
debug_print("unlinking %s\n", vcalviewer->tmpfile);
unlink(vcalviewer->tmpfile);
g_free(vcalviewer->tmpfile);
vcalviewer->tmpfile = NULL;
}
vcalviewer->mimeinfo = NULL;
}
static gchar *get_email_from_attendee_property(icalproperty *p)
{
gchar *tmp = NULL;
gchar *email = NULL;
if (p)
tmp = g_strdup(icalproperty_get_attendee(p));
if (!tmp)
return NULL;
if (!strncasecmp(tmp, "MAILTO:", strlen("MAILTO:")))
email = g_strdup(tmp+strlen("MAILTO:"));
else
email = g_strdup(tmp);
g_free(tmp);
return email;
}
static gchar *get_name_from_organizer_property(icalproperty *p)
{
gchar *tmp = NULL;
if (p && icalproperty_get_parameter_as_string(p, "CN") != NULL)
tmp = g_strdup(icalproperty_get_parameter_as_string(p, "CN"));
return tmp;
}
static gchar *get_email_from_organizer_property(icalproperty *p)
{
gchar *tmp = NULL;
gchar *email = NULL;
if (p)
tmp = g_strdup(icalproperty_get_organizer(p));
if (!tmp)
return NULL;
if (!strncasecmp(tmp, "MAILTO:", strlen("MAILTO:")))
email = g_strdup(tmp+strlen("MAILTO:"));
else
email = g_strdup(tmp);
g_free(tmp);
return email;
}
static icalproperty *vcalviewer_get_property(VCalViewer *vcalviewer, icalproperty_kind kind)
{
icalproperty *iprop = NULL;
if (!vcalviewer->icomp || !vcalviewer->comp)
return NULL;
iprop = icalcomponent_get_first_property(vcalviewer->icomp, kind);
if (!iprop)
iprop = icalcomponent_get_first_property(vcalviewer->comp, kind);
return iprop;
}
static GSList *vcalviewer_get_properties(VCalViewer *vcalviewer, icalproperty_kind kind)
{
GSList *list = NULL;
icalproperty *iprop = NULL;
if (!vcalviewer->icomp || !vcalviewer->comp)
return NULL;
iprop = icalcomponent_get_first_property(vcalviewer->icomp, kind);
if (!iprop) {
return NULL;
} else do {
list = g_slist_append(list, iprop);
} while ((iprop = icalcomponent_get_next_property(vcalviewer->icomp, kind)) != NULL);
return list;
}
static icalcomponent *vcalviewer_get_component(const gchar *file)
{
gchar *compstr = NULL;
icalcomponent *comp = NULL;
FILE *fp;
GByteArray *array;
gchar buf[BUFSIZ];
gint n_read;
gchar *str;
g_return_val_if_fail(file != NULL, NULL);
if ((fp = fopen(file, "rb")) == NULL) {
FILE_OP_ERROR(file, "fopen");
return NULL;
}
array = g_byte_array_new();
while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
if (n_read < sizeof(buf) && ferror(fp))
break;
g_byte_array_append(array, (guchar *)buf, n_read);
}
if (ferror(fp)) {
FILE_OP_ERROR("file stream", "fread");
g_byte_array_free(array, TRUE);
return NULL;
}
buf[0] = '\0';
g_byte_array_append(array, (guchar *)buf, 1);
compstr = (gchar *)array->data;
g_byte_array_free(array, FALSE);
fclose(fp);
if (compstr) {
comp = icalcomponent_new_from_string(compstr);
g_free(compstr);
}
return comp;
}
#define GTK_LABEL_SET_TEXT_TRIMMED(label, text) { \
gchar *tmplbl = strretchomp(g_strdup(text)); \
gtk_label_set_text(label, tmplbl); \
g_free(tmplbl); \
}
static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, enum icalproperty_method method);
static void vcalviewer_reset(VCalViewer *vcalviewer)
{
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
g_free(vcalviewer->url);
vcalviewer->url = NULL;
gtk_widget_hide(vcalviewer->uribtn);
vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_CANCEL);
}
static gchar *get_attendee_replying(VCalViewer *vcalviewer)
{
gchar *attendee = NULL;
icalproperty *p = NULL;
p = vcalviewer_get_property(vcalviewer, ICAL_ATTENDEE_PROPERTY);
if (!p)
return NULL;
attendee = get_email_from_attendee_property(p);
icalproperty_free(p);
return attendee;
}
static gchar *get_attendee_replying_name(VCalViewer *vcalviewer)
{
gchar *name = NULL;
icalproperty *p = NULL;
icalparameter *param = NULL;
p = vcalviewer_get_property(vcalviewer, ICAL_ATTENDEE_PROPERTY);
if (!p)
return NULL;
param = icalproperty_get_first_parameter(p, ICAL_CN_PARAMETER);
if (param)
name = g_strdup(icalparameter_get_cn(param));
icalproperty_free(p);
return name;
}
enum icalparameter_partstat get_attendee_reply(VCalViewer *vcalviewer)
{
icalproperty *p = NULL;
icalparameter *param = NULL;
enum icalparameter_partstat status = 0;
p = vcalviewer_get_property(vcalviewer, ICAL_ATTENDEE_PROPERTY);
if (!p)
return 0;
param = icalproperty_get_first_parameter(p, ICAL_PARTSTAT_PARAMETER);
if (param) {
status = icalparameter_get_partstat(param);
icalproperty_free(p);
}
return status;
}
enum icalparameter_partstat get_attendee_replying_cutype(VCalViewer *vcalviewer)
{
icalproperty *p = NULL;
icalparameter *param = NULL;
enum icalparameter_cutype status = 0;
p = vcalviewer_get_property(vcalviewer, ICAL_ATTENDEE_PROPERTY);
if (!p)
return 0;
param = icalproperty_get_first_parameter(p, ICAL_CUTYPE_PARAMETER);
if (param) {
status = icalparameter_get_cutype(param);
icalproperty_free(p);
}
return status;
}
/*FIXME*/
static void vcalviewer_get_attendees(VCalViewer *vcalviewer, VCalEvent *event)
{
GSList *attendees = vcalviewer_get_properties(vcalviewer, ICAL_ATTENDEE_PROPERTY);
GSList *cur = attendees;
while (cur && cur->data) {
icalproperty *iprop = (icalproperty *)cur->data;
gchar *email = get_email_from_attendee_property(iprop);
const gchar *name = NULL;
icalparameter *param = NULL;
icalparameter *cutype = NULL;
param = icalproperty_get_first_parameter(iprop, ICAL_CN_PARAMETER);
if (param)
name = icalparameter_get_cn(param);
param = icalproperty_get_first_parameter(iprop, ICAL_PARTSTAT_PARAMETER);
cutype= icalproperty_get_first_parameter(iprop, ICAL_CUTYPE_PARAMETER);
if (email && param) {
debug_print("updating %s: %d\n", email, icalparameter_get_partstat(param));
vcal_manager_update_answer(event, email, name,
icalparameter_get_partstat(param),
cutype?icalparameter_get_cutype(cutype):ICAL_CUTYPE_INDIVIDUAL);
} else if (email) {
debug_print("updating %s: %d\n", email, ICAL_PARTSTAT_NEEDSACTION);
vcal_manager_update_answer(event, email, name,
ICAL_PARTSTAT_NEEDSACTION,
cutype?icalparameter_get_cutype(cutype):ICAL_CUTYPE_INDIVIDUAL);
}
g_free(email);
icalproperty_free(iprop);
cur = cur->next;
}
g_slist_free(cur);
}
static PrefsAccount *get_account_from_attendee(icalproperty *attendee)
{
gchar *email = get_email_from_attendee_property(attendee);
if (email != NULL && account_find_from_address(email) != NULL)
return account_find_from_address(email);
return NULL;
}
static PrefsAccount *get_account_from_attendees(VCalViewer *vcalviewer)
{
GSList *attendees = vcalviewer_get_properties(vcalviewer, ICAL_ATTENDEE_PROPERTY);
GSList *cur = attendees;
PrefsAccount *account = NULL;
while (cur && cur->data) {
icalproperty *iprop = (icalproperty *)cur->data;
if (get_account_from_attendee(iprop)) {
account = get_account_from_attendee(iprop);
icalproperty_free(iprop);
break;
}
icalproperty_free(iprop);
cur = cur->next;
}
g_slist_free(cur);
return account;
}
static gchar *vcalviewer_get_recurrence(VCalViewer *vcalviewer)
{
gchar *rrule = NULL;
icalproperty *iprop = vcalviewer_get_property(vcalviewer, ICAL_RRULE_PROPERTY);
if (iprop) {
struct icalrecurrencetype recur = icalproperty_get_rrule(iprop);
rrule = g_strdup(icalrecurrencetype_as_string(&recur));
icalproperty_free(iprop);
}
return rrule;
}
static gchar *vcalviewer_get_dtstart(VCalViewer *vcalviewer)
{
gchar *dtstart = NULL;
icalproperty *iprop = vcalviewer_get_property(vcalviewer, ICAL_DTSTART_PROPERTY);
if (iprop) {
struct icaltimetype itt = icalproperty_get_dtstart(iprop);
dtstart = g_strdup(icaltime_as_ical_string(itt));
icalproperty_free(iprop);
}
return dtstart;
}
static gchar *vcalviewer_get_dtend(VCalViewer *vcalviewer)
{
gchar *dtend = NULL;
icalproperty *iprop = vcalviewer_get_property(vcalviewer, ICAL_DTEND_PROPERTY);
if (iprop) {
struct icaltimetype itt = icalproperty_get_dtend(iprop);
dtend = g_strdup(icaltime_as_ical_string(itt));
icalproperty_free(iprop);
} else {
iprop = vcalviewer_get_property(vcalviewer, ICAL_DURATION_PROPERTY);
if (iprop) {
struct icaldurationtype duration = icalproperty_get_duration(iprop);
struct icaltimetype itt;
icalproperty_free(iprop);
iprop = vcalviewer_get_property(vcalviewer, ICAL_DTSTART_PROPERTY);
itt = icalproperty_get_dtstart(iprop);
if (iprop) {
icalproperty_free(iprop);
dtend = g_strdup(icaltime_as_ical_string(icaltime_add(itt,duration)));
}
}
}
return dtend;
}
static void vcalviewer_show_unavailable(VCalViewer *vcalviewer, gboolean visi)
{
if (visi)
gtk_widget_show_all(vcalviewer->unavail_box);
else
gtk_widget_hide(vcalviewer->unavail_box);
}
static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, enum icalproperty_method method)
{
int i = 0;
gtk_widget_hide(vcalviewer->reedit);
gtk_widget_hide(vcalviewer->cancel);
gtk_widget_hide(vcalviewer->answer);
gtk_widget_hide(vcalviewer->button);
for (i = 0; i < 3; i++)
gtk_combo_box_remove_text(GTK_COMBO_BOX(vcalviewer->answer), 0);
vcalviewer_show_unavailable(vcalviewer, FALSE);
if (method == ICAL_METHOD_REQUEST && event && !event->rec_occurence) {
PrefsAccount *account = vcal_manager_get_account_from_event(event);
if (!account)
account = get_account_from_attendees(vcalviewer);
if (!account && event) {
account = account_get_default();
vcal_manager_update_answer(event, account->address,
account->name,
ICAL_PARTSTAT_NEEDSACTION,
ICAL_CUTYPE_INDIVIDUAL);
}
if (account) {
gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Accept"));
gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Tentatively accept"));
gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Decline"));
gtk_widget_set_sensitive(vcalviewer->answer, TRUE);
gtk_widget_set_sensitive(vcalviewer->button, TRUE);
gtk_widget_show(vcalviewer->answer);
gtk_widget_show(vcalviewer->button);
} else {
gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), "-");
gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
gtk_widget_set_sensitive(vcalviewer->button, FALSE);
}
} else {
gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), "-");
gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
gtk_widget_set_sensitive(vcalviewer->button, FALSE);
}
gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
if (event && event->method == ICAL_METHOD_REQUEST) {
PrefsAccount *account = vcal_manager_get_account_from_event(event);
gchar *internal_ifb = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
"vcalendar", G_DIR_SEPARATOR_S,
"internal.ifb", NULL);
gchar *myfb = file_read_to_str(internal_ifb);
gchar *dtstart = vcalviewer_get_dtstart(vcalviewer);
gchar *dtend = vcalviewer_get_dtend(vcalviewer);
g_free(internal_ifb);
if (account) {
enum icalparameter_partstat answer =
vcal_manager_get_reply_for_attendee(event, account->address);
if (answer == ICAL_PARTSTAT_ACCEPTED)
gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
if (answer == ICAL_PARTSTAT_TENTATIVE)
gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 1);
if (answer == ICAL_PARTSTAT_DECLINED)
gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 2);
if (dtstart && dtend && myfb && *myfb
&& answer != ICAL_PARTSTAT_ACCEPTED
&& answer != ICAL_PARTSTAT_TENTATIVE) {
if (!attendee_available(NULL, dtstart, dtend, myfb))
vcalviewer_show_unavailable(vcalviewer, TRUE);
}
}
g_free(dtstart);
g_free(dtend);
g_free(myfb);
}
}
void vcalviewer_display_event (VCalViewer *vcalviewer, VCalEvent *event)
{
GSList *list = NULL;
gchar *attendees = NULL;
gboolean firstatt = TRUE;
gboolean mine = FALSE;
gchar *label = NULL;
gboolean save_evt = FALSE;
if (!event)
return;
if (!vcalviewer)
return;
if (event->type == ICAL_VTODO_COMPONENT) {
label = g_strjoin(" ", _("You have a Todo item."),
_("Details follow:"), NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
} else if (event->method == ICAL_METHOD_REQUEST) {
if (account_find_from_address(event->organizer)) {
label = g_strjoin(" ", _("You have created a meeting."),
_("Details follow:"), NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
mine = TRUE;
} else {
label = g_strjoin(" ", _("You have been invited to a meeting."),
_("Details follow:"), NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
}
}
else if (event->method == ICAL_METHOD_REPLY) {
enum icalparameter_partstat answer = get_attendee_reply(vcalviewer);
enum icalparameter_cutype cutype = get_attendee_replying_cutype(vcalviewer);
gchar *attendee = get_attendee_replying(vcalviewer);
gchar *name = get_attendee_replying_name(vcalviewer);
vcal_manager_update_answer(event, attendee, name, answer, cutype);
save_evt = TRUE;
if (!attendee) {
label = g_strjoin(" ",
_("You have received an answer to an unknown meeting proposal."),
_("Details follow:"), NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
} else {
label = g_strdup_printf(_("You have received an answer to a meeting proposal.\n"
"%s has %s the invitation whose details follow:"),
attendee, vcal_manager_get_reply_text_for_attendee(event, attendee));
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
g_free(attendee);
}
} else if (event->method == ICAL_METHOD_CANCEL) {
label = g_strjoin(" ",
_("A meeting to which you had been invited has been cancelled."),
_("Details follow:"), NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
save_evt = TRUE;
refresh_folder_contents(vcalviewer);
} else {
label = g_strjoin(" ", _("You have been forwarded an appointment."),
_("Details follow:"), NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
}
g_free(label);
if (event->orgname && strlen(event->orgname)
&& event->organizer && strlen(event->organizer)) {
gchar *addr = g_strconcat(event->orgname, " <", event->organizer, ">", NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
g_free(addr);
} else if (event->organizer && strlen(event->organizer)) {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), event->organizer);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
}
if (event->summary && strlen(event->summary)) {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), event->summary);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
}
if (event->description && strlen(event->description)) {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), event->description);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
}
g_free(vcalviewer->url);
if (event->url && strlen(event->url)) {
vcalviewer->url = g_strdup(event->url);
gtk_widget_show(vcalviewer->uribtn);
} else {
vcalviewer->url = NULL;
gtk_widget_hide(vcalviewer->uribtn);
}
if (event->start && strlen(event->start)) {
if (event->recur && strlen(event->recur)) {
gchar *tmp = g_strdup_printf(_("%s <span weight=\"bold\">(this event recurs)</span>"),
event->start);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
g_free(tmp);
} else if (event->rec_occurence) {
gchar *tmp = g_strdup_printf(_("%s <span weight=\"bold\">(this event is part of a recurring event)</span>"),
event->start);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), tmp);
gtk_label_set_use_markup(GTK_LABEL(vcalviewer->start), TRUE);
g_free(tmp);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), event->start);
}
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
}
if (event->end && strlen(event->end)) {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), event->end);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
}
attendees = g_strdup("");
for (list = vcal_manager_get_answers_emails(event);
list && list->data; list = list->next) {
gchar *attendee = (gchar *)list->data;
gchar *name = vcal_manager_get_attendee_name(event, attendee);
gchar *ename = g_markup_printf_escaped("%s", name?name:"");
gchar *eatt = g_markup_printf_escaped("%s", attendee);
enum icalparameter_partstat acode = vcal_manager_get_reply_for_attendee(event, attendee);
gchar *answer = vcal_manager_get_reply_text_for_attendee(event, attendee);
gchar *type = vcal_manager_get_cutype_text_for_attendee(event, attendee);
gchar *tmp = NULL;
gint e_len, n_len;
tmp = g_strdup_printf(
"%s%s<%s> (%s, <span%s>%s</span>)",
(ename && strlen(ename))?ename:"",
(ename && strlen(ename))?" ":"",
(eatt && strlen(eatt))?eatt:"",
(type && strlen(type))?type:"",
(acode != ICAL_PARTSTAT_ACCEPTED ? " foreground=\"red\"":""),
(answer && strlen(answer))?answer:"");
e_len = strlen(attendees);
n_len = strlen(tmp);
if (e_len) {
attendees = g_realloc(attendees, e_len+n_len+2);
*(attendees+e_len) = '\n';
strcpy(attendees+e_len+1, tmp);
} else {
attendees = g_realloc(attendees, e_len+n_len+1);
strcpy(attendees, tmp);
}
g_free(tmp);
g_free(answer);
g_free(type);
g_free(name);
g_free(ename);
g_free(eatt);
}
if (attendees && strlen(attendees)) {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), attendees);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
}
g_free(attendees);
gtk_label_set_use_markup(GTK_LABEL(vcalviewer->attendees), TRUE);
if (!mine)
if (event->type != ICAL_VTODO_COMPONENT)
vcalviewer_answer_set_choices(vcalviewer, event, event->method);
else
vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_PUBLISH);
else {
vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_REPLY);
gtk_widget_show(vcalviewer->reedit);
gtk_widget_show(vcalviewer->cancel);
}
if (save_evt)
vcal_manager_save_event(event, TRUE);
}
gchar *vcalviewer_get_uid_from_mimeinfo(MimeInfo *mimeinfo)
{
gchar *tmpfile = procmime_get_tmp_file_name(mimeinfo);
gchar *compstr = NULL;
icalcomponent *comp = NULL, *icomp = NULL;
icalproperty *iprop = NULL;
gchar *res = NULL;
if (procmime_get_part(tmpfile, mimeinfo) < 0) {
g_warning("Can't get mimepart file");
g_free(tmpfile);
return NULL;
}
compstr = file_read_to_str(tmpfile);
unlink(tmpfile);
g_free(tmpfile);
comp = icalcomponent_new_from_string(compstr);
g_free(compstr);
if (!comp) {
g_warning("can't get component");
return NULL;
}
icomp = icalcomponent_get_inner(comp);
if (!icomp) {
g_warning("can't get inner component");
icalcomponent_free(comp);
return NULL;
}
iprop = icalcomponent_get_first_property(icomp, ICAL_UID_PROPERTY);
if (iprop) {
res = g_strdup(icalproperty_get_uid(iprop));
icalproperty_free(iprop);
} else {
g_warning("can't get property");
}
icalcomponent_free(comp);
debug_print("got uid: %s\n", res);
return res;
}
static void vcalviewer_get_request_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo, gboolean is_todo)
{
icalproperty *iprop = NULL;
gchar *org = NULL, *summary = NULL, *description = NULL, *url = NULL;
gchar *dtstart = NULL, *dtend = NULL, *tzid = NULL, *orgname = NULL;
gchar *recur = NULL;
enum icalproperty_method method = ICAL_METHOD_REQUEST;
VCalEvent *event = NULL;
gchar *tmp;
const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
const gchar *saveme = procmime_mimeinfo_get_parameter(mimeinfo, "vcalsave");
gchar * uid = vcalviewer_get_uid_from_mimeinfo(mimeinfo);
gint sequence = 0;
if (!charset)
charset=CS_ISO_8859_1;
iprop = vcalviewer_get_property(vcalviewer, ICAL_SEQUENCE_PROPERTY);
if (iprop) {
sequence = icalproperty_get_sequence(iprop);
icalproperty_free(iprop);
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_METHOD_PROPERTY);
if (iprop) {
method = icalproperty_get_method(iprop);
icalproperty_free(iprop);
}
/* see if we have it registered and more recent */
event = vcal_manager_load_event(uid);
if (event && event->sequence >= sequence) {
charset = CS_INTERNAL;
event->method = method;
vcalviewer_display_event(vcalviewer, event);
vcal_manager_free_event(event);
g_free(uid);
return;
} else if (event) {
vcal_manager_free_event(event);
}
/* load it and register it */
iprop = vcalviewer_get_property(vcalviewer, ICAL_ORGANIZER_PROPERTY);
if (iprop) {
tmp = get_email_from_organizer_property(iprop);
if (tmp && !g_utf8_validate(tmp, -1, NULL))
org = conv_codeset_strdup(tmp, charset, CS_UTF_8);
else if (tmp)
org = g_strdup(tmp);
else
org = NULL;
g_free(tmp);
icalproperty_free(iprop);
tmp = get_name_from_organizer_property(iprop);
if (tmp && !g_utf8_validate(tmp, -1, NULL))
orgname = conv_codeset_strdup(tmp, charset, CS_UTF_8);
else if (tmp)
orgname = g_strdup(tmp);
else
orgname = NULL;
g_free(tmp);
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_SUMMARY_PROPERTY);
if (iprop) {
if (!g_utf8_validate(icalproperty_get_summary(iprop), -1, NULL))
summary = conv_codeset_strdup(icalproperty_get_summary(iprop), charset, CS_UTF_8);
else
summary = g_strdup(icalproperty_get_summary(iprop));
icalproperty_free(iprop);
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_DESCRIPTION_PROPERTY);
if (iprop) {
if (!g_utf8_validate(icalproperty_get_description(iprop), -1, NULL))
description = conv_codeset_strdup(icalproperty_get_description(iprop), charset, CS_UTF_8);
else
description = g_strdup(icalproperty_get_description(iprop));
icalproperty_free(iprop);
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_URL_PROPERTY);
if (iprop) {
if (!g_utf8_validate(icalproperty_get_url(iprop), -1, NULL))
url = conv_codeset_strdup(icalproperty_get_url(iprop), charset, CS_UTF_8);
else
url = g_strdup(icalproperty_get_url(iprop));
icalproperty_free(iprop);
}
dtstart = vcalviewer_get_dtstart(vcalviewer);
dtend = vcalviewer_get_dtend(vcalviewer);
recur = vcalviewer_get_recurrence(vcalviewer);
iprop = vcalviewer_get_property(vcalviewer, ICAL_TZID_PROPERTY);
if (iprop) {
tzid = g_strdup(icalproperty_get_tzid(iprop));
icalproperty_free(iprop);
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_METHOD_PROPERTY);
if (iprop) {
method = icalproperty_get_method(iprop);
icalproperty_free(iprop);
}
event = vcal_manager_new_event( uid,
org, orgname, summary, description,
dtstart, dtend, recur, tzid, url, method, sequence,
is_todo?ICAL_VTODO_COMPONENT:ICAL_VEVENT_COMPONENT);
vcalviewer_get_attendees(vcalviewer, event);
if (!saveme || strcmp(saveme,"no"))
vcal_manager_save_event(event, FALSE);
g_free(org);
g_free(orgname);
g_free(summary);
g_free(description);
g_free(url);
g_free(uid);
g_free(dtstart);
g_free(dtend);
g_free(recur);
g_free(tzid);
vcalviewer_display_event(vcalviewer, event);
vcal_manager_free_event(event);
}
static void vcalviewer_get_reply_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
{
icalproperty *iprop = NULL;
gchar *tmp = NULL;
const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
gchar *label = NULL;
enum icalparameter_partstat answer = get_attendee_reply(vcalviewer);
enum icalparameter_cutype cutype = get_attendee_replying_cutype(vcalviewer);
gchar *attendee = get_attendee_replying(vcalviewer);
gchar *name = get_attendee_replying_name(vcalviewer);
if (!charset)
charset=CS_ISO_8859_1;
iprop = vcalviewer_get_property(vcalviewer, ICAL_UID_PROPERTY);
if (iprop) {
VCalEvent *event = vcal_manager_load_event(icalproperty_get_uid(iprop));
if (event) {
charset = CS_INTERNAL;
event->method = ICAL_METHOD_REPLY;
vcalviewer_display_event(vcalviewer, event);
vcal_manager_free_event(event);
return;
}
}
/* unknown answer but get the replier anyway */
if (!attendee) {
label = g_strjoin(" ",
_("You have received an answer to an unknown meeting proposal."),
_("Details follow:"), NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
} else {
label = g_strdup_printf(_("You have received an answer to a meeting proposal.\n"
"%s has %s the invitation whose details follow:"),
attendee, vcal_manager_answer_get_text(answer));
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
g_free(attendee);
}
g_free(label);
iprop = vcalviewer_get_property(vcalviewer, ICAL_ORGANIZER_PROPERTY);
if (iprop) {
gchar *org, *orgname;
tmp = get_email_from_organizer_property(iprop);
if (tmp && !g_utf8_validate(tmp, -1, NULL))
org = conv_codeset_strdup(tmp, charset, CS_UTF_8);
else if (tmp)
org = g_strdup(tmp);
else
org = NULL;
g_free(tmp);
tmp = get_name_from_organizer_property(iprop);
if (tmp && !g_utf8_validate(tmp, -1, NULL))
orgname = conv_codeset_strdup(tmp, charset, CS_UTF_8);
else if (tmp)
orgname = g_strdup(tmp);
else
orgname = NULL;
g_free(tmp);
if (orgname && org) {
gchar *addr = g_strconcat(orgname, " <", org, ">", NULL);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
g_free(addr);
} else if (org) {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), org);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
}
icalproperty_free(iprop);
g_free(org);
g_free(orgname);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_SUMMARY_PROPERTY);
if (iprop) {
if (!g_utf8_validate(icalproperty_get_summary(iprop), -1, NULL))
tmp = conv_codeset_strdup(icalproperty_get_summary(iprop), charset, CS_UTF_8);
else
tmp = g_strdup(icalproperty_get_summary(iprop));
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), tmp);
g_free(tmp);
icalproperty_free(iprop);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_DESCRIPTION_PROPERTY);
if (iprop) {
if (!g_utf8_validate(icalproperty_get_description(iprop), -1, NULL))
tmp = conv_codeset_strdup(icalproperty_get_description(iprop), charset, CS_UTF_8);
else
tmp = g_strdup(icalproperty_get_description(iprop));
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), tmp);
g_free(tmp);
icalproperty_free(iprop);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_URL_PROPERTY);
g_free(vcalviewer->url);
if (iprop) {
if (!g_utf8_validate(icalproperty_get_url(iprop), -1, NULL))
tmp = conv_codeset_strdup(icalproperty_get_url(iprop), charset, CS_UTF_8);
else
tmp = g_strdup(icalproperty_get_url(iprop));
vcalviewer->url = g_strdup(tmp);
g_free(tmp);
icalproperty_free(iprop);
gtk_widget_show(vcalviewer->uribtn);
} else {
vcalviewer->url = NULL;
gtk_widget_hide(vcalviewer->uribtn);
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_DTSTART_PROPERTY);
if (iprop) {
struct icaltimetype itt = (icalproperty_get_dtstart(iprop));
gchar buft[512];
time_t tmp = icaltime_as_timet(itt);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), ctime_r(&tmp, buft));
icalproperty_free(iprop);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
}
iprop = vcalviewer_get_property(vcalviewer, ICAL_DTEND_PROPERTY);
if (iprop) {
struct icaltimetype itt = (icalproperty_get_dtstart(iprop));
gchar buft[512];
time_t tmp = icaltime_as_timet(itt);
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), ctime_r(&tmp, buft));
icalproperty_free(iprop);
} else {
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
}
GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REPLY);
}
static void vcalviewer_get_info(VCalViewer *vcalviewer, MimeInfo *mimeinfo)
{
icalproperty *method = NULL;
gboolean is_todo = FALSE;
gchar *tmpfile = get_tmpfile(vcalviewer);
if (vcalviewer->comp) {
icalcomponent_free(vcalviewer->comp);
vcalviewer->comp = NULL;
vcalviewer->icomp = NULL;
}
if (!tmpfile) {
vcalviewer_reset(vcalviewer);
return;
}
vcalviewer->comp = vcalviewer_get_component(tmpfile);
if (vcalviewer->comp)
vcalviewer->icomp= icalcomponent_get_inner(vcalviewer->comp);
else {
vcalviewer_reset(vcalviewer);
return;
}
method = vcalviewer_get_property(vcalviewer, ICAL_METHOD_PROPERTY);
if (vcalviewer->icomp && icalcomponent_isa(vcalviewer->icomp) == ICAL_VTODO_COMPONENT)
is_todo = TRUE;
debug_print("is_todo %d\n", is_todo);
if (icalcomponent_isa(vcalviewer->comp) == ICAL_VCALENDAR_COMPONENT && method) {
if (icalproperty_get_method(method) == ICAL_METHOD_REQUEST
|| icalproperty_get_method(method) == ICAL_METHOD_PUBLISH
|| icalproperty_get_method(method) == ICAL_METHOD_CANCEL)
vcalviewer_get_request_values(vcalviewer, mimeinfo, is_todo);
else if (icalproperty_get_method(method) == ICAL_METHOD_REPLY)
vcalviewer_get_reply_values(vcalviewer, mimeinfo);
else
vcalviewer_reset(vcalviewer);
} else if (is_todo && !method) {
vcalviewer_get_request_values(vcalviewer, mimeinfo, is_todo);
} else
vcalviewer_reset(vcalviewer);
}
static VCalViewer *s_vcalviewer = NULL;
static void vcal_viewer_show_mimepart(MimeViewer *_mimeviewer, const gchar *file, MimeInfo *mimeinfo)
{
VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
s_vcalviewer = vcalviewer;
if (mimeinfo == NULL) {
vcal_viewer_clear_viewer(_mimeviewer);
return;
}
debug_print("vcal_viewer_show_mimepart : %s\n", file);
vcal_viewer_clear_viewer(_mimeviewer);
gtk_widget_show_all(vcalviewer->scrolledwin);
g_free(vcalviewer->file);
vcalviewer->file = g_strdup(file);
vcalviewer->mimeinfo = mimeinfo;
vcalviewer_get_info(vcalviewer, mimeinfo);
GTK_EVENTS_FLUSH();
gtk_widget_set_size_request(vcalviewer->description,
vcalviewer->scrolledwin->allocation.width - 200, -1);
gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->summary), TRUE);
gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->description), TRUE);
gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
if (prefs_common.textfont) {
PangoFontDescription *font_desc;
font_desc = pango_font_description_from_string
(prefs_common.textfont);
if (font_desc) {
gtk_widget_modify_font(
vcalviewer->description, font_desc);
pango_font_description_free(font_desc);
}
}
}
void vcalviewer_reload(void)
{
if (s_vcalviewer) {
MainWindow *mainwin = mainwindow_get_mainwindow();
Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
folder_item_scan(folder->inbox);
if (mainwin && mainwin->summaryview->folder_item) {
FolderItem *cur = mainwin->summaryview->folder_item;
if (cur->folder == folder)
folder_item_scan(cur);
}
if (mainwin && mainwin->summaryview->folder_item == folder->inbox) {
debug_print("reload: %p, %p\n", (MimeViewer *)s_vcalviewer, s_vcalviewer->mimeinfo);
summary_redisplay_msg(mainwin->summaryview);
}
}
}
static void vcal_viewer_destroy_viewer(MimeViewer *_mimeviewer)
{
VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
debug_print("vcal_viewer_destroy_viewer\n");
if (s_vcalviewer == vcalviewer)
s_vcalviewer = NULL;
vcal_viewer_clear_viewer(_mimeviewer);
g_free(vcalviewer);
}
static gboolean vcalviewer_reedit_cb(GtkButton *widget, gpointer data)
{
VCalViewer *vcalviewer = (VCalViewer *)data;
gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
VCalEvent *event = NULL;
s_vcalviewer = vcalviewer;
/* see if we have it registered and more recent */
event = vcal_manager_load_event(uid);
vcal_meeting_create(event);
vcal_manager_free_event(event);
return TRUE;
}
static gboolean vcalviewer_uribtn_cb(GtkButton *widget, gpointer data)
{
VCalViewer *vcalviewer = (VCalViewer *)data;
if (vcalviewer->url)
open_uri(vcalviewer->url, prefs_common.uri_cmd);
return TRUE;
}
static void refresh_folder_contents(VCalViewer *vcalviewer)
{
Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
if (folder) {
MainWindow *mainwin = mainwindow_get_mainwindow();
folder_item_scan(folder->inbox);
if (mainwin->summaryview->folder_item == folder->inbox)
summary_show(mainwin->summaryview, folder->inbox);
}
}
static gboolean vcalviewer_cancel_cb(GtkButton *widget, gpointer data)
{
VCalViewer *vcalviewer = (VCalViewer *)data;
gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
VCalEvent *event = NULL;
VCalMeeting *meet = NULL;
gchar *file = NULL;
gint val = 0;
val = alertpanel_full(_("Cancel meeting"),
_("Are you sure you want to cancel this meeting?\n"
"A notification will be sent to attendees."),
GTK_STOCK_NO, GTK_STOCK_YES, NULL, FALSE,
NULL, ALERT_WARNING, G_ALERTDEFAULT);
if (val != G_ALERTALTERNATE)
return TRUE;
s_vcalviewer = vcalviewer;
event = vcal_manager_load_event(uid);
if (!event)
return TRUE;
event->method = ICAL_METHOD_CANCEL;
meet = vcal_meeting_create_hidden(event);
if (!vcal_meeting_send(meet)) {
event->method = ICAL_METHOD_REQUEST;
vcal_manager_save_event(event, TRUE);
vcal_manager_free_event(event);
refresh_folder_contents(vcalviewer);
vcalviewer_reset(vcalviewer);
return TRUE;
}
vcal_manager_save_event(event, TRUE);
file = vcal_manager_get_event_file(event->uid);
unlink(file);
vcal_manager_free_event(event);
g_free(file);
refresh_folder_contents(vcalviewer);
vcalviewer_reset(vcalviewer);
return TRUE;
}
static gboolean vcalviewer_action_cb(GtkButton *widget, gpointer data)
{
VCalViewer *vcalviewer = (VCalViewer *)data;
VCalEvent *event = NULL;
icalproperty *iprop = NULL;
gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(vcalviewer->answer));
enum icalparameter_partstat reply[3] = {ICAL_PARTSTAT_ACCEPTED, ICAL_PARTSTAT_TENTATIVE, ICAL_PARTSTAT_DECLINED};
PrefsAccount *account = NULL;
debug_print("index chosen %d\n", index);
if (index < 0 || index > 2) {
return TRUE;
}
s_vcalviewer = vcalviewer;
iprop = vcalviewer_get_property(vcalviewer, ICAL_UID_PROPERTY);
if (iprop) {
event = vcal_manager_load_event(icalproperty_get_uid(iprop));
icalproperty_free(iprop);
}
if (!event) {
g_warning("can't get event\n");
return TRUE;
}
account = get_account_from_attendees(vcalviewer);
if (!account) {
AlertValue val = alertpanel_full(_("No account found"),
_("You have no account matching any attendee.\n"
"Do you want to reply anyway ?"),
GTK_STOCK_CANCEL, _("+Reply anyway"), NULL, FALSE,
NULL, ALERT_QUESTION, G_ALERTDEFAULT);
if (val == G_ALERTALTERNATE) {
account = account_get_default();
vcal_manager_update_answer(event, account->address,
account->name,
ICAL_PARTSTAT_NEEDSACTION,
ICAL_CUTYPE_INDIVIDUAL);
} else
return TRUE;
}
vcal_manager_update_answer(event, account->address, account->name, reply[index], 0);
if (event->organizer && *(event->organizer) && !vcal_manager_reply(account, event)) {
g_warning("couldn't send reply\n");
} else {
debug_print("no organizer, not sending answer\n");
}
vcal_manager_save_event(event, TRUE);
vcalviewer_display_event(vcalviewer, event);
vcal_manager_free_event(event);
return TRUE;
};
#define TABLE_ADD_LINE(label_text, widget) { \
gchar *tmpstr = g_strdup_printf("<span weight=\"bold\">%s</span>",\
label_text); \
GtkWidget *label = gtk_label_new(tmpstr); \
g_free(tmpstr); \
gtk_label_set_use_markup (GTK_LABEL (label), TRUE); \
gtk_misc_set_alignment (GTK_MISC(label), 1, 0); \
gtk_table_attach (GTK_TABLE (vcalviewer->table), \
label, 0, 1, i, i+1, \
GTK_FILL, GTK_FILL, 6, 6); \
gtk_table_attach (GTK_TABLE (vcalviewer->table), \
widget, 1, 2, i, i+1, \
GTK_FILL, GTK_FILL, 6, 6); \
if (GTK_IS_LABEL(widget)) { \
gtk_label_set_use_markup(GTK_LABEL (widget), TRUE); \
gtk_misc_set_alignment (GTK_MISC(widget),0, 0); \
gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); \
} \
i++; \
}
static gchar *vcal_viewer_get_selection(MimeViewer *_viewer)
{
VCalViewer *viewer = (VCalViewer *)_viewer;
if (viewer->summary == NULL)
return NULL;
if (gtk_label_get_text(GTK_LABEL(viewer->description))
&& strlen(gtk_label_get_text(GTK_LABEL(viewer->description))) > 2) {
gint start, end;
if (gtk_label_get_selection_bounds(GTK_LABEL(viewer->description),
&start, &end)) {
gchar *tmp = g_strdup(gtk_label_get_text(
GTK_LABEL(viewer->description))+start);
tmp[end-start] = '\0';
return tmp;
} else {
return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->description)));
}
}
else if (gtk_label_get_text(GTK_LABEL(viewer->summary))
&& strlen(gtk_label_get_text(GTK_LABEL(viewer->summary))) > 2)
return g_strdup(gtk_label_get_text(GTK_LABEL(viewer->summary)));
else
return NULL;
}
static gboolean vcal_viewer_scroll_page(MimeViewer *_viewer, gboolean up)
{
VCalViewer *viewer = (VCalViewer *)_viewer;
GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
GTK_SCROLLED_WINDOW(viewer->scrolledwin));
return gtkutils_scroll_page(viewer->table, vadj, up);
}
static void vcal_viewer_scroll_one_line(MimeViewer *_viewer, gboolean up)
{
VCalViewer *viewer = (VCalViewer *)_viewer;
GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(
GTK_SCROLLED_WINDOW(viewer->scrolledwin));
gtkutils_scroll_one_line(viewer->table, vadj, up);
}
MimeViewer *vcal_viewer_create(void)
{
VCalViewer *vcalviewer;
int i = 0;
GtkWidget *hbox = NULL, *vbox = NULL;
GtkStyle *style;
GtkWidget *warning_img;
GtkWidget *warning_label;
debug_print("Creating vcal view...\n");
vcalviewer = g_new0(VCalViewer, 1);
vcalviewer->mimeviewer.factory = &vcal_viewer_factory;
vcalviewer->mimeviewer.get_widget = vcal_viewer_get_widget;
vcalviewer->mimeviewer.show_mimepart = vcal_viewer_show_mimepart;
vcalviewer->mimeviewer.clear_viewer = vcal_viewer_clear_viewer;
vcalviewer->mimeviewer.destroy_viewer = vcal_viewer_destroy_viewer;
vcalviewer->mimeviewer.get_selection = vcal_viewer_get_selection;
vcalviewer->mimeviewer.scroll_page = vcal_viewer_scroll_page;
vcalviewer->mimeviewer.scroll_one_line = vcal_viewer_scroll_one_line;
vcalviewer->table = gtk_table_new(8, 2, FALSE);
vcalviewer->type = gtk_label_new("meeting");
vcalviewer->who = gtk_label_new("who");
vcalviewer->start = gtk_label_new("start");
vcalviewer->end = gtk_label_new("end");
vcalviewer->summary = gtk_label_new("summary");
vcalviewer->description = gtk_label_new("description");
vcalviewer->attendees = gtk_label_new("attendees");
vcalviewer->answer = gtk_combo_box_new_text();
vcalviewer->url = NULL;
vcalviewer->button = gtk_button_new_with_label(_("Answer"));
vcalviewer->reedit = gtk_button_new_with_label(_("Edit meeting..."));
vcalviewer->cancel = gtk_button_new_with_label(_("Cancel meeting..."));
vcalviewer->uribtn = gtk_button_new_with_label(_("Launch website"));
vcalviewer->unavail_box = gtk_hbox_new(FALSE, 6);
warning_img = gtk_image_new_from_stock
(GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
warning_label = gtk_label_new(_("You are already busy at this time."));
gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_img, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vcalviewer->unavail_box), warning_label, FALSE, FALSE, 0);
hbox = gtk_hbox_new(FALSE, 6);
gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->answer, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->button, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->reedit, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->cancel, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->uribtn, FALSE, FALSE, 0);
vbox = gtk_vbox_new(FALSE, 6);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), vcalviewer->unavail_box, FALSE, FALSE, 0);
vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REQUEST);
gtk_label_set_selectable(GTK_LABEL(vcalviewer->type), TRUE);
gtk_label_set_selectable(GTK_LABEL(vcalviewer->who), TRUE);
gtk_label_set_selectable(GTK_LABEL(vcalviewer->start), TRUE);
gtk_label_set_selectable(GTK_LABEL(vcalviewer->end), TRUE);
gtk_label_set_selectable(GTK_LABEL(vcalviewer->summary), TRUE);
gtk_label_set_selectable(GTK_LABEL(vcalviewer->description), TRUE);
gtk_label_set_selectable(GTK_LABEL(vcalviewer->attendees), TRUE);
/* gtk_widget_ensure_style(vcalviewer->who);
style = gtk_style_copy
(gtk_widget_get_style(vcalviewer->who));
style->fg[GTK_STATE_NORMAL] = uri_color;
style->fg[GTK_STATE_ACTIVE] = uri_color;
style->fg[GTK_STATE_PRELIGHT] = uri_color;
gtk_widget_set_style(vcalviewer->who, style);
gtk_widget_ensure_style(vcalviewer->attendees);
style = gtk_style_copy
(gtk_widget_get_style(vcalviewer->attendees));
style->fg[GTK_STATE_NORMAL] = uri_color;
style->fg[GTK_STATE_ACTIVE] = uri_color;
style->fg[GTK_STATE_PRELIGHT] = uri_color;
gtk_widget_set_style(vcalviewer->attendees, style);
*/
g_signal_connect(G_OBJECT(vcalviewer->button), "clicked",
G_CALLBACK(vcalviewer_action_cb), vcalviewer);
g_signal_connect(G_OBJECT(vcalviewer->reedit), "clicked",
G_CALLBACK(vcalviewer_reedit_cb), vcalviewer);
g_signal_connect(G_OBJECT(vcalviewer->cancel), "clicked",
G_CALLBACK(vcalviewer_cancel_cb), vcalviewer);
g_signal_connect(G_OBJECT(vcalviewer->uribtn), "clicked",
G_CALLBACK(vcalviewer_uribtn_cb), vcalviewer);
TABLE_ADD_LINE(_("Event:"), vcalviewer->type);
TABLE_ADD_LINE(_("Organizer:"), vcalviewer->who);
TABLE_ADD_LINE(_("Summary:"), vcalviewer->summary);
TABLE_ADD_LINE(_("Starting:"), vcalviewer->start);
TABLE_ADD_LINE(_("Ending:"), vcalviewer->end);
TABLE_ADD_LINE(_("Description:"), vcalviewer->description);
TABLE_ADD_LINE(_("Attendees:"), vcalviewer->attendees);
gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
TABLE_ADD_LINE(_("Action:"), vbox);
vcalviewer->scrolledwin = gtk_scrolled_window_new(NULL, NULL);
gtk_scrolled_window_add_with_viewport(
GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
vcalviewer->table);
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
gtk_widget_show_all(vcalviewer->scrolledwin);
return (MimeViewer *) vcalviewer;
}
static gchar *content_types[] =
{"text/calendar", NULL};
MimeViewerFactory vcal_viewer_factory =
{
content_types,
0,
vcal_viewer_create,
};
static gint alert_timeout_tag = 0;
static gint scan_timeout_tag = 0;
static gint vcal_webcal_check(gpointer data)
{
Folder *root = folder_find_from_name ("vCalendar", vcal_folder_get_class());
if (prefs_common.work_offline)
return TRUE;
manual_update = FALSE;
folderview_check_new(root);
manual_update = TRUE;
return TRUE;
}
void vcalendar_init(void)
{
GtkItemFactory *ifactory;
MainWindow *mainwin = mainwindow_get_mainwindow();
SummaryView *summaryview = mainwin->summaryview;
Folder *folder = NULL;
GSList *events = NULL;
GSList *cur = NULL;
gchar *tmp = NULL;
gchar *directory = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
"vcalendar", NULL);
START_TIMING("");
if (!is_dir_exist(directory))
make_dir (directory);
g_free(directory);
vcal_prefs_init();
mimeview_register_viewer_factory(&vcal_viewer_factory);
folder_register_class(vcal_folder_get_class());
folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
if (!folder) {
START_TIMING("creating folder");
folder = folder_new(vcal_folder_get_class(), "vCalendar", NULL);
folder->klass->create_tree(folder);
folder_add(folder);
folder_scan_tree(folder, TRUE);
END_TIMING();
}
if (folder) {
START_TIMING("scanning folder");
folder_item_scan(folder->inbox);
END_TIMING();
}
vcal_folder_gtk_init();
alert_timeout_tag = gtk_timeout_add(60*1000,
(GtkFunction)vcal_meeting_alert_check,
(gpointer)NULL);
scan_timeout_tag = gtk_timeout_add(3600*1000,
(GtkFunction)vcal_webcal_check,
(gpointer)NULL);
if (prefs_common.enable_color) {
gtkut_convert_int_to_gdk_color(prefs_common.uri_col,
&uri_color);
}
vcalendar_main_menu.path = _(vcalendar_main_menu.path);
vcalendar_context_menu.path = _(vcalendar_context_menu.path);
ifactory = gtk_item_factory_from_widget(mainwin->menubar);
gtk_item_factory_create_item(ifactory, &vcalendar_main_menu, mainwin, 1);
gtk_item_factory_create_item(summaryview->popupfactory, &vcalendar_context_menu, summaryview, 1);
END_TIMING();
}
void vcalendar_done(void)
{
MainWindow *mainwin = mainwindow_get_mainwindow();
FolderView *folderview = NULL;
FolderItem *fitem = NULL;
GtkItemFactory *ifactory;
SummaryView *summaryview = NULL;
GtkWidget *widget;
icalmemory_free_ring();
if (mainwin == NULL)
return;
summaryview = mainwin->summaryview;
folderview = mainwin->folderview;
fitem = folderview->summaryview->folder_item;
if (fitem &&
fitem->folder->klass == vcal_folder_get_class()) {
folderview_unselect(folderview);
summary_clear_all(folderview->summaryview);
}
mimeview_unregister_viewer_factory(&vcal_viewer_factory);
folder_unregister_class(vcal_folder_get_class());
vcal_folder_gtk_done();
vcal_prefs_done();
gtk_timeout_remove(alert_timeout_tag);
alert_timeout_tag = 0;
gtk_timeout_remove(scan_timeout_tag);
scan_timeout_tag = 0;
ifactory = gtk_item_factory_from_widget(mainwin->menubar);
widget = gtk_item_factory_get_widget(ifactory, vcalendar_main_menu.path);
gtk_widget_destroy(widget);
gtk_item_factory_delete_item(ifactory, vcalendar_main_menu.path);
widget = gtk_item_factory_get_widget(summaryview->popupfactory, vcalendar_context_menu.path);
gtk_widget_destroy(widget);
gtk_item_factory_delete_item(summaryview->popupfactory, vcalendar_context_menu.path);
}
syntax highlighted by Code2HTML, v. 0.9.1