[evolution/kill-bonobo] Get the calendar view popup menu working.



commit ad17dfabe588f03cc21e4ee5aca86f4c540e517e
Author: Matthew Barnes <mbarnes redhat com>
Date:   Fri Aug 14 19:34:43 2009 -0400

    Get the calendar view popup menu working.

 calendar/gui/calendar-commands.c            |   49 --
 calendar/gui/e-cal-list-view.c              |   15 +-
 calendar/gui/e-calendar-view.c              |  688 ++++-----------------------
 calendar/gui/e-calendar-view.h              |    4 +-
 calendar/gui/e-day-view.c                   |   13 +-
 calendar/gui/e-week-view.c                  |    8 +-
 calendar/gui/gnome-cal.h                    |    4 +-
 modules/calendar/e-cal-shell-content.c      |    7 +-
 modules/calendar/e-cal-shell-view-actions.c |  576 ++++++++++++++++++++++-
 modules/calendar/e-cal-shell-view-private.c |  135 ++++++
 modules/calendar/e-cal-shell-view-private.h |    7 +
 ui/evolution-calendars.ui                   |    1 +
 12 files changed, 816 insertions(+), 691 deletions(-)
---
diff --git a/calendar/gui/calendar-commands.c b/calendar/gui/calendar-commands.c
index 32bf54e..6368857 100644
--- a/calendar/gui/calendar-commands.c
+++ b/calendar/gui/calendar-commands.c
@@ -136,54 +136,6 @@ show_list_view_clicked (BonoboUIComponent *uic, gpointer data, const gchar *path
 	gnome_calendar_set_view (gcal, GNOME_CAL_LIST_VIEW);
 }
 
-static void
-purge_cmd (BonoboUIComponent *uic, gpointer data, const gchar *path)
-{
-	GnomeCalendar *gcal;
-	GtkWidget *dialog, *parent, *box, *label, *spin;
-	gint response;
-
-	gcal = GNOME_CALENDAR (data);
-
-	/* create the dialog */
-	parent = gtk_widget_get_toplevel (GTK_WIDGET (gcal));
-	dialog = gtk_message_dialog_new (
-		(GtkWindow *)parent,
-		GTK_DIALOG_DESTROY_WITH_PARENT,
-		GTK_MESSAGE_WARNING,
-		GTK_BUTTONS_OK_CANCEL,
-		_("This operation will permanently erase all events older than the selected amount of time. If you continue, you will not be able to recover these events."));
-	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
-
-	box = gtk_hbox_new (FALSE, 6);
-	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), box, TRUE, FALSE, 6);
-
-	label = gtk_label_new (_("Purge events older than"));
-	gtk_box_pack_start (GTK_BOX (box), label, TRUE, FALSE, 6);
-	spin = gtk_spin_button_new_with_range (0.0, 1000.0, 1.0);
-	gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 60.0);
-	gtk_box_pack_start (GTK_BOX (box), spin, FALSE, FALSE, 6);
-	label = gtk_label_new (_("days"));
-	gtk_box_pack_start (GTK_BOX (box), label, TRUE, FALSE, 6);
-
-	gtk_widget_show_all (box);
-
-	/* run the dialog */
-	response = gtk_dialog_run (GTK_DIALOG (dialog));
-	if (response == GTK_RESPONSE_OK) {
-		gint days;
-		time_t tt;
-
-		days = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin));
-		tt = time (NULL);
-		tt -= (days * (24 * 3600));
-
-		gnome_calendar_purge (gcal, tt);
-	}
-
-	gtk_widget_destroy (dialog);
-}
-
 struct _sensitize_item {
 	const gchar *command;
 	guint32 enable;
@@ -342,7 +294,6 @@ static BonoboUIVerb verbs [] = {
 	BONOBO_UI_VERB ("ShowMonthView", show_month_view_clicked),
 	BONOBO_UI_VERB ("ShowListView", show_list_view_clicked),
 
-	BONOBO_UI_VERB ("CalendarPurge", purge_cmd),
 	BONOBO_UI_VERB ("HelpDebug", help_debug),
 	BONOBO_UI_VERB_END
 };
diff --git a/calendar/gui/e-cal-list-view.c b/calendar/gui/e-cal-list-view.c
index 1f9ca3f..e82bd3c 100644
--- a/calendar/gui/e-cal-list-view.c
+++ b/calendar/gui/e-cal-list-view.c
@@ -72,7 +72,7 @@ static gboolean  e_cal_list_view_get_visible_time_range (ECalendarView *cal_view
 static gboolean  e_cal_list_view_popup_menu             (GtkWidget *widget);
 
 static void      e_cal_list_view_show_popup_menu        (ECalListView *cal_list_view, gint row,
-							 GdkEvent *gdk_event);
+							 GdkEventButton *event);
 static gboolean  e_cal_list_view_on_table_double_click   (GtkWidget *table, gint row, gint col,
 							 GdkEvent *event, gpointer data);
 static gboolean  e_cal_list_view_on_table_right_click   (GtkWidget *table, gint row, gint col,
@@ -364,14 +364,11 @@ e_cal_list_view_destroy (GtkObject *object)
 }
 
 static void
-e_cal_list_view_show_popup_menu (ECalListView *cal_list_view, gint row, GdkEvent *gdk_event)
+e_cal_list_view_show_popup_menu (ECalListView *cal_list_view,
+                                 gint row,
+                                 GdkEventButton *event)
 {
-#if 0 /* KILL-BONOBO */
-	GtkMenu *menu;
-
-	menu = e_calendar_view_create_popup_menu (E_CALENDAR_VIEW (cal_list_view));
-	gtk_menu_popup(menu, NULL, NULL, NULL, NULL, gdk_event?gdk_event->button.button:0, gdk_event?gdk_event->button.time:gtk_get_current_event_time());
-#endif
+	e_calendar_view_popup_event (E_CALENDAR_VIEW (cal_list_view), event);
 }
 
 static gboolean
@@ -413,7 +410,7 @@ e_cal_list_view_on_table_right_click (GtkWidget *table, gint row, gint col, GdkE
 {
 	ECalListView *cal_list_view = E_CAL_LIST_VIEW (data);
 
-	e_cal_list_view_show_popup_menu (cal_list_view, row, event);
+	e_cal_list_view_show_popup_menu (cal_list_view, row, (GdkEventButton *) event);
 	return TRUE;
 }
 
diff --git a/calendar/gui/e-calendar-view.c b/calendar/gui/e-calendar-view.c
index 3575c11..f2d20b3 100644
--- a/calendar/gui/e-calendar-view.c
+++ b/calendar/gui/e-calendar-view.c
@@ -57,7 +57,6 @@
 #include "print.h"
 #include "goto.h"
 /*#include "a11y/ea-calendar.h"*/  /* KILL-BONOBO */
-#include "e-cal-popup.h"
 #include "misc.h"
 
 #define E_CALENDAR_VIEW_GET_PRIVATE(obj) \
@@ -83,6 +82,7 @@ enum {
 /* FIXME Why are we emitting these event signals here? Can't the model just be listened to? */
 /* Signal IDs */
 enum {
+	POPUP_EVENT,
 	SELECTION_CHANGED,
 	SELECTED_TIME_CHANGED,
 	TIMEZONE_CHANGED,
@@ -221,69 +221,82 @@ e_calendar_view_class_init (ECalendarViewClass *class)
 			G_PARAM_READWRITE |
 			G_PARAM_CONSTRUCT_ONLY));
 
-	/* Create class' signals */
-	signals[SELECTION_CHANGED] =
-		g_signal_new ("selection_changed",
-			      G_TYPE_FROM_CLASS (class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (ECalendarViewClass, selection_changed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
-	signals[SELECTED_TIME_CHANGED] =
-		g_signal_new ("selected_time_changed",
-			      G_TYPE_FROM_CLASS (class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (ECalendarViewClass, selected_time_changed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
-	signals[TIMEZONE_CHANGED] =
-		g_signal_new ("timezone_changed",
-			      G_TYPE_FROM_CLASS (class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (ECalendarViewClass, timezone_changed),
-			      NULL, NULL,
-			      e_marshal_VOID__POINTER_POINTER,
-			      G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
-
-	signals[EVENT_CHANGED] =
-		g_signal_new ("event_changed",
-			      G_TYPE_FROM_CLASS (object_class),
-			      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-			      G_STRUCT_OFFSET (ECalendarViewClass, event_changed),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__POINTER,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_POINTER);
-
-	signals[EVENT_ADDED] =
-		g_signal_new ("event_added",
-			      G_TYPE_FROM_CLASS (object_class),
-			      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-			      G_STRUCT_OFFSET (ECalendarViewClass, event_added),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__POINTER,
-			      G_TYPE_NONE, 1,
-			      G_TYPE_POINTER);
-
-	signals[USER_CREATED] =
-		g_signal_new ("user_created",
-			      G_TYPE_FROM_CLASS (class),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (ECalendarViewClass, user_created),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
-
-	signals[OPEN_EVENT] =
-		g_signal_new ("open_event",
-			      G_TYPE_FROM_CLASS (class),
-			      G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
-			      G_STRUCT_OFFSET (ECalendarViewClass, open_event),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE, 0);
+	signals[POPUP_EVENT] = g_signal_new (
+		"popup-event",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_FIRST,
+		G_STRUCT_OFFSET (ECalendarViewClass, popup_event),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__BOXED,
+		G_TYPE_NONE, 1,
+		GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+	signals[SELECTION_CHANGED] = g_signal_new (
+		"selection-changed",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (ECalendarViewClass, selection_changed),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[SELECTED_TIME_CHANGED] = g_signal_new (
+		"selected-time-changed",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (ECalendarViewClass, selected_time_changed),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[TIMEZONE_CHANGED] = g_signal_new (
+		"timezone-changed",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (ECalendarViewClass, timezone_changed),
+		NULL, NULL,
+		e_marshal_VOID__POINTER_POINTER,
+		G_TYPE_NONE, 2,
+		G_TYPE_POINTER,
+		G_TYPE_POINTER);
+
+	signals[EVENT_CHANGED] = g_signal_new (
+		"event-changed",
+		G_TYPE_FROM_CLASS (object_class),
+		G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (ECalendarViewClass, event_changed),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__POINTER,
+		G_TYPE_NONE, 1,
+		G_TYPE_POINTER);
+
+	signals[EVENT_ADDED] = g_signal_new (
+		"event-added",
+		G_TYPE_FROM_CLASS (object_class),
+		G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (ECalendarViewClass, event_added),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__POINTER,
+		G_TYPE_NONE, 1,
+		G_TYPE_POINTER);
+
+	signals[USER_CREATED] = g_signal_new (
+		"user-created",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (ECalendarViewClass, user_created),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[OPEN_EVENT] = g_signal_new (
+		"open-event",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (ECalendarViewClass, open_event),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
 
         /*
          * Key bindings
@@ -291,9 +304,8 @@ e_calendar_view_class_init (ECalendarViewClass *class)
 
 	binding_set = gtk_binding_set_by_class (class);
 
-	gtk_binding_entry_add_signal (binding_set, GDK_o,
-                                      GDK_CONTROL_MASK,
-                                      "open_event", 0);
+	gtk_binding_entry_add_signal (
+		binding_set, GDK_o, GDK_CONTROL_MASK, "open-event", 0);
 
 #if 0  /* KILL-BONOBO */
 	/* init the accessibility support for e_day_view */
@@ -308,10 +320,19 @@ e_calendar_view_init (ECalendarView *calendar_view)
 }
 
 void
+e_calendar_view_popup_event (ECalendarView *calendar_view,
+                             GdkEventButton *event)
+{
+	g_return_if_fail (E_IS_CALENDAR_VIEW (calendar_view));
+	g_return_if_fail (event != NULL);
+
+	g_signal_emit (calendar_view, signals[POPUP_EVENT], 0, event);
+}
+
+void
 e_calendar_view_add_event (ECalendarView *cal_view, ECal *client, time_t dtstart,
 		      icaltimezone *default_zone, icalcomponent *icalcomp, gboolean in_top_canvas)
 {
-#if 0  /* KILL-BONOBO */
 	ECalComponent *comp;
 	struct icaltimetype itime, old_dtstart, old_dtend;
 	time_t tt_start, tt_end, new_dtstart = 0;
@@ -429,7 +450,6 @@ e_calendar_view_add_event (ECalendarView *cal_view, ECal *client, time_t dtstart
 	}
 
 	g_object_unref (comp);
-#endif
 }
 
 GnomeCalendar *
@@ -1184,536 +1204,6 @@ e_calendar_view_delete_selected_occurrence (ECalendarView *cal_view)
 	g_object_unref (comp);
 }
 
-static void
-on_new_task (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-#if 0  /* KILL-BONOBO */
-	ECalendarView *cal_view = data;
-	time_t dtstart, dtend;
-
-	e_calendar_view_get_selected_time_range (cal_view, &dtstart, &dtend);
-	gnome_calendar_new_task (cal_view->priv->calendar, &dtstart, &dtend);
-#endif
-}
-
-static void
-on_edit_appointment (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-	GList *selected;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (selected) {
-		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
-
-		if (event)
-			e_calendar_view_edit_appointment (cal_view, event->comp_data->client,
-						     event->comp_data->icalcomp,
-						     icalcomponent_get_first_property(event->comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY) != NULL);
-
-		g_list_free (selected);
-	}
-}
-
-static void
-on_print (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-#if 0  /* KILL-BONOBO */
-	ECalendarView *cal_view = data;
-
-	calendar_command_print (cal_view->priv->calendar, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG);
-#endif
-}
-
-static void
-on_save_as (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-	GList *selected;
-	gchar *filename;
-	gchar *ical_string;
-	ECalendarViewEvent *event;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (!selected)
-		return;
-
-	filename = e_file_dialog_save (_("Save as..."), NULL);
-	if (filename == NULL)
-		return;
-
-	event = (ECalendarViewEvent *) selected->data;
-	ical_string = e_cal_get_component_as_string (event->comp_data->client, event->comp_data->icalcomp);
-	if (ical_string == NULL) {
-		g_warning ("Couldn't convert item to a string");
-		return;
-	}
-
-	e_write_file_uri (filename, ical_string);
-	g_free (ical_string);
-
-	g_list_free (selected);
-}
-
-static void
-transfer_item_to (ECalendarViewEvent *event, ECal *dest_client, gboolean remove_item)
-{
-	const gchar *uid;
-	gchar *new_uid;
-	icalcomponent *orig_icalcomp;
-	icalproperty *icalprop;
-
-	uid = icalcomponent_get_uid (event->comp_data->icalcomp);
-
-	/* put the new object into the destination calendar */
-	if (e_cal_get_object (dest_client, uid, NULL, &orig_icalcomp, NULL)) {
-		icalcomponent_free (orig_icalcomp);
-
-		if (!e_cal_modify_object (dest_client, event->comp_data->icalcomp, CALOBJ_MOD_ALL, NULL))
-			return;
-	} else {
-		if (e_cal_util_component_is_instance (event->comp_data->icalcomp)) {
-			icalcomponent *icalcomp = NULL;
-
-			if (e_cal_get_object (event->comp_data->client, uid, NULL, &icalcomp, NULL)) {
-				/* use master object when working with recurring event */
-				orig_icalcomp = icalcomponent_new_clone (icalcomp);
-				icalcomponent_free (icalcomp);
-			} else {
-				/* ... or remove the recurrence id property... */
-				orig_icalcomp = icalcomponent_new_clone (event->comp_data->icalcomp);
-
-				if (e_cal_util_component_has_recurrences (orig_icalcomp)) {
-					/* ... for non-detached instances, to make it a master object */
-					icalproperty *prop;
-
-					prop = icalcomponent_get_first_property (orig_icalcomp, ICAL_RECURRENCEID_PROPERTY);
-					if (prop)
-						icalcomponent_remove_property (orig_icalcomp, prop);
-				}
-			}
-		} else
-			orig_icalcomp = icalcomponent_new_clone (event->comp_data->icalcomp);
-
-		icalprop = icalproperty_new_x ("1");
-		icalproperty_set_x_name (icalprop, "X-EVOLUTION-MOVE-CALENDAR");
-		icalcomponent_add_property (orig_icalcomp, icalprop);
-
-		if (!remove_item) {
-			/* change the UID to avoid problems with duplicated UIDs */
-			new_uid = e_cal_component_gen_uid ();
-			icalcomponent_set_uid (orig_icalcomp, new_uid);
-
-			g_free (new_uid);
-		}
-
-		new_uid = NULL;
-		if (!e_cal_create_object (dest_client, orig_icalcomp, &new_uid, NULL)) {
-			icalcomponent_free (orig_icalcomp);
-			return;
-		}
-
-		if (new_uid)
-			g_free (new_uid);
-		icalcomponent_free (orig_icalcomp);
-	}
-
-	/* remove the item from the source calendar */
-	if (remove_item) {
-		if (e_cal_util_component_is_instance (event->comp_data->icalcomp) || e_cal_util_component_has_recurrences (event->comp_data->icalcomp)) {
-			gchar *rid = NULL;
-			struct icaltimetype recur_id = icalcomponent_get_recurrenceid (event->comp_data->icalcomp);
-
-			if (!icaltime_is_null_time (recur_id))
-				rid = icaltime_as_ical_string_r (recur_id);
-
-			e_cal_remove_object_with_mod (event->comp_data->client, uid, rid, CALOBJ_MOD_ALL, NULL);
-			g_free (rid);
-		} else
-			e_cal_remove_object (event->comp_data->client, uid, NULL);
-	}
-}
-
-static void
-transfer_selected_items (ECalendarView *cal_view, gboolean remove_item)
-{
-	GList *selected, *l;
-	ESource *destination_source;
-	ECal *dest_client;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (!selected)
-		return;
-
-	/* prompt the user for destination source */
-	destination_source = select_source_dialog ((GtkWindow *) gtk_widget_get_toplevel ((GtkWidget *)cal_view), E_CAL_SOURCE_TYPE_EVENT);
-	if (!destination_source)
-		return;
-
-	/* open the destination calendar */
-	dest_client = auth_new_cal_from_source (destination_source, E_CAL_SOURCE_TYPE_EVENT);
-	if (!dest_client || !e_cal_open (dest_client, FALSE, NULL)) {
-		if (dest_client)
-			g_object_unref (dest_client);
-		g_object_unref (destination_source);
-		return;
-	}
-
-#if 0 /* KILL-BONOBO */
-	/* process all selected events */
-	if (remove_item)
-		e_calendar_view_set_status_message (cal_view, _("Moving items"), -1);
-	else
-		e_calendar_view_set_status_message (cal_view, _("Copying items"), -1);
-#endif
-
-	for (l = selected; l != NULL; l = l->next)
-		transfer_item_to ((ECalendarViewEvent *) l->data, dest_client, remove_item);
-
-#if 0 /* KILL-BONOBO */
-	e_calendar_view_set_status_message (cal_view, NULL, -1);
-#endif
-
-	/* free memory */
-	g_object_unref (destination_source);
-	g_object_unref (dest_client);
-	g_list_free (selected);
-}
-
-static void
-on_copy_to (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-
-	transfer_selected_items (cal_view, FALSE);
-}
-
-static void
-on_move_to (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-
-	transfer_selected_items (cal_view, TRUE);
-}
-
-static void
-on_meeting (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-	GList *selected;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (selected) {
-		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
-		e_calendar_view_edit_appointment (cal_view, event->comp_data->client, event->comp_data->icalcomp, TRUE);
-
-		g_list_free (selected);
-	}
-}
-
-static void
-set_attendee_status_for_delegate (icalcomponent *icalcomp, ECal *client)
-{
-	icalproperty *prop;
-	icalparameter *param;
-	gchar *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);
-
-	for (prop = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
-			prop;
-			prop = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
-		const gchar *attendee = icalproperty_get_attendee (prop);
-
-		if (!g_ascii_strcasecmp (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) {
-		gchar *temp = g_strdup_printf ("MAILTO:%s", address);
-
-		prop = icalproperty_new_attendee ((const gchar *) 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
-on_delegate (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-	GList *selected;
-	guint32 flags = 0;
-	icalcomponent *clone;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (selected) {
-		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
-
-		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;
-
-		e_calendar_view_open_event_with_flags (cal_view, event->comp_data->client, clone, flags);
-
-		icalcomponent_free (clone);
-		g_list_free (selected);
-	}
-}
-
-static void
-on_forward (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-	GList *selected;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (selected) {
-		ECalComponent *comp;
-		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
-
-		comp = e_cal_component_new ();
-		e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp));
-		itip_send_comp (E_CAL_COMPONENT_METHOD_PUBLISH, comp, event->comp_data->client, NULL, NULL, NULL, TRUE, FALSE);
-
-		g_list_free (selected);
-		g_object_unref (comp);
-	}
-}
-
-static void
-on_reply (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-	GList *selected;
-	gboolean reply_all = FALSE;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (selected) {
-		ECalComponent *comp;
-		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
-
-		comp = e_cal_component_new ();
-		e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp));
-		reply_to_calendar_comp (E_CAL_COMPONENT_METHOD_REPLY, comp, event->comp_data->client, reply_all, NULL, NULL);
-
-		g_list_free (selected);
-		g_object_unref (comp);
-	}
-}
-
-static void
-on_reply_all (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-	GList *selected;
-	gboolean reply_all = TRUE;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (selected) {
-		ECalComponent *comp;
-		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
-
-		comp = e_cal_component_new ();
-		e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp));
-		reply_to_calendar_comp (E_CAL_COMPONENT_METHOD_REPLY, comp, event->comp_data->client, reply_all, NULL, NULL);
-
-		g_list_free (selected);
-		g_object_unref (comp);
-	}
-}
-
-static void
-on_delete_appointment (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-
-	e_calendar_view_delete_selected_event (cal_view);
-}
-
-static void
-on_unrecur_appointment (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-	ECalendarViewEvent *event;
-	ECalComponent *comp, *new_comp;
-	ECalComponentDateTime date;
-	struct icaltimetype itt;
-	GList *selected;
-	ECal *client;
-	gchar *new_uid;
-	ECalComponentId *id = NULL;
-
-	selected = e_calendar_view_get_selected_events (cal_view);
-	if (!selected)
-		return;
-
-	event = (ECalendarViewEvent *) selected->data;
-	client = g_object_ref (event->comp_data->client);
-
-	date.value = &itt;
-	date.tzid = NULL;
-
-	/* For the recurring object, we add an exception to get rid of the
-	   instance. */
-
-	comp = e_cal_component_new ();
-	e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp));
-	id = e_cal_component_get_id (comp);
-
-	/* For the unrecurred instance we duplicate the original object,
-	   create a new uid for it, get rid of the recurrence rules, and set
-	   the start & end times to the instances times. */
-	new_comp = e_cal_component_new ();
-	e_cal_component_set_icalcomponent (new_comp, icalcomponent_new_clone (event->comp_data->icalcomp));
-
-	new_uid = e_cal_component_gen_uid ();
-	e_cal_component_set_uid (new_comp, new_uid);
-	g_free (new_uid);
-	e_cal_component_set_recurid (new_comp, NULL);
-	e_cal_component_set_rdate_list (new_comp, NULL);
-	e_cal_component_set_rrule_list (new_comp, NULL);
-	e_cal_component_set_exdate_list (new_comp, NULL);
-	e_cal_component_set_exrule_list (new_comp, NULL);
-
-	date.value = &itt;
-	date.tzid = icaltimezone_get_tzid (e_calendar_view_get_timezone (cal_view));
-
-	*date.value = icaltime_from_timet_with_zone (event->comp_data->instance_start, FALSE,
-						     e_calendar_view_get_timezone (cal_view));
-	cal_comp_set_dtstart_with_oldzone (client, new_comp, &date);
-	*date.value = icaltime_from_timet_with_zone (event->comp_data->instance_end, FALSE,
-						     e_calendar_view_get_timezone (cal_view));
-	cal_comp_set_dtend_with_oldzone (client, new_comp, &date);
-	e_cal_component_commit_sequence (new_comp);
-
-	/* Now update both ECalComponents. Note that we do this last since at
-	 * present the updates happen synchronously so our event may disappear.
-	 */
-
-	if (!e_cal_remove_object_with_mod (client, id->uid, id->rid, CALOBJ_MOD_THIS,
-				NULL))
-		g_message ("on_unrecur_appointment(): Could not remove the old object!");
-
-	e_cal_component_free_id (id);
-	g_object_unref (comp);
-
-	if (!e_cal_create_object (client, e_cal_component_get_icalcomponent (new_comp), &new_uid, NULL))
-		g_message ("on_unrecur_appointment(): Could not update the object!");
-	else
-		g_free (new_uid);
-
-	g_object_unref (new_comp);
-	g_object_unref (client);
-	g_list_free (selected);
-}
-
-static void
-on_delete_occurrence (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-
-	e_calendar_view_delete_selected_occurrence (cal_view);
-}
-
-static void
-on_cut (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-
-	e_calendar_view_cut_clipboard (cal_view);
-}
-
-static void
-on_copy (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-
-	e_calendar_view_copy_clipboard (cal_view);
-}
-
-static void
-on_paste (EPopup *ep, EPopupItem *pitem, gpointer data)
-{
-	ECalendarView *cal_view = data;
-
-	e_calendar_view_paste_clipboard (cal_view);
-}
-
-static EPopupItem ecv_main_items [] = {
-	{ E_POPUP_ITEM, (gchar *) "30.task", (gchar *) N_("New _Task"), on_new_task, NULL, (gchar *) "stock_task", 0, 0},
-
-	{ E_POPUP_BAR, (gchar *) "40."},
-	{ E_POPUP_ITEM, (gchar *) "40.print", (gchar *) N_("P_rint..."), on_print, NULL, (gchar *) GTK_STOCK_PRINT, 0, 0 },
-
-	{ E_POPUP_BAR, (gchar *) "50." },
-	{ E_POPUP_ITEM, (gchar *) "50.paste", (gchar *) N_("_Paste"), on_paste, NULL, (gchar *) GTK_STOCK_PASTE, 0, E_CAL_POPUP_SELECT_EDITABLE },
-
-	{ E_POPUP_BAR, (gchar *) "60." },
-	/* FIXME: hook in this somehow */
-	{ E_POPUP_SUBMENU, (gchar *) "60.view", (gchar *) N_("_Current View") },
-};
-
-static EPopupItem ecv_child_items [] = {
-	{ E_POPUP_ITEM, (gchar *) "00.open", (gchar *) N_("_Open"), on_edit_appointment, NULL, (gchar *) GTK_STOCK_OPEN, 0, E_CAL_POPUP_SELECT_NOTEDITING },
-	{ E_POPUP_ITEM, (gchar *) "10.saveas", (gchar *) N_("_Save As..."), on_save_as, NULL, (gchar *) GTK_STOCK_SAVE_AS, 0, E_CAL_POPUP_SELECT_NOTEDITING },
-
-	{ E_POPUP_BAR, (gchar *) "30." },
-
-	{ E_POPUP_ITEM, (gchar *) "31.cut", (gchar *) N_("C_ut"), on_cut, NULL, (gchar *) GTK_STOCK_CUT, 0, E_CAL_POPUP_SELECT_NOTEDITING|E_CAL_POPUP_SELECT_EDITABLE|E_CAL_POPUP_SELECT_ORGANIZER },
-	{ E_POPUP_ITEM, (gchar *) "32.copy", (gchar *) N_("_Copy"), on_copy, NULL, (gchar *) GTK_STOCK_COPY, 0, E_CAL_POPUP_SELECT_NOTEDITING|E_CAL_POPUP_SELECT_ORGANIZER },
-	{ E_POPUP_ITEM, (gchar *) "33.paste", (gchar *) N_("_Paste"), on_paste, NULL, (gchar *) GTK_STOCK_PASTE, 0, E_CAL_POPUP_SELECT_EDITABLE },
-
-	{ E_POPUP_BAR, (gchar *) "40." },
-
-	{ E_POPUP_ITEM, (gchar *) "43.copyto", (gchar *) N_("Cop_y to Calendar..."), on_copy_to, NULL, NULL, 0, E_CAL_POPUP_SELECT_NOTEDITING },
-	{ E_POPUP_ITEM, (gchar *) "44.moveto", (gchar *) N_("Mo_ve to Calendar..."), on_move_to, NULL, NULL, 0, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE },
-	{ E_POPUP_ITEM, (gchar *) "45.delegate", (gchar *) 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, (gchar *) "46.schedule", (gchar *) 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, (gchar *) "47.forward", (gchar *) N_("_Forward as iCalendar..."), on_forward, NULL, (gchar *) "mail-forward", 0, E_CAL_POPUP_SELECT_NOTEDITING },
-	{ E_POPUP_ITEM, (gchar *) "48.reply", (gchar *) N_("_Reply"), on_reply, NULL, (gchar *) "mail-reply-sender", E_CAL_POPUP_SELECT_MEETING | E_CAL_POPUP_SELECT_NOTEDITING },
-	{ E_POPUP_ITEM, (gchar *) "49.reply-all", (gchar *) N_("Reply to _All"), on_reply_all, NULL, (gchar *) "mail-reply-all", E_CAL_POPUP_SELECT_MEETING, E_CAL_POPUP_SELECT_NOTEDITING },
-
-	{ E_POPUP_BAR, (gchar *) "50." },
-
-	{ E_POPUP_ITEM, (gchar *) "51.delete", (gchar *) N_("_Delete"), on_delete_appointment, NULL, (gchar *) GTK_STOCK_DELETE, E_CAL_POPUP_SELECT_NONRECURRING, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE },
-	{ E_POPUP_ITEM, (gchar *) "52.move", (gchar *) N_("Make this Occurrence _Movable"), on_unrecur_appointment, NULL, NULL, E_CAL_POPUP_SELECT_RECURRING | E_CAL_POPUP_SELECT_INSTANCE, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE },
-	{ E_POPUP_ITEM, (gchar *) "53.delete", (gchar *) N_("Delete this _Occurrence"), on_delete_occurrence, NULL, (gchar *) GTK_STOCK_DELETE, E_CAL_POPUP_SELECT_RECURRING, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE },
-	{ E_POPUP_ITEM, (gchar *) "54.delete", (gchar *) N_("Delete _All Occurrences"), on_delete_appointment, NULL, (gchar *) GTK_STOCK_DELETE, E_CAL_POPUP_SELECT_RECURRING, E_CAL_POPUP_SELECT_NOTEDITING | E_CAL_POPUP_SELECT_EDITABLE },
-};
-
 void
 e_calendar_view_open_event (ECalendarView *cal_view)
 {
diff --git a/calendar/gui/e-calendar-view.h b/calendar/gui/e-calendar-view.h
index 58334d3..5af1d77 100644
--- a/calendar/gui/e-calendar-view.h
+++ b/calendar/gui/e-calendar-view.h
@@ -108,6 +108,7 @@ struct _ECalendarViewClass {
 	GtkTableClass parent_class;
 
 	/* Notification signals */
+	void (* popup_event) (ECalendarView *cal_view, GdkEventButton *event);
 	void (* selection_changed) (ECalendarView *cal_view);
 	void (* selected_time_changed) (ECalendarView *cal_view);
 	void (* timezone_changed) (ECalendarView *cal_view, icaltimezone *old_zone, icaltimezone *new_zone);
@@ -150,7 +151,8 @@ void           e_calendar_view_delete_selected_events (ECalendarView *cal_view);
 void           e_calendar_view_delete_selected_occurrence (ECalendarView *cal_view);
 CompEditor*    e_calendar_view_open_event_with_flags (ECalendarView *cal_view, ECal *client, icalcomponent *icalcomp, guint32 flags);
 
-GtkMenu       *e_calendar_view_create_popup_menu (ECalendarView *cal_view);
+void           e_calendar_view_popup_event	(ECalendarView *cal_view,
+						 GdkEventButton *event);
 
 void           e_calendar_view_add_event (ECalendarView *cal_view, ECal *client, time_t dtstart,
 				     icaltimezone *default_zone, icalcomponent *icalcomp, gboolean in_top_canvas);
diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c
index 879155f..ffd980e 100644
--- a/calendar/gui/e-day-view.c
+++ b/calendar/gui/e-day-view.c
@@ -261,7 +261,7 @@ static void e_day_view_on_event_right_click (EDayView *day_view,
 					     gint day,
 					     gint event_num);
 static void e_day_view_show_popup_menu (EDayView *day_view,
-					GdkEvent *gdk_event,
+					GdkEventButton *event,
 					gint day,
 					gint event_num);
 
@@ -3748,7 +3748,7 @@ popup_destroyed_cb (gpointer data, GObject *where_object_was)
 
 static void
 e_day_view_show_popup_menu (EDayView *day_view,
-			    GdkEvent *gdk_event,
+			    GdkEventButton *event,
 			    gint day,
 			    gint event_num)
 {
@@ -3757,11 +3757,7 @@ e_day_view_show_popup_menu (EDayView *day_view,
 	day_view->popup_event_day = day;
 	day_view->popup_event_num = event_num;
 
-#if 0 /* KILL-BONOBO */
-	popup = e_calendar_view_create_popup_menu (E_CALENDAR_VIEW (day_view));
-	g_object_weak_ref (G_OBJECT (popup), popup_destroyed_cb, day_view);
-	gtk_menu_popup (popup, NULL, NULL, NULL, NULL, gdk_event?gdk_event->button.button:0, gdk_event?gdk_event->button.time:gtk_get_current_event_time());
-#endif
+	e_calendar_view_popup_event (E_CALENDAR_VIEW (day_view), event);
 }
 
 static gboolean
@@ -3843,8 +3839,7 @@ e_day_view_on_event_right_click (EDayView *day_view,
 				 gint day,
 				 gint event_num)
 {
-	e_day_view_show_popup_menu (day_view, (GdkEvent*)bevent,
-				    day, event_num);
+	e_day_view_show_popup_menu (day_view, bevent, day, event_num);
 }
 
 static gboolean
diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c
index 7efd90a..e027ef2 100644
--- a/calendar/gui/e-week-view.c
+++ b/calendar/gui/e-week-view.c
@@ -4324,15 +4324,9 @@ e_week_view_show_popup_menu (EWeekView	     *week_view,
 			     GdkEventButton  *bevent,
 			     gint	      event_num)
 {
-	GtkMenu *popup;
-
 	week_view->popup_event_num = event_num;
 
-#if 0 /* KILL-BONOBO */
-	popup = e_calendar_view_create_popup_menu (E_CALENDAR_VIEW (week_view));
-	g_object_weak_ref (G_OBJECT (popup), popup_destroyed_cb, week_view);
-	gtk_menu_popup (popup, NULL, NULL, NULL, NULL, bevent?bevent->button:0, bevent?bevent->time:gtk_get_current_event_time());
-#endif
+	e_calendar_view_popup_event (E_CALENDAR_VIEW (week_view), bevent);
 }
 
 static gboolean
diff --git a/calendar/gui/gnome-cal.h b/calendar/gui/gnome-cal.h
index 437bce0..adcacf8 100644
--- a/calendar/gui/gnome-cal.h
+++ b/calendar/gui/gnome-cal.h
@@ -24,8 +24,8 @@
  *
  */
 
-#ifndef GNOME_CALENDAR_APP_H
-#define GNOME_CALENDAR_APP_H
+#ifndef GNOME_CALENDAR_H
+#define GNOME_CALENDAR_H
 
 #include <time.h>
 #include <gtk/gtk.h>
diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c
index eccd146..0dd3ff1 100644
--- a/modules/calendar/e-cal-shell-content.c
+++ b/modules/calendar/e-cal-shell-content.c
@@ -33,6 +33,8 @@
 #include "calendar/gui/e-cal-model-calendar.h"
 #include "calendar/gui/e-calendar-table.h"
 #include "calendar/gui/e-calendar-view.h"
+#include "calendar/gui/e-day-view.h"
+#include "calendar/gui/e-week-view.h"
 
 #include "widgets/menus/gal-view-etable.h"
 
@@ -138,12 +140,10 @@ cal_shell_content_notify_view_id_cb (ECalShellContent *cal_shell_content)
 static FocusLocation
 cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content)
 {
-        return FOCUS_OTHER;
-#if 0  /* TEMPORARILY DISABLED */
 	GtkWidget *widget;
 	GnomeCalendar *calendar;
 	GnomeCalendarViewType view_type;
-	ECalendarView calendar_view;
+	ECalendarView *calendar_view;
 	ECalendarTable *task_table;
 	EMemoTable *memo_table;
 	ETable *table;
@@ -205,7 +205,6 @@ cal_shell_content_get_focus_location (ECalShellContent *cal_shell_content)
 	}
 
 	return FOCUS_OTHER;
-#endif
 }
 
 static void
diff --git a/modules/calendar/e-cal-shell-view-actions.c b/modules/calendar/e-cal-shell-view-actions.c
index bb8ee69..699cf24 100644
--- a/modules/calendar/e-cal-shell-view-actions.c
+++ b/modules/calendar/e-cal-shell-view-actions.c
@@ -271,7 +271,74 @@ static void
 action_calendar_purge_cb (GtkAction *action,
                           ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	EShellView *shell_view;
+	EShellWindow *shell_window;
+	ECalShellContent *cal_shell_content;
+	GnomeCalendar *calendar;
+	GtkSpinButton *spin_button;
+	GtkWidget *container;
+	GtkWidget *dialog;
+	GtkWidget *widget;
+	gint days;
+	time_t tt;
+
+	shell_view = E_SHELL_VIEW (cal_shell_view);
+	shell_window = e_shell_view_get_shell_window (shell_view);
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+
+	dialog = gtk_message_dialog_new (
+		GTK_WINDOW (shell_window),
+		GTK_DIALOG_DESTROY_WITH_PARENT,
+		GTK_MESSAGE_WARNING,
+		GTK_BUTTONS_OK_CANCEL,
+		_("This operation will permanently erase all events older "
+		  "than the selected amount of time. If you continue, you "
+		  "will not be able to recover these events."));
+
+	gtk_dialog_set_default_response (
+		GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+
+	container = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+	widget = gtk_hbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, FALSE, 6);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	/* Translators: This is the first part of the sentence:
+	 * "Purge events older than <<spin-button>> days" */
+	widget = gtk_label_new (_("Purge events older than"));
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, FALSE, 6);
+	gtk_widget_show (widget);
+
+	widget = gtk_spin_button_new_with_range (0.0, 1000.0, 1.0);
+	gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), 60.0);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 6);
+	gtk_widget_show (widget);
+
+	spin_button = GTK_SPIN_BUTTON (widget);
+
+	/* Translators: This is the last part of the sentence:
+	 * "Purge events older than <<spin-button>> days" */
+	widget = gtk_label_new (_("days"));
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, FALSE, 6);
+	gtk_widget_show (widget);
+
+	if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
+		goto exit;
+
+	days = gtk_spin_button_get_value_as_int (spin_button);
+
+	tt = time (NULL);
+	tt -= (days * (24 * 3600));
+
+	gnome_calendar_purge (calendar, tt);
+
+exit:
+	gtk_widget_destroy (dialog);
 }
 
 static void
@@ -437,14 +504,157 @@ static void
 action_event_copy_cb (GtkAction *action,
                       ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	EShellView *shell_view;
+	EShellWindow *shell_window;
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	GnomeCalendar *calendar;
+	ECalendarView *calendar_view;
+	ESource *destination_source = NULL;
+	ECal *destination_client = NULL;
+	GList *selected, *iter;
+
+	shell_view = E_SHELL_VIEW (cal_shell_view);
+	shell_window = e_shell_view_get_shell_window (shell_view);
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (selected != NULL);
+
+	/* Get a destination source from the user. */
+	destination_source = select_source_dialog (
+		GTK_WINDOW (shell_window), E_CAL_SOURCE_TYPE_EVENT);
+	if (destination_source == NULL)
+		return;
+
+	/* Open the destination calendar. */
+	destination_client = auth_new_cal_from_source (
+		destination_source, E_CAL_SOURCE_TYPE_EVENT);
+	if (destination_client == NULL)
+		goto exit;
+	if (!e_cal_open (destination_client, FALSE, NULL))
+		goto exit;
+
+	e_cal_shell_view_set_status_message (
+		cal_shell_view, _("Copying Items"), -1.0);
+
+	for (iter = selected; iter != NULL; iter = iter->next) {
+		ECalendarViewEvent *event = iter->data;
+		gboolean remove = FALSE;
+
+		e_cal_shell_view_transfer_item_to (
+			cal_shell_view, event, destination_client, remove);
+	}
+
+	e_cal_shell_view_set_status_message (cal_shell_view, NULL, -1.0);
+
+exit:
+	if (destination_client != NULL)
+		g_object_unref (destination_client);
+	if (destination_source != NULL)
+		g_object_unref (destination_source);
+	g_list_free (selected);
 }
 
 static void
 action_event_delegate_cb (GtkAction *action,
                           ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	GnomeCalendar *calendar;
+	ECalendarView *calendar_view;
+	ECalendarViewEvent *event;
+	ECalComponent *component;
+	ECal *client;
+	GList *selected;
+	icalcomponent *clone;
+	icalproperty *property;
+	gboolean found = FALSE;
+	gchar *attendee;
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (g_list_length (selected) == 1);
+
+	event = selected->data;
+	client = event->comp_data->client;
+	clone = icalcomponent_new_clone (event->comp_data->icalcomp);
+
+	/* Set the attendee status for the delegate. */
+
+	component = e_cal_component_new ();
+	e_cal_component_set_icalcomponent (
+		component, icalcomponent_new_clone (clone));
+
+	attendee = itip_get_comp_attendee (component, client);
+	property = icalcomponent_get_first_property (
+		clone, ICAL_ATTENDEE_PROPERTY);
+
+	while (property != NULL) {
+		const gchar *candidate;
+
+		candidate = icalproperty_get_attendee (property);
+		candidate = itip_strip_mailto (candidate);
+
+		if (g_ascii_strcasecmp (candidate, attendee) == 0) {
+			icalparameter *parameter;
+
+			parameter = icalparameter_new_role (
+				ICAL_ROLE_NONPARTICIPANT);
+			icalproperty_set_parameter (property, parameter);
+
+			parameter = icalparameter_new_partstat (
+				ICAL_PARTSTAT_DELEGATED);
+			icalproperty_set_parameter (property, parameter);
+
+			found = TRUE;
+			break;
+		}
+
+		property = icalcomponent_get_next_property (
+			clone, ICAL_ATTENDEE_PROPERTY);
+	}
+
+	/* If the attendee is not already in the component, add it. */
+	if (!found) {
+		icalparameter *parameter;
+		gchar *address;
+
+		address = g_strdup_printf ("MAILTO:%s", attendee);
+
+		property = icalproperty_new_attendee (address);
+		icalcomponent_add_property (clone, property);
+
+		parameter = icalparameter_new_role (ICAL_ROLE_NONPARTICIPANT);
+		icalproperty_add_parameter (property, parameter);
+
+		parameter = icalparameter_new_cutype (ICAL_CUTYPE_INDIVIDUAL);
+		icalproperty_add_parameter (property, parameter);
+
+		parameter = icalparameter_new_rsvp (ICAL_RSVP_TRUE);
+		icalproperty_add_parameter (property, parameter);
+
+		g_free (address);
+	}
+
+	g_free (attendee);
+	g_object_unref (component);
+
+	e_calendar_view_open_event_with_flags (
+		calendar_view, event->comp_data->client, clone,
+		COMP_EDITOR_MEETING | COMP_EDITOR_DELEGATE);
+
+	icalcomponent_free (clone);
+	g_list_free (selected);
 }
 
 static void
@@ -482,7 +692,39 @@ static void
 action_event_forward_cb (GtkAction *action,
                          ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	ECalendarView *calendar_view;
+	GnomeCalendar *calendar;
+	ECalendarViewEvent *event;
+	ECalComponent *component;
+	ECal *client;
+	icalcomponent *icalcomp;
+	GList *selected;
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (g_list_length (selected) == 1);
+
+	event = selected->data;
+	client = event->comp_data->client;
+	icalcomp = event->comp_data->icalcomp;
+
+	component = e_cal_component_new ();
+
+	e_cal_component_set_icalcomponent (
+		component, icalcomponent_new_clone (icalcomp));
+	itip_send_comp (
+		E_CAL_COMPONENT_METHOD_PUBLISH,
+		component, client, NULL, NULL, NULL, TRUE, FALSE);
+
+	g_object_unref (component);
+
+	g_list_free (selected);
 }
 
 static void
@@ -512,7 +754,60 @@ static void
 action_event_move_cb (GtkAction *action,
                       ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	EShellView *shell_view;
+	EShellWindow *shell_window;
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	GnomeCalendar *calendar;
+	ECalendarView *calendar_view;
+	ESource *destination_source = NULL;
+	ECal *destination_client = NULL;
+	GList *selected, *iter;
+
+	shell_view = E_SHELL_VIEW (cal_shell_view);
+	shell_window = e_shell_view_get_shell_window (shell_view);
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (selected != NULL);
+
+	/* Get a destination source from the user. */
+	destination_source = select_source_dialog (
+		GTK_WINDOW (shell_window), E_CAL_SOURCE_TYPE_EVENT);
+	if (destination_source == NULL)
+		return;
+
+	/* Open the destination calendar. */
+	destination_client = auth_new_cal_from_source (
+		destination_source, E_CAL_SOURCE_TYPE_EVENT);
+	if (destination_client == NULL)
+		goto exit;
+	if (!e_cal_open (destination_client, FALSE, NULL))
+		goto exit;
+
+	e_cal_shell_view_set_status_message (
+		cal_shell_view, _("Moving Items"), -1.0);
+
+	for (iter = selected; iter != NULL; iter = iter->next) {
+		ECalendarViewEvent *event = iter->data;
+		gboolean remove = TRUE;
+
+		e_cal_shell_view_transfer_item_to (
+			cal_shell_view, event, destination_client, remove);
+	}
+
+	e_cal_shell_view_set_status_message (cal_shell_view, NULL, -1.0);
+
+exit:
+	if (destination_client != NULL)
+		g_object_unref (destination_client);
+	if (destination_source != NULL)
+		g_object_unref (destination_source);
+	g_list_free (selected);
 }
 
 static void
@@ -536,7 +831,91 @@ static void
 action_event_occurrence_movable_cb (GtkAction *action,
                                     ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	GnomeCalendar *calendar;
+	ECalModel *model;
+	ECalendarView *calendar_view;
+	ECalendarViewEvent *event;
+	ECalComponent *exception_component;
+	ECalComponent *recurring_component;
+	ECalComponentDateTime date;
+	ECalComponentId *id;
+	ECal *client;
+	icalcomponent *icalcomp;
+	icaltimetype itt;
+	icaltimezone *timezone;
+	GList *selected;
+	gchar *uid;
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	model = e_calendar_view_get_model (calendar_view);
+	timezone = e_cal_model_get_timezone (model);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (g_list_length (selected) == 1);
+
+	event = selected->data;
+	client = event->comp_data->client;
+	icalcomp = event->comp_data->icalcomp;
+
+	/* For the recurring object, we add an exception
+	 * to get rid of the instance. */
+
+	recurring_component = e_cal_component_new ();
+	e_cal_component_set_icalcomponent (
+		recurring_component, icalcomponent_new_clone (icalcomp));
+	id = e_cal_component_get_id (recurring_component);
+
+	/* For the unrecurred instance, we duplicate the original object,
+	 * create a new UID for it, get rid of the recurrence rules, and
+	 * set the start and end times to the instance times. */
+
+	exception_component = e_cal_component_new ();
+	e_cal_component_set_icalcomponent (
+		exception_component, icalcomponent_new_clone (icalcomp));
+
+	uid = e_cal_component_gen_uid ();
+	e_cal_component_set_uid (exception_component, uid);
+	g_free (uid);
+
+	e_cal_component_set_recurid (exception_component, NULL);
+	e_cal_component_set_rdate_list (exception_component, NULL);
+	e_cal_component_set_rrule_list (exception_component, NULL);
+	e_cal_component_set_exdate_list (exception_component, NULL);
+	e_cal_component_set_exrule_list (exception_component, NULL);
+
+	date.value = &itt;
+	date.tzid = icaltimezone_get_tzid (timezone);
+	*date.value = icaltime_from_timet_with_zone (
+		event->comp_data->instance_start, FALSE, timezone);
+	cal_comp_set_dtstart_with_oldzone (client, exception_component, &date);
+	*date.value = icaltime_from_timet_with_zone (
+		event->comp_data->instance_end, FALSE, timezone);
+	cal_comp_set_dtstart_with_oldzone (client, exception_component, &date);
+	e_cal_component_commit_sequence (exception_component);
+
+	/* Now update both ECalComponents.  Note that we do this last
+	*  since at present the updates happend synchronously so our
+	*  event may disappear. */
+
+	e_cal_remove_object_with_mod (
+		client, id->uid, id->rid, CALOBJ_MOD_THIS, NULL);
+
+	e_cal_component_free_id (id);
+	g_object_unref (recurring_component);
+
+	icalcomp = e_cal_component_get_icalcomponent (exception_component);
+	if (e_cal_create_object (client, icalcomp, &uid, NULL))
+		g_free (uid);
+
+	g_object_unref (exception_component);
+
+	g_list_free (selected);
 }
 
 static void
@@ -560,35 +939,195 @@ static void
 action_event_print_cb (GtkAction *action,
                        ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	GnomeCalendar *calendar;
+	ECalendarView *calendar_view;
+	ECalendarViewEvent *event;
+	ECalComponent *component;
+	ECal *client;
+	icalcomponent *icalcomp;
+	GList *selected;
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (g_list_length (selected) == 1);
+
+	event = selected->data;
+	client = event->comp_data->client;
+	icalcomp = event->comp_data->icalcomp;
+
+	component = e_cal_component_new ();
+
+	e_cal_component_set_icalcomponent (
+		component, icalcomponent_new_clone (icalcomp));
+	print_comp (
+		component, client, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG);
+
+	g_object_unref (component);
+
+	g_list_free (selected);
 }
 
 static void
 action_event_reply_cb (GtkAction *action,
                        ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	ECalendarView *calendar_view;
+	GnomeCalendar *calendar;
+	ECalendarViewEvent *event;
+	ECalComponent *component;
+	ECal *client;
+	icalcomponent *icalcomp;
+	GList *selected;
+	gboolean reply_all = FALSE;
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (g_list_length (selected) == 1);
+
+	event = selected->data;
+	client = event->comp_data->client;
+	icalcomp = event->comp_data->icalcomp;
+
+	component = e_cal_component_new ();
+
+	e_cal_component_set_icalcomponent (
+		component, icalcomponent_new_clone (icalcomp));
+	reply_to_calendar_comp (
+		E_CAL_COMPONENT_METHOD_REPLY,
+		component, client, reply_all, NULL, NULL);
+
+	g_object_unref (component);
+
+	g_list_free (selected);
 }
 
 static void
 action_event_reply_all_cb (GtkAction *action,
                            ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	ECalendarView *calendar_view;
+	GnomeCalendar *calendar;
+	ECalendarViewEvent *event;
+	ECalComponent *component;
+	ECal *client;
+	icalcomponent *icalcomp;
+	GList *selected;
+	gboolean reply_all = TRUE;
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (g_list_length (selected) == 1);
+
+	event = selected->data;
+	client = event->comp_data->client;
+	icalcomp = event->comp_data->icalcomp;
+
+	component = e_cal_component_new ();
+
+	e_cal_component_set_icalcomponent (
+		component, icalcomponent_new_clone (icalcomp));
+	reply_to_calendar_comp (
+		E_CAL_COMPONENT_METHOD_REPLY,
+		component, client, reply_all, NULL, NULL);
+
+	g_object_unref (component);
+
+	g_list_free (selected);
 }
 
 static void
 action_event_save_as_cb (GtkAction *action,
                          ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	GnomeCalendar *calendar;
+	ECalendarView *calendar_view;
+	ECalendarViewEvent *event;
+	ECal *client;
+	icalcomponent *icalcomp;
+	GList *selected;
+	gchar *filename = NULL;
+	gchar *string = NULL;
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (g_list_length (selected) == 1);
+
+	event = selected->data;
+	client = event->comp_data->client;
+	icalcomp = event->comp_data->icalcomp;
+
+	filename = e_file_dialog_save (_("Save As..."), NULL);
+	if (filename == NULL)
+		goto exit;
+
+	string = e_cal_get_component_as_string (client, icalcomp);
+	if (string == NULL) {
+		g_warning ("Could not convert item to a string");
+		goto exit;
+	}
+
+	e_write_file_uri (filename, string);
+
+exit:
+	g_free (filename);
+	g_free (string);
+
+	g_list_free (selected);
 }
 
 static void
 action_event_schedule_cb (GtkAction *action,
                           ECalShellView *cal_shell_view)
 {
-	/* FIXME */
+	ECalShellContent *cal_shell_content;
+	GnomeCalendarViewType view_type;
+	GnomeCalendar *calendar;
+	ECalendarView *calendar_view;
+	ECalendarViewEvent *event;
+	ECal *client;
+	icalcomponent *icalcomp;
+	GList *selected;
+
+	cal_shell_content = cal_shell_view->priv->cal_shell_content;
+	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
+	view_type = gnome_calendar_get_view (calendar);
+	calendar_view = gnome_calendar_get_calendar_view (calendar, view_type);
+
+	selected = e_calendar_view_get_selected_events (calendar_view);
+	g_return_if_fail (g_list_length (selected) == 1);
+
+	event = selected->data;
+	client = event->comp_data->client;
+	icalcomp = event->comp_data->icalcomp;
+
+	e_calendar_view_edit_appointment (
+		calendar_view, client, icalcomp, TRUE);
+
+	g_list_free (selected);
 }
 
 static void
@@ -1132,6 +1671,21 @@ e_cal_shell_view_actions_init (ECalShellView *cal_shell_view)
 	action = ACTION (CALENDAR_JUMP_TO);
 	g_object_set (action, "short-label", _("Go To"), NULL);
 
+	action = ACTION (CALENDAR_VIEW_DAY);
+	g_object_set (action, "is-important", TRUE, NULL);
+
+	action = ACTION (CALENDAR_VIEW_LIST);
+	g_object_set (action, "is-important", TRUE, NULL);
+
+	action = ACTION (CALENDAR_VIEW_MONTH);
+	g_object_set (action, "is-important", TRUE, NULL);
+
+	action = ACTION (CALENDAR_VIEW_WEEK);
+	g_object_set (action, "is-important", TRUE, NULL);
+
+	action = ACTION (CALENDAR_VIEW_WORKWEEK);
+	g_object_set (action, "is-important", TRUE, NULL);
+
 	action = ACTION (EVENT_DELETE);
 	g_object_set (action, "short-label", _("Delete"), NULL);
 
diff --git a/modules/calendar/e-cal-shell-view-private.c b/modules/calendar/e-cal-shell-view-private.c
index 8c18176..719e705 100644
--- a/modules/calendar/e-cal-shell-view-private.c
+++ b/modules/calendar/e-cal-shell-view-private.c
@@ -107,6 +107,16 @@ cal_shell_view_date_navigator_scroll_event_cb (ECalShellView *cal_shell_view,
 		cal_shell_view, calitem);
 }
 
+static void
+cal_shell_view_popup_event_cb (EShellView *shell_view,
+                               GdkEventButton *event)
+{
+	const gchar *widget_path;
+
+	widget_path = "/calendar-event-popup";
+	e_shell_view_show_popup_menu (shell_view, widget_path, event);
+}
+
 static gboolean
 cal_shell_view_selector_popup_event_cb (EShellView *shell_view,
                                         ESource *primary_source,
@@ -254,6 +264,7 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view)
 	ECalendarTable *task_table;
 	ESourceSelector *selector;
 	ECalModel *model;
+	gint ii;
 
 	shell_view = E_SHELL_VIEW (cal_shell_view);
 	shell_backend = e_shell_view_get_shell_backend (shell_view);
@@ -288,6 +299,17 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view)
 
 	/* KILL-BONOBO FIXME -- Need to connect to the "user-created"
 	 *                      signal for each ECalendarView. */
+	for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) {
+		ECalendarView *calendar_view;
+
+		calendar_view =
+			gnome_calendar_get_calendar_view (calendar, ii);
+
+		g_signal_connect_swapped (
+			calendar_view, "popup-event",
+			G_CALLBACK (cal_shell_view_popup_event_cb),
+			cal_shell_view);
+	}
 
 	g_signal_connect_swapped (
 		calendar, "dates-shown-changed",
@@ -648,6 +670,119 @@ e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view,
 }
 
 void
+e_cal_shell_view_transfer_item_to (ECalShellView *cal_shell_view,
+                                   ECalendarViewEvent *event,
+                                   ECal *destination_client,
+                                   gboolean remove)
+{
+	icalcomponent *icalcomp;
+	icalcomponent *icalcomp_clone;
+	icalcomponent *icalcomp_event;
+	gboolean success;
+	const gchar *uid;
+
+	/* XXX This function should be split up into
+	 *     smaller, more understandable pieces. */
+
+	g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view));
+	g_return_if_fail (event != NULL);
+	g_return_if_fail (E_IS_CAL (destination_client));
+
+	icalcomp_event = event->comp_data->icalcomp;
+	uid = icalcomponent_get_uid (icalcomp_event);
+
+	/* Put the new object into the destination calendar. */
+
+	success = e_cal_get_object (
+		destination_client, uid, NULL, &icalcomp, NULL);
+
+	if (success) {
+		icalcomponent_free (icalcomp);
+		success = e_cal_modify_object (
+			destination_client, icalcomp_event,
+			CALOBJ_MOD_ALL, NULL);
+		if (!success)
+			return;
+	} else {
+		icalproperty *icalprop;
+		gchar *new_uid;
+
+		if (e_cal_util_component_is_instance (icalcomp_event)) {
+			success = e_cal_get_object (
+				event->comp_data->client,
+				uid, NULL, &icalcomp, NULL);
+			if (success) {
+				/* Use master object when working
+				 * with a recurring event ... */
+				icalcomp_clone =
+					icalcomponent_new_clone (icalcomp);
+				icalcomponent_free (icalcomp);
+			} else {
+				/* ... or remove the recurrence ID ... */
+				icalcomp_clone =
+					icalcomponent_new_clone (icalcomp_event);
+				if (e_cal_util_component_has_recurrences (icalcomp_clone)) {
+					/* ... for non-detached instances,
+					 * to make it a master object. */
+					icalprop = icalcomponent_get_first_property (
+						icalcomp_clone, ICAL_RECURRENCEID_PROPERTY);
+					if (icalprop != NULL)
+						icalcomponent_remove_property (
+							icalcomp_clone, icalprop);
+				}
+			}
+		} else
+			icalcomp_clone =
+				icalcomponent_new_clone (icalcomp_event);
+
+		icalprop = icalproperty_new_x ("1");
+		icalproperty_set_x_name (icalprop, "X-EVOLUTION-MOVE-CALENDAR");
+		icalcomponent_add_property (icalcomp_clone, icalprop);
+
+		if (!remove) {
+			/* Change the UID to avoid problems with
+			 * duplicated UIDs. */
+			new_uid = e_cal_component_gen_uid ();
+			icalcomponent_set_uid (icalcomp_clone, new_uid);
+			g_free (new_uid);
+		}
+
+		new_uid = NULL;
+		success = e_cal_create_object (
+			destination_client, icalcomp_clone, &new_uid, NULL);
+		if (!success) {
+			icalcomponent_free (icalcomp_clone);
+			return;
+		}
+
+		icalcomponent_free (icalcomp_clone);
+		g_free (new_uid);
+	}
+
+	if (remove) {
+		ECal *source_client = event->comp_data->client;
+
+		/* Remove the item from the source calendar. */
+		if (e_cal_util_component_is_instance (icalcomp_event) ||
+			e_cal_util_component_has_recurrences (icalcomp_event)) {
+			icaltimetype icaltime;
+			gchar *rid;
+
+			icaltime =
+				icalcomponent_get_recurrenceid (icalcomp_event);
+			if (!icaltime_is_null_time (icaltime))
+				rid = icaltime_as_ical_string_r (icaltime);
+			else
+				rid = NULL;
+			e_cal_remove_object_with_mod (
+				source_client, uid, rid, CALOBJ_MOD_ALL, NULL);
+			g_free (rid);
+		} else
+			e_cal_remove_object (source_client, uid, NULL);
+	}
+}
+
+void
 e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view)
 {
 	EShellView *shell_view;
diff --git a/modules/calendar/e-cal-shell-view-private.h b/modules/calendar/e-cal-shell-view-private.h
index 2e1388a..77f9e1b 100644
--- a/modules/calendar/e-cal-shell-view-private.h
+++ b/modules/calendar/e-cal-shell-view-private.h
@@ -34,6 +34,7 @@
 #include "e-util/e-dialog-utils.h"
 #include "widgets/misc/e-popup-action.h"
 
+#include "calendar/common/authentication.h"
 #include "calendar/gui/calendar-config.h"
 #include "calendar/gui/comp-util.h"
 #include "calendar/gui/e-cal-list-view.h"
@@ -45,6 +46,7 @@
 #include "calendar/gui/dialogs/copy-source-dialog.h"
 #include "calendar/gui/dialogs/event-editor.h"
 #include "calendar/gui/dialogs/memo-editor.h"
+#include "calendar/gui/dialogs/select-source-dialog.h"
 #include "calendar/gui/dialogs/task-editor.h"
 
 #include "e-cal-shell-backend.h"
@@ -127,6 +129,11 @@ void		e_cal_shell_view_set_status_message
 					(ECalShellView *cal_shell_view,
 					 const gchar *status_message,
 					 gdouble percent);
+void		e_cal_shell_view_transfer_item_to
+					(ECalShellView *cal_shell_view,
+					 ECalendarViewEvent *event,
+					 ECal *destination_client,
+					 gboolean remove);
 void		e_cal_shell_view_update_sidebar
 					(ECalShellView *cal_shell_view);
 void		e_cal_shell_view_update_search_filter
diff --git a/ui/evolution-calendars.ui b/ui/evolution-calendars.ui
index 59900ea..267d6f0 100644
--- a/ui/evolution-calendars.ui
+++ b/ui/evolution-calendars.ui
@@ -60,6 +60,7 @@
     <menuitem action='event-new'/>
     <menuitem action='event-all-day-new'/>
     <menuitem action='event-meeting-new'/>
+    <menuitem action='task-new'/>
     <separator/>
     <menuitem action='event-popup-print'/>
     <separator/>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]