From 58338b08f3a880320bed171256850d326b895c23 Mon Sep 17 00:00:00 2001 From: Milan Crha Date: Mon, 5 Nov 2007 10:45:03 +0000 Subject: ** Fix for bug #351932 2007-11-05 Milan Crha ** Fix for bug #351932 * widgets/misc/e-dateedit.h: (e_date_edit_have_time): * widgets/misc/e-dateedit.c: (e_date_edit_have_time): Extend API to be able to check if time is set independently of date part. * calendar/gui/dialogs/task-page.c: (check_start_before_end), (times_updated), (start_date_changed_cb), (due_date_changed_cb), (init_widgets): Ensure due date is not before start date. svn path=/trunk/; revision=34500 --- calendar/ChangeLog | 8 ++ calendar/gui/dialogs/task-page.c | 154 ++++++++++++++++++++++++++++++++++++++- widgets/misc/ChangeLog | 8 ++ widgets/misc/e-dateedit.c | 14 ++++ widgets/misc/e-dateedit.h | 3 + 5 files changed, 185 insertions(+), 2 deletions(-) diff --git a/calendar/ChangeLog b/calendar/ChangeLog index 75cd7a898a..4fe959dfae 100644 --- a/calendar/ChangeLog +++ b/calendar/ChangeLog @@ -1,3 +1,11 @@ +2007-11-05 Milan Crha + + ** Fix for bug #351932 + + * gui/dialogs/task-page.c: (check_start_before_end), (times_updated), + (start_date_changed_cb), (due_date_changed_cb), (init_widgets): + Ensure due date is not before start date. + 2007-11-05 Milan Crha ** Fix for bug #315101 diff --git a/calendar/gui/dialogs/task-page.c b/calendar/gui/dialogs/task-page.c index 647005857c..e6db2e932e 100644 --- a/calendar/gui/dialogs/task-page.c +++ b/calendar/gui/dialogs/task-page.c @@ -1687,6 +1687,156 @@ field_changed_cb (GtkWidget *widget, gpointer data) comp_editor_page_notify_changed (COMP_EDITOR_PAGE (tpage)); } +static gboolean +check_start_before_end (struct icaltimetype *start_tt, + icaltimezone *start_zone, + struct icaltimetype *end_tt, + icaltimezone *end_zone, + gboolean adjust_end_time, + gboolean adjust_by_hour) +{ + struct icaltimetype end_tt_copy; + int cmp; + + /* Convert the end time to the same timezone as the start time. */ + end_tt_copy = *end_tt; + icaltimezone_convert_time (&end_tt_copy, end_zone, start_zone); + + /* Now check if the start time is after the end time. If it is, + we need to modify one of the times. */ + cmp = icaltime_compare (*start_tt, end_tt_copy); + if (cmp > 0) { + if (adjust_end_time) { + /* Modify the end time, to be the start + 1 hour/day. */ + *end_tt = *start_tt; + icaltime_adjust (end_tt, 0, adjust_by_hour ? 1 : 24, 0, 0); + icaltimezone_convert_time (end_tt, start_zone, + end_zone); + } else { + /* Modify the start time, to be the end - 1 hour/day. */ + *start_tt = *end_tt; + icaltime_adjust (start_tt, 0, adjust_by_hour ? -1 : -24, 0, 0); + icaltimezone_convert_time (start_tt, end_zone, + start_zone); + } + return TRUE; + } + + return FALSE; +} + +/* + * This is called whenever the start or due dates. + * It makes sure that the start date < end date. It also emits the notification + * signals so the other event editor pages update their labels etc. + * + * If adjust_end_time is TRUE, if the start time < end time it will adjust + * the end time. If FALSE it will adjust the start time. If the user sets the + * start or end time, the other time is adjusted to make it valid. + * + * Time part of the value is changed only when both edits have time set, + * otherwise times will differ one hour. + */ +static void +times_updated (TaskPage *tpage, gboolean adjust_end_time) +{ + TaskPagePrivate *priv; + struct icaltimetype start_tt = icaltime_null_time(); + struct icaltimetype end_tt = icaltime_null_time(); + gboolean date_set; + gboolean set_start_date = FALSE, set_end_date = FALSE, adjust_by_hour; + icaltimezone *zone; + + priv = tpage->priv; + + if (priv->updating) + return; + + date_set = e_date_edit_get_date (E_DATE_EDIT (priv->start_date), + &start_tt.year, + &start_tt.month, + &start_tt.day); + if (!date_set) + return; + + date_set = e_date_edit_get_date (E_DATE_EDIT (priv->due_date), + &end_tt.year, + &end_tt.month, + &end_tt.day); + if (!date_set) + return; + + /* For DATE-TIME events, we have to convert to the same + timezone before comparing. */ + e_date_edit_get_time_of_day (E_DATE_EDIT (priv->start_date), + &start_tt.hour, + &start_tt.minute); + e_date_edit_get_time_of_day (E_DATE_EDIT (priv->due_date), + &end_tt.hour, + &end_tt.minute); + + zone = e_timezone_entry_get_timezone (E_TIMEZONE_ENTRY (priv->timezone)); + adjust_by_hour = e_date_edit_have_time (E_DATE_EDIT (priv->due_date)) && + e_date_edit_have_time (E_DATE_EDIT (priv->start_date)); + + if (check_start_before_end (&start_tt, zone, + &end_tt, zone, + adjust_end_time, + adjust_by_hour)) { + if (adjust_end_time) + set_end_date = TRUE; + else + set_start_date = TRUE; + } + + + if (set_start_date) { + g_signal_handlers_block_matched (priv->start_date, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, tpage); + e_date_edit_set_date (E_DATE_EDIT (priv->start_date), start_tt.year, start_tt.month, start_tt.day); + if (adjust_by_hour) + e_date_edit_set_time_of_day (E_DATE_EDIT (priv->start_date), start_tt.hour, start_tt.minute); + g_signal_handlers_unblock_matched (priv->start_date, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, tpage); + } + + if (set_end_date) { + g_signal_handlers_block_matched (priv->due_date, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, tpage); + e_date_edit_set_date (E_DATE_EDIT (priv->due_date), end_tt.year, end_tt.month, end_tt.day); + if (adjust_by_hour) + e_date_edit_set_time_of_day (E_DATE_EDIT (priv->due_date), end_tt.hour, end_tt.minute); + g_signal_handlers_unblock_matched (priv->due_date, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, tpage); + } + + /* Notify upstream */ + date_changed_cb ((EDateEdit *) priv->start_date, tpage); + date_changed_cb ((EDateEdit *) priv->due_date, tpage); +} + +static void +start_date_changed_cb (GtkWidget *widget, gpointer data) +{ + TaskPage *tpage; + + tpage = TASK_PAGE (data); + + if (!tpage->priv->updating) { + field_changed_cb (widget, data); + times_updated (tpage, TRUE); + } +} + +static void +due_date_changed_cb (GtkWidget *widget, gpointer data) +{ + TaskPage *tpage; + + tpage = TASK_PAGE (data); + + if (!tpage->priv->updating) { + field_changed_cb (widget, data); + times_updated (tpage, FALSE); + } +} + static void source_changed_cb (ESourceComboBox *source_combo_box, TaskPage *tpage) { @@ -1861,9 +2011,9 @@ init_widgets (TaskPage *tpage) g_signal_connect((priv->summary), "changed", G_CALLBACK (field_changed_cb), tpage); g_signal_connect (priv->start_date, "changed", - G_CALLBACK (field_changed_cb), tpage); + G_CALLBACK (start_date_changed_cb), tpage); g_signal_connect (priv->due_date, "changed", - G_CALLBACK (field_changed_cb), tpage); + G_CALLBACK (due_date_changed_cb), tpage); g_signal_connect((priv->timezone), "changed", G_CALLBACK (field_changed_cb), tpage); g_signal_connect((priv->categories), "changed", diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog index 9b7eb344a5..c25fcfc9b4 100644 --- a/widgets/misc/ChangeLog +++ b/widgets/misc/ChangeLog @@ -1,3 +1,11 @@ +2007-11-05 Milan Crha + + ** Part of fix for bug #351932 + + * e-dateedit.h: (e_date_edit_have_time): + * e-dateedit.c: (e_date_edit_have_time): Extend API to be able + to check if time is set independently of date part. + 2007-10-29 Kjartan Maraas * e-activity-handler.c: (e_activity_handler_new): diff --git a/widgets/misc/e-dateedit.c b/widgets/misc/e-dateedit.c index d1598074e7..c5399d8637 100644 --- a/widgets/misc/e-dateedit.c +++ b/widgets/misc/e-dateedit.c @@ -1953,6 +1953,20 @@ e_date_edit_time_is_valid (EDateEdit *dedit) return TRUE; } +/** + * e_date_edit_have_time + * Check if time is set, i.e. it isn't 'None'/empty. Date can be set in this case. + * + * @param dedit an EDateEdit widget. + * @return TRUE is time is set, FALSE otherwise. + **/ +gboolean +e_date_edit_have_time (EDateEdit *dedit) +{ + g_return_val_if_fail (dedit != NULL, FALSE); + + return !dedit->priv->date_set_to_none && !dedit->priv->time_set_to_none; +} static gboolean e_date_edit_set_date_internal (EDateEdit *dedit, diff --git a/widgets/misc/e-dateedit.h b/widgets/misc/e-dateedit.h index ffc6d87ac1..1e9aa4142c 100644 --- a/widgets/misc/e-dateedit.h +++ b/widgets/misc/e-dateedit.h @@ -86,6 +86,9 @@ void e_date_edit_set_editable (EDateEdit *dedit, gboolean gboolean e_date_edit_date_is_valid (EDateEdit *dedit); gboolean e_date_edit_time_is_valid (EDateEdit *dedit); +/* Returns TRUE if time was set, FALSE otherwise. */ +gboolean e_date_edit_have_time (EDateEdit *dedit); + /* Returns the last valid date & time set, or -1 if the date & time was set to 'None' and this is permitted via e_date_edit_set_allow_no_date_set. */ time_t e_date_edit_get_time (EDateEdit *dedit); -- cgit