From 5786eb64a18ed1302ac6e10dc8aea2cc2d346ba1 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Wed, 2 Jun 2004 09:33:36 +0000 Subject: add a drag delete handler. (table_drag_data_get): support text/vcard 2004-06-02 Larry Ewing * gui/e-tasks.c (table_drag_data_delete): add a drag delete handler. (table_drag_data_get): support text/vcard drags. (setup_widgets): setup the etable as a drag source. * gui/tasks-component.c: add source selector Drag & Drop handlers. svn path=/trunk/; revision=26151 --- calendar/gui/e-tasks.c | 121 +++++++++++++++++++++ calendar/gui/tasks-component.c | 236 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 357 insertions(+) (limited to 'calendar/gui') diff --git a/calendar/gui/e-tasks.c b/calendar/gui/e-tasks.c index 22b2b1ce29..947cf60a11 100644 --- a/calendar/gui/e-tasks.c +++ b/calendar/gui/e-tasks.c @@ -102,6 +102,16 @@ enum { LAST_SIGNAL }; +enum DndTargetType { + TARGET_VCALENDAR +}; + +static GtkTargetEntry list_drag_types[] = { + { "text/calendar", 0, TARGET_VCALENDAR }, + { "text/x-calendar", 0, TARGET_VCALENDAR } +}; +static const int num_list_drag_types = sizeof (list_drag_types) / sizeof (list_drag_types[0]); + static GtkTableClass *parent_class; static guint e_tasks_signals[LAST_SIGNAL] = { 0 }; @@ -325,6 +335,96 @@ setup_config (ETasks *tasks) priv->notifications = g_list_prepend (priv->notifications, GUINT_TO_POINTER (not)); } +static void +table_drag_data_get (ETable *table, + int row, + int col, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint info, + guint time, + ETasks *tasks) +{ + ETasksPrivate *priv; + ECalModelComponent *comp_data; + + priv = tasks->priv; + + if (priv->current_uid) { + ETableModel *model; + + model = e_calendar_table_get_model (E_CALENDAR_TABLE (priv->tasks_view)); + + comp_data = e_cal_model_get_component_at (E_CAL_MODEL (model), row); + + 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, comp_str, strlen (comp_str)); + } + icalcomponent_free (vcal); + } + } +} + +/* +static void +table_drag_begin (ETable *table, + int row, + int col, + GdkDragContext *context, + ETasks *tasks) +{ + +} + + +static void +table_drag_end (ETable *table, + int row, + int col, + GdkDragContext *context, + ETasks *tasks) +{ + +} +*/ + +static void +table_drag_data_delete (ETable *table, + int row, + int col, + GdkDragContext *context, + ETasks *tasks) +{ + ETasksPrivate *priv; + ECalModelComponent *comp_data; + ETableModel *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 (E_CAL_MODEL (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); +} + #define E_TASKS_TABLE_DEFAULT_STATE \ "" \ "" \ @@ -374,6 +474,27 @@ setup_widgets (ETasks *tasks) gtk_paned_add1 (GTK_PANED (paned), priv->tasks_view); gtk_widget_show (priv->tasks_view); + + e_table_drag_source_set (etable, GDK_BUTTON1_MASK, + list_drag_types, num_list_drag_types, + GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_ASK); + + g_signal_connect (etable, "table_drag_data_get", + G_CALLBACK(table_drag_data_get), tasks); + g_signal_connect (etable, "table_drag_data_delete", + G_CALLBACK(table_drag_data_delete), tasks); + /* + e_table_drag_dest_set (e_table_scrolled_get_table (E_TABLE_SCROLLED (editor->table)), + 0, list_drag_types, num_list_drag_types, GDK_ACTION_LINK); + + g_signal_connect (e_table_scrolled_get_table (E_TABLE_SCROLLED (editor->table)), + "table_drag_motion", G_CALLBACK(table_drag_motion_cb), editor); + g_signal_connect (e_table_scrolled_get_table (E_TABLE_SCROLLED (editor->table)), + "table_drag_drop", G_CALLBACK (table_drag_drop_cb), editor); + g_signal_connect (e_table_scrolled_get_table (E_TABLE_SCROLLED (editor->table)), + "table_drag_data_received", G_CALLBACK(table_drag_data_received_cb), editor); + */ + g_signal_connect (etable, "cursor_change", G_CALLBACK (table_cursor_change_cb), tasks); g_signal_connect (etable, "selection_change", G_CALLBACK (table_selection_change_cb), tasks); diff --git a/calendar/gui/tasks-component.c b/calendar/gui/tasks-component.c index 054ed3fe62..2f76ce0110 100644 --- a/calendar/gui/tasks-component.c +++ b/calendar/gui/tasks-component.c @@ -52,6 +52,16 @@ #define CREATE_TASK_ID "task" #define CREATE_TASK_LIST_ID "task-list" +enum DndTargetType { + DND_TARGET_TYPE_CALENDAR_LIST, +}; +#define CALENDAR_TYPE "text/calendar" +#define XCALENDAR_TYPE "text/x-calendar" +static GtkTargetEntry drag_types[] = { + { CALENDAR_TYPE, 0, DND_TARGET_TYPE_CALENDAR_LIST }, + { XCALENDAR_TYPE, 0, DND_TARGET_TYPE_CALENDAR_LIST } +}; +static gint num_drag_types = sizeof(drag_types) / sizeof(drag_types[0]); #define PARENT_TYPE bonobo_object_get_type () @@ -453,6 +463,219 @@ impl_upgradeFromVersion (PortableServer_Servant servant, g_error_free(err); } +static gboolean +selector_tree_drag_drop (GtkWidget *widget, + GdkDragContext *context, + int x, + int y, + guint time, + CalendarComponent *component) +{ + GtkTreeViewColumn *column; + int cell_x; + int cell_y; + GtkTreePath *path; + GtkTreeModel *model; + GtkTreeIter iter; + gpointer data; + + if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, y, &path, + &column, &cell_x, &cell_y)) + return FALSE; + + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + if (!gtk_tree_model_get_iter (model, &iter, path)) { + gtk_tree_path_free (path); + return FALSE; + } + + gtk_tree_model_get (model, &iter, 0, &data, -1); + + if (E_IS_SOURCE_GROUP (data)) { + g_object_unref (data); + gtk_tree_path_free (path); + return FALSE; + } + + gtk_tree_path_free (path); + return TRUE; +} + +static gboolean +selector_tree_drag_motion (GtkWidget *widget, + GdkDragContext *context, + int x, + int y, + guint time, + gpointer user_data) +{ + GtkTreePath *path = NULL; + gpointer data = NULL; + GtkTreeViewDropPosition pos; + GtkTreeModel *model; + GtkTreeIter iter; + GdkDragAction action = GDK_ACTION_DEFAULT; + + if (!gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget), + x, y, &path, &pos)) + goto finish; + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + if (!gtk_tree_model_get_iter (model, &iter, path)) + goto finish; + + gtk_tree_model_get (model, &iter, 0, &data, -1); + + if (E_IS_SOURCE_GROUP (data) || e_source_get_readonly (data)) + goto finish; + + gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW (widget), path, GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); + action = context->suggested_action; + + finish: + if (path) + gtk_tree_path_free (path); + if (data) + g_object_unref (data); + + gdk_drag_status (context, action, time); + return TRUE; +} + +static gboolean +update_single_object (ECal *client, icalcomponent *icalcomp) +{ + char *uid; + icalcomponent *tmp_icalcomp; + + uid = (char *) 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 +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 update_single_object (client, icalcomp); + 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) { + success = update_single_object (client, subcomp); + if (!success) + return success; + } + + subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT); + } + + return TRUE; +} + +static void +selector_tree_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time, + gpointer user_data) +{ + GtkTreePath *path = NULL; + GtkTreeViewDropPosition pos; + gpointer source = NULL; + GtkTreeModel *model; + GtkTreeIter iter; + gboolean success = FALSE; + icalcomponent *icalcomp = NULL; + ECal *client = NULL; + + if (!gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget), + x, y, &path, &pos)) + goto finish; + + model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); + + if (!gtk_tree_model_get_iter (model, &iter, path)) + goto finish; + + + gtk_tree_model_get (model, &iter, 0, &source, -1); + + if (E_IS_SOURCE_GROUP (source) || e_source_get_readonly (source)) + goto finish; + + icalcomp = icalparser_parse_string (data->data); + + if (icalcomp) { + char * uid; + + /* FIXME deal with GDK_ACTION_ASK */ + if (context->action == GDK_ACTION_COPY) { + 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)) { + success = TRUE; + update_objects (client, icalcomp); + } + + g_object_unref (client); + } + + icalcomponent_free (icalcomp); + } + + finish: + if (source) + g_object_unref (source); + if (path) + gtk_tree_path_free (path); + + gtk_drag_finish (context, success, context->action == GDK_ACTION_MOVE, time); +} + +static void +selector_tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, gpointer data) +{ + gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW (widget), + NULL, GTK_TREE_VIEW_DROP_BEFORE); +} + + static void control_activate_cb (BonoboControl *control, gboolean activate, gpointer data) { @@ -634,6 +857,19 @@ create_component_view (TasksComponent *tasks_component) /* Create sidebar selector */ component_view->source_selector = e_source_selector_new (tasks_component->priv->source_list); + + g_signal_connect (component_view->source_selector, "drag-motion", G_CALLBACK (selector_tree_drag_motion), + tasks_component); + g_signal_connect (component_view->source_selector, "drag-leave", G_CALLBACK (selector_tree_drag_leave), + tasks_component); + g_signal_connect (component_view->source_selector, "drag-drop", G_CALLBACK (selector_tree_drag_drop), + tasks_component); + g_signal_connect (component_view->source_selector, "drag-data-received", + G_CALLBACK (selector_tree_drag_data_received), tasks_component); + + gtk_drag_dest_set(component_view->source_selector, GTK_DEST_DEFAULT_ALL, drag_types, + num_drag_types, GDK_ACTION_COPY | GDK_ACTION_MOVE); + gtk_widget_show (component_view->source_selector); selector_scrolled_window = gtk_scrolled_window_new (NULL, NULL); -- cgit v1.2.3