evolution r36822 - in branches/kill-bonobo: addressbook/gui/component addressbook/gui/widgets calendar/gui calendar/modules



Author: mbarnes
Date: Sat Nov 29 15:26:50 2008
New Revision: 36822
URL: http://svn.gnome.org/viewvc/evolution?rev=36822&view=rev

Log:
Get drag-and-drop-to-source-selector working for contacts, memos and tasks.
Utilizes the new ESourceSelector::data-dropped signal.


Added:
   branches/kill-bonobo/calendar/gui/e-memo-list-selector.c
   branches/kill-bonobo/calendar/gui/e-memo-list-selector.h
   branches/kill-bonobo/calendar/gui/e-task-list-selector.c
   branches/kill-bonobo/calendar/gui/e-task-list-selector.h
Modified:
   branches/kill-bonobo/addressbook/gui/component/e-book-shell-sidebar.c
   branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.c
   branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.h
   branches/kill-bonobo/addressbook/gui/component/eab-composer-util.c
   branches/kill-bonobo/addressbook/gui/widgets/e-addressbook-selector.c
   branches/kill-bonobo/addressbook/gui/widgets/e-addressbook-selector.h
   branches/kill-bonobo/calendar/gui/Makefile.am
   branches/kill-bonobo/calendar/gui/e-calendar-selector.c
   branches/kill-bonobo/calendar/gui/e-memos.c
   branches/kill-bonobo/calendar/modules/e-cal-shell-content.c
   branches/kill-bonobo/calendar/modules/e-memo-shell-content.c
   branches/kill-bonobo/calendar/modules/e-memo-shell-sidebar.c
   branches/kill-bonobo/calendar/modules/e-task-shell-content.c
   branches/kill-bonobo/calendar/modules/e-task-shell-sidebar.c

Modified: branches/kill-bonobo/addressbook/gui/component/e-book-shell-sidebar.c
==============================================================================
--- branches/kill-bonobo/addressbook/gui/component/e-book-shell-sidebar.c	(original)
+++ branches/kill-bonobo/addressbook/gui/component/e-book-shell-sidebar.c	Sat Nov 29 15:26:50 2008
@@ -21,6 +21,7 @@
 
 #include "e-book-shell-sidebar.h"
 
+#include <string.h>
 #include <glib/gi18n.h>
 
 #include <e-book-shell-view.h>

Modified: branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.c
==============================================================================
--- branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.c	(original)
+++ branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.c	Sat Nov 29 15:26:50 2008
@@ -276,6 +276,12 @@
 	e_book_shell_content_set_current_view (
 		book_shell_content, E_ADDRESSBOOK_VIEW (widget));
 
+	/* XXX We have to keep the addressbook selector informed of the
+	 *     current view so it can move contacts via drag-and-drop. */
+	e_addressbook_selector_set_current_view (
+		E_ADDRESSBOOK_SELECTOR (selector),
+		E_ADDRESSBOOK_VIEW (widget));
+
 	view_instance = e_addressbook_view_get_view_instance (view);
 	view_id = gal_view_instance_get_current_view_id (view_instance);
 	e_shell_view_set_view_id (shell_view, view_id);

Modified: branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.h
==============================================================================
--- branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.h	(original)
+++ branches/kill-bonobo/addressbook/gui/component/e-book-shell-view-private.h	Sat Nov 29 15:26:50 2008
@@ -40,6 +40,7 @@
 #include "addressbook/gui/contact-list-editor/e-contact-list-editor.h"
 #include "addressbook/gui/widgets/eab-gui-util.h"
 #include "addressbook/gui/widgets/e-addressbook-view.h"
+#include "addressbook/gui/widgets/e-addressbook-selector.h"
 
 #include <e-book-shell-content.h>
 #include <e-book-shell-sidebar.h>

Modified: branches/kill-bonobo/addressbook/gui/component/eab-composer-util.c
==============================================================================
--- branches/kill-bonobo/addressbook/gui/component/eab-composer-util.c	(original)
+++ branches/kill-bonobo/addressbook/gui/component/eab-composer-util.c	Sat Nov 29 15:26:50 2008
@@ -18,6 +18,7 @@
 
 #include "eab-composer-util.h"
 
+#include <string.h>
 #include <glib/gi18n.h>
 #include <libebook/e-contact.h>
 #include <libebook/e-destination.h>

Modified: branches/kill-bonobo/addressbook/gui/widgets/e-addressbook-selector.c
==============================================================================
--- branches/kill-bonobo/addressbook/gui/widgets/e-addressbook-selector.c	(original)
+++ branches/kill-bonobo/addressbook/gui/widgets/e-addressbook-selector.c	Sat Nov 29 15:26:50 2008
@@ -33,7 +33,7 @@
 typedef struct _MergeContext MergeContext;
 
 struct _EAddressbookSelectorPrivate {
-	gint dummy_value;
+	EAddressbookView *current_view;
 };
 
 struct _MergeContext {
@@ -49,6 +49,11 @@
 };
 
 enum {
+	PROP_0,
+	PROP_CURRENT_VIEW
+};
+
+enum {
 	DND_TARGET_TYPE_VCARD,
 	DND_TARGET_TYPE_SOURCE_VCARD
 };
@@ -192,168 +197,124 @@
 }
 
 static void
-addressbook_selector_drag_leave (GtkWidget *widget,
-                                 GdkDragContext *context,
-                                 guint time_)
-{
-	/* XXX This is exactly the same as in ECalendarSelector.
-	 *     Consider merging this callback into ESourceSelector. */
+addressbook_selector_set_property (GObject *object,
+                                   guint property_id,
+                                   const GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CURRENT_VIEW:
+			e_addressbook_selector_set_current_view (
+				E_ADDRESSBOOK_SELECTOR (object),
+				g_value_get_object (value));
+			return;
+	}
 
-	GtkTreeView *tree_view;
-	GtkTreeViewDropPosition pos;
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
 
-	tree_view = GTK_TREE_VIEW (widget);
-	pos = GTK_TREE_VIEW_DROP_BEFORE;
+static void
+addressbook_selector_get_property (GObject *object,
+                                   guint property_id,
+                                   GValue *value,
+                                   GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CURRENT_VIEW:
+			g_value_set_object (
+				value,
+				e_addressbook_selector_get_current_view (
+				E_ADDRESSBOOK_SELECTOR (object)));
+			return;
+	}
 
-	gtk_tree_view_set_drag_dest_row (tree_view, NULL, pos);
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 }
 
-static gboolean
-addressbook_selector_drag_motion (GtkWidget *widget,
-                                  GdkDragContext *context,
-                                  gint x,
-                                  gint y,
-                                  guint time_)
+static void
+addressbook_selector_dispose (GObject *object)
 {
-	/* XXX This is exactly the same as in ECalendarSelector.
-	 *     Consider merging this callback into ESourceSelector. */
-
-	GtkTreeView *tree_view;
-	GtkTreeModel *model;
-	GtkTreePath *path = NULL;
-	GtkTreeIter iter;
-	GtkTreeViewDropPosition pos;
-	GdkDragAction action = 0;
-	gpointer object;
-
-	tree_view = GTK_TREE_VIEW (widget);
-	model = gtk_tree_view_get_model (tree_view);
-
-	if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL))
-		goto exit;
-
-	if (!gtk_tree_model_get_iter (model, &iter, path))
-		goto exit;
+	EAddressbookSelectorPrivate *priv;
 
-	gtk_tree_model_get (model, &iter, 0, &object, -1);
+	priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (object);
 
-	if (!E_IS_SOURCE (object) || e_source_get_readonly (object))
-		goto exit;
-
-	gtk_tree_view_set_drag_dest_row (
-		tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_BEFORE);
-
-	pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
-	gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
-
-	if (context->actions & GDK_ACTION_MOVE)
-		action = GDK_ACTION_MOVE;
-	else
-		action = context->suggested_action;
-
-exit:
-	if (path != NULL)
-		gtk_tree_path_free (path);
+	if (priv->current_view != NULL) {
+		g_object_unref (priv->current_view);
+		priv->current_view = NULL;
+	}
 
-	if (object != NULL)
-		g_object_unref (object);
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
 
-	gdk_drag_status (context, action, time_);
+static void
+addressbook_selector_constructed (GObject *object)
+{
+	ESourceSelector *selector;
 
-	return TRUE;
+	selector = E_SOURCE_SELECTOR (object);
+	addressbook_selector_load_primary_source (selector);
 }
 
-static gboolean
-addressbook_selector_drag_drop (GtkWidget *widget,
-                                GdkDragContext *context,
-                                gint x,
-                                gint y,
-                                guint time_)
-{
-	/* XXX This is exactly the same as in ECalendarSelector.
-	 *     Consider merging this callback into ESourceSelector. */
-
-	GtkTreeView *tree_view;
-	GtkTreeModel *model;
-	GtkTreePath *path;
-	GtkTreeIter iter;
-	gboolean drop_zone;
-	gboolean valid;
-	gpointer object;
+static void
+addressbook_selector_primary_selection_changed (ESourceSelector *selector)
+{
+	ESource *source;
+	GConfClient *client;
+	const gchar *key;
+	const gchar *string;
 
-	tree_view = GTK_TREE_VIEW (widget);
-	model = gtk_tree_view_get_model (tree_view);
+	/* XXX If ESourceSelector had a "primary-uid" property,
+	 *     we could just bind the GConf key to it. */
 
-	if (!gtk_tree_view_get_path_at_pos (
-		tree_view, x, y, &path, NULL, NULL, NULL))
-		return FALSE;
+	source = e_source_selector_peek_primary_selection (selector);
+	if (source == NULL)
+		return;
 
-	valid = gtk_tree_model_get_iter (model, &iter, path);
-	gtk_tree_path_free (path);
-	g_return_val_if_fail (valid, FALSE);
-
-	gtk_tree_model_get (model, &iter, 0, &object, -1);
-	drop_zone = E_IS_SOURCE (object);
-	g_object_unref (object);
-
-	return drop_zone;
+	client = gconf_client_get_default ();
+	key = PRIMARY_ADDRESSBOOK_KEY;
+	string = e_source_peek_uid (source);
+	gconf_client_set_string (client, key, string, NULL);
+	g_object_unref (client);
 }
 
-static void
-addressbook_selector_drag_data_received (GtkWidget *widget,
-                                         GdkDragContext *context,
-                                         gint x,
-                                         gint y,
-                                         GtkSelectionData *selection_data,
-                                         guint info,
-                                         guint time_)
-{
-	/* XXX This is NEARLY the same as in ECalendarSelector.
-	 *     Consider merging this callback into ESourceSelector.
-	 *     Use a callback to allow subclasses to handle the
-	 *     received selection data. */
-
+static gboolean
+addressbook_selector_data_dropped (ESourceSelector *selector,
+                                   GtkSelectionData *selection_data,
+                                   ESource *destination,
+                                   GdkDragAction action,
+                                   guint info)
+{
+	EAddressbookSelectorPrivate *priv;
 	MergeContext *merge_context;
-	GtkTreeView *tree_view;
-	GtkTreeModel *model;
-	GtkTreePath *path = NULL;
-	GtkTreeIter iter;
+	EAddressbookModel *model;
 	EBook *source_book;
 	EBook *target_book;
 	GList *list;
 	const gchar *string;
 	gboolean remove_from_source;
-	gboolean success = FALSE;
-	gpointer object;
 
-	tree_view = GTK_TREE_VIEW (widget);
-	model = gtk_tree_view_get_model (tree_view);
+	priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (selector);
+	g_return_val_if_fail (priv->current_view != NULL, FALSE);
 
 	string = (const gchar *) selection_data->data;
-	remove_from_source = (context->action == GDK_ACTION_MOVE);
-
-	if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL))
-		goto exit;
-
-	if (!gtk_tree_model_get_iter (model, &iter, path))
-		goto exit;
-
-	gtk_tree_model_get (model, &iter, 0, &object, -1);
-
-	if (!E_IS_SOURCE (object) || e_source_get_readonly (object))
-		goto exit;
+	remove_from_source = (action == GDK_ACTION_MOVE);
 
-	target_book = e_book_new (object, NULL);
+	target_book = e_book_new (destination, NULL);
 	if (target_book == NULL)
-		goto exit;
+		return FALSE;
 
 	e_book_open (target_book, FALSE, NULL);
 
+	/* XXX Function assumes both out arguments are provided.  All we
+	 *     care about is the contact list; source_book will be NULL. */
 	eab_book_and_contact_list_from_string (string, &source_book, &list);
 	if (list == NULL)
-		goto exit;
+		return FALSE;
 
-	/* XXX Get the currently selected EBook. */
+	model = e_addressbook_view_get_model (priv->current_view);
+	source_book = e_addressbook_model_get_book (model);
+	g_return_val_if_fail (E_IS_BOOK (source_book), FALSE);
 
 	merge_context = merge_context_new (source_book, target_book, list);
 	merge_context->remove_from_source = remove_from_source;
@@ -363,71 +324,38 @@
 		(EBookIdCallback) addressbook_selector_merge_next_cb,
 		merge_context);
 
-	success = TRUE;
-
-exit:
-	if (path != NULL)
-		gtk_tree_path_free (path);
-
-	if (object != NULL)
-		g_object_unref (object);
-
-	gtk_drag_finish (context, success, remove_from_source, time_);
-}
-
-static void
-addressbook_selector_primary_selection_changed (ESourceSelector *selector)
-{
-	ESource *source;
-	GConfClient *client;
-	const gchar *key;
-	const gchar *string;
-
-	/* XXX If ESourceSelector had a "primary-uid" property,
-	 *     we could just bind the GConf key to it. */
-
-	source = e_source_selector_peek_primary_selection (selector);
-	if (source == NULL)
-		return;
-
-	client = gconf_client_get_default ();
-	key = PRIMARY_ADDRESSBOOK_KEY;
-	string = e_source_peek_uid (source);
-	gconf_client_set_string (client, key, string, NULL);
-	g_object_unref (client);
-}
-
-static void
-addressbook_selector_constructed (GObject *object)
-{
-	ESourceSelector *selector;
-
-	selector = E_SOURCE_SELECTOR (object);
-	addressbook_selector_load_primary_source (selector);
+	return TRUE;
 }
 
 static void
 addressbook_selector_class_init (EAddressbookSelectorClass *class)
 {
 	GObjectClass *object_class;
-	GtkWidgetClass *widget_class;
 	ESourceSelectorClass *selector_class;
 
 	parent_class = g_type_class_peek_parent (class);
 	g_type_class_add_private (class, sizeof (EAddressbookSelectorPrivate));
 
 	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = addressbook_selector_set_property;
+	object_class->get_property = addressbook_selector_get_property;
+	object_class->dispose = addressbook_selector_dispose;
 	object_class->constructed = addressbook_selector_constructed;
 
-	widget_class = GTK_WIDGET_CLASS (class);
-	widget_class->drag_leave = addressbook_selector_drag_leave;
-	widget_class->drag_motion = addressbook_selector_drag_motion;
-	widget_class->drag_drop = addressbook_selector_drag_drop;
-	widget_class->drag_data_received = addressbook_selector_drag_data_received;
-
 	selector_class = E_SOURCE_SELECTOR_CLASS (class);
 	selector_class->primary_selection_changed =
 		addressbook_selector_primary_selection_changed;
+	selector_class->data_dropped = addressbook_selector_data_dropped;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_CURRENT_VIEW,
+		g_param_spec_object (
+			"current-view",
+			NULL,
+			NULL,
+			E_TYPE_ADDRESSBOOK_VIEW,
+			G_PARAM_READWRITE));
 }
 
 static void
@@ -477,3 +405,39 @@
 		E_TYPE_ADDRESSBOOK_SELECTOR,
 		"source-list", source_list, NULL);
 }
+
+EAddressbookView *
+e_addressbook_selector_get_current_view (EAddressbookSelector *selector)
+{
+	g_return_val_if_fail (E_IS_ADDRESSBOOK_SELECTOR (selector), NULL);
+
+	return selector->priv->current_view;
+}
+
+void
+e_addressbook_selector_set_current_view (EAddressbookSelector *selector,
+                                         EAddressbookView *current_view)
+{
+	/* XXX This is only needed for moving contacts via drag-and-drop.
+	 *     The selection data doesn't include the source of the data
+	 *     (the model for the currently selected address book view),
+	 *     so we have to rely on it being provided to us.  I would
+	 *     be happy to see this function go away. */
+
+	g_return_if_fail (E_IS_ADDRESSBOOK_SELECTOR (selector));
+
+	if (current_view != NULL)
+		g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (current_view));
+
+	if (selector->priv->current_view != NULL) {
+		g_object_unref (selector->priv->current_view);
+		selector->priv->current_view = NULL;
+	}
+
+	if (current_view != NULL)
+		g_object_ref (current_view);
+
+	selector->priv->current_view = current_view;
+
+	g_object_notify (G_OBJECT (selector), "current-view");
+}

Modified: branches/kill-bonobo/addressbook/gui/widgets/e-addressbook-selector.h
==============================================================================
--- branches/kill-bonobo/addressbook/gui/widgets/e-addressbook-selector.h	(original)
+++ branches/kill-bonobo/addressbook/gui/widgets/e-addressbook-selector.h	Sat Nov 29 15:26:50 2008
@@ -23,6 +23,7 @@
 
 #include <libedataserver/e-source-list.h>
 #include <libedataserverui/e-source-selector.h>
+#include "e-addressbook-view.h"
 
 /* Standard GObject macros */
 #define E_TYPE_ADDRESSBOOK_SELECTOR \
@@ -60,6 +61,12 @@
 
 GType		e_addressbook_selector_get_type	(void);
 GtkWidget *	e_addressbook_selector_new	(ESourceList *source_list);
+EAddressbookView *
+		e_addressbook_selector_get_current_view
+						(EAddressbookSelector *selector);
+void		e_addressbook_selector_set_current_view
+						(EAddressbookSelector *selector,
+						 EAddressbookView *current_view);
 
 G_END_DECLS
 

Modified: branches/kill-bonobo/calendar/gui/Makefile.am
==============================================================================
--- branches/kill-bonobo/calendar/gui/Makefile.am	(original)
+++ branches/kill-bonobo/calendar/gui/Makefile.am	Sat Nov 29 15:26:50 2008
@@ -133,6 +133,8 @@
 	e-meeting-types.h			\
 	e-meeting-utils.c			\
 	e-meeting-utils.h			\
+	e-memo-list-selector.c			\
+	e-memo-list-selector.h			\
 	e-memo-table.c				\
 	e-memo-table.h				\
 	e-memo-table-config.c			\
@@ -143,6 +145,8 @@
 	e-select-names-editable.h		\
 	e-select-names-renderer.c		\
 	e-select-names-renderer.h		\
+	e-task-list-selector.c			\
+	e-task-list-selector.h			\
 	e-week-view-config.c			\
 	e-week-view-config.h			\
 	e-week-view-event-item.c		\

Modified: branches/kill-bonobo/calendar/gui/e-calendar-selector.c
==============================================================================
--- branches/kill-bonobo/calendar/gui/e-calendar-selector.c	(original)
+++ branches/kill-bonobo/calendar/gui/e-calendar-selector.c	Sat Nov 29 15:26:50 2008
@@ -103,129 +103,16 @@
 	return TRUE;
 }
 
-static void
-calendar_selector_drag_leave (GtkWidget *widget,
-                              GdkDragContext *context,
-                              guint time_)
-{
-	/* XXX This is exactly the same as in EAddressbookSelector.
-	 *     Consider merging this callback into ESourceSelector. */
-
-	GtkTreeView *tree_view;
-	GtkTreeViewDropPosition pos;
-
-	tree_view = GTK_TREE_VIEW (widget);
-	pos = GTK_TREE_VIEW_DROP_BEFORE;
-
-	gtk_tree_view_set_drag_dest_row (tree_view, NULL, pos);
-}
-
-static gboolean
-calendar_selector_drag_motion (GtkWidget *widget,
-                               GdkDragContext *context,
-                               gint x,
-                               gint y,
-                               guint time_)
-{
-	/* XXX This is exactly the same as in EAddressbookSelector.
-	 *     Consider merging this callback into ESourceSelector. */
-
-	GtkTreeView *tree_view;
-	GtkTreeModel *model;
-	GtkTreePath *path = NULL;
-	GtkTreeIter iter;
-	GtkTreeViewDropPosition pos;
-	GdkDragAction action = 0;
-	gpointer object;
-
-	tree_view = GTK_TREE_VIEW (widget);
-	model = gtk_tree_view_get_model (tree_view);
-
-	if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL))
-		goto exit;
-
-	if (!gtk_tree_model_get_iter (model, &iter, path))
-		goto exit;
-
-	gtk_tree_model_get (model, &iter, 0, &object, -1);
-
-	if (E_IS_SOURCE_GROUP (object) || e_source_get_readonly (object))
-		goto exit;
-
-	pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE;
-	gtk_tree_view_set_drag_dest_row (tree_view, path, pos);
-
-	if (context->actions & GDK_ACTION_MOVE)
-		action = GDK_ACTION_MOVE;
-	else
-		action = context->suggested_action;
-
-exit:
-	if (path != NULL)
-		gtk_tree_path_free (path);
-
-	if (object != NULL)
-		g_object_unref (object);
-
-	gdk_drag_status (context, action, time_);
-
-	return TRUE;
-}
-
 static gboolean
-calendar_selector_drag_drop (GtkWidget *widget,
-                             GdkDragContext *context,
-                             gint x,
-                             gint y,
-                             guint time_)
+calendar_selector_data_dropped (ESourceSelector *selector,
+                                GtkSelectionData *selection_data,
+                                ESource *destination,
+                                GdkDragAction action,
+                                guint info)
 {
-	/* XXX This is exactly the same as in EAddressbookSelector.
-	 *     Consider merging this callback into ESourceSelector. */
-
-	GtkTreeView *tree_view;
-	GtkTreeModel *model;
-	GtkTreePath *path;
-	GtkTreeIter iter;
-	gboolean drop_zone;
-	gboolean valid;
-	gpointer object;
-
-	tree_view = GTK_TREE_VIEW (widget);
-	model = gtk_tree_view_get_model (tree_view);
-
-	if (!gtk_tree_view_get_path_at_pos (
-		tree_view, x, y, &path, NULL, NULL, NULL))
-		return FALSE;
-
-	valid = gtk_tree_model_get_iter (model, &iter, path);
-	gtk_tree_path_free (path);
-	g_return_val_if_fail (valid, FALSE);
-
-	gtk_tree_model_get (model, &iter, 0, &object, -1);
-	drop_zone = E_IS_SOURCE (object);
-	g_object_unref (object);
-
-	return drop_zone;
-}
-
-static void
-calendar_selector_drag_data_received (GtkWidget *widget,
-                                      GdkDragContext *context,
-                                      gint x,
-                                      gint y,
-                                      GtkSelectionData *selection_data,
-                                      guint info,
-                                      guint time_)
-{
-	/* XXX This is NEARLY the same as in EAddressbookSelector.
-	 *     Consider merging this callback into ESourceSelector.
-	 *     Use a callback to allow subclasses to handle the
-	 *     received selection data. */
-
 	GtkTreeView *tree_view;
 	GtkTreeModel *model;
 	GtkTreePath *path = NULL;
-	GtkTreeIter iter;
 	ECal *client;
 	icalcomponent *icalcomp;
 	const gchar *string;
@@ -233,22 +120,11 @@
 	gboolean success = FALSE;
 	gpointer object = NULL;
 
-	tree_view = GTK_TREE_VIEW (widget);
+	tree_view = GTK_TREE_VIEW (selector);
 	model = gtk_tree_view_get_model (tree_view);
 
 	string = (const gchar *) selection_data->data;
-	remove_from_source = (context->action == GDK_ACTION_MOVE);
-
-	if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL))
-		goto exit;
-
-	if (!gtk_tree_model_get_iter (model, &iter, path))
-		goto exit;
-
-	gtk_tree_model_get (model, &iter, 0, &object, -1);
-
-	if (!E_IS_SOURCE (object) || e_source_get_readonly (object))
-		goto exit;
+	remove_from_source = (action == GDK_ACTION_MOVE);
 
 	icalcomp = icalparser_parse_string (string);
 
@@ -256,7 +132,7 @@
 		goto exit;
 
 	/* FIXME Deal with GDK_ACTION_ASK. */
-	if (context->action == GDK_ACTION_COPY) {
+	if (action == GDK_ACTION_COPY) {
 		gchar *uid;
 
 		uid = e_cal_component_gen_uid ();
@@ -264,7 +140,7 @@
 	}
 
 	client = auth_new_cal_from_source (
-		E_SOURCE (object), E_CAL_SOURCE_TYPE_EVENT);
+		destination, E_CAL_SOURCE_TYPE_EVENT);
 
 	if (client != NULL) {
 		if (e_cal_open (client, TRUE, NULL)) {
@@ -277,6 +153,8 @@
 
 	icalcomponent_free (icalcomp);
 
+	success = TRUE;
+
 exit:
 	if (path != NULL)
 		gtk_tree_path_free (path);
@@ -284,22 +162,19 @@
 	if (object != NULL)
 		g_object_unref (object);
 
-	gtk_drag_finish (context, success, remove_from_source, time_);
+	return TRUE;
 }
 
 static void
 calendar_selector_class_init (ECalendarSelectorClass *class)
 {
-	GtkWidgetClass *widget_class;
+	ESourceSelectorClass *source_selector_class;
 
 	parent_class = g_type_class_peek_parent (class);
 	g_type_class_add_private (class, sizeof (ECalendarSelectorPrivate));
 
-	widget_class = GTK_WIDGET_CLASS (class);
-	widget_class->drag_leave = calendar_selector_drag_leave;
-	widget_class->drag_motion = calendar_selector_drag_motion;
-	widget_class->drag_drop = calendar_selector_drag_drop;
-	widget_class->drag_data_received = calendar_selector_drag_data_received;
+	source_selector_class = E_SOURCE_SELECTOR_CLASS (class);
+	source_selector_class->data_dropped = calendar_selector_data_dropped;
 }
 
 static void

Added: branches/kill-bonobo/calendar/gui/e-memo-list-selector.c
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/gui/e-memo-list-selector.c	Sat Nov 29 15:26:50 2008
@@ -0,0 +1,287 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-memo-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-memo-list-selector.h"
+
+#include <string.h>
+#include <libecal/e-cal.h>
+#include "calendar/common/authentication.h"
+#include "calendar/gui/comp-util.h"
+
+#define E_MEMO_LIST_SELECTOR_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MEMO_LIST_SELECTOR, EMemoListSelectorPrivate))
+
+struct _EMemoListSelectorPrivate {
+	gint dummy_value;
+};
+
+enum {
+	DND_TARGET_TYPE_CALENDAR_LIST
+};
+
+static GtkTargetEntry drag_types[] = {
+	{ "text/calendar", 0, DND_TARGET_TYPE_CALENDAR_LIST },
+	{ "text/x-calendar", 0, DND_TARGET_TYPE_CALENDAR_LIST }
+};
+
+static gpointer parent_class;
+
+static gboolean
+memo_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
+memo_list_selector_update_objects (ECal *client,
+                                   icalcomponent *icalcomp)
+{
+	icalcomponent *subcomp;
+	icalcomponent_kind kind;
+
+	kind = icalcomponent_isa (icalcomp);
+	if (kind == ICAL_VJOURNAL_COMPONENT)
+		return memo_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_VJOURNAL_COMPONENT) {
+			success = memo_list_selector_update_single_object (
+				client, subcomp);
+			if (!success)
+				return FALSE;
+		}
+
+		subcomp = icalcomponent_get_next_component (
+			icalcomp, ICAL_ANY_COMPONENT);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+memo_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 = memo_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_JOURNAL);
+	if (client == NULL) {
+		g_message ("Cannot create source client to remove old memo");
+		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 memo");
+
+	g_object_unref (client);
+
+exit:
+	g_free (old_uid);
+
+	return success;
+}
+
+static gboolean
+memo_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_JOURNAL);
+
+	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 = memo_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
+memo_list_selector_class_init (EMemoListSelectorClass *class)
+{
+	ESourceSelectorClass *source_selector_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (EMemoListSelectorPrivate));
+
+	source_selector_class = E_SOURCE_SELECTOR_CLASS (class);
+	source_selector_class->data_dropped = memo_list_selector_data_dropped;
+}
+
+static void
+memo_list_selector_init (EMemoListSelector *selector)
+{
+	selector->priv = E_MEMO_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_memo_list_selector_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		const GTypeInfo type_info = {
+			sizeof (EMemoListSelectorClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) memo_list_selector_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (EMemoListSelector),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) memo_list_selector_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			E_TYPE_SOURCE_SELECTOR, "EMemoListSelector",
+			&type_info, 0);
+	}
+
+	return type;
+}
+
+GtkWidget *
+e_memo_list_selector_new (ESourceList *source_list)
+{
+	g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), NULL);
+
+	return g_object_new (
+		E_TYPE_MEMO_LIST_SELECTOR,
+		"source-list", source_list, NULL);
+}

Added: branches/kill-bonobo/calendar/gui/e-memo-list-selector.h
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/gui/e-memo-list-selector.h	Sat Nov 29 15:26:50 2008
@@ -0,0 +1,71 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-memo-list-selector.h
+ *
+ * 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.
+ */
+
+/* XXX This widget is nearly identical to ETaskListSelector.  If
+ *     ECalendarSelector ever learns how to move selections from
+ *     one source to another, perhaps these ESourceSelector sub-
+ *     classes could someday be combined. */
+
+#ifndef E_MEMO_LIST_SELECTOR_H
+#define E_MEMO_LIST_SELECTOR_H
+
+#include <libedataserver/e-source-list.h>
+#include <libedataserverui/e-source-selector.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MEMO_LIST_SELECTOR \
+	(e_memo_list_selector_get_type ())
+#define E_MEMO_LIST_SELECTOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MEMO_LIST_SELECTOR, EMemoListSelector))
+#define E_MEMO_LIST_SELECTOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MEMO_LIST_SELECTOR, EMemoListSelectorClass))
+#define E_IS_MEMO_LIST_SELECTOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MEMO_LIST_SELECTOR))
+#define E_IS_MEMO_LIST_SELECTOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MEMO_LIST_SELECTOR))
+#define E_MEMO_LIST_SELECTOR_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MEMO_LIST_SELECTOR, EMemoListSelectorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMemoListSelector EMemoListSelector;
+typedef struct _EMemoListSelectorClass EMemoListSelectorClass;
+typedef struct _EMemoListSelectorPrivate EMemoListSelectorPrivate;
+
+struct _EMemoListSelector {
+	ESourceSelector parent;
+	EMemoListSelectorPrivate *priv;
+};
+
+struct _EMemoListSelectorClass {
+	ESourceSelectorClass parent_class;
+};
+
+GType		e_memo_list_selector_get_type	(void);
+GtkWidget *	e_memo_list_selector_new	(ESourceList *source_list);
+
+G_END_DECLS
+
+#endif /* E_MEMO_LIST_SELECTOR_H */

Modified: branches/kill-bonobo/calendar/gui/e-memos.c
==============================================================================
--- branches/kill-bonobo/calendar/gui/e-memos.c	(original)
+++ branches/kill-bonobo/calendar/gui/e-memos.c	Sat Nov 29 15:26:50 2008
@@ -193,126 +193,6 @@
 	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));
-
-			/* do not free this pointer, it owns libical */
-			/* g_free (comp_str); */
-		}
-
-		icalcomponent_free (vcal);
-		g_free (comp_str);
-	}
-}
-
-static void
-table_drag_data_get (ETable             *table,
-		     int                 row,
-		     int                 col,
-		     GdkDragContext     *context,
-		     GtkSelectionData   *selection_data,
-		     guint               info,
-		     guint               time,
-		     EMemos             *memos)
-{
-	EMemosPrivate *priv;
-
-	priv = memos->priv;
-
-	if (info == TARGET_VCALENDAR) {
-		/* we will pass an icalcalendar component for both types */
-		GSList *components = NULL;
-
-		do_for_selected_components (E_MEMO_TABLE (priv->memos_view), obtain_list_of_components, &components);
-
-		if (components) {
-			cal_comp_selection_set_string_list (selection_data, components);
-
-			g_slist_foreach (components, (GFunc)g_free, NULL);
-			g_slist_free (components);
-		}
-	}
-}
-
 static void
 setup_widgets (EMemos *memos)
 {

Added: branches/kill-bonobo/calendar/gui/e-task-list-selector.c
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/gui/e-task-list-selector.c	Sat Nov 29 15:26:50 2008
@@ -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[] = {
+	{ "text/calendar", 0, DND_TARGET_TYPE_CALENDAR_LIST },
+	{ "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);
+}

Added: branches/kill-bonobo/calendar/gui/e-task-list-selector.h
==============================================================================
--- (empty file)
+++ branches/kill-bonobo/calendar/gui/e-task-list-selector.h	Sat Nov 29 15:26:50 2008
@@ -0,0 +1,71 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* e-task-list-selector.h
+ *
+ * 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.
+ */
+
+/* XXX This widget is nearly identical to EMemoListSelector.  If
+ *     ECalendarSelector ever learns how to move selections from
+ *     one source to another, perhaps these ESourceSelector sub-
+ *     classes could someday be combined. */
+
+#ifndef E_TASK_LIST_SELECTOR_H
+#define E_TASK_LIST_SELECTOR_H
+
+#include <libedataserver/e-source-list.h>
+#include <libedataserverui/e-source-selector.h>
+
+/* Standard GObject macros */
+#define E_TYPE_TASK_LIST_SELECTOR \
+	(e_task_list_selector_get_type ())
+#define E_TASK_LIST_SELECTOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_TASK_LIST_SELECTOR, ETaskListSelector))
+#define E_TASK_LIST_SELECTOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_TASK_LIST_SELECTOR, ETaskListSelectorClass))
+#define E_IS_TASK_LIST_SELECTOR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_TASK_LIST_SELECTOR))
+#define E_IS_TASK_LIST_SELECTOR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_TASK_LIST_SELECTOR))
+#define E_TASK_LIST_SELECTOR_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_TASK_LIST_SELECTOR, ETaskListSelectorClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ETaskListSelector ETaskListSelector;
+typedef struct _ETaskListSelectorClass ETaskListSelectorClass;
+typedef struct _ETaskListSelectorPrivate ETaskListSelectorPrivate;
+
+struct _ETaskListSelector {
+	ESourceSelector parent;
+	ETaskListSelectorPrivate *priv;
+};
+
+struct _ETaskListSelectorClass {
+	ESourceSelectorClass parent_class;
+};
+
+GType		e_task_list_selector_get_type	(void);
+GtkWidget *	e_task_list_selector_new	(ESourceList *source_list);
+
+G_END_DECLS
+
+#endif /* E_TASK_LIST_SELECTOR_H */

Modified: branches/kill-bonobo/calendar/modules/e-cal-shell-content.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-cal-shell-content.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-cal-shell-content.c	Sat Nov 29 15:26:50 2008
@@ -21,6 +21,7 @@
 
 #include "e-cal-shell-content.h"
 
+#include <string.h>
 #include <glib/gi18n.h>
 
 #include "e-util/gconf-bridge.h"

Modified: branches/kill-bonobo/calendar/modules/e-memo-shell-content.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-memo-shell-content.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-memo-shell-content.c	Sat Nov 29 15:26:50 2008
@@ -26,6 +26,7 @@
 #include "e-util/gconf-bridge.h"
 
 #include "calendar/gui/calendar-config.h"
+#include "calendar/gui/comp-util.h"
 #include "calendar/gui/e-cal-model-memos.h"
 #include "calendar/gui/e-memo-table.h"
 #include "calendar/gui/e-memo-table-config.h"
@@ -91,6 +92,45 @@
 }
 
 static void
+memo_shell_content_table_foreach_cb (gint model_row,
+                                     gpointer user_data)
+{
+	ECalModelComponent *comp_data;
+	icalcomponent *clone;
+	icalcomponent *vcal;
+	gchar *string;
+
+	struct {
+		ECalModel *model;
+		GSList *list;
+	} *foreach_data = user_data;
+
+	comp_data = e_cal_model_get_component_at (
+		foreach_data->model, model_row);
+
+	vcal = e_cal_util_new_top_level ();
+	clone = icalcomponent_new_clone (comp_data->icalcomp);
+	e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp);
+	icalcomponent_add_component (vcal, clone);
+
+	/* String is owned by libical; do not free. */
+	string = icalcomponent_as_ical_string (vcal);
+	if (string != NULL) {
+		ESource *source;
+		const gchar *source_uid;
+
+		source = e_cal_get_source (comp_data->client);
+		source_uid = e_source_peek_uid (source);
+
+		foreach_data->list = g_slist_prepend (
+			foreach_data->list,
+			g_strdup_printf ("%s\n%s", source_uid, string));
+	}
+
+	icalcomponent_free (vcal);
+}
+
+static void
 memo_shell_content_table_drag_data_get_cb (EMemoShellContent *memo_shell_content,
                                            gint row,
                                            gint col,
@@ -99,7 +139,33 @@
                                            guint info,
                                            guint time)
 {
-	/* FIXME */
+	EMemoTable *memo_table;
+	ETable *table;
+
+	struct {
+		ECalModel *model;
+		GSList *list;
+	} foreach_data;
+
+	if (info != TARGET_VCALENDAR)
+		return;
+
+	memo_table = e_memo_shell_content_get_memo_table (memo_shell_content);
+	table = e_memo_table_get_table (memo_table);
+
+	foreach_data.model = e_memo_table_get_model (memo_table);
+	foreach_data.list = NULL;
+
+	e_table_selected_row_foreach (
+		table, memo_shell_content_table_foreach_cb,
+		&foreach_data);
+
+	if (foreach_data.list != NULL) {
+		cal_comp_selection_set_string_list (
+			selection_data, foreach_data.list);
+		g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL);
+		g_slist_free (foreach_data.list);
+	}
 }
 
 static void
@@ -110,7 +176,7 @@
 {
 	/* 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
+	 * don't want to delete not-moved memos.  There is no such information
 	 * which event has been moved and which not, so skip this method. */
 }
 

Modified: branches/kill-bonobo/calendar/modules/e-memo-shell-sidebar.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-memo-shell-sidebar.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-memo-shell-sidebar.c	Sat Nov 29 15:26:50 2008
@@ -29,7 +29,7 @@
 #include "e-util/e-util.h"
 #include "calendar/common/authentication.h"
 #include "calendar/gui/calendar-config.h"
-#include "calendar/gui/e-calendar-selector.h"
+#include "calendar/gui/e-memo-list-selector.h"
 #include "calendar/gui/misc.h"
 
 #include "e-memo-shell-view.h"
@@ -388,7 +388,7 @@
 
 	container = GTK_CONTAINER (widget);
 
-	widget = e_calendar_selector_new (source_list);
+	widget = e_memo_list_selector_new (source_list);
 	e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE);
 	gtk_container_add (container, widget);
 	a11y = gtk_widget_get_accessible (widget);

Modified: branches/kill-bonobo/calendar/modules/e-task-shell-content.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-task-shell-content.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-task-shell-content.c	Sat Nov 29 15:26:50 2008
@@ -26,6 +26,7 @@
 #include "e-util/gconf-bridge.h"
 
 #include "calendar/gui/calendar-config.h"
+#include "calendar/gui/comp-util.h"
 #include "calendar/gui/e-cal-model-tasks.h"
 #include "calendar/gui/e-calendar-table.h"
 #include "calendar/gui/e-calendar-table-config.h"
@@ -92,6 +93,45 @@
 }
 
 static void
+task_shell_content_table_foreach_cb (gint model_row,
+                                     gpointer user_data)
+{
+	ECalModelComponent *comp_data;
+	icalcomponent *clone;
+	icalcomponent *vcal;
+	gchar *string;
+
+	struct {
+		ECalModel *model;
+		GSList *list;
+	} *foreach_data = user_data;
+
+	comp_data = e_cal_model_get_component_at (
+		foreach_data->model, model_row);
+
+	vcal = e_cal_util_new_top_level ();
+	clone = icalcomponent_new_clone (comp_data->icalcomp);
+	e_cal_util_add_timezones_from_component (vcal, comp_data->icalcomp);
+	icalcomponent_add_component (vcal, clone);
+
+	/* String is owned by libical; do not free. */
+	string = icalcomponent_as_ical_string (vcal);
+	if (string != NULL) {
+		ESource *source;
+		const gchar *source_uid;
+
+		source = e_cal_get_source (comp_data->client);
+		source_uid = e_source_peek_uid (source);
+
+		foreach_data->list = g_slist_prepend (
+			foreach_data->list,
+			g_strdup_printf ("%s\n%s", source_uid, string));
+	}
+
+	icalcomponent_free (vcal);
+}
+
+static void
 task_shell_content_table_drag_data_get_cb (ETaskShellContent *task_shell_content,
                                            gint row,
                                            gint col,
@@ -100,7 +140,33 @@
                                            guint info,
                                            guint time)
 {
-	/* FIXME */
+	ECalendarTable *task_table;
+	ETable *table;
+
+	struct {
+		ECalModel *model;
+		GSList *list;
+	} foreach_data;
+
+	if (info != TARGET_VCALENDAR)
+		return;
+
+	task_table = e_task_shell_content_get_task_table (task_shell_content);
+	table = e_calendar_table_get_table (task_table);
+
+	foreach_data.model = e_calendar_table_get_model (task_table);
+	foreach_data.list = NULL;
+
+	e_table_selected_row_foreach (
+		table, task_shell_content_table_foreach_cb,
+		&foreach_data);
+
+	if (foreach_data.list != NULL) {
+		cal_comp_selection_set_string_list (
+			selection_data, foreach_data.list);
+		g_slist_foreach (foreach_data.list, (GFunc) g_free, NULL);
+		g_slist_free (foreach_data.list);
+	}
 }
 
 static void

Modified: branches/kill-bonobo/calendar/modules/e-task-shell-sidebar.c
==============================================================================
--- branches/kill-bonobo/calendar/modules/e-task-shell-sidebar.c	(original)
+++ branches/kill-bonobo/calendar/modules/e-task-shell-sidebar.c	Sat Nov 29 15:26:50 2008
@@ -29,7 +29,7 @@
 #include "e-util/e-util.h"
 #include "calendar/common/authentication.h"
 #include "calendar/gui/calendar-config.h"
-#include "calendar/gui/e-calendar-selector.h"
+#include "calendar/gui/e-task-list-selector.h"
 #include "calendar/gui/misc.h"
 
 #include "e-task-shell-view.h"
@@ -361,7 +361,7 @@
 
 	container = GTK_CONTAINER (widget);
 
-	widget = e_calendar_selector_new (source_list);
+	widget = e_task_list_selector_new (source_list);
 	e_source_selector_set_select_new (E_SOURCE_SELECTOR (widget), TRUE);
 	gtk_container_add (container, widget);
 	a11y = gtk_widget_get_accessible (widget);



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