Rodrigo, Attached is the patch for HEAD. I modified it a little according to the changes of selection_received() in e-cal-view.c of HEAD. As I tested, with my patch, drag and drop bewteen different window works fine. However, I found a bug in the existing code before applying my patch. When I try to drag a event from main canvas to top canvas in the same window, evolution will hang there. gdb shows it hangs at malloc() in icalmemory_new_buffer() in icalmemory.c. Sorry I cannot figure out why. Dragging from top canvas to top canvas in the same window works fine. Anyway, this is unrelated to this patch. Thanks a lot! Harry Rodrigo Moya wrote: On Sat, 2003-09-27 at 05:56, Harry Lu wrote:Hi, Calendar Developers, Here is a patch draft for 48869(Cannot drap&drop appointment from one window to another) based on 1.4 branch. It is a little large, but most of the logic is copied from existing code. I don't know if it can be commited in 1.4 because of the feature frozen, but I'd like someone to review my patch first and give some suggestions. I will provide a silimar patch for HEAD later when this patch is reviewd and agreed by calendar owners.it looks ok from a first look, although, as you say, this cannot be committed to 1.4 branch. So, please, provide the patch for HEAD.Second, dragging between different window, most of the code is copied from selection_received() which paste a calendar component to current selection. So, dragging between different window means a copy and paste.what does this mean? cheers |
Index: calendar//ChangeLog =================================================================== RCS file: /cvs/gnome/evolution/calendar/ChangeLog,v retrieving revision 1.1878 diff -u -r1.1878 ChangeLog --- calendar//ChangeLog 10 Oct 2003 05:29:34 -0000 1.1878 +++ calendar//ChangeLog 13 Oct 2003 07:53:02 -0000 @@ -1,3 +1,13 @@ +2003-10-13 Harry Lu <harry lu sun com> + + Fix for #48869. + + * gui/e-day-view.c (e_day_view_on_drag_data_get): Provide a + icalcomponent for both TARGET_CALENDAR_EVENT and TARGET_VCALENDAR. + (e_day_view_on_top_canvas_drag_data_received): If dragging between + different window, make it works like a copy and paste. + (e_day_view_on_main_canvas_drag_data_received): ditto. + 2003-10-10 Hans Petter Jansson <hpj ximian com> * gui/Makefile.am (etspec_DATA): Add e-cal-list-view.etspec. Index: calendar//gui/e-day-view.c =================================================================== RCS file: /cvs/gnome/evolution/calendar/gui/e-day-view.c,v retrieving revision 1.219 diff -u -r1.219 e-day-view.c --- calendar//gui/e-day-view.c 1 Sep 2003 06:15:33 -0000 1.219 +++ calendar//gui/e-day-view.c 13 Oct 2003 07:54:03 -0000 @@ -6821,15 +6821,8 @@ event = &g_array_index (day_view->events[day], EDayViewEvent, event_num); - if (info == TARGET_CALENDAR_EVENT) { - const char *event_uid; - - event_uid = icalcomponent_get_uid (event->comp_data->icalcomp); - g_return_if_fail (event_uid != NULL); - - gtk_selection_data_set (selection_data, selection_data->target, - 8, event_uid, strlen (event_uid)); - } else if (info == TARGET_VCALENDAR) { + if (info == TARGET_CALENDAR_EVENT || info == TARGET_VCALENDAR) { + /* we will pass an icalcalendar component for both types */ char *comp_str; icalcomponent *vcal; @@ -6864,24 +6857,30 @@ ECalViewPosition pos; gint day, start_day, end_day, num_days; gint start_offset, end_offset; - gchar *event_uid; CalComponent *comp; CalComponentDateTime date; struct icaltimetype itt; time_t dt; gboolean all_day_event; CalClient *client; + gboolean drag_from_same_window; + + if (day_view->drag_event_day != -1) + drag_from_same_window = TRUE; + else + drag_from_same_window = FALSE; client = e_cal_model_get_default_client (e_cal_view_get_model (E_CAL_VIEW (day_view))); /* Note that we only support DnD within the EDayView at present. */ if ((data->length >= 0) && (data->format == 8) && (day_view->drag_event_day != -1)) { + /* We are dragging in the same window */ + pos = e_day_view_convert_position_in_top_canvas (day_view, x, y, &day, NULL); if (pos != E_CAL_VIEW_POS_OUTSIDE) { - const char *uid; num_days = 1; start_offset = 0; end_offset = 0; @@ -6911,13 +6910,6 @@ client = event->comp_data->client; - event_uid = data->data; - - uid = icalcomponent_get_uid (event->comp_data->icalcomp); - - if (!event_uid || !uid || strcmp (event_uid, uid)) - g_warning ("Unexpected event UID"); - /* We clone the event since we don't want to change the original comp here. Otherwise we would not detect that the event's time @@ -7005,6 +6997,160 @@ } } + if ((data->length >= 0) && (data->format == 8) + && !drag_from_same_window) { + /* We are dragging between different window */ + + char *comp_str, *default_tzid;; + icalcomponent *icalcomp; + icalcomponent_kind kind; + time_t dtstart, tt_start, tt_end; + struct icaldurationtype ic_dur; + struct icaltimetype itime; + char * uid; + icaltimezone *default_zone; + + pos = e_day_view_convert_position_in_top_canvas (day_view, + x, y, &day, + NULL); + if (pos == E_CAL_VIEW_POS_OUTSIDE) + goto error; + + comp_str = (char *) data->data; + icalcomp = icalparser_parse_string ((const char *) comp_str); + if (!icalcomp) + goto error; + + default_tzid = calendar_config_get_timezone (); + cal_client_get_timezone (client, default_tzid, &default_zone); + + /* check the type of the component */ + kind = icalcomponent_isa (icalcomp); + if (kind != ICAL_VCALENDAR_COMPONENT && + kind != ICAL_VEVENT_COMPONENT && + kind != ICAL_VTODO_COMPONENT && + kind != ICAL_VJOURNAL_COMPONENT) { + goto error; + } + + if (kind == ICAL_VCALENDAR_COMPONENT) { + icalcomponent_kind child_kind; + icalcomponent *subcomp; + struct icaltimetype old_dtstart, old_dtend; + + subcomp = icalcomponent_get_first_component ( + icalcomp, ICAL_ANY_COMPONENT); + while (subcomp) { + child_kind = icalcomponent_isa (subcomp); + if (child_kind == ICAL_VEVENT_COMPONENT || + child_kind == ICAL_VTODO_COMPONENT || + child_kind == ICAL_VJOURNAL_COMPONENT) { + start_offset = 0; + end_offset = 0; + + old_dtstart = icalcomponent_get_dtstart (subcomp); + tt_start = icaltime_as_timet (old_dtstart); + old_dtend = icalcomponent_get_dtend (subcomp); + tt_end = icaltime_as_timet (old_dtend); + ic_dur = icaldurationtype_from_int (tt_end - tt_start); + if (icaldurationtype_as_int (ic_dur) > 60*60*24) { + /* This is a long event */ + start_offset = old_dtstart.hour * 60 + old_dtstart.minute; + end_offset = old_dtstart.hour * 60 + old_dtend.minute; + } + + if (start_offset == 0 && end_offset == 0) + all_day_event = TRUE; + else + all_day_event = FALSE; + + dtstart = day_view->day_starts[day] + start_offset * 60; + itime = icaltime_from_timet_with_zone (dtstart, FALSE, default_zone); + if (all_day_event) + itime.is_date = TRUE; + icalcomponent_set_dtstart (subcomp, itime); + + itime = icaltime_add (itime, ic_dur); + if (all_day_event) + itime.is_date = TRUE; + icalcomponent_set_dtend (subcomp, itime); + + uid = cal_component_gen_uid (); + comp = cal_component_new (); + cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (subcomp)); + cal_component_set_uid (comp, uid); + + cal_client_update_object (client, comp); + if (itip_organizer_is_user (comp, client) && + send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), + client, comp, TRUE)) { + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + client, NULL); + } + + free (uid); + g_object_unref (comp); + + } + subcomp = icalcomponent_get_next_component ( + icalcomp, ICAL_ANY_COMPONENT); + } + } + else { + struct icaltimetype old_dtstart, old_dtend; + start_offset = 0; + end_offset = 0; + + old_dtstart = icalcomponent_get_dtstart (icalcomp); + tt_start = icaltime_as_timet (old_dtstart); + old_dtend = icalcomponent_get_dtend (icalcomp); + tt_end = icaltime_as_timet (old_dtend); + ic_dur = icaldurationtype_from_int (tt_end - tt_start); + if (icaldurationtype_as_int (ic_dur) > 60*60*24) { + /* This is a long event */ + start_offset = old_dtstart.hour * 60 + old_dtstart.minute; + end_offset = old_dtstart.hour * 60 + old_dtend.minute; + } + + if (start_offset == 0 && end_offset == 0) + all_day_event = TRUE; + else + all_day_event = FALSE; + + dtstart = day_view->day_starts[day] + start_offset * 60; + itime = icaltime_from_timet_with_zone (dtstart, FALSE, default_zone); + if (all_day_event) + itime.is_date = TRUE; + icalcomponent_set_dtstart (icalcomp, itime); + + itime = icaltime_add (itime, ic_dur); + if (all_day_event) + itime.is_date = TRUE; + icalcomponent_set_dtend (icalcomp, itime); + + uid = cal_component_gen_uid (); + comp = cal_component_new (); + cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (icalcomp)); + cal_component_set_uid (comp, uid); + + cal_client_update_object (client, comp); + + if (itip_organizer_is_user (comp, client) && + send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), + client, comp, TRUE)) { + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, client, NULL); + } + + free (uid); + g_object_unref (comp); + } + gtk_drag_finish (context, TRUE, TRUE, time); + return; + } + +error: gtk_drag_finish (context, FALSE, FALSE, time); } @@ -7023,12 +7169,17 @@ ECalViewPosition pos; gint day, row, start_row, end_row, num_rows, scroll_x, scroll_y; gint start_offset, end_offset; - gchar *event_uid; CalComponent *comp; CalComponentDateTime date; struct icaltimetype itt; time_t dt; CalClient *client; + gboolean drag_from_same_window; + + if (day_view->drag_event_day != -1) + drag_from_same_window = TRUE; + else + drag_from_same_window = FALSE; client = e_cal_model_get_default_client (e_cal_view_get_model (E_CAL_VIEW (day_view))); @@ -7040,11 +7191,12 @@ /* Note that we only support DnD within the EDayView at present. */ if ((data->length >= 0) && (data->format == 8) && (day_view->drag_event_day != -1)) { + /* We are dragging in the same window */ + pos = e_day_view_convert_position_in_main_canvas (day_view, x, y, &day, &row, NULL); if (pos != E_CAL_VIEW_POS_OUTSIDE) { - const char *uid; num_rows = 1; start_offset = 0; end_offset = 0; @@ -7074,12 +7226,6 @@ client = event->comp_data->client; - event_uid = data->data; - - uid = icalcomponent_get_uid (event->comp_data->icalcomp); - if (!event_uid || !uid || strcmp (event_uid, uid)) - g_warning ("Unexpected event UID"); - /* We use a temporary shallow copy of comp since we don't want to change the original comp here. Otherwise we would not detect that the event's time @@ -7141,6 +7287,120 @@ } } + if ((data->length >= 0) && (data->format == 8) + && !drag_from_same_window) { + /* We are dragging between different window */ + + char *comp_str, *default_tzid; + icalcomponent *icalcomp; + icalcomponent_kind kind; + time_t dtstart, tt_start, tt_end; + struct icaldurationtype ic_dur; + struct icaltimetype itime; + char * uid; + icaltimezone *default_zone; + + pos = e_day_view_convert_position_in_main_canvas (day_view, + x, y, &day, + &row, NULL); + if (pos == E_CAL_VIEW_POS_OUTSIDE) + goto error; + + comp_str = (char *) data->data; + icalcomp = icalparser_parse_string ((const char *) comp_str); + if (!icalcomp) + goto error; + + default_tzid = calendar_config_get_timezone (); + cal_client_get_timezone (client, default_tzid, &default_zone); + + /* check the type of the component */ + kind = icalcomponent_isa (icalcomp); + if (kind != ICAL_VCALENDAR_COMPONENT && + kind != ICAL_VEVENT_COMPONENT && + kind != ICAL_VTODO_COMPONENT && + kind != ICAL_VJOURNAL_COMPONENT) { + goto error; + } + + dtstart = e_day_view_convert_grid_position_to_time (day_view, day, row); + + if (kind == ICAL_VCALENDAR_COMPONENT) { + icalcomponent_kind child_kind; + icalcomponent *subcomp; + + subcomp = icalcomponent_get_first_component ( + icalcomp, ICAL_ANY_COMPONENT); + while (subcomp) { + child_kind = icalcomponent_isa (subcomp); + if (child_kind == ICAL_VEVENT_COMPONENT || + child_kind == ICAL_VTODO_COMPONENT || + child_kind == ICAL_VJOURNAL_COMPONENT) { + tt_start = icaltime_as_timet (icalcomponent_get_dtstart (subcomp)); + tt_end = icaltime_as_timet (icalcomponent_get_dtend (subcomp)); + ic_dur = icaldurationtype_from_int (tt_end - tt_start); + itime = icaltime_from_timet_with_zone (dtstart, FALSE, default_zone); + + icalcomponent_set_dtstart (subcomp, itime); + itime = icaltime_add (itime, ic_dur); + icalcomponent_set_dtend (subcomp, itime); + + uid = cal_component_gen_uid (); + comp = cal_component_new (); + cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (subcomp)); + cal_component_set_uid (comp, uid); + + cal_client_update_object (client, comp); + if (itip_organizer_is_user (comp, client) && + send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), + client, comp, TRUE)) { + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + client, NULL); + } + + free (uid); + g_object_unref (comp); + + } + subcomp = icalcomponent_get_next_component ( + icalcomp, ICAL_ANY_COMPONENT); + } + + icalcomponent_free (icalcomp); + } + else { + tt_start = icaltime_as_timet (icalcomponent_get_dtstart (icalcomp)); + tt_end = icaltime_as_timet (icalcomponent_get_dtend (icalcomp)); + ic_dur = icaldurationtype_from_int (tt_end - tt_start); + itime = icaltime_from_timet_with_zone (dtstart, FALSE, default_zone); + + icalcomponent_set_dtstart (icalcomp, itime); + itime = icaltime_add (itime, ic_dur); + icalcomponent_set_dtend (icalcomp, itime); + + uid = cal_component_gen_uid (); + comp = cal_component_new (); + cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp)); + cal_component_set_uid (comp, uid); + + cal_client_update_object (client, comp); + + if (itip_organizer_is_user (comp, client) && + send_component_dialog ((GtkWindow *) gtk_widget_get_toplevel (GTK_WIDGET (day_view)), + client, comp, TRUE)) { + itip_send_comp (CAL_COMPONENT_METHOD_REQUEST, comp, + client, NULL); + } + + free (uid); + g_object_unref (comp); + } + gtk_drag_finish (context, TRUE, TRUE, time); + return; + } + +error: gtk_drag_finish (context, FALSE, FALSE, time); }