diff options
Diffstat (limited to 'calendar/gui/e-task-list-selector.c')
-rw-r--r-- | calendar/gui/e-task-list-selector.c | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/calendar/gui/e-task-list-selector.c b/calendar/gui/e-task-list-selector.c new file mode 100644 index 0000000000..fa6bd328d9 --- /dev/null +++ b/calendar/gui/e-task-list-selector.c @@ -0,0 +1,288 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-task-list-selector.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "e-task-list-selector.h" + +#include <string.h> +#include <libecal/e-cal.h> +#include "calendar/common/authentication.h" +#include "calendar/gui/comp-util.h" + +#define E_TASK_LIST_SELECTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_TASK_LIST_SELECTOR, ETaskListSelectorPrivate)) + +struct _ETaskListSelectorPrivate { + gint dummy_value; +}; + +enum { + DND_TARGET_TYPE_CALENDAR_LIST +}; + +static GtkTargetEntry drag_types[] = { + { (gchar *) "text/calendar", 0, DND_TARGET_TYPE_CALENDAR_LIST }, + { (gchar *) "text/x-calendar", 0, DND_TARGET_TYPE_CALENDAR_LIST } +}; + +static gpointer parent_class; + +static gboolean +task_list_selector_update_single_object (ECal *client, + icalcomponent *icalcomp) +{ + gchar *uid; + icalcomponent *tmp_icalcomp; + + uid = (gchar *) icalcomponent_get_uid (icalcomp); + + if (e_cal_get_object (client, uid, NULL, &tmp_icalcomp, NULL)) + return e_cal_modify_object ( + client, icalcomp, CALOBJ_MOD_ALL, NULL); + + return e_cal_create_object (client, icalcomp, &uid, NULL); +} + +static gboolean +task_list_selector_update_objects (ECal *client, + icalcomponent *icalcomp) +{ + icalcomponent *subcomp; + icalcomponent_kind kind; + + kind = icalcomponent_isa (icalcomp); + if (kind == ICAL_VTODO_COMPONENT || kind == ICAL_VEVENT_COMPONENT) + return task_list_selector_update_single_object ( + client, icalcomp); + else if (kind != ICAL_VCALENDAR_COMPONENT) + return FALSE; + + subcomp = icalcomponent_get_first_component ( + icalcomp, ICAL_ANY_COMPONENT); + while (subcomp != NULL) { + 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 FALSE; + } else if (kind == ICAL_VTODO_COMPONENT || + kind == ICAL_VEVENT_COMPONENT) { + success = task_list_selector_update_single_object ( + client, subcomp); + if (!success) + return FALSE; + } + + subcomp = icalcomponent_get_next_component ( + icalcomp, ICAL_ANY_COMPONENT); + } + + return TRUE; +} + +static gboolean +task_list_selector_process_data (ESourceSelector *selector, + ECal *client, + const gchar *source_uid, + icalcomponent *icalcomp, + GdkDragAction action) +{ + ESourceList *source_list; + ESource *source; + icalcomponent *tmp_icalcomp = NULL; + const gchar *uid; + gchar *old_uid = NULL; + gboolean success = FALSE; + gboolean read_only = TRUE; + GError *error = NULL; + + /* FIXME Deal with GDK_ACTION_ASK. */ + if (action == GDK_ACTION_COPY) { + old_uid = g_strdup (icalcomponent_get_uid (icalcomp)); + uid = e_cal_component_gen_uid (); + icalcomponent_set_uid (icalcomp, uid); + } + + uid = icalcomponent_get_uid (icalcomp); + if (old_uid == NULL) + old_uid = g_strdup (uid); + + if (e_cal_get_object (client, uid, NULL, &tmp_icalcomp, &error)) { + icalcomponent_free (tmp_icalcomp); + success = TRUE; + goto exit; + } + + if (error != NULL && error->code != E_CALENDAR_STATUS_OBJECT_NOT_FOUND) { + g_message ( + "Failed to search the object in destination " + "task list: %s", error->message); + g_error_free (error); + goto exit; + } + + success = task_list_selector_update_objects (client, icalcomp); + + if (!success || action != GDK_ACTION_MOVE) + goto exit; + + source_list = e_source_selector_get_source_list (selector); + source = e_source_list_peek_source_by_uid (source_list, source_uid); + + if (!E_IS_SOURCE (source) || e_source_get_readonly (source)) + goto exit; + + client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_TODO); + if (client == NULL) { + g_message ("Cannot create source client to remove old task"); + goto exit; + } + + e_cal_is_read_only (client, &read_only, NULL); + if (!read_only && e_cal_open (client, TRUE, NULL)) + e_cal_remove_object (client, old_uid, NULL); + else if (!read_only) + g_message ("Cannot open source client to remove old task"); + + g_object_unref (client); + +exit: + g_free (old_uid); + + return success; +} + +static gboolean +task_list_selector_data_dropped (ESourceSelector *selector, + GtkSelectionData *selection_data, + ESource *destination, + GdkDragAction action, + guint info) +{ + ECal *client; + GSList *list, *iter; + gboolean success = FALSE; + + client = auth_new_cal_from_source ( + destination, E_CAL_SOURCE_TYPE_TODO); + + if (client == NULL || !e_cal_open (client, TRUE, NULL)) + goto exit; + + list = cal_comp_selection_get_string_list (selection_data); + + for (iter = list; iter != NULL; iter = iter->next) { + gchar *source_uid = iter->data; + icalcomponent *icalcomp; + gchar *component_string; + + /* Each string is "source_uid\ncomponent_string". */ + component_string = strchr (source_uid, '\n'); + if (component_string == NULL) + continue; + + *component_string++ = '\0'; + icalcomp = icalparser_parse_string (component_string); + if (icalcomp == NULL) + continue; + + success = task_list_selector_process_data ( + selector, client, source_uid, icalcomp, action); + + icalcomponent_free (icalcomp); + } + + g_slist_foreach (list, (GFunc) g_free, NULL); + g_slist_free (list); + +exit: + if (client != NULL) + g_object_unref (client); + + return success; +} + +static void +task_list_selector_class_init (ETaskListSelectorClass *class) +{ + ESourceSelectorClass *source_selector_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ETaskListSelectorPrivate)); + + source_selector_class = E_SOURCE_SELECTOR_CLASS (class); + source_selector_class->data_dropped = task_list_selector_data_dropped; +} + +static void +task_list_selector_init (ETaskListSelector *selector) +{ + selector->priv = E_TASK_LIST_SELECTOR_GET_PRIVATE (selector); + + gtk_drag_dest_set ( + GTK_WIDGET (selector), GTK_DEST_DEFAULT_ALL, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_COPY | GDK_ACTION_MOVE); +} + +GType +e_task_list_selector_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (ETaskListSelectorClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) task_list_selector_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ETaskListSelector), + 0, /* n_preallocs */ + (GInstanceInitFunc) task_list_selector_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_SOURCE_SELECTOR, "ETaskListSelector", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_task_list_selector_new (ESourceList *source_list) +{ + g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), NULL); + + return g_object_new ( + E_TYPE_TASK_LIST_SELECTOR, + "source-list", source_list, NULL); +} |