aboutsummaryrefslogtreecommitdiffstats
path: root/calendar/gui/comp-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'calendar/gui/comp-util.c')
-rw-r--r--calendar/gui/comp-util.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/calendar/gui/comp-util.c b/calendar/gui/comp-util.c
index 9504c7bda7..9a58a8cf6b 100644
--- a/calendar/gui/comp-util.c
+++ b/calendar/gui/comp-util.c
@@ -33,6 +33,7 @@
#include "dialogs/delete-comp.h"
#include <libecal/e-cal-component.h>
#include "e-util/e-categories-config.h"
+#include "common/authentication.h"
@@ -607,3 +608,191 @@ cal_comp_set_dtend_with_oldzone (ECal *client, ECalComponent *comp, const ECalCo
e_cal_component_free_datetime (&olddate);
}
+
+static gboolean
+update_single_object (ECal *client, icalcomponent *icalcomp, gboolean fail_on_modify)
+{
+ const char *uid;
+ char *tmp;
+ icalcomponent *tmp_icalcomp;
+ gboolean res;
+
+ uid = icalcomponent_get_uid (icalcomp);
+
+ if (e_cal_get_object (client, uid, NULL, &tmp_icalcomp, NULL)) {
+ if (fail_on_modify)
+ return FALSE;
+
+ return e_cal_modify_object (client, icalcomp, CALOBJ_MOD_ALL, NULL);
+ }
+
+ tmp = NULL;
+ res = e_cal_create_object (client, icalcomp, &tmp, NULL);
+
+ g_free (tmp);
+
+ return res;
+}
+
+static gboolean
+update_objects (ECal *client, icalcomponent *icalcomp)
+{
+ icalcomponent *subcomp;
+ icalcomponent_kind kind;
+
+ kind = icalcomponent_isa (icalcomp);
+ if (kind == ICAL_VTODO_COMPONENT ||
+ kind == ICAL_VEVENT_COMPONENT ||
+ kind == ICAL_VJOURNAL_COMPONENT)
+ return update_single_object (client, icalcomp, kind == ICAL_VJOURNAL_COMPONENT);
+ else if (kind != ICAL_VCALENDAR_COMPONENT)
+ return FALSE;
+
+ subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT);
+ while (subcomp) {
+ gboolean success;
+
+ kind = icalcomponent_isa (subcomp);
+ if (kind == ICAL_VTIMEZONE_COMPONENT) {
+ icaltimezone *zone;
+
+ zone = icaltimezone_new ();
+ icaltimezone_set_component (zone, subcomp);
+
+ success = e_cal_add_timezone (client, zone, NULL);
+ icaltimezone_free (zone, 1);
+ if (!success)
+ return success;
+ } else if (kind == ICAL_VTODO_COMPONENT ||
+ kind == ICAL_VEVENT_COMPONENT ||
+ kind == ICAL_VJOURNAL_COMPONENT) {
+ success = update_single_object (client, subcomp, kind == ICAL_VJOURNAL_COMPONENT);
+ if (!success)
+ return success;
+ }
+
+ subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT);
+ }
+
+ return TRUE;
+}
+
+/**
+ * cal_comp_process_source_list_drop:
+ * Processes the drop signal over the ESourceList.
+ * @param destination Where to put the component.
+ * @param comp Component to move/copy.
+ * @param action What to do.
+ * @param source_uid Where the component comes from; used when moving.
+ * @param source_list The ESourceList over which the event was called.
+ * @return Whether was the operation successful.
+ **/
+gboolean
+cal_comp_process_source_list_drop (ECal *destination, icalcomponent *comp, GdkDragAction action, const char *source_uid, ESourceList *source_list)
+{
+ const char * uid;
+ char *old_uid = NULL;
+ icalcomponent *tmp_icalcomp = NULL;
+ GError *error = NULL;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (destination != NULL, FALSE);
+ g_return_val_if_fail (comp != NULL, FALSE);
+ g_return_val_if_fail (source_uid != NULL, FALSE);
+ g_return_val_if_fail (source_list != NULL, FALSE);
+
+ /* FIXME deal with GDK_ACTION_ASK */
+ if (action == GDK_ACTION_COPY) {
+ char *tmp;
+
+ old_uid = g_strdup (icalcomponent_get_uid (comp));
+ tmp = e_cal_component_gen_uid ();
+
+ icalcomponent_set_uid (comp, tmp);
+ g_free (tmp);
+ }
+
+ uid = icalcomponent_get_uid (comp);
+ if (!old_uid)
+ old_uid = g_strdup (uid);
+
+ if (!e_cal_get_object (destination, uid, NULL, &tmp_icalcomp, &error)) {
+ if ((error != NULL) && (error->code != E_CALENDAR_STATUS_OBJECT_NOT_FOUND)) {
+ switch (e_cal_get_source_type (destination)) {
+ case E_CAL_SOURCE_TYPE_EVENT:
+ g_message ("Failed to search the object in destination event list: %s", error->message);
+ break;
+ case E_CAL_SOURCE_TYPE_TODO:
+ g_message ("Failed to search the object in destination task list: %s", error->message);
+ break;
+ case E_CAL_SOURCE_TYPE_JOURNAL:
+ g_message ("Failed to search the object in destination memo list: %s", error->message);
+ break;
+ default:
+ break;
+ }
+ } else {
+ /* this will report success by last item, but we don't care */
+ success = update_objects (destination, comp);
+
+ if (success && action == GDK_ACTION_MOVE) {
+ /* remove components rather here, because we know which has been moved */
+ ESource *source_source;
+ ECal *source_client;
+
+ source_source = e_source_list_peek_source_by_uid (source_list, source_uid);
+
+ if (source_source && !E_IS_SOURCE_GROUP (source_source) && !e_source_get_readonly (source_source)) {
+ source_client = auth_new_cal_from_source (source_source, e_cal_get_source_type (destination));
+
+ if (source_client) {
+ gboolean read_only = TRUE;
+
+ e_cal_is_read_only (source_client, &read_only, NULL);
+
+ if (!read_only && e_cal_open (source_client, TRUE, NULL))
+ e_cal_remove_object (source_client, old_uid, NULL);
+ else if (!read_only) {
+ switch (e_cal_get_source_type (destination)) {
+ case E_CAL_SOURCE_TYPE_EVENT:
+ g_message ("Cannot open source client to remove old event");
+ break;
+ case E_CAL_SOURCE_TYPE_TODO:
+ g_message ("Cannot open source client to remove old task");
+ break;
+ case E_CAL_SOURCE_TYPE_JOURNAL:
+ g_message ("Cannot open source client to remove old memo");
+ break;
+ default:
+ break;
+ }
+ }
+
+ g_object_unref (source_client);
+ } else {
+ switch (e_cal_get_source_type (destination)) {
+ case E_CAL_SOURCE_TYPE_EVENT:
+ g_message ("Cannot create source client to remove old event");
+ break;
+ case E_CAL_SOURCE_TYPE_TODO:
+ g_message ("Cannot create source client to remove old task");
+ break;
+ case E_CAL_SOURCE_TYPE_JOURNAL:
+ g_message ("Cannot create source client to remove old memo");
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ g_clear_error (&error);
+ } else
+ icalcomponent_free (tmp_icalcomp);
+
+ g_free (old_uid);
+
+ return success;
+}