diff options
Diffstat (limited to 'calendar/gui/comp-util.c')
-rw-r--r-- | calendar/gui/comp-util.c | 189 |
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; +} |