aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Crha <mcrha@redhat.com>2007-11-05 18:07:23 +0800
committerMilan Crha <mcrha@src.gnome.org>2007-11-05 18:07:23 +0800
commita1a1f31ef8aa921e84f82d0e88b00ead5e92c738 (patch)
tree1ef2ab796f73424e443a8dd156963bfbd05284e6
parentabf34a4520db2714e688fcdc01f3e5cbb890bc73 (diff)
downloadgsoc2013-evolution-a1a1f31ef8aa921e84f82d0e88b00ead5e92c738.tar.gz
gsoc2013-evolution-a1a1f31ef8aa921e84f82d0e88b00ead5e92c738.tar.zst
gsoc2013-evolution-a1a1f31ef8aa921e84f82d0e88b00ead5e92c738.zip
** Fix for bug #315101
2007-11-05 Milan Crha <mcrha@redhat.com> ** Fix for bug #315101 * drag and drop to other source for multiselect * gui/comp-util.h: * gui/comp-util.c: (cal_comp_selection_set_string_list), (cal_comp_selection_get_string_list): Two new helper functions to set and get list of strings into GtkSelectionData. * gui/e-tasks.c: (get_selected_components_cb), (do_for_selected_components), (obtain_list_of_components), (table_drag_data_get): * gui/e-memos.c: (get_selected_components_cb), (do_for_selected_components), (obtain_list_of_components), (table_drag_data_get): Pass list of selected components as data for drag and drop instead of focused component from the list. * gui/e-tasks.c: (table_drag_data_delete): * gui/e-memos.c: (table_drag_data_delete): Obsolete now. * gui/tasks-component.c: (selector_tree_drag_data_received): * gui/memos-component.c: (selector_tree_drag_data_received): Receiving list of components, so made changes here to reflect it. svn path=/trunk/; revision=34496
-rw-r--r--calendar/ChangeLog22
-rw-r--r--calendar/gui/comp-util.c69
-rw-r--r--calendar/gui/comp-util.h5
-rw-r--r--calendar/gui/e-memos.c140
-rw-r--r--calendar/gui/e-tasks.c139
-rw-r--r--calendar/gui/memos-component.c94
-rw-r--r--calendar/gui/tasks-component.c94
7 files changed, 442 insertions, 121 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 473cf11508..75cd7a898a 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,5 +1,27 @@
2007-11-05 Milan Crha <mcrha@redhat.com>
+ ** Fix for bug #315101
+
+ * drag and drop to other source for multiselect
+ * gui/comp-util.h:
+ * gui/comp-util.c: (cal_comp_selection_set_string_list),
+ (cal_comp_selection_get_string_list): Two new helper functions
+ to set and get list of strings into GtkSelectionData.
+ * gui/e-tasks.c: (get_selected_components_cb),
+ (do_for_selected_components), (obtain_list_of_components),
+ (table_drag_data_get):
+ * gui/e-memos.c: (get_selected_components_cb),
+ (do_for_selected_components), (obtain_list_of_components),
+ (table_drag_data_get): Pass list of selected components as data
+ for drag and drop instead of focused component from the list.
+ * gui/e-tasks.c: (table_drag_data_delete):
+ * gui/e-memos.c: (table_drag_data_delete): Obsolete now.
+ * gui/tasks-component.c: (selector_tree_drag_data_received):
+ * gui/memos-component.c: (selector_tree_drag_data_received):
+ Receiving list of components, so made changes here to reflect it.
+
+2007-11-05 Milan Crha <mcrha@redhat.com>
+
** Fix for bug #318604
* Enable source when adding event to disabled source.
diff --git a/calendar/gui/comp-util.c b/calendar/gui/comp-util.c
index 6919302b73..0be96dbefa 100644
--- a/calendar/gui/comp-util.c
+++ b/calendar/gui/comp-util.c
@@ -432,3 +432,72 @@ cal_comp_util_get_n_icons (ECalComponent *comp)
return num_icons;
}
+
+/**
+ * cal_comp_selection_set_string_list
+ * Stores list of strings into selection target data.
+ * Use @ref cal_comp_selection_get_string_list to get this list from target data.
+ *
+ * @param data Selection data, where to put list of strings.
+ * @param str_list List of strings. (Each element is of type const gchar *.)
+ **/
+void
+cal_comp_selection_set_string_list (GtkSelectionData *data, GSList *str_list)
+{
+ /* format is "str1\0str2\0...strN\0" */
+ GSList *p;
+ GByteArray *array;
+
+ g_return_if_fail (data != NULL);
+
+ if (!str_list)
+ return;
+
+ array = g_byte_array_new ();
+ for (p = str_list; p; p = p->next) {
+ const guint8 *c = p->data;
+
+ if (c)
+ g_byte_array_append (array, c, strlen ((const char *) c) + 1);
+ }
+
+ gtk_selection_data_set (data, data->target, 8, array->data, array->len);
+ g_byte_array_free (array, TRUE);
+}
+
+/**
+ * cal_comp_selection_get_string_list
+ * Converts data from selection to list of strings. Data should be assigned
+ * to selection data with @ref cal_comp_selection_set_string_list.
+ * Each string in newly created list should be freed by g_free.
+ * List itself should be freed by g_slist_free.
+ *
+ * @param data Selection data, where to put list of strings.
+ * @return Newly allocated GSList of strings.
+ **/
+GSList *
+cal_comp_selection_get_string_list (GtkSelectionData *data)
+{
+ /* format is "str1\0str2\0...strN\0" */
+ char *inptr, *inend;
+ GSList *list;
+
+ g_return_val_if_fail (data != NULL, NULL);
+
+ list = NULL;
+ inptr = (char *)data->data;
+ inend = (char *)(data->data + data->length);
+
+ while (inptr < inend) {
+ char *start = inptr;
+
+ while (inptr < inend && *inptr)
+ inptr++;
+
+ list = g_slist_prepend (list, g_strndup (start, inptr - start));
+
+ inptr++;
+ }
+
+ return list;
+}
diff --git a/calendar/gui/comp-util.h b/calendar/gui/comp-util.h
index 651fde686a..dfc5165b66 100644
--- a/calendar/gui/comp-util.h
+++ b/calendar/gui/comp-util.h
@@ -22,7 +22,9 @@
#ifndef COMP_UTIL_H
#define COMP_UTIL_H
+#include <glib.h>
#include <gtk/gtkwidget.h>
+#include <gtk/gtkselection.h>
#include <libecal/e-cal-component.h>
#include <libecal/e-cal.h>
@@ -47,4 +49,7 @@ ECalComponent *cal_comp_event_new_with_current_time (ECal *client, gboolean all_
ECalComponent *cal_comp_task_new_with_defaults (ECal *client);
ECalComponent *cal_comp_memo_new_with_defaults (ECal *client);
+void cal_comp_selection_set_string_list (GtkSelectionData *data, GSList *str_list);
+GSList *cal_comp_selection_get_string_list (GtkSelectionData *data);
+
#endif
diff --git a/calendar/gui/e-memos.c b/calendar/gui/e-memos.c
index d20d909808..a028f5e47b 100644
--- a/calendar/gui/e-memos.c
+++ b/calendar/gui/e-memos.c
@@ -341,6 +341,94 @@ setup_config (EMemos *memos)
priv->notifications = g_list_prepend (priv->notifications, GUINT_TO_POINTER (not));
}
+struct AffectedComponents {
+ EMemoTable *memo_table;
+ GSList *components; /* contains pointers to ECalModelComponent */
+};
+
+/**
+ * get_selected_components_cb
+ * Helper function to fill list of selected components in EMemoTable.
+ * This function is called from e_table_selected_row_foreach.
+ **/
+static void
+get_selected_components_cb (int model_row, gpointer data)
+{
+ struct AffectedComponents *ac = (struct AffectedComponents *) data;
+
+ if (!ac || !ac->memo_table)
+ return;
+
+ ac->components = g_slist_prepend (ac->components, e_cal_model_get_component_at (E_CAL_MODEL (e_memo_table_get_model (ac->memo_table)), model_row));
+}
+
+/**
+ * do_for_selected_components
+ * Calls function func for all selected components in memo_table.
+ *
+ * @param memo_table Table with selected components of our interest.
+ * @param func Function to be called on each selected component from cal_table.
+ * The first parameter of this function is a pointer to ECalModelComponent and
+ * the second parameter of this function is pointer to cal_table
+ * @param user_data User data, will be passed to func.
+ **/
+static void
+do_for_selected_components (EMemoTable *memo_table, GFunc func, gpointer user_data)
+{
+ ETable *etable;
+ struct AffectedComponents ac;
+
+ g_return_if_fail (memo_table != NULL);
+
+ ac.memo_table = memo_table;
+ ac.components = NULL;
+
+ etable = e_table_scrolled_get_table (E_TABLE_SCROLLED (memo_table->etable));
+ e_table_selected_row_foreach (etable, get_selected_components_cb, &ac);
+
+ g_slist_foreach (ac.components, func, user_data);
+ g_slist_free (ac.components);
+}
+
+/**
+ * obtain_list_of_components
+ * As a callback function to convert each ECalModelComponent to string
+ * of format "source_uid\ncomponent_str" and add this newly allocated
+ * string to the list of components. Strings should be freed with g_free.
+ *
+ * @param data ECalModelComponent object.
+ * @param user_data Pointer to GSList list, where to put new strings.
+ **/
+static void
+obtain_list_of_components (gpointer data, gpointer user_data)
+{
+ GSList **list;
+ ECalModelComponent *comp_data;
+
+ list = (GSList **) user_data;
+ comp_data = (ECalModelComponent *) data;
+
+ if (list && comp_data) {
+ char *comp_str;
+ icalcomponent *vcal;
+
+ vcal = e_cal_util_new_top_level ();
+ e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp);
+ icalcomponent_add_component (vcal, icalcomponent_new_clone (comp_data->icalcomp));
+
+ comp_str = icalcomponent_as_ical_string (vcal);
+ if (comp_str) {
+ ESource *source = e_cal_get_source (comp_data->client);
+ const char *source_uid = e_source_peek_uid (source);
+
+ *list = g_slist_prepend (*list, g_strdup_printf ("%s\n%s", source_uid, comp_str));
+ g_free (comp_str);
+ }
+
+ icalcomponent_free (vcal);
+ }
+}
+
static void
table_drag_data_get (ETable *table,
int row,
@@ -352,35 +440,20 @@ table_drag_data_get (ETable *table,
EMemos *memos)
{
EMemosPrivate *priv;
- ECalModelComponent *comp_data;
priv = memos->priv;
- if (priv->current_uid) {
- ECalModel *model;
+ if (info == TARGET_VCALENDAR) {
+ /* we will pass an icalcalendar component for both types */
+ GSList *components = NULL;
- model = e_memo_table_get_model (
- E_MEMO_TABLE (priv->memos_view));
+ do_for_selected_components (E_MEMO_TABLE (priv->memos_view), obtain_list_of_components, &components);
- comp_data = e_cal_model_get_component_at (model, row);
+ if (components) {
+ cal_comp_selection_set_string_list (selection_data, components);
- if (info == TARGET_VCALENDAR) {
- /* we will pass an icalcalendar component for both types */
- char *comp_str;
- icalcomponent *vcal;
-
- vcal = e_cal_util_new_top_level ();
- e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp);
- icalcomponent_add_component (
- vcal,
- icalcomponent_new_clone (comp_data->icalcomp));
-
- comp_str = icalcomponent_as_ical_string (vcal);
- if (comp_str) {
- gtk_selection_data_set (selection_data, selection_data->target,
- 8, (unsigned char *)comp_str, strlen (comp_str));
- }
- icalcomponent_free (vcal);
+ g_slist_foreach (components, (GFunc)g_free, NULL);
+ g_slist_free (components);
}
}
}
@@ -392,22 +465,11 @@ table_drag_data_delete (ETable *table,
GdkDragContext *context,
EMemos *memos)
{
- EMemosPrivate *priv;
- ECalModelComponent *comp_data;
- ECalModel *model;
- gboolean read_only = TRUE;
-
- priv = memos->priv;
-
- model = e_memo_table_get_model (
- E_MEMO_TABLE (priv->memos_view));
- comp_data = e_cal_model_get_component_at (model, row);
-
- e_cal_is_read_only (comp_data->client, &read_only, NULL);
- if (read_only)
- return;
-
- e_cal_remove_object (comp_data->client, icalcomponent_get_uid (comp_data->icalcomp), NULL);
+ /* Moved components are deleted from source immediately when moved,
+ because some of them can be part of destination source, and we
+ don't want to delete not-moved tasks. There is no such information
+ which event has been moved and which not, so skip this method.
+ */
}
#define E_MEMOS_TABLE_DEFAULT_STATE \
diff --git a/calendar/gui/e-tasks.c b/calendar/gui/e-tasks.c
index 13c1be8a4c..44e417b5bb 100644
--- a/calendar/gui/e-tasks.c
+++ b/calendar/gui/e-tasks.c
@@ -429,6 +429,94 @@ setup_config (ETasks *tasks)
priv->notifications = g_list_prepend (priv->notifications, GUINT_TO_POINTER (not));
}
+struct AffectedComponents {
+ ECalendarTable *cal_table;
+ GSList *components; /* contains pointers to ECalModelComponent */
+};
+
+/**
+ * get_selected_components_cb
+ * Helper function to fill list of selected components in ECalendarTable.
+ * This function is called from e_table_selected_row_foreach.
+ **/
+static void
+get_selected_components_cb (int model_row, gpointer data)
+{
+ struct AffectedComponents *ac = (struct AffectedComponents *) data;
+
+ if (!ac || !ac->cal_table)
+ return;
+
+ ac->components = g_slist_prepend (ac->components, e_cal_model_get_component_at (E_CAL_MODEL (ac->cal_table->model), model_row));
+}
+
+/**
+ * do_for_selected_components
+ * Calls function func for all selected components in cal_table.
+ *
+ * @param cal_table Table with selected components of our interest.
+ * @param func Function to be called on each selected component from cal_table.
+ * The first parameter of this function is a pointer to ECalModelComponent and
+ * the second parameter of this function is pointer to cal_table
+ * @param user_data User data, will be passed to func.
+ **/
+static void
+do_for_selected_components (ECalendarTable *cal_table, GFunc func, gpointer user_data)
+{
+ ETable *etable;
+ struct AffectedComponents ac;
+
+ g_return_if_fail (cal_table != NULL);
+
+ ac.cal_table = cal_table;
+ ac.components = NULL;
+
+ etable = e_table_scrolled_get_table (E_TABLE_SCROLLED (cal_table->etable));
+ e_table_selected_row_foreach (etable, get_selected_components_cb, &ac);
+
+ g_slist_foreach (ac.components, func, user_data);
+ g_slist_free (ac.components);
+}
+
+/**
+ * obtain_list_of_components
+ * As a callback function to convert each ECalModelComponent to string
+ * of format "source_uid\ncomponent_str" and add this newly allocated
+ * string to the list of components. Strings should be freed with g_free.
+ *
+ * @param data ECalModelComponent object.
+ * @param user_data Pointer to GSList list, where to put new strings.
+ **/
+static void
+obtain_list_of_components (gpointer data, gpointer user_data)
+{
+ GSList **list;
+ ECalModelComponent *comp_data;
+
+ list = (GSList **) user_data;
+ comp_data = (ECalModelComponent *) data;
+
+ if (list && comp_data) {
+ char *comp_str;
+ icalcomponent *vcal;
+
+ vcal = e_cal_util_new_top_level ();
+ e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp);
+ icalcomponent_add_component (vcal, icalcomponent_new_clone (comp_data->icalcomp));
+
+ comp_str = icalcomponent_as_ical_string (vcal);
+ if (comp_str) {
+ ESource *source = e_cal_get_source (comp_data->client);
+ const char *source_uid = e_source_peek_uid (source);
+
+ *list = g_slist_prepend (*list, g_strdup_printf ("%s\n%s", source_uid, comp_str));
+ g_free (comp_str);
+ }
+
+ icalcomponent_free (vcal);
+ }
+}
+
static void
table_drag_data_get (ETable *table,
int row,
@@ -440,33 +528,20 @@ table_drag_data_get (ETable *table,
ETasks *tasks)
{
ETasksPrivate *priv;
- ECalModelComponent *comp_data;
priv = tasks->priv;
- if (priv->current_uid) {
- ECalModel *model;
+ if (info == TARGET_VCALENDAR) {
+ /* we will pass an icalcalendar component for both types */
+ GSList *components = NULL;
- model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view));
- comp_data = e_cal_model_get_component_at (model, row);
+ do_for_selected_components (E_CALENDAR_TABLE (priv->tasks_view), obtain_list_of_components, &components);
- if (info == TARGET_VCALENDAR) {
- /* we will pass an icalcalendar component for both types */
- char *comp_str;
- icalcomponent *vcal;
-
- vcal = e_cal_util_new_top_level ();
- e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp);
- icalcomponent_add_component (
- vcal,
- icalcomponent_new_clone (comp_data->icalcomp));
-
- comp_str = icalcomponent_as_ical_string (vcal);
- if (comp_str) {
- gtk_selection_data_set (selection_data, selection_data->target,
- 8, (unsigned char *)comp_str, strlen (comp_str));
- }
- icalcomponent_free (vcal);
+ if (components) {
+ cal_comp_selection_set_string_list (selection_data, components);
+
+ g_slist_foreach (components, (GFunc)g_free, NULL);
+ g_slist_free (components);
}
}
}
@@ -501,21 +576,11 @@ table_drag_data_delete (ETable *table,
GdkDragContext *context,
ETasks *tasks)
{
- ETasksPrivate *priv;
- ECalModelComponent *comp_data;
- ECalModel *model;
- gboolean read_only = TRUE;
- priv = tasks->priv;
-
- model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view));
- comp_data = e_cal_model_get_component_at (model, row);
-
- e_cal_is_read_only (comp_data->client, &read_only, NULL);
- if (read_only)
- return;
-
- if(gdk_drag_drop_succeeded(context))
- e_cal_remove_object (comp_data->client, icalcomponent_get_uid (comp_data->icalcomp), NULL);
+ /* Moved components are deleted from source immediately when moved,
+ because some of them can be part of destination source, and we
+ don't want to delete not-moved tasks. There is no such information
+ which event has been moved and which not, so skip this method.
+ */
}
#define E_TASKS_TABLE_DEFAULT_STATE \
diff --git a/calendar/gui/memos-component.c b/calendar/gui/memos-component.c
index 5024a5f2e7..40b71cf5f5 100644
--- a/calendar/gui/memos-component.c
+++ b/calendar/gui/memos-component.c
@@ -758,6 +758,8 @@ selector_tree_drag_data_received (GtkWidget *widget,
gboolean success = FALSE;
icalcomponent *icalcomp = NULL;
ECal *client = NULL;
+ GSList *components, *p;
+ MemosComponent *component = MEMOS_COMPONENT (user_data);
if (!gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget),
x, y, &path, &pos))
@@ -771,47 +773,97 @@ selector_tree_drag_data_received (GtkWidget *widget,
gtk_tree_model_get (model, &iter, 0, &source, -1);
- if (E_IS_SOURCE_GROUP (source) || e_source_get_readonly (source))
+ if (E_IS_SOURCE_GROUP (source) || e_source_get_readonly (source) || !data->data)
goto finish;
- icalcomp = icalparser_parse_string ((char *)data->data);
-
- if (icalcomp) {
- char * uid;
+ client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_JOURNAL);
+
+ if (!client || !e_cal_open (client, TRUE, NULL))
+ goto finish;
+
+ components = cal_comp_selection_get_string_list (data);
+ for (p = components; p; p = p->next) {
+ const char * uid;
+ char *old_uid = NULL;
+ icalcomponent *tmp_icalcomp = NULL;
+ GError *error = NULL;
+ char *comp_str; /* do not free this! */
+
+ /* p->data is "source_uid\ncomponent_string" */
+ comp_str = strchr (p->data, '\n');
+ if (!comp_str)
+ continue;
+
+ comp_str [0] = 0;
+ comp_str++;
+ icalcomp = icalparser_parse_string (comp_str);
+
+ if (!icalcomp)
+ continue;
/* FIXME deal with GDK_ACTION_ASK */
if (context->action == GDK_ACTION_COPY) {
+ old_uid = g_strdup (icalcomponent_get_uid (icalcomp));
uid = e_cal_component_gen_uid ();
icalcomponent_set_uid (icalcomp, uid);
}
- client = auth_new_cal_from_source (source,
- E_CAL_SOURCE_TYPE_JOURNAL);
-
- if (client) {
- if (e_cal_open (client, TRUE, NULL)) {
+ uid = icalcomponent_get_uid (icalcomp);
+ if (!old_uid)
+ old_uid = g_strdup (uid);
+
+ if (!e_cal_get_object (client, uid, NULL, &tmp_icalcomp, &error)) {
+ 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);
+ else {
+ /* this will report success by last item, but we don't care */
success = update_objects (client, icalcomp);
+
+ if (success && context->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 (component->priv->source_list, p->data);
+
+ 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_SOURCE_TYPE_JOURNAL);
+
+ 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)
+ g_message ("Cannot open source client to remove old memo");
+
+ g_object_unref (source_client);
+ } else
+ g_message ("Cannot create source client to remove old memo");
+ }
+ }
}
-
- g_object_unref (client);
- }
-
+
+ g_clear_error (&error);
+ } else
+ icalcomponent_free (tmp_icalcomp);
+
+ g_free (old_uid);
icalcomponent_free (icalcomp);
}
+ g_slist_foreach (components, (GFunc)g_free, NULL);
+ g_slist_free (components);
finish:
+ if (client)
+ g_object_unref (client);
if (source)
g_object_unref (source);
if (path)
gtk_tree_path_free (path);
- if (!success && context->action == GDK_ACTION_MOVE) {
- /* because the delete parameter of 'gtk_drag_finish' doesn't work
- as expected, then we change context->action to GDK_ACTION_COPY
- to prevent from deleting data when the drag was unsuccessful.
- */
- context->action = GDK_ACTION_COPY;
- }
gtk_drag_finish (context, success, success && context->action == GDK_ACTION_MOVE, time);
}
diff --git a/calendar/gui/tasks-component.c b/calendar/gui/tasks-component.c
index cc87d9d287..2f8c563aa7 100644
--- a/calendar/gui/tasks-component.c
+++ b/calendar/gui/tasks-component.c
@@ -742,6 +742,8 @@ selector_tree_drag_data_received (GtkWidget *widget,
gboolean success = FALSE;
icalcomponent *icalcomp = NULL;
ECal *client = NULL;
+ GSList *components, *p;
+ TasksComponent *component = TASKS_COMPONENT (user_data);
if (!gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget),
x, y, &path, &pos))
@@ -755,48 +757,92 @@ selector_tree_drag_data_received (GtkWidget *widget,
gtk_tree_model_get (model, &iter, 0, &source, -1);
- if (E_IS_SOURCE_GROUP (source) || e_source_get_readonly (source))
+ if (E_IS_SOURCE_GROUP (source) || e_source_get_readonly (source) || !data->data)
goto finish;
- icalcomp = icalparser_parse_string ((char *)data->data);
+ client = auth_new_cal_from_source (source, E_CAL_SOURCE_TYPE_TODO);
- if (icalcomp) {
+ if (!client || !e_cal_open (client, TRUE, NULL))
+ goto finish;
+
+ components = cal_comp_selection_get_string_list (data);
+ for (p = components; p; p = p->next) {
const char * uid;
-
+ char *old_uid = NULL;
+ icalcomponent *tmp_icalcomp = NULL;
+ GError *error = NULL;
+ char *comp_str; /* do not free this! */
+
+ /* p->data is "source_uid\ncomponent_string" */
+ comp_str = strchr (p->data, '\n');
+ if (!comp_str)
+ continue;
+
+ comp_str [0] = 0;
+ comp_str++;
+ icalcomp = icalparser_parse_string (comp_str);
+
+ if (!icalcomp)
+ continue;
+
/* FIXME deal with GDK_ACTION_ASK */
if (context->action == GDK_ACTION_COPY) {
+ old_uid = g_strdup (icalcomponent_get_uid (icalcomp));
uid = e_cal_component_gen_uid ();
icalcomponent_set_uid (icalcomp, uid);
}
- client = auth_new_cal_from_source (source,
- E_CAL_SOURCE_TYPE_TODO);
-
- if (client) {
- if (e_cal_open (client, TRUE, NULL)) {
- icalcomponent *tmp_icalcomp = NULL;
- GError *error = NULL;
- uid = icalcomponent_get_uid (icalcomp);
- if (!e_cal_get_object (client, uid, NULL, &tmp_icalcomp, &error)) {
- 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);
- else {
- success = TRUE;
- update_objects (client, icalcomp);
- }
+ uid = icalcomponent_get_uid (icalcomp);
+ if (!old_uid)
+ old_uid = g_strdup (uid);
+
+ if (!e_cal_get_object (client, uid, NULL, &tmp_icalcomp, &error)) {
+ 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);
+ else {
+ /* this will report success by last item, but we don't care */
+ success = update_objects (client, icalcomp);
- g_clear_error (&error);
- } else
- icalcomponent_free (tmp_icalcomp);
+ if (success && context->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 (component->priv->source_list, p->data);
+
+ 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_SOURCE_TYPE_TODO);
+
+ 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)
+ g_message ("Cannot open source client to remove old task");
+
+ g_object_unref (source_client);
+ } else
+ g_message ("Cannot create source client to remove old task");
+ }
+ }
}
- g_object_unref (client);
- }
+ g_clear_error (&error);
+ } else
+ icalcomponent_free (tmp_icalcomp);
+ g_free (old_uid);
icalcomponent_free (icalcomp);
}
+ g_slist_foreach (components, (GFunc)g_free, NULL);
+ g_slist_free (components);
finish:
+ if (client)
+ g_object_unref (client);
if (source)
g_object_unref (source);
if (path)