Files
evolution/plugins/groupwise-features/process-meeting.c
Jonathon Jongsma c2ee0afbc8 Rename EError to EAlert to match general use better
The EError mechanism is used both for error dialogs as well as basic alerts or
user prompts, so we should give it a more general name which matches this use.

This patch also cleans up a few includes of e-alert.h (formerly e-error.h) that
were not actually being used.

https://bugzilla.gnome.org/show_bug.cgi?id=602963
2009-11-30 13:33:04 -06:00

433 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-alert.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_alert_run_dialog_for_args (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_alert_run_dialog_for_args (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_alert_run_dialog_for_args (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);
}
}
}