aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2011-11-25 18:40:28 +0800
committerMilan Crha <mcrha@redhat.com>2011-11-25 18:40:28 +0800
commit8664187d640655a6c1fc44e99937ea8037cf4932 (patch)
tree1e829940abf85acda39abbb77a6b52560f5ba205 /plugins
parentc8fcaf727d7bf60a83219f8d1751cff9e43dfee8 (diff)
downloadgsoc2013-evolution-8664187d640655a6c1fc44e99937ea8037cf4932.tar
gsoc2013-evolution-8664187d640655a6c1fc44e99937ea8037cf4932.tar.gz
gsoc2013-evolution-8664187d640655a6c1fc44e99937ea8037cf4932.tar.bz2
gsoc2013-evolution-8664187d640655a6c1fc44e99937ea8037cf4932.tar.lz
gsoc2013-evolution-8664187d640655a6c1fc44e99937ea8037cf4932.tar.xz
gsoc2013-evolution-8664187d640655a6c1fc44e99937ea8037cf4932.tar.zst
gsoc2013-evolution-8664187d640655a6c1fc44e99937ea8037cf4932.zip
Bug #659491 - Hung when accepting calendar invite
Diffstat (limited to 'plugins')
-rw-r--r--plugins/itip-formatter/itip-formatter.c759
-rw-r--r--plugins/itip-formatter/itip-view.c5
2 files changed, 469 insertions, 295 deletions
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index e4f32010bd..06068ba5ac 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -130,6 +130,11 @@ struct _itip_puri {
*/
gboolean no_reply_wanted;
+ guint update_item_progress_info_id;
+ guint update_item_error_info_id;
+ ItipViewResponse update_item_response;
+ gboolean can_delete_invitation_from_cache;
+ GHashTable *real_comps; /* ESource's UID -> ECalComponent stored on the server */
};
void format_itip (EPlugin *ep, EMFormatHookTarget *target);
@@ -422,25 +427,18 @@ find_from_address (struct _itip_puri *pitip,
static ECalComponent *
get_real_item (struct _itip_puri *pitip)
{
- ECalComponent *comp;
- icalcomponent *icalcomp;
- gboolean found = FALSE;
- const gchar *uid;
-
- e_cal_component_get_uid (pitip->comp, &uid);
+ ECalComponent *comp = NULL;
+ ESource *source;
- found = e_cal_client_get_object_sync (pitip->current_client, uid, NULL, &icalcomp, NULL, NULL);
- if (!found)
- return NULL;
+ source = e_client_get_source (E_CLIENT (pitip->current_client));
+ if (source)
+ comp = g_hash_table_lookup (pitip->real_comps, e_source_peek_uid (source));
- comp = e_cal_component_new ();
- if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
- g_object_unref (comp);
- icalcomponent_free (icalcomp);
+ if (!comp) {
return NULL;
}
- return comp;
+ return e_cal_component_clone (comp);
}
static void
@@ -843,6 +841,8 @@ get_object_without_rid_ready_cb (GObject *source_object,
g_clear_error (&error);
if (icalcomp) {
+ ECalComponent *comp;
+
fd->puri->current_client = cal_client;
fd->keep_alarm_check = (fd->puri->method == ICAL_METHOD_PUBLISH || fd->puri->method == ICAL_METHOD_REQUEST) &&
(icalcomponent_get_first_component (icalcomp, ICAL_VALARM_COMPONENT) ||
@@ -851,7 +851,13 @@ get_object_without_rid_ready_cb (GObject *source_object,
icalcomponent_get_first_component (icalcomp, ICAL_XPROCEDUREALARM_COMPONENT) ||
icalcomponent_get_first_component (icalcomp, ICAL_XEMAILALARM_COMPONENT));
- icalcomponent_free (icalcomp);
+ comp = e_cal_component_new_from_icalcomponent (icalcomp);
+ if (comp) {
+ ESource *source = e_client_get_source (E_CLIENT (cal_client));
+
+ g_hash_table_insert (fd->puri->real_comps, g_strdup (e_source_peek_uid (source)), comp);
+ }
+
find_cal_update_ui (fd, cal_client);
decrease_find_data (fd);
return;
@@ -886,6 +892,8 @@ get_object_with_rid_ready_cb (GObject *source_object,
g_clear_error (&error);
if (icalcomp) {
+ ECalComponent *comp;
+
fd->puri->current_client = cal_client;
fd->keep_alarm_check = (fd->puri->method == ICAL_METHOD_PUBLISH || fd->puri->method == ICAL_METHOD_REQUEST) &&
(icalcomponent_get_first_component (icalcomp, ICAL_VALARM_COMPONENT) ||
@@ -894,7 +902,13 @@ get_object_with_rid_ready_cb (GObject *source_object,
icalcomponent_get_first_component (icalcomp, ICAL_XPROCEDUREALARM_COMPONENT) ||
icalcomponent_get_first_component (icalcomp, ICAL_XEMAILALARM_COMPONENT));
- icalcomponent_free (icalcomp);
+ comp = e_cal_component_new_from_icalcomponent (icalcomp);
+ if (comp) {
+ ESource *source = e_client_get_source (E_CLIENT (cal_client));
+
+ g_hash_table_insert (fd->puri->real_comps, g_strdup (e_source_peek_uid (source)), comp);
+ }
+
find_cal_update_ui (fd, cal_client);
decrease_find_data (fd);
return;
@@ -1311,7 +1325,224 @@ get_uri_for_part (CamelMimePart *mime_part)
return path;
}
-static gboolean
+static void
+update_item_progress_info (struct _itip_puri *pitip,
+ const gchar *message)
+{
+ if (pitip->update_item_progress_info_id) {
+ itip_view_remove_lower_info_item (ITIP_VIEW (pitip->view), pitip->update_item_progress_info_id);
+ pitip->update_item_progress_info_id = 0;
+
+ if (!message)
+ itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), TRUE);
+ }
+
+ if (pitip->update_item_error_info_id) {
+ itip_view_remove_lower_info_item (ITIP_VIEW (pitip->view), pitip->update_item_error_info_id);
+ pitip->update_item_error_info_id = 0;
+ }
+
+ if (message) {
+ itip_view_set_buttons_sensitive (ITIP_VIEW (pitip->view), FALSE);
+ pitip->update_item_progress_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+ ITIP_VIEW_INFO_ITEM_TYPE_PROGRESS,
+ message);
+ }
+}
+
+static void
+finish_message_delete_with_rsvp (struct _itip_puri *pitip,
+ ECalClient *client)
+{
+ gboolean save_schedules = e_cal_client_check_save_schedules (client);
+
+ if (!save_schedules && pitip->delete_message && pitip->folder)
+ camel_folder_delete_message (pitip->folder, pitip->uid);
+
+ if (itip_view_get_rsvp (ITIP_VIEW (pitip->view))) {
+ ECalComponent *comp = NULL;
+ icalcomponent *ical_comp;
+ icalproperty *prop;
+ icalvalue *value;
+ const gchar *attendee, *comment;
+ GSList *l, *list = NULL;
+ gboolean found;
+
+ comp = e_cal_component_clone (pitip->comp);
+ if (comp == NULL)
+ return;
+
+ if (pitip->to_address == NULL)
+ find_to_address (pitip, pitip->ical_comp, NULL);
+ g_assert (pitip->to_address != NULL);
+
+ ical_comp = e_cal_component_get_icalcomponent (comp);
+
+ /* Remove all attendees except the one we are responding as */
+ found = FALSE;
+ for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY);
+ prop != NULL;
+ prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) {
+ 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);
+
+ /* We do this to ensure there is at most one
+ * attendee in the response */
+ if (found || g_ascii_strcasecmp (pitip->to_address, text))
+ list = g_slist_prepend (list, prop);
+ else if (!g_ascii_strcasecmp (pitip->to_address, text))
+ found = TRUE;
+ g_free (text);
+ }
+
+ for (l = list; l; l = l->next) {
+ prop = l->data;
+ icalcomponent_remove_property (ical_comp, prop);
+ icalproperty_free (prop);
+ }
+ g_slist_free (list);
+
+ /* Add a comment if there user set one */
+ comment = itip_view_get_rsvp_comment (ITIP_VIEW (pitip->view));
+ if (comment) {
+ GSList comments;
+ ECalComponentText text;
+
+ text.value = comment;
+ text.altrep = NULL;
+
+ comments.data = &text;
+ comments.next = NULL;
+
+ e_cal_component_set_comment_list (comp, &comments);
+ }
+
+ e_cal_component_rescan (comp);
+ if (itip_send_comp (E_CAL_COMPONENT_METHOD_REPLY, comp, pitip->current_client, pitip->top_level, NULL, NULL, TRUE, FALSE) && pitip->folder) {
+ camel_folder_set_message_flags (
+ pitip->folder, pitip->uid,
+ CAMEL_MESSAGE_ANSWERED,
+ CAMEL_MESSAGE_ANSWERED);
+ }
+
+ g_object_unref (comp);
+ }
+
+ update_item_progress_info (pitip, NULL);
+}
+
+static void
+receive_objects_ready_cb (GObject *ecalclient,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ECalClient *client = E_CAL_CLIENT (ecalclient);
+ ESource *source = e_client_get_source (E_CLIENT (client));
+ struct _itip_puri *pitip = user_data;
+ gboolean save_schedules;
+ GError *error = NULL;
+
+ if (!e_cal_client_receive_objects_finish (client, result, &error)) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
+ !g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED)) {
+ update_item_progress_info (pitip, NULL);
+ pitip->update_item_error_info_id = itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+ _("Unable to send item to calendar '%s'. %s"),
+ e_source_peek_name (source), error ? error->message : _("Unknown error"));
+ }
+ g_clear_error (&error);
+ return;
+ }
+
+ itip_view_set_source_list (ITIP_VIEW (pitip->view), NULL);
+
+ itip_view_clear_lower_info_items (ITIP_VIEW (pitip->view));
+
+ switch (pitip->update_item_response) {
+ case ITIP_VIEW_RESPONSE_ACCEPT:
+ itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+ _("Sent to calendar '%s' as accepted"), e_source_peek_name (source));
+ break;
+ case ITIP_VIEW_RESPONSE_TENTATIVE:
+ itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+ _("Sent to calendar '%s' as tentative"), e_source_peek_name (source));
+ break;
+ case ITIP_VIEW_RESPONSE_DECLINE:
+ /* FIXME some calendars just might not save it at all, is this accurate? */
+ itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+ _("Sent to calendar '%s' as declined"), e_source_peek_name (source));
+ break;
+ case ITIP_VIEW_RESPONSE_CANCEL:
+ /* FIXME some calendars just might not save it at all, is this accurate? */
+ itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
+ _("Sent to calendar '%s' as canceled"), e_source_peek_name (source));
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ /*FIXME Save schedules is misused here, remove it */
+ save_schedules = e_cal_client_check_save_schedules (client);
+
+ /* FIXME Remove this and handle this at the groupwise mail provider */
+ if (save_schedules && pitip->can_delete_invitation_from_cache && pitip->folder) {
+ CamelFolderChangeInfo *changes = NULL;
+ const gchar *tag = NULL;
+ CamelMessageInfo *mi;
+ mi = camel_folder_summary_get (pitip->folder->summary, pitip->uid);
+ if (mi) {
+ changes = camel_folder_change_info_new ();
+
+ if (itip_view_get_recur_check_state (ITIP_VIEW (pitip->view))) {
+ /* Recurring appointment and "apply-to-all" is selected */
+ tag = camel_message_info_user_tag (mi, "recurrence-key");
+ if (tag) {
+ gint i;
+ GPtrArray *known_uids;
+
+ known_uids = camel_folder_summary_get_array (pitip->folder->summary);
+ for (i = 0; known_uids && i < known_uids->len; i++) {
+ const gchar *uid = g_ptr_array_index (known_uids, i);
+ CamelMessageInfo *mi2;
+
+ mi2 = camel_folder_summary_get (pitip->folder->summary, uid);
+ if (!mi2)
+ continue;
+
+ if (camel_message_info_user_tag (mi2, "recurrence-key") &&
+ g_str_equal (camel_message_info_user_tag (mi2, "recurrence-key"), tag)) {
+ camel_folder_summary_remove_uid (pitip->folder->summary, mi2->uid);
+ camel_folder_change_info_remove_uid (changes, mi2->uid);
+ }
+
+ camel_message_info_free (mi2);
+ }
+ }
+ } else {
+ /* Either not a recurring appointment or "apply-to-all" is not selected. So just delete this instance alone */
+ camel_folder_summary_remove_uid (pitip->folder->summary, pitip->uid);
+ camel_folder_change_info_remove_uid (changes, pitip->uid);
+ }
+
+ camel_folder_changed (pitip->folder, changes);
+ camel_folder_change_info_free (changes);
+ camel_message_info_free (mi);
+ }
+ }
+
+ finish_message_delete_with_rsvp (pitip, client);
+}
+
+static void
update_item (struct _itip_puri *pitip,
ItipViewResponse response)
{
@@ -1319,11 +1550,10 @@ update_item (struct _itip_puri *pitip,
icalproperty *prop;
icalcomponent *clone;
ECalComponent *clone_comp;
- ESource *source;
- GError *error = NULL;
- gboolean result = TRUE;
gchar *str;
+ update_item_progress_info (pitip, _("Saving changes to the calendar. Please wait..."));
+
/* Set X-MICROSOFT-CDO-REPLYTIME to record the time at which
* the user accepted/declined the request. (Outlook ignores
* SEQUENCE in REPLY reponses and instead requires that each
@@ -1359,11 +1589,11 @@ update_item (struct _itip_puri *pitip,
clone_comp = e_cal_component_new ();
if (!e_cal_component_set_icalcomponent (clone_comp, clone)) {
- itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("Unable to parse item"));
- result = FALSE;
+ update_item_progress_info (pitip, NULL);
+ pitip->update_item_error_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+ ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("Unable to parse item"));
goto cleanup;
}
- source = e_client_get_source (E_CLIENT (pitip->current_client));
if (itip_view_get_keep_alarm_check_state (ITIP_VIEW (pitip->view))) {
ECalComponent *real_comp;
@@ -1446,48 +1676,13 @@ update_item (struct _itip_puri *pitip,
e_cal_component_set_attachment_list (clone_comp, new_attachments);
}
- if (!e_cal_client_receive_objects_sync (pitip->current_client, pitip->top_level, NULL, &error)) {
- itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
- _("Unable to send item to calendar '%s'. %s"),
- e_source_peek_name (source), error->message);
- g_error_free (error);
- result = FALSE;
- } else {
- itip_view_set_source_list (ITIP_VIEW (pitip->view), NULL);
-
- itip_view_clear_lower_info_items (ITIP_VIEW (pitip->view));
-
- switch (response) {
- case ITIP_VIEW_RESPONSE_ACCEPT:
- itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
- _("Sent to calendar '%s' as accepted"), e_source_peek_name (source));
- break;
- case ITIP_VIEW_RESPONSE_TENTATIVE:
- itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
- _("Sent to calendar '%s' as tentative"), e_source_peek_name (source));
- break;
- case ITIP_VIEW_RESPONSE_DECLINE:
- /* FIXME some calendars just might not save it at all, is this accurate? */
- itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
- _("Sent to calendar '%s' as declined"), e_source_peek_name (source));
- break;
- case ITIP_VIEW_RESPONSE_CANCEL:
- /* FIXME some calendars just might not save it at all, is this accurate? */
- itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO,
- _("Sent to calendar '%s' as canceled"), e_source_peek_name (source));
- break;
- default:
- g_assert_not_reached ();
- break;
- }
+ pitip->update_item_response = response;
- /* FIXME Should we hide or desensitize the buttons now? */
- }
+ e_cal_client_receive_objects (pitip->current_client, pitip->top_level, pitip->cancellable, receive_objects_ready_cb, pitip);
cleanup:
icalcomponent_remove_component (pitip->top_level, clone);
g_object_unref (clone_comp);
- return result;
}
/* TODO These operations should be available in e-cal-component.c */
@@ -1613,133 +1808,239 @@ update_x (ECalComponent *pitip_comp,
}
static void
-update_attendee_status (struct _itip_puri *pitip)
+modify_object_cb (GObject *ecalclient,
+ GAsyncResult *result,
+ gpointer user_data)
{
- ECalComponent *comp = NULL;
- icalcomponent *icalcomp = NULL, *org_icalcomp;
- const gchar *uid;
- gchar *rid = NULL;
- const gchar *delegate;
+ ECalClient *client = E_CAL_CLIENT (ecalclient);
+ struct _itip_puri *pitip = user_data;
GError *error = NULL;
- /* Obtain our version */
- e_cal_component_get_uid (pitip->comp, &uid);
- org_icalcomp = e_cal_component_get_icalcomponent (pitip->comp);
+ if (!e_cal_client_modify_object_finish (client, result, &error)) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
+ g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED)) {
+ g_clear_error (&error);
+ return;
+ }
+
+ update_item_progress_info (pitip, NULL);
+ pitip->update_item_error_info_id = itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view),
+ ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+ _("Unable to update attendee. %s"), error ? error->message : _("Unknown error"));
+ g_clear_error (&error);
+ } else {
+ update_item_progress_info (pitip, NULL);
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+ ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Attendee status updated"));
+ }
+}
+
+static void
+update_attendee_status_icalcomp (struct _itip_puri *pitip,
+ icalcomponent *icalcomp)
+{
+ ECalComponent *comp;
+ const gchar *uid = NULL;
+ gchar *rid;
+ GSList *attendees;
+
+ e_cal_component_get_uid (pitip->comp, &uid);
rid = e_cal_component_get_recurid_as_string (pitip->comp);
- /* search for a master object if the detached object doesn't exist in the calendar */
- if (e_cal_client_get_object_sync (pitip->current_client, uid, rid, &icalcomp, NULL, NULL) || (rid && e_cal_client_get_object_sync (pitip->current_client, uid, NULL, &icalcomp, NULL, NULL))) {
- GSList *attendees;
+ comp = e_cal_component_new ();
+ if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
+ icalcomponent_free (icalcomp);
- comp = e_cal_component_new ();
- if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
- icalcomponent_free (icalcomp);
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, _("The meeting is invalid and cannot be updated"));
+ } else {
+ icalcomponent *org_icalcomp;
+ const gchar *delegate;
+
+ org_icalcomp = e_cal_component_get_icalcomponent (pitip->comp);
+
+ e_cal_component_get_attendee_list (pitip->comp, &attendees);
+ if (attendees != NULL) {
+ ECalComponentAttendee *a = attendees->data;
+ icalproperty *prop, *del_prop;
+
+ prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
+ if ((a->status == ICAL_PARTSTAT_DELEGATED) && (del_prop = find_attendee (org_icalcomp, itip_strip_mailto (a->delto))) && !(find_attendee (icalcomp, itip_strip_mailto (a->delto)))) {
+ gint response;
+ delegate = icalproperty_get_attendee (del_prop);
+ response = e_alert_run_dialog_for_args (GTK_WINDOW (gtk_widget_get_toplevel (pitip->view)),
+ "org.gnome.itip-formatter:add-delegate",
+ itip_strip_mailto (a->value),
+ itip_strip_mailto (delegate), NULL);
+ if (response == GTK_RESPONSE_YES) {
+ icalcomponent_add_property (icalcomp, icalproperty_new_clone (del_prop));
+ e_cal_component_rescan (comp);
+ } else if (response == GTK_RESPONSE_NO) {
+ remove_delegate (pitip, delegate, itip_strip_mailto (a->value), comp);
+ goto cleanup;
+ } else {
+ goto cleanup;
+ }
+ }
- itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, "The meeting is invalid and cannot be updated");
- } else {
- e_cal_component_get_attendee_list (pitip->comp, &attendees);
- if (attendees != NULL) {
- ECalComponentAttendee *a = attendees->data;
- icalproperty *prop, *del_prop;
-
- prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
- if ((a->status == ICAL_PARTSTAT_DELEGATED) && (del_prop = find_attendee (org_icalcomp, itip_strip_mailto (a->delto))) && !(find_attendee (icalcomp, itip_strip_mailto (a->delto)))) {
- gint response;
- delegate = icalproperty_get_attendee (del_prop);
+ if (prop == NULL) {
+ gint response;
+
+ if (a->delfrom && *a->delfrom) {
response = e_alert_run_dialog_for_args (GTK_WINDOW (gtk_widget_get_toplevel (pitip->view)),
"org.gnome.itip-formatter:add-delegate",
- itip_strip_mailto (a->value),
- itip_strip_mailto (delegate), NULL);
+ itip_strip_mailto (a->delfrom),
+ itip_strip_mailto (a->value), NULL);
if (response == GTK_RESPONSE_YES) {
- icalcomponent_add_property (icalcomp, icalproperty_new_clone (del_prop));
+ /* Already declared in this function */
+ icalproperty *prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
+ icalcomponent_add_property (icalcomp,icalproperty_new_clone (prop));
e_cal_component_rescan (comp);
} else if (response == GTK_RESPONSE_NO) {
- remove_delegate (pitip, delegate, itip_strip_mailto (a->value), comp);
+ remove_delegate (pitip,
+ itip_strip_mailto (a->value),
+ itip_strip_mailto (a->delfrom),
+ comp);
goto cleanup;
} else {
goto cleanup;
}
}
- if (prop == NULL) {
- gint response;
-
- if (a->delfrom && *a->delfrom) {
- response = e_alert_run_dialog_for_args (GTK_WINDOW (gtk_widget_get_toplevel (pitip->view)),
- "org.gnome.itip-formatter:add-delegate",
- itip_strip_mailto (a->delfrom),
- itip_strip_mailto (a->value), NULL);
- if (response == GTK_RESPONSE_YES) {
- /* Already declared in this function */
- icalproperty *prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
- icalcomponent_add_property (icalcomp,icalproperty_new_clone (prop));
- e_cal_component_rescan (comp);
- } else if (response == GTK_RESPONSE_NO) {
- remove_delegate (pitip,
- itip_strip_mailto (a->value),
- itip_strip_mailto (a->delfrom),
- comp);
- goto cleanup;
- } else {
- goto cleanup;
- }
- }
-
- response = e_alert_run_dialog_for_args (GTK_WINDOW (gtk_widget_get_toplevel (pitip->view)),
- "org.gnome.itip-formatter:add-unknown-attendee", NULL);
+ response = e_alert_run_dialog_for_args (GTK_WINDOW (gtk_widget_get_toplevel (pitip->view)),
+ "org.gnome.itip-formatter:add-unknown-attendee", NULL);
- if (response == GTK_RESPONSE_YES) {
- change_status (icalcomp, itip_strip_mailto (a->value), a->status);
- e_cal_component_rescan (comp);
- } else {
- goto cleanup;
- }
- } else if (a->status == ICAL_PARTSTAT_NONE || a->status == ICAL_PARTSTAT_X) {
- itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
- _("Attendee status could not be updated because the status is invalid"));
- goto cleanup;
+ if (response == GTK_RESPONSE_YES) {
+ change_status (icalcomp, itip_strip_mailto (a->value), a->status);
+ e_cal_component_rescan (comp);
} else {
- if (a->status == ICAL_PARTSTAT_DELEGATED) {
- /* *prop already declared in this function */
- icalproperty *prop, *new_prop;
+ goto cleanup;
+ }
+ } else if (a->status == ICAL_PARTSTAT_NONE || a->status == ICAL_PARTSTAT_X) {
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
+ _("Attendee status could not be updated because the status is invalid"));
+ goto cleanup;
+ } else {
+ if (a->status == ICAL_PARTSTAT_DELEGATED) {
+ /* *prop already declared in this function */
+ icalproperty *prop, *new_prop;
- prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
- icalcomponent_remove_property (icalcomp, prop);
+ prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
+ icalcomponent_remove_property (icalcomp, prop);
- new_prop = find_attendee (org_icalcomp, itip_strip_mailto (a->value));
- icalcomponent_add_property (icalcomp, icalproperty_new_clone (new_prop));
- } else
- change_status (icalcomp, itip_strip_mailto (a->value), a->status);
+ new_prop = find_attendee (org_icalcomp, itip_strip_mailto (a->value));
+ icalcomponent_add_property (icalcomp, icalproperty_new_clone (new_prop));
+ } else
+ change_status (icalcomp, itip_strip_mailto (a->value), a->status);
- e_cal_component_rescan (comp);
- }
+ e_cal_component_rescan (comp);
}
}
+ }
+
+ update_x (pitip->comp, comp);
- update_x (pitip->comp, comp);
+ if (itip_view_get_update (ITIP_VIEW (pitip->view))) {
+ e_cal_component_commit_sequence (comp);
+ itip_send_comp (E_CAL_COMPONENT_METHOD_REQUEST, comp, pitip->current_client, NULL, NULL, NULL, TRUE, FALSE);
+ }
+
+ update_item_progress_info (pitip, _("Saving changes to the calendar. Please wait..."));
+
+ e_cal_client_modify_object (pitip->current_client, icalcomp, rid ? CALOBJ_MOD_THIS : CALOBJ_MOD_ALL, pitip->cancellable, modify_object_cb, pitip);
+
+ cleanup:
+ g_object_unref (comp);
+}
- if (itip_view_get_update (ITIP_VIEW (pitip->view))) {
- e_cal_component_commit_sequence (comp);
- itip_send_comp (E_CAL_COMPONENT_METHOD_REQUEST, comp, pitip->current_client, NULL, NULL, NULL, TRUE, FALSE);
+static void
+update_attendee_status_get_object_without_rid_cb (GObject *ecalclient,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ECalClient *client = E_CAL_CLIENT (ecalclient);
+ struct _itip_puri *pitip = user_data;
+ icalcomponent *icalcomp = NULL;
+ GError *error = NULL;
+
+ if (!e_cal_client_get_object_finish (client, result, &icalcomp, &error)) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
+ g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED)) {
+ g_clear_error (&error);
+ return;
}
- if (!e_cal_client_modify_object_sync (pitip->current_client, icalcomp, rid ? CALOBJ_MOD_THIS : CALOBJ_MOD_ALL, NULL, &error)) {
- itip_view_add_lower_info_item_printf (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR,
- _("Unable to update attendee. %s"), error->message);
+ g_clear_error (&error);
- g_error_free (error);
- } else {
- itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Attendee status updated"));
+ update_item_progress_info (pitip, NULL);
+ pitip->update_item_error_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+ ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
+ _("Attendee status can not be updated because the item no longer exists"));
+ return;
+ }
+
+ update_attendee_status_icalcomp (pitip, icalcomp);
+}
+
+static void
+update_attendee_status_get_object_with_rid_cb (GObject *ecalclient,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ECalClient *client = E_CAL_CLIENT (ecalclient);
+ struct _itip_puri *pitip = user_data;
+ icalcomponent *icalcomp = NULL;
+ GError *error = NULL;
+
+ if (!e_cal_client_get_object_finish (client, result, &icalcomp, &error)) {
+ const gchar *uid;
+ gchar *rid;
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
+ g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED)) {
+ g_clear_error (&error);
+ return;
}
- } else {
- itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
- _("Attendee status can not be updated because the item no longer exists"));
+
+ g_clear_error (&error);
+
+ e_cal_component_get_uid (pitip->comp, &uid);
+ rid = e_cal_component_get_recurid_as_string (pitip->comp);
+
+ if (!rid || !*rid) {
+ g_free (rid);
+
+ update_item_progress_info (pitip, NULL);
+ pitip->update_item_error_info_id = itip_view_add_lower_info_item (ITIP_VIEW (pitip->view),
+ ITIP_VIEW_INFO_ITEM_TYPE_WARNING,
+ _("Attendee status can not be updated because the item no longer exists"));
+ return;
+ }
+
+ e_cal_client_get_object (pitip->current_client, uid, NULL, pitip->cancellable, update_attendee_status_get_object_without_rid_cb, pitip);
+
+ g_free (rid);
+ return;
}
- cleanup:
- if (comp != NULL)
- g_object_unref (comp);
+ update_attendee_status_icalcomp (pitip, icalcomp);
+}
+
+static void
+update_attendee_status (struct _itip_puri *pitip)
+{
+ const gchar *uid = NULL;
+ gchar *rid;
+
+ /* Obtain our version */
+ e_cal_component_get_uid (pitip->comp, &uid);
+ rid = e_cal_component_get_recurid_as_string (pitip->comp);
+
+ update_item_progress_info (pitip, _("Saving changes to the calendar. Please wait..."));
+
+ /* search for a master object if the detached object doesn't exist in the calendar */
+ e_cal_client_get_object (pitip->current_client, uid, rid, pitip->cancellable, update_attendee_status_get_object_with_rid_cb, pitip);
+
g_free (rid);
}
@@ -2220,11 +2521,11 @@ view_response_cb (GtkWidget *widget,
gpointer data)
{
struct _itip_puri *pitip = data;
- gboolean status = FALSE, delete_invitation_from_cache = FALSE;
+ gboolean status = FALSE;
icalproperty *prop;
ECalComponentTransparency trans;
- gboolean flag, save_schedules;
+ pitip->can_delete_invitation_from_cache = FALSE;
if (pitip->method == ICAL_METHOD_PUBLISH || pitip->method == ICAL_METHOD_REQUEST) {
if (itip_view_get_free_time_check_state (ITIP_VIEW (pitip->view)))
e_cal_component_set_transparency (pitip->comp, E_CAL_COMPONENT_TRANSP_TRANSPARENT);
@@ -2248,9 +2549,6 @@ view_response_cb (GtkWidget *widget,
icalcomponent_add_property (pitip->ical_comp, prop);
}
- /*FIXME Save schedules is misused here, remove it */
- save_schedules = e_cal_client_check_save_schedules (pitip->current_client);
-
switch (response) {
case ITIP_VIEW_RESPONSE_ACCEPT:
if (pitip->type != E_CAL_CLIENT_SOURCE_TYPE_MEMOS)
@@ -2260,9 +2558,8 @@ view_response_cb (GtkWidget *widget,
status = TRUE;
if (status) {
e_cal_component_rescan (pitip->comp);
- flag = update_item (pitip, response);
- if (save_schedules && flag)
- delete_invitation_from_cache = TRUE;
+ pitip->can_delete_invitation_from_cache = TRUE;
+ update_item (pitip, response);
}
break;
case ITIP_VIEW_RESPONSE_TENTATIVE:
@@ -2270,10 +2567,8 @@ view_response_cb (GtkWidget *widget,
ICAL_PARTSTAT_TENTATIVE);
if (status) {
e_cal_component_rescan (pitip->comp);
- flag = update_item (pitip, response);
- if (save_schedules && flag)
- delete_invitation_from_cache = TRUE;
-
+ pitip->can_delete_invitation_from_cache = TRUE;
+ update_item (pitip, response);
}
break;
case ITIP_VIEW_RESPONSE_DECLINE:
@@ -2289,9 +2584,8 @@ view_response_cb (GtkWidget *widget,
if (status) {
e_cal_component_rescan (pitip->comp);
- flag = update_item (pitip, response);
- if (save_schedules && flag)
- delete_invitation_from_cache = TRUE;
+ pitip->can_delete_invitation_from_cache = TRUE;
+ update_item (pitip, response);
}
break;
case ITIP_VIEW_RESPONSE_UPDATE:
@@ -2309,133 +2603,6 @@ view_response_cb (GtkWidget *widget,
default:
break;
}
-
- /* FIXME Remove this and handle this at the groupwise mail provider */
- if (delete_invitation_from_cache && pitip->folder) {
- CamelFolderChangeInfo *changes = NULL;
- const gchar *tag = NULL;
- CamelMessageInfo *mi;
- mi = camel_folder_summary_get (pitip->folder->summary, pitip->uid);
- if (mi) {
- changes = camel_folder_change_info_new ();
-
- if (itip_view_get_recur_check_state (ITIP_VIEW (pitip->view))) {
- /* Recurring appointment and "apply-to-all" is selected */
- tag = camel_message_info_user_tag (mi, "recurrence-key");
- if (tag) {
- gint i;
- GPtrArray *known_uids;
-
- known_uids = camel_folder_summary_get_array (pitip->folder->summary);
- for (i = 0; known_uids && i < known_uids->len; i++) {
- const gchar *uid = g_ptr_array_index (known_uids, i);
- CamelMessageInfo *mi2;
-
- mi2 = camel_folder_summary_get (pitip->folder->summary, uid);
- if (!mi2)
- continue;
-
- if (camel_message_info_user_tag (mi2, "recurrence-key") &&
- g_str_equal (camel_message_info_user_tag (mi2, "recurrence-key"), tag)) {
- camel_folder_summary_remove_uid (pitip->folder->summary, mi2->uid);
- camel_folder_change_info_remove_uid (changes, mi2->uid);
- }
-
- camel_message_info_free (mi2);
- }
- }
- } else {
- /* Either not a recurring appointment or "apply-to-all" is not selected. So just delete this instance alone */
- camel_folder_summary_remove_uid (pitip->folder->summary, pitip->uid);
- camel_folder_change_info_remove_uid (changes, pitip->uid);
- }
-
- camel_folder_changed (pitip->folder, changes);
- camel_folder_change_info_free (changes);
- camel_message_info_free (mi);
- }
- }
-
- if (!save_schedules && pitip->delete_message && pitip->folder)
- camel_folder_delete_message (pitip->folder, pitip->uid);
-
- if (itip_view_get_rsvp (ITIP_VIEW (pitip->view)) && status) {
- ECalComponent *comp = NULL;
- icalcomponent *ical_comp;
- icalvalue *value;
- const gchar *attendee, *comment;
- GSList *l, *list = NULL;
- gboolean found;
-
- comp = e_cal_component_clone (pitip->comp);
- if (comp == NULL)
- return;
-
- if (pitip->to_address == NULL)
- find_to_address (pitip, pitip->ical_comp, NULL);
- g_assert (pitip->to_address != NULL);
-
- ical_comp = e_cal_component_get_icalcomponent (comp);
-
- /* Remove all attendees except the one we are responding as */
- found = FALSE;
- for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY);
- prop != NULL;
- prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY))
- {
- 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);
-
- /* We do this to ensure there is at most one
- * attendee in the response */
- if (found || g_ascii_strcasecmp (pitip->to_address, text))
- list = g_slist_prepend (list, prop);
- else if (!g_ascii_strcasecmp (pitip->to_address, text))
- found = TRUE;
- g_free (text);
- }
-
- for (l = list; l; l = l->next) {
- prop = l->data;
- icalcomponent_remove_property (ical_comp, prop);
- icalproperty_free (prop);
- }
- g_slist_free (list);
-
- /* Add a comment if there user set one */
- comment = itip_view_get_rsvp_comment (ITIP_VIEW (pitip->view));
- if (comment) {
- GSList comments;
- ECalComponentText text;
-
- text.value = comment;
- text.altrep = NULL;
-
- comments.data = &text;
- comments.next = NULL;
-
- e_cal_component_set_comment_list (comp, &comments);
- }
-
- e_cal_component_rescan (comp);
- if (itip_send_comp (E_CAL_COMPONENT_METHOD_REPLY, comp, pitip->current_client, pitip->top_level, NULL, NULL, TRUE, FALSE) && pitip->folder) {
- camel_folder_set_message_flags (
- pitip->folder, pitip->uid,
- CAMEL_MESSAGE_ANSWERED,
- CAMEL_MESSAGE_ANSWERED);
- }
-
- g_object_unref (comp);
-
- }
}
static gboolean
@@ -2881,6 +3048,7 @@ puri_free (EMFormatPURI *puri)
g_free (pitip->my_address);
pitip->my_address = NULL;
g_free (pitip->uid);
+ g_hash_table_destroy (pitip->real_comps);
}
void
@@ -2915,6 +3083,7 @@ format_itip (EPlugin *ep,
puri->msg = ((EMFormat *) target->format)->message;
puri->part = target->part;
puri->cancellable = g_cancellable_new ();
+ puri->real_comps = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
puri->puri.free = puri_free;
g_object_unref (settings);
diff --git a/plugins/itip-formatter/itip-view.c b/plugins/itip-formatter/itip-view.c
index fd4190b593..eb08828ed9 100644
--- a/plugins/itip-formatter/itip-view.c
+++ b/plugins/itip-formatter/itip-view.c
@@ -2192,6 +2192,11 @@ itip_view_set_buttons_sensitive (ItipView *view,
priv->buttons_sensitive = sensitive;
gtk_widget_set_sensitive (priv->button_box, priv->buttons_sensitive);
+ gtk_widget_set_sensitive (priv->update_box, priv->buttons_sensitive);
+ gtk_widget_set_sensitive (priv->recur_box, priv->buttons_sensitive);
+ gtk_widget_set_sensitive (priv->options_box, priv->buttons_sensitive);
+ gtk_widget_set_sensitive (priv->selector_box, priv->buttons_sensitive);
+ gtk_widget_set_sensitive (priv->rsvp_box, priv->buttons_sensitive);
}
gboolean