429 lines
11 KiB
C
429 lines
11 KiB
C
/*
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) version 3.
|
|
*
|
|
* 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with the program; if not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*
|
|
* Authors:
|
|
* Chenthill Palanisamy (pchenthill@novell.com)
|
|
*
|
|
* Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <glib/gi18n.h>
|
|
#include <gtk/gtk.h>
|
|
#include <libecal/e-cal.h>
|
|
|
|
#include <e-util/e-error.h>
|
|
#include <shell/e-shell-view.h>
|
|
|
|
#include <calendar/gui/e-calendar-view.h>
|
|
#include <calendar/gui/itip-utils.h>
|
|
#include <calendar/gui/gnome-cal.h>
|
|
|
|
#include "gw-ui.h"
|
|
|
|
typedef struct {
|
|
ECal *ecal;
|
|
icalcomponent *icalcomp;
|
|
} ReceiveData;
|
|
|
|
static void
|
|
finalize_receive_data (ReceiveData *r_data)
|
|
{
|
|
if (r_data->ecal) {
|
|
g_object_unref (r_data->ecal);
|
|
r_data->ecal = NULL;
|
|
}
|
|
|
|
if (r_data->ecal) {
|
|
icalcomponent_free (r_data->icalcomp);
|
|
r_data->icalcomp = NULL;
|
|
}
|
|
|
|
g_free (r_data);
|
|
}
|
|
|
|
static gboolean
|
|
receive_objects (gpointer data)
|
|
{
|
|
GError *error = NULL;
|
|
ReceiveData *r_data = data;
|
|
|
|
icalcomponent_set_method (r_data->icalcomp, ICAL_METHOD_REQUEST);
|
|
|
|
if (!e_cal_receive_objects (r_data->ecal, r_data->icalcomp, &error)) {
|
|
/* FIXME show an error dialog */
|
|
g_error_free (error);
|
|
}
|
|
|
|
finalize_receive_data (r_data);
|
|
return TRUE;
|
|
}
|
|
|
|
static icalproperty *
|
|
find_attendee (icalcomponent *ical_comp, const gchar *address)
|
|
{
|
|
icalproperty *prop;
|
|
|
|
if (address == NULL)
|
|
return NULL;
|
|
|
|
for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY);
|
|
prop != NULL;
|
|
prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) {
|
|
icalvalue *value;
|
|
const gchar *attendee;
|
|
gchar *text;
|
|
|
|
value = icalproperty_get_value (prop);
|
|
if (!value)
|
|
continue;
|
|
|
|
attendee = icalvalue_get_string (value);
|
|
|
|
text = g_strdup (itip_strip_mailto (attendee));
|
|
text = g_strstrip (text);
|
|
if (!g_ascii_strcasecmp (address, text)) {
|
|
g_free (text);
|
|
break;
|
|
}
|
|
g_free (text);
|
|
}
|
|
|
|
return prop;
|
|
}
|
|
static void
|
|
change_status (icalcomponent *ical_comp, const gchar *address, icalparameter_partstat status)
|
|
{
|
|
icalproperty *prop;
|
|
|
|
prop = find_attendee (ical_comp, address);
|
|
if (prop) {
|
|
icalparameter *param;
|
|
|
|
icalproperty_remove_parameter (prop, ICAL_PARTSTAT_PARAMETER);
|
|
param = icalparameter_new_partstat (status);
|
|
icalproperty_add_parameter (prop, param);
|
|
} else {
|
|
icalparameter *param;
|
|
|
|
prop = icalproperty_new_attendee (address);
|
|
icalcomponent_add_property (ical_comp, prop);
|
|
|
|
param = icalparameter_new_role (ICAL_ROLE_OPTPARTICIPANT);
|
|
icalproperty_add_parameter (prop, param);
|
|
|
|
param = icalparameter_new_partstat (status);
|
|
icalproperty_add_parameter (prop, param);
|
|
}
|
|
}
|
|
|
|
static void
|
|
process_meeting (ECalendarView *cal_view, icalparameter_partstat status)
|
|
{
|
|
GList *selected;
|
|
icalcomponent *clone;
|
|
|
|
selected = e_calendar_view_get_selected_events (cal_view);
|
|
if (selected) {
|
|
ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
|
|
ECalComponent *comp = e_cal_component_new ();
|
|
ReceiveData *r_data = g_new0 (ReceiveData, 1);
|
|
gboolean recurring = FALSE;
|
|
GThread *thread = NULL;
|
|
GError *error = NULL;
|
|
gchar *address = NULL;
|
|
|
|
e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp));
|
|
address = itip_get_comp_attendee (comp, event->comp_data->client);
|
|
|
|
if (e_cal_component_has_recurrences (comp) || e_cal_component_is_instance (comp))
|
|
recurring = TRUE;
|
|
|
|
/* Free comp */
|
|
g_object_unref (comp);
|
|
comp = NULL;
|
|
|
|
clone = icalcomponent_new_clone (event->comp_data->icalcomp);
|
|
change_status (clone, address, status);
|
|
|
|
r_data->ecal = g_object_ref (event->comp_data->client);
|
|
r_data->icalcomp = clone;
|
|
|
|
if (recurring) {
|
|
gint response;
|
|
const gchar *msg;
|
|
|
|
if (status == ICAL_PARTSTAT_ACCEPTED || status == ICAL_PARTSTAT_TENTATIVE)
|
|
msg = "org.gnome.evolution.process_meeting:recurrence-accept";
|
|
else
|
|
msg = "org.gnome.evolution.process_meeting:recurrence-decline";
|
|
|
|
response = e_error_run (GTK_WINDOW (gtk_widget_get_toplevel ((GtkWidget *)cal_view)), msg, NULL);
|
|
if (response == GTK_RESPONSE_YES) {
|
|
icalproperty *prop;
|
|
const gchar *uid = icalcomponent_get_uid (r_data->icalcomp);
|
|
|
|
prop = icalproperty_new_x ("All");
|
|
icalproperty_set_x_name (prop, "X-GW-RECUR-INSTANCES-MOD-TYPE");
|
|
icalcomponent_add_property (r_data->icalcomp, prop);
|
|
|
|
prop = icalproperty_new_x (uid);
|
|
icalproperty_set_x_name (prop, "X-GW-RECURRENCE-KEY");
|
|
icalcomponent_add_property (r_data->icalcomp, prop);
|
|
|
|
} else if (response == GTK_RESPONSE_CANCEL) {
|
|
finalize_receive_data (r_data);
|
|
return;
|
|
}
|
|
}
|
|
|
|
thread = g_thread_create ((GThreadFunc) receive_objects, r_data , FALSE, &error);
|
|
if (!thread) {
|
|
g_warning (G_STRLOC ": %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
}
|
|
|
|
static ECalendarView *
|
|
get_calendar_view (EShellView *shell_view)
|
|
{
|
|
EShellContent *shell_content;
|
|
GnomeCalendar *gcal = NULL;
|
|
GnomeCalendarViewType view_type;
|
|
|
|
g_return_val_if_fail (shell_view != NULL, NULL);
|
|
|
|
shell_content = e_shell_view_get_shell_content (shell_view);
|
|
|
|
g_object_get (shell_content, "calendar", &gcal, NULL);
|
|
|
|
view_type = gnome_calendar_get_view (gcal);
|
|
|
|
return gnome_calendar_get_calendar_view (gcal, view_type);
|
|
}
|
|
|
|
void
|
|
gw_meeting_accept_cb (GtkAction *action, EShellView *shell_view)
|
|
{
|
|
ECalendarView *cal_view = get_calendar_view (shell_view);
|
|
g_return_if_fail (cal_view != NULL);
|
|
|
|
process_meeting (cal_view, ICAL_PARTSTAT_ACCEPTED);
|
|
}
|
|
|
|
void
|
|
gw_meeting_accept_tentative_cb (GtkAction *action, EShellView *shell_view)
|
|
{
|
|
ECalendarView *cal_view = get_calendar_view (shell_view);
|
|
g_return_if_fail (cal_view != NULL);
|
|
|
|
process_meeting (cal_view, ICAL_PARTSTAT_TENTATIVE);
|
|
}
|
|
|
|
void
|
|
gw_meeting_decline_cb (GtkAction *action, EShellView *shell_view)
|
|
{
|
|
ECalendarView *cal_view = get_calendar_view (shell_view);
|
|
g_return_if_fail (cal_view != NULL);
|
|
|
|
process_meeting (cal_view, ICAL_PARTSTAT_DECLINED);
|
|
}
|
|
|
|
typedef struct {
|
|
ECal *client;
|
|
ECalComponent *comp;
|
|
CalObjModType mod;
|
|
} ThreadData;
|
|
|
|
static void
|
|
add_retract_data (ECalComponent *comp, const gchar *retract_comment, CalObjModType mod)
|
|
{
|
|
icalcomponent *icalcomp = NULL;
|
|
icalproperty *icalprop = NULL;
|
|
|
|
icalcomp = e_cal_component_get_icalcomponent (comp);
|
|
if (retract_comment && *retract_comment)
|
|
icalprop = icalproperty_new_x (retract_comment);
|
|
else
|
|
icalprop = icalproperty_new_x ("0");
|
|
icalproperty_set_x_name (icalprop, "X-EVOLUTION-RETRACT-COMMENT");
|
|
icalcomponent_add_property (icalcomp, icalprop);
|
|
|
|
if (mod == CALOBJ_MOD_ALL)
|
|
icalprop = icalproperty_new_x ("All");
|
|
else
|
|
icalprop = icalproperty_new_x ("This");
|
|
icalproperty_set_x_name (icalprop, "X-EVOLUTION-RECUR-MOD");
|
|
icalcomponent_add_property (icalcomp, icalprop);
|
|
}
|
|
|
|
static void
|
|
free_thread_data (ThreadData *data)
|
|
{
|
|
if (data == NULL)
|
|
return;
|
|
|
|
if (data->client)
|
|
g_object_unref (data->client);
|
|
|
|
if (data->comp)
|
|
g_object_unref (data->comp);
|
|
|
|
g_free (data);
|
|
}
|
|
|
|
static gpointer
|
|
retract_object (gpointer val)
|
|
{
|
|
ThreadData *data = val;
|
|
icalcomponent *icalcomp = NULL, *mod_comp = NULL;
|
|
GList *users = NULL;
|
|
gchar *rid = NULL;
|
|
const gchar *uid;
|
|
GError *error = NULL;
|
|
|
|
add_retract_data (data->comp, NULL, data->mod);
|
|
|
|
icalcomp = e_cal_component_get_icalcomponent (data->comp);
|
|
icalcomponent_set_method (icalcomp, ICAL_METHOD_CANCEL);
|
|
|
|
if (!e_cal_send_objects (data->client, icalcomp, &users,
|
|
&mod_comp, &error)) {
|
|
/* FIXME report error */
|
|
g_warning ("Unable to retract the meeting \n");
|
|
g_clear_error (&error);
|
|
return GINT_TO_POINTER (1);
|
|
}
|
|
|
|
if (mod_comp)
|
|
icalcomponent_free (mod_comp);
|
|
|
|
if (users) {
|
|
g_list_foreach (users, (GFunc) g_free, NULL);
|
|
g_list_free (users);
|
|
}
|
|
|
|
rid = e_cal_component_get_recurid_as_string (data->comp);
|
|
e_cal_component_get_uid (data->comp, &uid);
|
|
|
|
if (!e_cal_remove_object_with_mod (data->client, uid,
|
|
rid, data->mod, &error)) {
|
|
g_warning ("Unable to remove the item \n");
|
|
g_clear_error (&error);
|
|
return GINT_TO_POINTER (1);
|
|
}
|
|
g_free (rid);
|
|
|
|
free_thread_data (data);
|
|
return GINT_TO_POINTER (0);
|
|
}
|
|
|
|
static void
|
|
object_created_cb (CompEditor *ce, gpointer data)
|
|
{
|
|
GThread *thread = NULL;
|
|
gint response;
|
|
GError *error = NULL;
|
|
|
|
gtk_widget_hide (GTK_WIDGET (ce));
|
|
|
|
response = e_error_run (GTK_WINDOW (gtk_widget_get_toplevel ((GtkWidget *)ce)), "org.gnome.evolution.process_meeting:resend-retract", NULL);
|
|
if (response == GTK_RESPONSE_NO) {
|
|
free_thread_data (data);
|
|
return;
|
|
}
|
|
|
|
thread = g_thread_create ((GThreadFunc) retract_object, data , FALSE, &error);
|
|
if (!thread) {
|
|
g_warning (G_STRLOC ": %s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
|
|
void
|
|
gw_resend_meeting_cb (GtkAction *action, EShellView *shell_view)
|
|
{
|
|
GList *selected;
|
|
ECalendarView *cal_view = get_calendar_view (shell_view);
|
|
|
|
g_return_if_fail (cal_view != NULL);
|
|
|
|
selected = e_calendar_view_get_selected_events (cal_view);
|
|
if (selected) {
|
|
ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
|
|
ECalComponent *comp = e_cal_component_new ();
|
|
ECalComponent *new_comp = NULL;
|
|
gboolean recurring = FALSE;
|
|
CalObjModType mod = CALOBJ_MOD_THIS;
|
|
ThreadData *data = NULL;
|
|
gint response;
|
|
const gchar *msg;
|
|
/* inserting the boolean to share the code between resend and retract */
|
|
gboolean resend = TRUE;
|
|
|
|
e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp));
|
|
if (e_cal_component_has_recurrences (comp) || e_cal_component_is_instance (comp))
|
|
recurring = TRUE;
|
|
|
|
if (recurring == TRUE)
|
|
msg = "org.gnome.evolution.process_meeting:resend-recurrence";
|
|
else
|
|
msg = "org.gnome.evolution.process_meeting:resend";
|
|
|
|
response = e_error_run (GTK_WINDOW (e_shell_view_get_shell_window (shell_view)), msg, NULL);
|
|
if (response == GTK_RESPONSE_YES) {
|
|
mod = CALOBJ_MOD_ALL;
|
|
} else if (response == GTK_RESPONSE_CANCEL) {
|
|
g_object_unref (comp);
|
|
return;
|
|
}
|
|
|
|
data = g_new0 (ThreadData, 1);
|
|
data->client = g_object_ref (event->comp_data->client);
|
|
data->comp = comp;
|
|
data->mod = mod;
|
|
|
|
if (resend)
|
|
{
|
|
guint flags = 0;
|
|
gchar *new_uid = NULL;
|
|
CompEditor *ce;
|
|
icalcomponent *icalcomp;
|
|
|
|
flags |= COMP_EDITOR_NEW_ITEM;
|
|
flags |= COMP_EDITOR_MEETING;
|
|
flags |= COMP_EDITOR_USER_ORG;
|
|
|
|
new_comp = e_cal_component_clone (comp);
|
|
new_uid = e_cal_component_gen_uid ();
|
|
e_cal_component_set_recurid (new_comp, NULL);
|
|
e_cal_component_set_uid (new_comp, new_uid);
|
|
icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (new_comp));
|
|
ce = e_calendar_view_open_event_with_flags (cal_view, data->client, icalcomp, flags);
|
|
|
|
g_signal_connect (ce, "object_created", G_CALLBACK (object_created_cb), data);
|
|
g_object_unref (new_comp);
|
|
g_free (new_uid);
|
|
}
|
|
}
|
|
}
|