aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--calendar/ChangeLog39
-rw-r--r--calendar/gui/dialogs/comp-editor.c68
-rw-r--r--calendar/gui/dialogs/event-editor.c37
-rw-r--r--calendar/gui/dialogs/meeting-page.c71
-rw-r--r--calendar/gui/e-cal-popup.c85
-rw-r--r--calendar/gui/e-calendar-view.c55
-rw-r--r--calendar/gui/e-meeting-list-view.c43
-rw-r--r--calendar/gui/e-meeting-list-view.h3
-rw-r--r--calendar/gui/itip-utils.c155
-rw-r--r--calendar/gui/itip-utils.h2
10 files changed, 490 insertions, 68 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 020a748859..a6d6886dac 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,3 +1,42 @@
+2005-06-20 Chenthill Palanisamy <pchenthill@novell.com>
+
+ * gui/dialogs/comp-editor.c (save_comp_with_send),
+ (real_edit_comp), (set_attendees_for_delegation), (real_send_comp):
+ If a meeting is delegated. Send a Request to the delegate and a
+ reply to the organizer.
+ * gui/dialogs/event-editor.c: (event_editor_edit_comp): Add the
+ delegator alone in the meeting editor for personal calendar.
+ (event_editor_send_comp), (show_meeting): Show the scheduling
+ page if the meeting is being delegated.
+ * gui/dialogs/meeting-page.c: (clear_widgets),
+ (meeting_page_fill_widgets), (meeting_page_fill_component),
+ (add_clicked_cb), (remove_attendee), (remove_clicked_cb),
+ (init_widgets), (attendee_added_cb), (meeting_page_construct):
+ Do not allow only non-attendees to be added as delegatees.
+ While sending the delegated item remove the other attendees.
+ Allow only one delegate to be added for personal calendar.
+ * gui/e-cal-popup.c: (get_attendee_prop), (is_delegated)
+ (e_cal_popup_target_new_select):Disabled
+ the popup menu item if the meeting is already delegated.
+ * gui/e-cal-popup.h: Added a new mask to check if the meeting
+ is already delegated.
+ * gui/e-calendar-view.c: (set_attendee_status_for_delegate),
+ (on_delegate): Change the status of the attendee to delegated.
+ Set the new mask for the delegate popup menu item.
+ * gui/e-meeting-list-view.c: (e_meeting_list_view_class_init),
+ (attendee_edited_cb): Added a new signal to identify the attendee
+ added in meeting page. Do not remove the attendee if the user
+ modifies the existing email id to NULL value.
+ * gui/e-meeting-list-view.h: Added the notification signal.
+ * gui/itip-utils.h: Added a new function to get our email id
+ from the list of attendees.
+ * gui/itip-utils.c (get_attendee), (itip_get_comp_attendee),
+ (comp_from), (comp_to_list), (comp_subject), (comp_sentby),
+ (itip_send_comp): Send udpates to delegator only
+ if the rsvp is enabled. Set the status of the attendee
+ properly in the REPLY method, since there will two attendees
+ unlike the updating attendee status.
+
2005-06-18 Tor Lillqvist <tml@novell.com>
* gui/GNOME_Evolution_Calendar.server.in.in
diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c
index 495de600be..abd16741c4 100644
--- a/calendar/gui/dialogs/comp-editor.c
+++ b/calendar/gui/dialogs/comp-editor.c
@@ -731,19 +731,26 @@ save_comp_with_send (CompEditor *editor)
{
CompEditorPrivate *priv;
gboolean send;
+ gboolean delegate;
priv = editor->priv;
-
+
send = priv->changed && priv->needs_send;
+ delegate = priv->flags & COMP_EDITOR_DELEGATE;
if (!save_comp (editor))
return FALSE;
- if (send && send_component_dialog ((GtkWindow *) editor, priv->client, priv->comp, !priv->existing_org)) {
+ if (delegate || (send && send_component_dialog ((GtkWindow *) editor, priv->client, priv->comp, !priv->existing_org))) {
if (itip_organizer_is_user (priv->comp, priv->client))
return comp_editor_send_comp (editor, E_CAL_COMPONENT_METHOD_REQUEST);
- else
- return comp_editor_send_comp (editor, E_CAL_COMPONENT_METHOD_REPLY);
+ else {
+ if (!comp_editor_send_comp (editor, E_CAL_COMPONENT_METHOD_REQUEST))
+ return FALSE;
+
+ if (delegate)
+ return comp_editor_send_comp (editor, E_CAL_COMPONENT_METHOD_REPLY);
+ }
}
return TRUE;
@@ -1801,6 +1808,9 @@ real_edit_comp (CompEditor *editor, ECalComponent *comp)
e_cal_get_local_attachment_store (priv->client));
cal_attachment_bar_set_comp_uid (priv->attachment_bar, g_strdup (uid));
+ if (!itip_organizer_is_user (comp, priv->client))
+ comp_editor_sensitize_attachment_bar (editor, FALSE);
+
fill_widgets (editor);
priv->changed =FALSE;
@@ -1808,20 +1818,58 @@ real_edit_comp (CompEditor *editor, ECalComponent *comp)
listen_for_changes (editor);
}
+/* TODO These functions should be available in e-cal-component.c */
+static void
+set_attendees_for_delegation (ECalComponent *comp, const char *address, ECalComponentItipMethod method)
+{
+ GSList *attendees, *l, *new;
+ icalproperty *prop;
+ icalparameter *param;
+ icalcomponent *icalcomp;
+
+ icalcomp = e_cal_component_get_icalcomponent (comp);
+
+ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
+ prop;
+ prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
+ const char *attendee = icalproperty_get_attendee (prop);
+ const char *delfrom;
+
+ param = icalproperty_get_first_parameter(prop, ICAL_DELEGATEDFROM_PARAMETER);
+ delfrom = icalparameter_get_delegatedfrom (param);
+ if (!(g_str_equal (itip_strip_mailto (attendee), address) ||
+ ((delfrom && *delfrom) &&
+ g_str_equal (itip_strip_mailto (delfrom), address)))) {
+ icalcomponent_remove_property (icalcomp, prop);
+ }
+
+ }
+
+}
static gboolean
real_send_comp (CompEditor *editor, ECalComponentItipMethod method)
{
CompEditorPrivate *priv;
- ECalComponent *tmp_comp;
+ ECalComponent *tmp_comp, *send_comp;
+ char *address = NULL;
g_return_val_if_fail (editor != NULL, FALSE);
g_return_val_if_fail (IS_COMP_EDITOR (editor), FALSE);
priv = editor->priv;
+ send_comp = e_cal_component_clone (priv->comp);
+ /* The user updates the delegated status to the Organizer, so remove all other attendees */
+ if ((priv->flags & COMP_EDITOR_DELEGATE)) {
+ address = itip_get_comp_attendee (send_comp, priv->client);
+
+ if (address)
+ set_attendees_for_delegation (send_comp, address, method);
+ }
+
if (!e_cal_component_has_attachments (priv->comp)) {
- if (itip_send_comp (method, priv->comp, priv->client,
+ if (itip_send_comp (method, send_comp, priv->client,
NULL, NULL)) {
#if 0
tmp_comp = priv->comp;
@@ -1830,20 +1878,19 @@ real_send_comp (CompEditor *editor, ECalComponentItipMethod method)
g_object_unref (tmp_comp);
comp_editor_set_changed (editor, TRUE);
- save_comp (editor);
#endif
+ save_comp (editor);
+ g_object_unref (send_comp);
return TRUE;
}
} else {
/* Clone the component with attachments set to CID:... */
- ECalComponent *send_comp;
int num_attachments, i;
GSList *attach_list = NULL;
GSList *mime_attach_list;
- send_comp = e_cal_component_clone (priv->comp);
num_attachments = e_cal_component_get_num_attachments (send_comp);
for (i = 0; i < num_attachments ; i++) {
@@ -1865,9 +1912,10 @@ real_send_comp (CompEditor *editor, ECalComponentItipMethod method)
g_object_unref (send_comp);
return TRUE;
}
- g_object_unref (send_comp);
}
+ g_object_unref (send_comp);
+ g_free (address);
comp_editor_set_changed (editor, TRUE);
return FALSE;
diff --git a/calendar/gui/dialogs/event-editor.c b/calendar/gui/dialogs/event-editor.c
index 72b4d8246b..01ec3936f1 100644
--- a/calendar/gui/dialogs/event-editor.c
+++ b/calendar/gui/dialogs/event-editor.c
@@ -208,6 +208,7 @@ event_editor_edit_comp (CompEditor *editor, ECalComponent *comp)
EventEditor *ee;
EventEditorPrivate *priv;
ECalComponentOrganizer organizer;
+ gboolean delegate;
ECal *client;
GSList *attendees = NULL;
@@ -215,17 +216,13 @@ event_editor_edit_comp (CompEditor *editor, ECalComponent *comp)
priv = ee->priv;
priv->updating = TRUE;
-
-
- client = comp_editor_get_e_cal (COMP_EDITOR (editor));
- if (priv->is_meeting && itip_organizer_is_user (comp, client)) {
- COMP_EDITOR_PAGE (priv->event_page)->flags |= COMP_EDITOR_PAGE_USER_ORG;
- COMP_EDITOR_PAGE (priv->recur_page)->flags |= COMP_EDITOR_PAGE_USER_ORG;
- }
-
+ delegate = (comp_editor_get_flags (COMP_EDITOR (editor)) & COMP_EDITOR_DELEGATE);
+
if (COMP_EDITOR_CLASS (event_editor_parent_class)->edit_comp)
COMP_EDITOR_CLASS (event_editor_parent_class)->edit_comp (editor, comp);
+ client = comp_editor_get_e_cal (COMP_EDITOR (editor));
+
/* Get meeting related stuff */
e_cal_component_get_organizer (comp, &organizer);
e_cal_component_get_attendee_list (comp, &attendees);
@@ -243,8 +240,9 @@ event_editor_edit_comp (CompEditor *editor, ECalComponent *comp)
} else {
GSList *l;
int row;
- const char *user_email;
-
+ char *user_email;
+
+ user_email = itip_get_comp_attendee (comp, client);
if (!priv->meeting_shown) {
comp_editor_append_page (COMP_EDITOR (ee),
COMP_EDITOR_PAGE (priv->sched_page),
@@ -254,16 +252,21 @@ event_editor_edit_comp (CompEditor *editor, ECalComponent *comp)
_("Invitations"));
}
- if (! (comp_editor_get_flags (COMP_EDITOR (editor)) & COMP_EDITOR_DELEGATE)) {
+ if (!(delegate && e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY))) {
for (l = attendees; l != NULL; l = l->next) {
ECalComponentAttendee *ca = l->data;
EMeetingAttendee *ia;
-
+
+ if (delegate && !g_str_equal (itip_strip_mailto (ca->value), user_email))
+ continue;
+
ia = E_MEETING_ATTENDEE (e_meeting_attendee_new_from_e_cal_component_attendee (ca));
- /* If we aren't the organizer or the attendee is just delegating, don't allow editing */
+ /* If we aren't the organizer or the attendee is just delegated, don't allow editing */
if (!comp_editor_get_user_org (editor) || e_meeting_attendee_is_set_delto (ia))
e_meeting_attendee_set_edit_level (ia, E_MEETING_ATTENDEE_EDIT_NONE);
+
+
e_meeting_store_add_attendee (priv->model, ia);
g_object_unref(ia);
@@ -299,9 +302,6 @@ event_editor_edit_comp (CompEditor *editor, ECalComponent *comp)
e_cal_component_free_attendee_list (attendees);
comp_editor_set_needs_send (COMP_EDITOR (ee), priv->meeting_shown && itip_organizer_is_user (comp, client));
- if (e_cal_component_has_organizer (comp) && (COMP_EDITOR_PAGE (priv->event_page)->flags &
- COMP_EDITOR_PAGE_MEETING))
- comp_editor_sensitize_attachment_bar (editor, itip_organizer_is_user (comp, client));
priv->updating = FALSE;
}
@@ -332,6 +332,8 @@ event_editor_send_comp (CompEditor *editor, ECalComponentItipMethod method)
if (!result)
return FALSE;
+ else
+ return TRUE;
}
parent:
@@ -428,8 +430,7 @@ show_meeting (EventEditor *ee)
}
if (comp_editor_get_flags (COMP_EDITOR (ee)) & COMP_EDITOR_DELEGATE)
comp_editor_show_page (COMP_EDITOR (ee), COMP_EDITOR_PAGE (priv->meet_page));
- if (comp_editor_get_existing_org (COMP_EDITOR (ee)) && !comp_editor_get_user_org (COMP_EDITOR (ee)))
- comp_editor_remove_page (COMP_EDITOR (ee), COMP_EDITOR_PAGE (priv->sched_page));
+
}
void
diff --git a/calendar/gui/dialogs/meeting-page.c b/calendar/gui/dialogs/meeting-page.c
index 263a415f41..93ae8353b5 100644
--- a/calendar/gui/dialogs/meeting-page.c
+++ b/calendar/gui/dialogs/meeting-page.c
@@ -101,7 +101,7 @@ static GtkWidget *meeting_page_get_widget (CompEditorPage *page);
static void meeting_page_focus_main_widget (CompEditorPage *page);
static gboolean meeting_page_fill_widgets (CompEditorPage *page, ECalComponent *comp);
static gboolean meeting_page_fill_component (CompEditorPage *page, ECalComponent *comp);
-
+static void attendee_added_cb (EMeetingListView *emlv, EMeetingAttendee *attendee, gpointer user_data);
G_DEFINE_TYPE (MeetingPage, meeting_page, TYPE_COMP_EDITOR_PAGE);
/* Class initialization function for the task page */
@@ -304,7 +304,7 @@ clear_widgets (MeetingPage *mpage)
}
if (e_cal_get_static_capability (COMP_EDITOR_PAGE (mpage)->client, CAL_STATIC_CAPABILITY_NO_ORGANIZER)) {
- gtk_label_set_label (GTK_LABEL (priv->org_label), _("From:"));
+ gtk_label_set_markup (GTK_LABEL (priv->org_label), _("<b>From:</b>"));
gtk_widget_hide (priv->existing_organizer_btn);
}
@@ -371,7 +371,9 @@ meeting_page_fill_widgets (CompEditorPage *page, ECalComponent *comp)
/* Component for cancellation */
priv->comp = e_cal_component_clone (comp);
-
+
+ priv->user_add = itip_get_comp_attendee (comp, COMP_EDITOR_PAGE (mpage)->client);
+
/* If there is an existing organizer show it properly */
if (e_cal_component_has_organizer (comp)) {
e_cal_component_get_organizer (comp, &organizer);
@@ -401,7 +403,7 @@ meeting_page_fill_widgets (CompEditorPage *page, ECalComponent *comp)
priv->user_org = FALSE;
}
- if (e_cal_get_static_capability (COMP_EDITOR_PAGE (mpage)->client, CAL_STATIC_CAPABILITY_NO_ORGANIZER))
+ if (e_cal_get_static_capability (COMP_EDITOR_PAGE (mpage)->client, CAL_STATIC_CAPABILITY_NO_ORGANIZER) && (COMP_EDITOR_PAGE (mpage)->flags & COMP_EDITOR_PAGE_DELEGATE))
string = g_strdup (priv->user_add);
else if ( organizer.cn != NULL)
string = g_strdup_printf ("%s <%s>", organizer.cn, strip);
@@ -495,6 +497,18 @@ meeting_page_fill_component (CompEditorPage *page, ECalComponent *comp)
EMeetingAttendee *ia = g_ptr_array_index (attendees, i);
ECalComponentAttendee *ca;
+ /* Remove the duplicate user from the component if present */
+ if (e_meeting_attendee_is_set_delto (ia)) {
+ for (l = attendee_list; l; l = l->next) {
+ ECalComponentAttendee *a = l->data;
+
+ if (g_str_equal (a->value, e_meeting_attendee_get_address (ia))) {
+ attendee_list = g_slist_remove (attendee_list, l->data);
+ break;
+ }
+ }
+ }
+
ca = e_meeting_attendee_as_e_cal_component_attendee (ia);
attendee_list = g_slist_append (attendee_list, ca);
@@ -635,7 +649,7 @@ add_clicked_cb (GtkButton *btn, MeetingPage *mpage)
attendee = e_meeting_store_add_attendee_with_defaults (mpage->priv->model);
if (COMP_EDITOR_PAGE (mpage)->flags & COMP_EDITOR_PAGE_DELEGATE) {
- e_meeting_attendee_set_delfrom (attendee, g_strdup (mpage->priv->user_add));
+ e_meeting_attendee_set_delfrom (attendee, g_strdup_printf ("MAILTO:%s", mpage->priv->user_add));
}
e_meeting_list_view_edit (mpage->priv->list_view, attendee);
@@ -674,6 +688,7 @@ remove_attendee (MeetingPage *mpage, EMeetingAttendee *ia)
{
MeetingPagePrivate *priv;
int pos = 0;
+ gboolean delegate = (COMP_EDITOR_PAGE (mpage)->flags & COMP_EDITOR_PAGE_DELEGATE);
priv = mpage->priv;
@@ -691,7 +706,9 @@ remove_attendee (MeetingPage *mpage, EMeetingAttendee *ia)
ib = e_meeting_store_find_attendee (priv->model, e_meeting_attendee_get_delfrom (ia), &pos);
if (ib != NULL) {
e_meeting_attendee_set_delto (ib, NULL);
- e_meeting_attendee_set_edit_level (ib, E_MEETING_ATTENDEE_EDIT_FULL);
+
+ if (!delegate)
+ e_meeting_attendee_set_edit_level (ib, E_MEETING_ATTENDEE_EDIT_FULL);
}
}
@@ -710,7 +727,7 @@ remove_attendee (MeetingPage *mpage, EMeetingAttendee *ia)
ia = ib;
}
-
+
sensitize_widgets (mpage);
}
@@ -751,6 +768,8 @@ remove_clicked_cb (GtkButton *btn, MeetingPage *mpage)
g_free (address);
if (!ia)
return;
+ else if (e_meeting_attendee_get_edit_level (ia) != E_MEETING_ATTENDEE_EDIT_FULL)
+ return;
remove_attendee (mpage, ia);
@@ -803,6 +822,39 @@ init_widgets (MeetingPage *mpage)
/* Contacts button */
g_signal_connect(priv->invite, "clicked", G_CALLBACK (invite_cb), mpage);
+
+ /* Meeting List View */
+ g_signal_connect (priv->list_view, "attendee_added", G_CALLBACK (attendee_added_cb), mpage);
+}
+
+static void
+attendee_added_cb (EMeetingListView *emlv, EMeetingAttendee *ia, gpointer user_data)
+{
+ MeetingPage *mpage = MEETING_PAGE (user_data);
+ MeetingPagePrivate *priv;
+ gboolean delegate = (COMP_EDITOR_PAGE (mpage)->flags & COMP_EDITOR_PAGE_DELEGATE);
+
+ priv = mpage->priv;
+
+ if (delegate) {
+ if (existing_attendee (ia, priv->comp))
+ e_meeting_store_remove_attendee (priv->model, ia);
+ else {
+ if (!e_cal_get_static_capability (COMP_EDITOR_PAGE(mpage)->client,
+ CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY)) {
+ const char *delegator_id = e_meeting_attendee_get_delfrom (ia);
+ EMeetingAttendee *delegator;
+
+ delegator = e_meeting_store_find_attendee (priv->model, delegator_id, NULL);
+ e_meeting_attendee_set_delto (delegator,
+ g_strdup (e_meeting_attendee_get_address (ia)));
+
+ gtk_widget_set_sensitive (priv->invite, FALSE);
+ gtk_widget_set_sensitive (priv->add, FALSE);
+ }
+ }
+ }
+
}
static void
@@ -953,11 +1005,6 @@ meeting_page_construct (MeetingPage *mpage, EMeetingStore *ems,
}
}
- if (backend_address)
- priv->user_add = backend_address;
- else
- priv->user_add = g_strdup (a->id->address);
-
g_object_unref(it);
if (address_strings)
diff --git a/calendar/gui/e-cal-popup.c b/calendar/gui/e-cal-popup.c
index 5dc4462833..3ecddd0bb4 100644
--- a/calendar/gui/e-cal-popup.c
+++ b/calendar/gui/e-cal-popup.c
@@ -109,6 +109,60 @@ ECalPopup *e_cal_popup_new(const char *menuid)
return eabp;
}
+static icalproperty *
+get_attendee_prop (icalcomponent *icalcomp, const char *address)
+{
+
+ icalproperty *prop;
+
+ if (!(address && *address))
+ return NULL;
+
+ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
+ prop;
+ prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
+ const char *attendee = icalproperty_get_attendee (prop);
+
+ if (g_str_equal (itip_strip_mailto (attendee), address)) {
+ return prop;
+ }
+ }
+ return NULL;
+}
+
+static gboolean
+is_delegated (icalcomponent *icalcomp, char *user_email)
+{
+ icalproperty *prop;
+ icalparameter *param;
+ const char *delto = NULL;
+
+ prop = get_attendee_prop (icalcomp, user_email);
+
+ if (prop) {
+ param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDTO_PARAMETER);
+ delto = icalparameter_get_delegatedto (param);
+ } else
+ return FALSE;
+
+ prop = get_attendee_prop (icalcomp, itip_strip_mailto (delto));
+
+ if (prop) {
+ const char *delfrom;
+ icalparameter_partstat status;
+
+ param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER);
+ delfrom = icalparameter_get_delegatedfrom (param);
+ param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
+ status = icalparameter_get_partstat (param);
+ if ((delfrom && *delfrom) && g_str_equal (itip_strip_mailto (delfrom), user_email)
+ && status != ICAL_PARTSTAT_DECLINED)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/**
* e_cal_popup_target_new_select:
* @eabp:
@@ -127,18 +181,22 @@ e_cal_popup_target_new_select(ECalPopup *eabp, struct _ECalModel *model, GPtrArr
ECalPopupTargetSelect *t = e_popup_target_new(&eabp->popup, E_CAL_POPUP_TARGET_SELECT, sizeof(*t));
guint32 mask = ~0;
ECal *client;
- gboolean read_only;
+ gboolean read_only, user_org = FALSE;
/* FIXME: This is duplicated in e-cal-menu */
t->model = model;
g_object_ref(t->model);
t->events = events;
-
+
if (t->events->len == 0) {
client = e_cal_model_get_default_client(t->model);
} else {
ECalModelComponent *comp_data = (ECalModelComponent *)t->events->pdata[0];
+ ECalComponent *comp;
+
+ comp = e_cal_component_new ();
+ e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (comp_data->icalcomp));
mask &= ~E_CAL_POPUP_SELECT_ANY;
if (t->events->len == 1)
@@ -163,28 +221,37 @@ e_cal_popup_target_new_select(ECalPopup *eabp, struct _ECalModel *model, GPtrArr
mask &= ~E_CAL_POPUP_SELECT_MEETING;
if (e_cal_util_component_has_organizer (comp_data->icalcomp)) {
- ECalComponent *comp;
- comp = e_cal_component_new ();
- e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (comp_data->icalcomp));
- if (!itip_organizer_is_user (comp, comp_data->client))
+ if (itip_organizer_is_user (comp, comp_data->client)) {
mask &= ~E_CAL_POPUP_SELECT_ORGANIZER;
+ user_org = TRUE;
+ }
- g_object_unref (comp);
} else {
/* organiser is synonym for owner in this case */
mask &= ~(E_CAL_POPUP_SELECT_ORGANIZER|E_CAL_POPUP_SELECT_NOTMEETING);
}
client = comp_data->client;
+
+ if (e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED)) {
+ char *user_email = itip_get_comp_attendee (comp, client);
+
+ if (e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY))
+ mask &= ~E_CAL_POPUP_SELECT_DELEGATABLE;
+ else if (!user_org && !is_delegated (comp_data->icalcomp, user_email))
+ mask &= ~E_CAL_POPUP_SELECT_DELEGATABLE;
+
+ g_object_unref (comp);
+
+ }
}
e_cal_is_read_only(client, &read_only, NULL);
if (!read_only)
mask &= ~E_CAL_POPUP_SELECT_EDITABLE;
- if (e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED))
- mask &= ~E_CAL_POPUP_SELECT_DELEGATABLE;
+
if (!e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_NO_TASK_ASSIGNMENT)
&& !e_cal_get_static_capability (client, CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK))
diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c
index 46acc4bf7d..d37ef722f6 100644
--- a/calendar/gui/e-calendar-view.c
+++ b/calendar/gui/e-calendar-view.c
@@ -1248,27 +1248,63 @@ on_meeting (EPopup *ep, EPopupItem *pitem, void *data)
}
static void
-set_attendee_status_for_delegate (icalcomponent *icalcomp, const char *email_id, ECal *client)
+set_attendee_status_for_delegate (icalcomponent *icalcomp, ECal *client)
{
icalproperty *prop;
+ icalparameter *param;
+ char *address = NULL;
+ ECalComponent *comp;
+ gboolean found = FALSE;
+
+ comp = e_cal_component_new ();
+ e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
+
+ address = itip_get_comp_attendee (comp, client);
- if (!email_id)
- return;
for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
prop;
prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
const char *attendee = icalproperty_get_attendee (prop);
- if (g_str_equal (attendee + 7, email_id)) {
- icalparameter *param;
+ if (g_str_equal (itip_strip_mailto (attendee), address)) {
+ param = icalparameter_new_role (ICAL_ROLE_NONPARTICIPANT);
+ icalproperty_set_parameter (prop, param);
param = icalparameter_new_partstat (ICAL_PARTSTAT_DELEGATED);
icalproperty_set_parameter (prop, param);
+
+ found = TRUE;
break;
}
}
+
+ /* We couldn find the attendee in the component, so add a new attendee */
+ if (!found) {
+ char *temp = g_strdup_printf ("MAILTO:%s", address);
+
+ prop = icalproperty_new_attendee ((const char *) temp);
+ icalcomponent_add_property (icalcomp, prop);
+
+ param = icalparameter_new_partstat (ICAL_PARTSTAT_DELEGATED);
+ icalproperty_add_parameter (prop, param);
+
+ param = icalparameter_new_role (ICAL_ROLE_NONPARTICIPANT);
+ icalproperty_add_parameter (prop, param);
+
+ param = icalparameter_new_cutype (ICAL_CUTYPE_INDIVIDUAL);
+ icalproperty_add_parameter (prop, param);
+
+ param = icalparameter_new_rsvp (ICAL_RSVP_TRUE);
+ icalproperty_add_parameter (prop, param);
+
+ g_free (temp);
+ }
+
+
+ g_free (address);
+ g_object_unref (comp);
}
static void
@@ -1277,6 +1313,7 @@ on_delegate (EPopup *ep, EPopupItem *pitem, void *data)
ECalendarView *cal_view = data;
GList *selected;
guint32 flags;
+ icalcomponent *clone;
selected = e_calendar_view_get_selected_events (cal_view);
if (selected) {
@@ -1284,12 +1321,14 @@ on_delegate (EPopup *ep, EPopupItem *pitem, void *data)
char *address;
e_cal_get_cal_address (event->comp_data->client, &address, NULL);
- set_attendee_status_for_delegate (event->comp_data->icalcomp, address, event->comp_data->client);
+ clone = icalcomponent_new_clone (event->comp_data->icalcomp);
+ set_attendee_status_for_delegate (clone, event->comp_data->client);
flags |= COMP_EDITOR_MEETING | COMP_EDITOR_DELEGATE;
- open_event_with_flags (cal_view, event->comp_data->client, event->comp_data->icalcomp, flags);
+ open_event_with_flags (cal_view, event->comp_data->client, clone, flags);
+ icalcomponent_free (clone);
g_list_free (selected);
}
}
@@ -1478,7 +1517,7 @@ static EPopupItem ecv_child_items [] = {
{ E_POPUP_ITEM, "41.copyto", N_("Cop_y to Calendar..."), on_copy_to, NULL, NULL, 0, E_CAL_POPUP_SELECT_NOTEDITING },
{ E_POPUP_ITEM, "42.moveto", N_("Mo_ve to Calendar..."), on_move_to, NULL, NULL, 0, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE },
- { E_POPUP_ITEM, "43.delegate", N_("_Delegate Meeting..."), on_delegate, NULL, NULL, 0, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE | E_CAL_POPUP_SELECT_DELEGATABLE },
+ { E_POPUP_ITEM, "43.delegate", N_("_Delegate Meeting..."), on_delegate, NULL, NULL, 0, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE | E_CAL_POPUP_SELECT_DELEGATABLE | E_CAL_POPUP_SELECT_MEETING},
{ E_POPUP_ITEM, "44.schedule", N_("_Schedule Meeting..."), on_meeting, NULL, NULL, 0, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE | E_CAL_POPUP_SELECT_NOTMEETING },
{ E_POPUP_ITEM, "45.forward", N_("_Forward as iCalendar..."), on_forward, NULL, "stock_mail-forward", 0, E_CAL_POPUP_SELECT_NOTEDITING },
diff --git a/calendar/gui/e-meeting-list-view.c b/calendar/gui/e-meeting-list-view.c
index d834a3cf49..3e91bea40c 100644
--- a/calendar/gui/e-meeting-list-view.c
+++ b/calendar/gui/e-meeting-list-view.c
@@ -56,6 +56,14 @@ struct _EMeetingListViewPrivate {
#define BUF_SIZE 1024
+/* Signal IDs */
+enum {
+ ATTENDEE_ADDED,
+ LAST_SIGNAL
+};
+
+static guint e_meeting_list_view_signals[LAST_SIGNAL] = { 0 };
+
static void name_selector_dialog_close_cb (ENameSelectorDialog *dialog, gint response, gpointer data);
static char *sections[] = {N_("Chair Persons"),
@@ -101,6 +109,16 @@ e_meeting_list_view_class_init (EMeetingListViewClass *klass)
object_class = G_OBJECT_CLASS (klass);
object_class->finalize = e_meeting_list_view_finalize;
+
+ e_meeting_list_view_signals [ATTENDEE_ADDED] =
+ g_signal_new ("attendee_added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EMeetingListViewClass, attendee_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1,
+ G_TYPE_POINTER);
}
@@ -209,6 +227,7 @@ attendee_edited_cb (GtkCellRenderer *renderer, const gchar *path, GList *address
GtkTreePath *treepath = gtk_tree_path_new_from_string (path);
int row = gtk_tree_path_get_indices (treepath)[0];
EMeetingAttendee *existing_attendee;
+ gboolean removed = FALSE;
existing_attendee = e_meeting_store_find_attendee_at_row (model, row);
@@ -219,8 +238,8 @@ attendee_edited_cb (GtkCellRenderer *renderer, const gchar *path, GList *address
for (l = addresses, m = names; l && m; l = l->next, m = m->next) {
char *name = m->data, *email = l->data;
- if (!((name && *name) || (email && *email)))
- continue;
+ if (!((name && *name) || (email && *email)))
+ continue;
if (e_meeting_store_find_attendee (model, email, NULL) != NULL)
continue;
@@ -237,26 +256,40 @@ attendee_edited_cb (GtkCellRenderer *renderer, const gchar *path, GList *address
}
}
- if (existing_attendee)
+ if (existing_attendee) {
+ removed = TRUE;
e_meeting_store_remove_attendee (model, existing_attendee);
+ }
} else if (g_list_length (addresses) == 1) {
char *name = names->data, *email = addresses->data;
int existing_row;
if (!((name && *name) || (email && *email)) || ((e_meeting_store_find_attendee (model, email, &existing_row) != NULL) && existing_row != row)){
- if (existing_attendee)
+ if (existing_attendee) {
+ removed = TRUE;
e_meeting_store_remove_attendee (model, existing_attendee);
+ }
} else {
value_edited (view, E_MEETING_STORE_ADDRESS_COL, path, email);
value_edited (view, E_MEETING_STORE_CN_COL, path, name);
}
} else {
- if (existing_attendee)
+ if (existing_attendee) {
+ const char *address = e_meeting_attendee_get_address (existing_attendee);
+
+ if (address && *address)
+ return;
+
+ removed = TRUE;
e_meeting_store_remove_attendee (model, existing_attendee);
+ }
}
gtk_tree_path_free (treepath);
+
+ if (!removed)
+ g_signal_emit_by_name (G_OBJECT (view), "attendee_added", (gpointer) existing_attendee);
}
static void
diff --git a/calendar/gui/e-meeting-list-view.h b/calendar/gui/e-meeting-list-view.h
index 6fc433b82c..9c17725aa1 100644
--- a/calendar/gui/e-meeting-list-view.h
+++ b/calendar/gui/e-meeting-list-view.h
@@ -47,6 +47,9 @@ struct _EMeetingListView {
struct _EMeetingListViewClass {
GtkTreeViewClass parent_class;
+
+ /* Notification Signals */
+ void (*attendee_added) (EMeetingListView *emlv, EMeetingAttendee *attendee);
};
GType e_meeting_list_view_get_type (void);
diff --git a/calendar/gui/itip-utils.c b/calendar/gui/itip-utils.c
index fa76efe579..517e3cad97 100644
--- a/calendar/gui/itip-utils.c
+++ b/calendar/gui/itip-utils.c
@@ -138,7 +138,81 @@ itip_sentby_is_user (ECalComponent *comp)
return user_sentby;
}
-
+
+static ECalComponentAttendee *
+get_attendee (GSList *attendees, char *address)
+{
+ GSList *l;
+
+ for (l = attendees; l; l = l->next) {
+ ECalComponentAttendee *attendee = l->data;
+
+ if (g_str_equal (itip_strip_mailto (attendee->value), address)) {
+ return attendee;
+ }
+ }
+
+ return NULL;
+}
+
+char *
+itip_get_comp_attendee (ECalComponent *comp, ECal *client)
+{
+ GSList *attendees;
+ EAccountList *al;
+ EAccount *a;
+ EIterator *it;
+ ECalComponentAttendee *attendee = NULL;
+ char *address = NULL;
+
+ e_cal_component_get_attendee_list (comp, &attendees);
+ al = itip_addresses_get ();
+
+ if (client)
+ e_cal_get_cal_address (client, &address, NULL);
+
+ if (address && *address) {
+ attendee = get_attendee (attendees, address);
+
+ if (attendee) {
+ char *user_email = g_strdup (itip_strip_mailto (attendee->value));
+
+ e_cal_component_free_attendee_list (attendees);
+ g_free (address);
+ return user_email;
+ }
+ }
+
+ for (it = e_list_get_iterator((EList *)al);
+ e_iterator_is_valid(it);
+ e_iterator_next(it)) {
+ a = (EAccount *) e_iterator_get(it);
+
+ if (!a->enabled)
+ continue;
+
+ attendee = get_attendee (attendees, a->id->address);
+ if (attendee) {
+ char *user_email = g_strdup (itip_strip_mailto (attendee->value));
+
+ e_cal_component_free_attendee_list (attendees);
+ g_free (address);
+ return user_email;
+ }
+ }
+
+ /* We could not find the attendee in the component, so just give the default
+ account address if the email address is not set in the backend */
+ /* FIXME do we have a better way ? */
+ if (!(address && *address)) {
+ a = itip_addresses_get_default ();
+ address = g_strdup (a->id->address);
+ }
+
+ e_cal_component_free_attendee_list (attendees);
+ return address;
+}
+
const gchar *
itip_strip_mailto (const gchar *address)
{
@@ -256,14 +330,22 @@ comp_from (ECalComponentItipMethod method, ECalComponent *comp)
ECalComponentAttendee *attendee;
GSList *attendees;
CORBA_char *str;
+ char *sender = NULL;
switch (method) {
case E_CAL_COMPONENT_METHOD_PUBLISH:
return CORBA_string_dup ("");
case E_CAL_COMPONENT_METHOD_REQUEST:
+ sender = itip_get_comp_attendee (comp, NULL);
+ if (sender) {
+ str = CORBA_string_dup (sender);
+ g_free (sender);
+ return str;
+ }
case E_CAL_COMPONENT_METHOD_CANCEL:
- case E_CAL_COMPONENT_METHOD_ADD:
+ case E_CAL_COMPONENT_METHOD_ADD:
+
e_cal_component_get_organizer (comp, &organizer);
if (organizer.value == NULL) {
e_notice (NULL, GTK_MESSAGE_ERROR,
@@ -294,6 +376,7 @@ comp_to_list (ECalComponentItipMethod method, ECalComponent *comp, GList *users)
ECalComponentOrganizer organizer;
GSList *attendees, *l;
gint len;
+ char *sender = NULL;
switch (method) {
case E_CAL_COMPONENT_METHOD_REQUEST:
@@ -318,6 +401,7 @@ comp_to_list (ECalComponentItipMethod method, ECalComponent *comp, GList *users)
_("An organizer must be set."));
return NULL;
}
+ sender = itip_get_comp_attendee (comp, NULL);
for (l = attendees; l != NULL; l = l->next) {
ECalComponentAttendee *att = l->data;
@@ -326,6 +410,12 @@ comp_to_list (ECalComponentItipMethod method, ECalComponent *comp, GList *users)
continue;
else if (!g_strcasecmp (att->value, organizer.value))
continue;
+ else if (!g_strcasecmp (itip_strip_mailto (att->value), sender))
+ continue;
+ else if (att->status == ICAL_PARTSTAT_DELEGATED && (att->delto && *att->delto)
+ && !(att->rsvp) && method == E_CAL_COMPONENT_METHOD_REQUEST)
+ continue;
+
recipient = &(to_list->_buffer[to_list->_length]);
if (att->cn)
@@ -336,6 +426,7 @@ comp_to_list (ECalComponentItipMethod method, ECalComponent *comp, GList *users)
to_list->_length++;
}
+ g_free (sender);
e_cal_component_free_attendee_list (attendees);
break;
@@ -351,19 +442,42 @@ comp_to_list (ECalComponentItipMethod method, ECalComponent *comp, GList *users)
return NULL;
}
- len = 1;
+ len = 2;
to_list = GNOME_Evolution_Composer_RecipientList__alloc ();
to_list->_maximum = len;
- to_list->_length = len;
+ to_list->_length = 0;
to_list->_buffer = CORBA_sequence_GNOME_Evolution_Composer_Recipient_allocbuf (len);
recipient = &(to_list->_buffer[0]);
+ to_list->_length++;
if (organizer.cn != NULL)
recipient->name = CORBA_string_dup (organizer.cn);
else
recipient->name = CORBA_string_dup ("");
recipient->address = CORBA_string_dup (itip_strip_mailto (organizer.value));
+
+ /* send the status to delegatee to the delegate also*/
+ e_cal_component_get_attendee_list (comp, &attendees);
+ sender = itip_get_comp_attendee (comp, NULL);
+
+ for (l = attendees; l != NULL; l = l->next) {
+ ECalComponentAttendee *att = l->data;
+
+ if (!g_strcasecmp (itip_strip_mailto (att->value), sender)){
+
+ if (!(att->delfrom && *att->delfrom))
+ break;
+
+ recipient = &(to_list->_buffer[to_list->_length]);
+ recipient->name = CORBA_string_dup ("");
+ recipient->address = CORBA_string_dup (itip_strip_mailto (att->delfrom));
+ to_list->_length++;
+ }
+
+ }
+ e_cal_component_free_attendee_list (attendees);
+
break;
default:
@@ -381,8 +495,10 @@ comp_subject (ECalComponentItipMethod method, ECalComponent *comp)
{
ECalComponentText caltext;
const char *description, *prefix = NULL;
- GSList *alist;
+ GSList *alist, *l;
CORBA_char *subject;
+ char *sender;
+ ECalComponentAttendee *a;
e_cal_component_get_summary (comp, &caltext);
if (caltext.value != NULL)
@@ -413,8 +529,18 @@ comp_subject (ECalComponentItipMethod method, ECalComponent *comp)
case E_CAL_COMPONENT_METHOD_REPLY:
e_cal_component_get_attendee_list (comp, &alist);
+ sender = itip_get_comp_attendee (comp, NULL);
+ if (sender) {
+
+ for (l = alist; l != NULL ; l = l->next) {
+ a = l->data;
+ if ((sender && *sender) && g_str_equal (itip_strip_mailto (a->value), sender))
+ break;
+ }
+ g_free (sender);
+ }
+
if (alist != NULL) {
- ECalComponentAttendee *a = alist->data;
switch (a->status) {
case ICAL_PARTSTAT_ACCEPTED:
@@ -426,6 +552,9 @@ comp_subject (ECalComponentItipMethod method, ECalComponent *comp)
case ICAL_PARTSTAT_DECLINED:
prefix = _("Declined");
break;
+ case ICAL_PARTSTAT_DELEGATED:
+ prefix = _("Delegated");
+ break;
default:
break;
}
@@ -614,6 +743,8 @@ static void
comp_sentby (ECalComponent *comp, ECal *client)
{
ECalComponentOrganizer organizer;
+ GList * attendees, *l;
+ char *user = NULL;
e_cal_component_get_organizer (comp, &organizer);
if (!organizer.value) {
@@ -630,6 +761,17 @@ comp_sentby (ECalComponent *comp, ECal *client)
return;
}
+ e_cal_component_get_attendee_list (comp, &attendees);
+ user = itip_get_comp_attendee (comp, client);
+ for (l = attendees; l; l = l->next) {
+ ECalComponentAttendee *a = l->data;
+
+ if (g_str_equal (itip_strip_mailto (a->value), user)) {
+ g_free (user);
+ return;
+ }
+ }
+
if (!itip_organizer_is_user (comp, client) && !itip_sentby_is_user (comp)) {
EAccount *a = itip_addresses_get_default ();
@@ -961,6 +1103,7 @@ itip_send_comp (ECalComponentItipMethod method, ECalComponent *send_comp,
top_level = comp_toplevel_with_zones (method, comp, client, zones);
ical_string = icalcomponent_as_ical_string (top_level);
+
if (e_cal_component_get_vtype (comp) == E_CAL_COMPONENT_EVENT) {
GNOME_Evolution_Composer_setBody (composer_server, ical_string, content_type, &ev);
} else {
diff --git a/calendar/gui/itip-utils.h b/calendar/gui/itip-utils.h
index bfbd4ab6fc..39e4f6d099 100644
--- a/calendar/gui/itip-utils.h
+++ b/calendar/gui/itip-utils.h
@@ -28,6 +28,8 @@ gboolean itip_sentby_is_user (ECalComponent *comp);
const gchar *itip_strip_mailto (const gchar *address);
+char *itip_get_comp_attendee (ECalComponent *comp, ECal *client);
+
gboolean itip_send_comp (ECalComponentItipMethod method, ECalComponent *comp,
ECal *client, icalcomponent *zones, GSList *attachments_list);