aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/itip-formatter/.cvsignore2
-rw-r--r--plugins/itip-formatter/ChangeLog25
-rw-r--r--plugins/itip-formatter/Makefile.am8
-rw-r--r--plugins/itip-formatter/itip-formatter.c260
-rw-r--r--plugins/itip-formatter/itip-view.c14
-rw-r--r--plugins/itip-formatter/itip-view.h1
-rw-r--r--plugins/itip-formatter/org-gnome-itip-formatter-errors.xml13
7 files changed, 288 insertions, 35 deletions
diff --git a/plugins/itip-formatter/.cvsignore b/plugins/itip-formatter/.cvsignore
index 76bd16c42d..12b8e0db22 100644
--- a/plugins/itip-formatter/.cvsignore
+++ b/plugins/itip-formatter/.cvsignore
@@ -3,4 +3,4 @@
Makefile
Makefile.in
*.eplug
-backup \ No newline at end of file
+org-gnome-itip-formatter-errors.xml.h
diff --git a/plugins/itip-formatter/ChangeLog b/plugins/itip-formatter/ChangeLog
index d4b47dc96a..379c562fc8 100644
--- a/plugins/itip-formatter/ChangeLog
+++ b/plugins/itip-formatter/ChangeLog
@@ -1,5 +1,30 @@
2005-01-03 JP Rosevear <jpr@novell.com>
+ * itip-view.h: add response enums
+
+ * itip-view.c (set_buttons): fiddle with button names and response enums
+
+ * itip-formatter.c (find_server): don't include our uid in the
+ conflicts search
+ (update_attendee_status): update the status of the attendee and
+ save it out
+ (adjust_item): get relevant properties for items that might
+ contain them if sent from an attendee
+ (get_real_item): get the actual, current item
+ (send_item): send the item
+ (view_response_cb): handle REPLY and REFRESH requests
+ (format_itip_object): adjust the item if necessary and set the
+ attendee for reply/refresh; prevent crash if no description
+ (pitip_free): skeleton free function
+ (format_itip): load delete message setting
+ (delete_toggled_cb): set delete message setting based on toggle
+ (itip_formatter_page_factory): make the delete message check box
+ work
+
+ * Makefile.am: install e-error messages
+
+2005-01-03 JP Rosevear <jpr@novell.com>
+
* itip-view.h: new protos, signal
* itip-view.c (set_info_items): be more generic so both upper and
diff --git a/plugins/itip-formatter/Makefile.am b/plugins/itip-formatter/Makefile.am
index 418d43830c..6805a7c9f6 100644
--- a/plugins/itip-formatter/Makefile.am
+++ b/plugins/itip-formatter/Makefile.am
@@ -11,4 +11,12 @@ plugin_LTLIBRARIES = liborg-gnome-itip-formatter.la
liborg_gnome_itip_formatter_la_SOURCES = itip-formatter.c itip-view.c itip-view.h
liborg_gnome_itip_formatter_la_LDFLAGS = -module -avoid-version
+error_DATA = org-gnome-itip-formatter-errors.xml
+error_i18n = $(error_DATA:.xml=.xml.h)
+errordir = $(privdatadir)/errors
+%.xml.h: %.xml
+ $(top_builddir)/e-util/e-error-tool $^
+
+BUILT_SOURCES = $(error_i18n)
+
EXTRA_DIST = org-gnome-itip-formatter.eplug.in \ No newline at end of file
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index 871c8cb3bf..7944d7be0a 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -33,6 +33,7 @@
#include <camel/camel-stream-mem.h>
#include <camel/camel-medium.h>
#include <camel/camel-mime-message.h>
+#include <camel/camel-folder.h>
#include <libecal/e-cal.h>
#include <libecal/e-cal-time-util.h>
#include <libedataserverui/e-source-option-menu.h>
@@ -43,12 +44,14 @@
#include <mail/em-format-html.h>
#include <e-util/e-account-list.h>
#include <e-util/e-icon-factory.h>
+#include <widgets/misc/e-error.h>
#include <calendar/gui/calendar-config.h>
#include <calendar/gui/itip-utils.h>
#include <calendar/common/authentication.h>
#include "itip-view.h"
#define CLASSID "itip://"
+#define GCONF_KEY_DELETE "/apps/evolution/itip/delete_processed"
void format_itip (EPlugin *ep, EMFormatHookTarget *target);
GtkWidget *itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data);
@@ -88,6 +91,8 @@ typedef struct {
gint view_only;
guint progress_info_id;
+
+ gboolean delete_message;
} FormatItipPObject;
typedef struct {
@@ -453,7 +458,7 @@ find_server (FormatItipPObject *pitip, ECalComponent *comp, gboolean show_select
source = m->data;
if (!fd) {
- char *start, *end;
+ char *start = NULL, *end = NULL;
fd = g_new0 (EItipControlFindData, 1);
fd->pitip = pitip;
@@ -464,7 +469,8 @@ find_server (FormatItipPObject *pitip, ECalComponent *comp, gboolean show_select
start = isodate_from_time_t (pitip->start_time);
end = isodate_from_time_t (pitip->end_time);
- fd->sexp = g_strdup_printf ("(occur-in-time-range? (make-time \"%s\") (make-time \"%s\"))", start, end);
+ fd->sexp = g_strdup_printf ("(and (occur-in-time-range? (make-time \"%s\") (make-time \"%s\")) (not (uid? \"%s\")))",
+ start, end, icalcomponent_get_uid (pitip->ical_comp));
g_message ("Sexp is %s", fd->sexp);
}
@@ -634,6 +640,139 @@ update_item (FormatItipPObject *pitip, ItipViewResponse response)
icalcomponent_remove_component (pitip->top_level, clone);
}
+static void
+update_attendee_status (FormatItipPObject *pitip)
+{
+ ECalComponent *comp = NULL;
+ icalcomponent *icalcomp = NULL;
+ const char *uid;
+ GError *error;
+
+ /* Obtain our version */
+ e_cal_component_get_uid (pitip->comp, &uid);
+ if (e_cal_get_object (pitip->current_ecal, uid, NULL, &icalcomp, NULL)) {
+ GSList *attendees;
+
+ 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 {
+ e_cal_component_get_attendee_list (pitip->comp, &attendees);
+ if (attendees != NULL) {
+ ECalComponentAttendee *a = attendees->data;
+ icalproperty *prop;
+
+ prop = find_attendee (icalcomp, itip_strip_mailto (a->value));
+
+ if (prop == NULL) {
+ if (e_error_run (NULL, "org.gnome.itip-formatter:add-unknown-attendee", NULL) == 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;
+ } else {
+ change_status (icalcomp, itip_strip_mailto (a->value), a->status);
+ e_cal_component_rescan (comp);
+ }
+ }
+ }
+
+ if (!e_cal_modify_object (pitip->current_ecal, icalcomp, CALOBJ_MOD_ALL, &error)) {
+ char *info;
+
+ info = g_strdup_printf (_("Unable to update attendee statusAttendee status updated. %s"), error->message);
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, info);
+ g_free (info);
+
+ g_error_free (error);
+ } else {
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("Attendee status updated"));
+ }
+ } 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"));
+ }
+
+ cleanup:
+ if (comp != NULL)
+ g_object_unref (comp);
+}
+
+static ECalComponent *
+get_real_item (FormatItipPObject *pitip)
+{
+ ECalComponent *comp;
+ icalcomponent *icalcomp;
+ gboolean found = FALSE;
+ const char *uid;
+
+ e_cal_component_get_uid (pitip->comp, &uid);
+
+ found = e_cal_get_object (pitip->current_ecal, uid, NULL, &icalcomp, NULL);
+ if (!found)
+ return NULL;
+
+ comp = e_cal_component_new ();
+ if (!e_cal_component_set_icalcomponent (comp, icalcomp)) {
+ g_object_unref (comp);
+ icalcomponent_free (icalcomp);
+ return NULL;
+ }
+
+ return comp;
+}
+
+static void
+adjust_item (FormatItipPObject *pitip, ECalComponent *comp)
+{
+ ECalComponent *real_comp;
+
+ real_comp = get_real_item (pitip);
+ if (real_comp != NULL) {
+ ECalComponentText text;
+ const char *string;
+ GSList *l;
+
+ e_cal_component_get_summary (real_comp, &text);
+ e_cal_component_set_summary (comp, &text);
+ e_cal_component_get_location (real_comp, &string);
+ e_cal_component_set_location (comp, string);
+ e_cal_component_get_description_list (real_comp, &l);
+ e_cal_component_set_description_list (comp, l);
+ e_cal_component_free_text_list (l);
+
+ g_object_unref (real_comp);
+ } else {
+ ECalComponentText text = {_("Unknown"), NULL};
+
+ e_cal_component_set_summary (comp, &text);
+ }
+}
+
+static void
+send_item (FormatItipPObject *pitip)
+{
+ ECalComponent *comp;
+
+ comp = get_real_item (pitip);
+
+ if (comp != NULL) {
+ itip_send_comp (E_CAL_COMPONENT_METHOD_REQUEST, comp, pitip->current_ecal, NULL);
+ g_object_unref (comp);
+
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_INFO, "Meeting information sent");
+ } else {
+ itip_view_add_lower_info_item (ITIP_VIEW (pitip->view), ITIP_VIEW_INFO_ITEM_TYPE_ERROR, "Unable to send meeting information, the meeting does not exist");
+ }
+}
+
static icalcomponent *
get_next (icalcompiter *iter)
{
@@ -667,7 +806,7 @@ extract_itip_data (FormatItipPObject *pitip)
content = camel_medium_get_content_object ((CamelMedium *) pitip->pobject.part);
mem = camel_stream_mem_new ();
camel_data_wrapper_write_to_stream (content, mem);
-
+
pitip->vcalendar = g_strndup (((CamelStreamMem *) mem)->buffer->data, ((CamelStreamMem *) mem)->buffer->len);
camel_object_unref (mem);
@@ -763,10 +902,21 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
update_item (pitip, response);
}
break;
+ case ITIP_VIEW_RESPONSE_UPDATE:
+ update_attendee_status (pitip);
+ break;
+ case ITIP_VIEW_RESPONSE_REFRESH:
+ send_item (pitip);
+ break;
default:
break;
}
+ if (pitip->delete_message) {
+ g_message ("Deleting!");
+ camel_folder_delete_message (((EMFormat *) pitip->pobject.format)->folder, ((EMFormat *) pitip->pobject.format)->uid);
+ }
+
if (e_cal_get_save_schedules (pitip->current_ecal))
return;
@@ -884,16 +1034,49 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
/* FIXME What to do here? */
itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_ERROR);
}
+
+ switch (pitip->method) {
+ case ICAL_METHOD_PUBLISH:
+ case ICAL_METHOD_REQUEST:
+ case ICAL_METHOD_ADD:
+ case ICAL_METHOD_CANCEL:
+ /* An organizer sent this */
+ e_cal_component_get_organizer (pitip->comp, &organizer);
+ itip_view_set_organizer (ITIP_VIEW (pitip->view), organizer.cn ? organizer.cn : itip_strip_mailto (organizer.value));
+ /* FIXME, do i need to strip the sentby somehow? Maybe with camel? */
+ itip_view_set_sentby (ITIP_VIEW (pitip->view), organizer.sentby);
- e_cal_component_get_organizer (pitip->comp, &organizer);
- itip_view_set_organizer (ITIP_VIEW (pitip->view), organizer.cn ? organizer.cn : itip_strip_mailto (organizer.value));
- /* FIXME, do i need to strip the sentby somehow? Maybe with camel? */
- itip_view_set_sentby (ITIP_VIEW (pitip->view), organizer.sentby);
+ /* FIXME try and match sender with organizer/attendee/sentby?
+ pd->from_address = camel_address_encode
+ ((CamelAddress *)from); g_message ("Detected from address %s",
+ pd->from_address);
+ */
+ break;
+ case ICAL_METHOD_REPLY:
+ case ICAL_METHOD_REFRESH:
+ /* Provide extra info, since its not in the component */
+ /* FIXME Check sequence number of meeting? */
+ adjust_item (pitip, pitip->comp);
+
+ case ICAL_METHOD_COUNTER:
+ case ICAL_METHOD_DECLINECOUNTER:
+ /* An attendee sent this */
+ e_cal_component_get_attendee_list (pitip->comp, &list);
+ if (list != NULL) {
+ ECalComponentAttendee *attendee;
+
+ attendee = list->data;
+
+ itip_view_set_attendee (ITIP_VIEW (pitip->view), attendee->cn ? attendee->cn : itip_strip_mailto (attendee->value));
-/* FIXME try and match sender with organizer/attendee/sentby?
- pd->from_address = camel_address_encode ((CamelAddress *)from);
- g_message ("Detected from address %s", pd->from_address);
-*/
+ e_cal_component_free_attendee_list (list);
+ }
+
+ break;
+ default:
+ /* FIXME What to do here? */
+ itip_view_set_mode (ITIP_VIEW (pitip->view), ITIP_VIEW_MODE_ERROR);
+ }
e_cal_component_get_summary (pitip->comp, &text);
itip_view_set_summary (ITIP_VIEW (pitip->view), text.value ? text.value : _("None"));
@@ -914,9 +1097,11 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
g_string_append_printf (gstring, "\n\n%s", text->value);
}
e_cal_component_free_text_list (list);
-
- itip_view_set_description (ITIP_VIEW (pitip->view), gstring->str);
- g_string_free (gstring, TRUE);
+
+ if (gstring) {
+ itip_view_set_description (ITIP_VIEW (pitip->view), gstring->str);
+ g_string_free (gstring, TRUE);
+ }
to_zone = calendar_config_get_icaltimezone ();
@@ -975,24 +1160,44 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
return TRUE;
}
+static void
+pitip_free (EMFormatHTMLPObject *pobject)
+{
+ FormatItipPObject *pitip = (FormatItipPObject *) pobject;
+
+
+}
+
void
format_itip (EPlugin *ep, EMFormatHookTarget *target)
{
FormatItipPObject *pitip;
-
+ GConfClient *gconf;
+
pitip = (FormatItipPObject *) em_format_html_add_pobject ((EMFormatHTML *) target->format, sizeof (FormatItipPObject), CLASSID, target->part, format_itip_object);
- // FIXME set the free function
-// pitip->object.free = pitip_free;
+ pitip->pobject.free = pitip_free;
+ gconf = gconf_client_get_default ();
+ pitip->delete_message = gconf_client_get_bool (gconf, GCONF_KEY_DELETE, NULL);
+ g_object_unref (gconf);
+
camel_stream_printf (target->stream, "<table border=0 width=\"100%%\" cellpadding=3><tr>");
camel_stream_printf (target->stream, "<td valign=top><object classid=\"%s\"></object></td><td width=100%% valign=top>", CLASSID);
camel_stream_printf (target->stream, "</td></tr></table>");
}
+static void
+delete_toggled_cb (GtkWidget *widget, gpointer data)
+{
+ EMConfigTargetPrefs *target = data;
+
+ gconf_client_set_bool (target->gconf, GCONF_KEY_DELETE, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)), NULL);
+}
+
GtkWidget *
itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data)
{
-// EMConfigTargetPrefs *target = (EMConfigTargetPrefs *) hook_data->config->target;
+ EMConfigTargetPrefs *target = (EMConfigTargetPrefs *) hook_data->config->target;
GtkWidget *page;
GtkWidget *tab_label;
GtkWidget *frame;
@@ -1003,10 +1208,6 @@ itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data)
GtkWidget *check;
GtkWidget *check_gaim;
- /* A structure to pass some stuff around */
-// stuff = g_new0 (struct bbdb_stuff, 1);
-// stuff->target = target;
-
/* Create a new notebook page */
page = gtk_vbox_new (FALSE, 0);
GTK_CONTAINER (page)->border_width = 12;
@@ -1017,7 +1218,7 @@ itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data)
frame = gtk_vbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
- /* "Automatic Contacts" */
+ /* "General" */
frame_label = gtk_label_new ("");
gtk_label_set_markup (GTK_LABEL (frame_label), _("<span weight=\"bold\">General</span>"));
GTK_MISC (frame_label)->xalign = 0.0;
@@ -1031,14 +1232,14 @@ itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data)
inner_vbox = gtk_vbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (hbox), inner_vbox, FALSE, FALSE, 0);
- /* Enable BBDB checkbox */
+ /* Delete message after acting */
+ /* FIXME Need a schema for this */
check = gtk_check_button_new_with_mnemonic (_("_Delete message after acting"));
-// gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), gconf_client_get_bool (target->gconf, GCONF_KEY_ENABLE, NULL));
-// g_signal_connect (GTK_TOGGLE_BUTTON (check), "toggled", G_CALLBACK (enable_toggled_cb), stuff);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), gconf_client_get_bool (target->gconf, GCONF_KEY_DELETE, NULL));
+ g_signal_connect (GTK_TOGGLE_BUTTON (check), "toggled", G_CALLBACK (delete_toggled_cb), target);
gtk_box_pack_start (GTK_BOX (inner_vbox), check, FALSE, FALSE, 0);
-// stuff->check = check;
- /* "Instant Messaging Contacts" */
+ /* "Conflict searching" */
frame = gtk_vbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (page), frame, TRUE, TRUE, 24);
@@ -1055,10 +1256,9 @@ itip_formatter_page_factory (EPlugin *ep, EConfigHookItemFactoryData *hook_data)
inner_vbox = gtk_vbox_new (FALSE, 6);
gtk_box_pack_start (GTK_BOX (hbox), inner_vbox, FALSE, FALSE, 0);
- /* Enable Gaim Checkbox */
+ /* Source selector */
check_gaim = gtk_label_new (_("Select the calendars to search for meeting conflicts"));
gtk_box_pack_start (GTK_BOX (inner_vbox), check_gaim, FALSE, FALSE, 0);
-// stuff->check_gaim = check_gaim;
gtk_widget_show_all (page);
diff --git a/plugins/itip-formatter/itip-view.c b/plugins/itip-formatter/itip-view.c
index 4b9f161e30..3734b74d92 100644
--- a/plugins/itip-formatter/itip-view.c
+++ b/plugins/itip-formatter/itip-view.c
@@ -534,22 +534,28 @@ set_buttons (ItipView *view)
break;
case ITIP_VIEW_MODE_ADD:
/* FIXME Right response? */
- set_one_button (view, "_Add", GTK_STOCK_ADD, ITIP_VIEW_RESPONSE_ACCEPT);
+ set_one_button (view, "_Add", GTK_STOCK_ADD, ITIP_VIEW_RESPONSE_UPDATE);
break;
case ITIP_VIEW_MODE_REFRESH:
/* FIXME Is this really the right button? */
- set_one_button (view, "_Refresh", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_REFRESH);
+ set_one_button (view, "_Send Meeting Information", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_REFRESH);
break;
case ITIP_VIEW_MODE_REPLY:
/* FIXME Is this really the right button? */
- set_one_button (view, "_Update", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_UPDATE);
+ set_one_button (view, "_Update Attendee Status", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_UPDATE);
break;
case ITIP_VIEW_MODE_CANCEL:
- set_one_button (view, "_Update", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_UPDATE);
+ set_one_button (view, "_Update", GTK_STOCK_REFRESH, ITIP_VIEW_RESPONSE_CANCEL);
break;
case ITIP_VIEW_MODE_COUNTER:
+ set_one_button (view, "_Decline", GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
+ set_one_button (view, "_Tentative", GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
+ set_one_button (view, "_Accept", GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
break;
case ITIP_VIEW_MODE_DECLINECOUNTER:
+ set_one_button (view, "_Decline", GTK_STOCK_CANCEL, ITIP_VIEW_RESPONSE_DECLINE);
+ set_one_button (view, "_Tentative", GTK_STOCK_DIALOG_QUESTION, ITIP_VIEW_RESPONSE_TENTATIVE);
+ set_one_button (view, "_Accept", GTK_STOCK_APPLY, ITIP_VIEW_RESPONSE_ACCEPT);
break;
default:
break;
diff --git a/plugins/itip-formatter/itip-view.h b/plugins/itip-formatter/itip-view.h
index c42a931b31..24b167dd31 100644
--- a/plugins/itip-formatter/itip-view.h
+++ b/plugins/itip-formatter/itip-view.h
@@ -59,6 +59,7 @@ typedef enum {
ITIP_VIEW_RESPONSE_TENTATIVE,
ITIP_VIEW_RESPONSE_DECLINE,
ITIP_VIEW_RESPONSE_UPDATE,
+ ITIP_VIEW_RESPONSE_CANCEL,
ITIP_VIEW_RESPONSE_REFRESH,
ITIP_VIEW_RESPONSE_OPEN
} ItipViewResponse;
diff --git a/plugins/itip-formatter/org-gnome-itip-formatter-errors.xml b/plugins/itip-formatter/org-gnome-itip-formatter-errors.xml
new file mode 100644
index 0000000000..7ed8c46d4b
--- /dev/null
+++ b/plugins/itip-formatter/org-gnome-itip-formatter-errors.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<error-list domain="org.gnome.itip-formatter">
+
+ <error id="meeting-update-failed" type="error">
+ <primary>Unable to save meeting to calendar</primary>
+ <secondary>The error sent back was "{0}".</secondary>
+ </error>
+
+ <error id="add-unknown-attendee" type="question">
+ <primary>This response is not from a current attendee. Add the sender as an attendee?</primary>
+ </error>
+
+</error-list>