From 54634a1357884543f64d00aa135bf8bc9a525880 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Sat, 27 Oct 2001 22:13:20 +0000 Subject: Delete appointments with empty summaries. Fixes Ximian bug #780. 2001-10-27 Federico Mena Quintero * gui/e-day-view.c (e_day_view_on_editing_stopped): Delete appointments with empty summaries. Fixes Ximian bug #780. * gui/e-week-view.c (e_week_view_on_editing_stopped): Likewise. * gui/dialogs/delete-comp.c (delete_component_dialog): Added an argument to specify whether we unconditionally want single components to be considered as not having a summary. * gui/comp-util.c (cal_comp_confirm_delete_empty_comp): New function. * gui/misc.[ch]: New files with miscellaneous utility functions; moved string_is_empty() over from calendar-model.c. * gui/calendar-model.c: Use the string_is_empty() function from misc.c. * gui/Makefile.am (evolution_calendar_SOURCES): Added misc.[ch] to the list of sources. svn path=/trunk/; revision=14233 --- calendar/gui/Makefile.am | 2 ++ calendar/gui/comp-util.c | 72 ++++++++++++++++++++++++++++++++++++++ calendar/gui/comp-util.h | 11 ++++++ calendar/gui/dialogs/comp-editor.c | 2 +- calendar/gui/dialogs/delete-comp.c | 11 ++++-- calendar/gui/dialogs/delete-comp.h | 1 + calendar/gui/e-calendar-table.c | 3 +- calendar/gui/e-day-view.c | 48 +++++++++++++++++++++++-- calendar/gui/e-week-view.c | 58 +++++++++++++++++++++++++----- calendar/gui/misc.c | 60 +++++++++++++++++++++++++++++++ calendar/gui/misc.h | 29 +++++++++++++++ 11 files changed, 283 insertions(+), 14 deletions(-) create mode 100644 calendar/gui/misc.c create mode 100644 calendar/gui/misc.h (limited to 'calendar/gui') diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am index 1a155efcd7..7a22f6abc7 100644 --- a/calendar/gui/Makefile.am +++ b/calendar/gui/Makefile.am @@ -142,6 +142,8 @@ evolution_calendar_SOURCES = \ itip-utils.c \ itip-utils.h \ main.c \ + misc.c \ + misc.h \ print.c \ print.h \ tag-calendar.c \ diff --git a/calendar/gui/comp-util.c b/calendar/gui/comp-util.c index 808d9be910..71efec2573 100644 --- a/calendar/gui/comp-util.c +++ b/calendar/gui/comp-util.c @@ -24,6 +24,7 @@ #endif #include "comp-util.h" +#include "dialogs/delete-comp.h" @@ -159,3 +160,74 @@ cal_comp_util_compare_event_timezones (CalComponent *comp, return retval; } + +/** + * cal_comp_confirm_delete_empty_comp: + * @comp: A calendar component. + * @client: Calendar client where the component purportedly lives. + * @widget: Widget to be used as the basis for UTF8 conversion. + * + * Assumming a calendar component with an empty SUMMARY property (as per + * string_is_empty()), asks whether the user wants to delete it based on + * whether the appointment is on the calendar server or not. If the + * component is on the server, this function will present a confirmation + * dialog and delete the component if the user tells it to. If the component + * is not on the server it will just return TRUE. + * + * Return value: A result code indicating whether the component + * was not on the server and is to be deleted locally, whether it + * was on the server and the user deleted it, or whether the + * user cancelled the deletion. + **/ +ConfirmDeleteEmptyCompResult +cal_comp_confirm_delete_empty_comp (CalComponent *comp, CalClient *client, GtkWidget *widget) +{ + const char *uid; + CalClientGetStatus status; + CalComponent *server_comp; + + g_return_val_if_fail (comp != NULL, EMPTY_COMP_DO_NOT_REMOVE); + g_return_val_if_fail (IS_CAL_COMPONENT (comp), EMPTY_COMP_DO_NOT_REMOVE); + g_return_val_if_fail (client != NULL, EMPTY_COMP_DO_NOT_REMOVE); + g_return_val_if_fail (IS_CAL_CLIENT (client), EMPTY_COMP_DO_NOT_REMOVE); + g_return_val_if_fail (widget != NULL, EMPTY_COMP_DO_NOT_REMOVE); + g_return_val_if_fail (GTK_IS_WIDGET (widget), EMPTY_COMP_DO_NOT_REMOVE); + + /* See if the component is on the server. If it is not, then it likely + * means that the appointment is new, only in the day view, and we + * haven't added it yet to the server. In that case, we don't need to + * confirm and we can just delete the event. Otherwise, we ask + * the user. + */ + cal_component_get_uid (comp, &uid); + + status = cal_client_get_object (client, uid, &server_comp); + + switch (status) { + case CAL_CLIENT_GET_SUCCESS: + gtk_object_unref (GTK_OBJECT (server_comp)); + /* Will handle confirmation below */ + break; + + case CAL_CLIENT_GET_SYNTAX_ERROR: + g_message ("confirm_delete_empty_appointment(): Syntax error when getting " + "object `%s'", + uid); + /* However, the object *is* in the server, so confirm */ + break; + + case CAL_CLIENT_GET_NOT_FOUND: + return EMPTY_COMP_REMOVE_LOCALLY; + + default: + g_assert_not_reached (); + } + + /* The event exists in the server, so confirm whether to delete it */ + + if (delete_component_dialog (comp, TRUE, 1, CAL_COMPONENT_EVENT, widget)) { + cal_client_remove_object (client, uid); + return EMPTY_COMP_REMOVED_FROM_SERVER; + } else + return EMPTY_COMP_DO_NOT_REMOVE; +} diff --git a/calendar/gui/comp-util.h b/calendar/gui/comp-util.h index 6ea71853fa..b8c3ea453d 100644 --- a/calendar/gui/comp-util.h +++ b/calendar/gui/comp-util.h @@ -22,6 +22,7 @@ #ifndef COMP_UTIL_H #define COMP_UTIL_H +#include #include #include @@ -35,4 +36,14 @@ gboolean cal_comp_util_compare_event_timezones (CalComponent *comp, CalClient *client, icaltimezone *zone); +typedef enum { + EMPTY_COMP_REMOVE_LOCALLY, + EMPTY_COMP_REMOVED_FROM_SERVER, + EMPTY_COMP_DO_NOT_REMOVE +} ConfirmDeleteEmptyCompResult; + +ConfirmDeleteEmptyCompResult cal_comp_confirm_delete_empty_comp (CalComponent *comp, + CalClient *client, + GtkWidget *widget); + #endif diff --git a/calendar/gui/dialogs/comp-editor.c b/calendar/gui/dialogs/comp-editor.c index 8d16df97f9..dc7d01cbde 100644 --- a/calendar/gui/dialogs/comp-editor.c +++ b/calendar/gui/dialogs/comp-editor.c @@ -1121,7 +1121,7 @@ delete_cmd (GtkWidget *widget, gpointer data) vtype = cal_component_get_vtype (priv->comp); - if (delete_component_dialog (priv->comp, 1, vtype, priv->window)) + if (delete_component_dialog (priv->comp, FALSE, 1, vtype, priv->window)) delete_comp (editor); } diff --git a/calendar/gui/dialogs/delete-comp.c b/calendar/gui/dialogs/delete-comp.c index 2dcfc5c47a..1fc757c38c 100644 --- a/calendar/gui/dialogs/delete-comp.c +++ b/calendar/gui/dialogs/delete-comp.c @@ -38,6 +38,9 @@ * delete_component_dialog: * @comp: A calendar component if a single component is to be deleted, or NULL * if more that one component is to be deleted. + * @consider_as_untitled: If deleting more than one component, this is ignored. + * Otherwise, whether to consider the component as not having a summary; if + * FALSE then the component's summary string will be used. * @n_comps: Number of components that are to be deleted. * @vtype: Type of the components that are to be deleted. This is ignored * if only one component is to be deleted, and the vtype is extracted from @@ -55,6 +58,7 @@ **/ gboolean delete_component_dialog (CalComponent *comp, + gboolean consider_as_untitled, int n_comps, CalComponentVType vtype, GtkWidget *widget) { @@ -80,9 +84,12 @@ delete_component_dialog (CalComponent *comp, char *tmp; vtype = cal_component_get_vtype (comp); - cal_component_get_summary (comp, &summary); - tmp = e_utf8_to_gtk_string (widget, summary.value); + if (!consider_as_untitled) { + cal_component_get_summary (comp, &summary); + tmp = e_utf8_to_gtk_string (widget, summary.value); + } else + tmp = NULL; switch (vtype) { case CAL_COMPONENT_EVENT: diff --git a/calendar/gui/dialogs/delete-comp.h b/calendar/gui/dialogs/delete-comp.h index 3c352a9bc8..64945b5bee 100644 --- a/calendar/gui/dialogs/delete-comp.h +++ b/calendar/gui/dialogs/delete-comp.h @@ -25,6 +25,7 @@ #include gboolean delete_component_dialog (CalComponent *comp, + gboolean consider_as_untitled, int n_comps, CalComponentVType vtype, GtkWidget *widget); diff --git a/calendar/gui/e-calendar-table.c b/calendar/gui/e-calendar-table.c index 7481848d9e..3dd04df9c2 100644 --- a/calendar/gui/e-calendar-table.c +++ b/calendar/gui/e-calendar-table.c @@ -764,7 +764,8 @@ e_calendar_table_delete_selected (ECalendarTable *cal_table) /* FIXME: this may be something other than a TODO component */ - if (delete_component_dialog (comp, n_selected, CAL_COMPONENT_TODO, GTK_WIDGET (cal_table))) + if (delete_component_dialog (comp, FALSE, n_selected, CAL_COMPONENT_TODO, + GTK_WIDGET (cal_table))) delete_selected_components (cal_table); } diff --git a/calendar/gui/e-day-view.c b/calendar/gui/e-day-view.c index 51e78b279f..38ae21668f 100644 --- a/calendar/gui/e-day-view.c +++ b/calendar/gui/e-day-view.c @@ -57,6 +57,7 @@ #include "e-day-view-top-item.h" #include "e-day-view-layout.h" #include "e-day-view-main-item.h" +#include "misc.h" /* Images */ #include "art/bell.xpm" @@ -3654,7 +3655,7 @@ e_day_view_delete_event_internal (EDayView *day_view, EDayViewEvent *event) vtype = cal_component_get_vtype (event->comp); - if (delete_component_dialog (event->comp, 1, vtype, + if (delete_component_dialog (event->comp, FALSE, 1, vtype, GTK_WIDGET (day_view))) { const char *uid; @@ -5607,7 +5608,6 @@ e_day_view_on_editing_started (EDayView *day_view, e_day_view_signals[SELECTION_CHANGED]); } - static void e_day_view_on_editing_stopped (EDayView *day_view, GnomeCanvasItem *item) @@ -5658,6 +5658,48 @@ e_day_view_on_editing_stopped (EDayView *day_view, NULL); g_assert (text != NULL); + if (string_is_empty (text)) { + ConfirmDeleteEmptyCompResult result; + + result = cal_comp_confirm_delete_empty_comp (event->comp, day_view->client, + GTK_WIDGET (day_view)); + + switch (result) { + case EMPTY_COMP_REMOVE_LOCALLY: { + const char *uid; + + cal_component_get_uid (event->comp, &uid); + + e_day_view_foreach_event_with_uid (day_view, uid, + e_day_view_remove_event_cb, NULL); + e_day_view_check_layout (day_view); + gtk_widget_queue_draw (day_view->top_canvas); + gtk_widget_queue_draw (day_view->main_canvas); + goto out; } + + case EMPTY_COMP_REMOVED_FROM_SERVER: + goto out; + + case EMPTY_COMP_DO_NOT_REMOVE: + /* But we cannot keep an empty summary, so make the + * canvas item refresh itself from the text that the + * component already had. + */ + + if (day == E_DAY_VIEW_LONG_EVENT) + e_day_view_reshape_long_event (day_view, event_num); + else + e_day_view_update_event_label (day_view, day, event_num); + + goto out; + + default: + g_assert_not_reached (); + } + + g_assert_not_reached (); + } + /* Only update the summary if necessary. */ cal_component_get_summary (event->comp, &summary); if (summary.value && !strcmp (text, summary.value)) { @@ -5675,6 +5717,8 @@ e_day_view_on_editing_stopped (EDayView *day_view, g_message ("e_day_view_on_editing_stopped(): Could not update the object!"); } + out: + g_free (text); gtk_signal_emit (GTK_OBJECT (day_view), diff --git a/calendar/gui/e-week-view.c b/calendar/gui/e-week-view.c index cf50604760..9b2a9fa40a 100644 --- a/calendar/gui/e-week-view.c +++ b/calendar/gui/e-week-view.c @@ -57,6 +57,7 @@ #include "e-week-view-layout.h" #include "e-week-view-main-item.h" #include "e-week-view-titles-item.h" +#include "misc.h" /* Images */ #include "art/bell.xpm" @@ -1254,7 +1255,7 @@ e_week_view_set_cal_client (EWeekView *week_view, * e_week_view_set_query: * @week_view: A week view. * @sexp: S-expression that defines the query. - * + * * Sets the query sexp that the week view will use for filtering the displayed * events. **/ @@ -1278,7 +1279,7 @@ e_week_view_set_query (EWeekView *week_view, const char *sexp) * e_week_view_set_default_category: * @week_view: A week view. * @category: Default category name or NULL for no category. - * + * * Sets the default category that will be used when creating new calendar * components from the week view. **/ @@ -3073,6 +3074,45 @@ e_week_view_on_editing_stopped (EWeekView *week_view, NULL); g_assert (text != NULL); + if (string_is_empty (text)) { + ConfirmDeleteEmptyCompResult result; + + result = cal_comp_confirm_delete_empty_comp (event->comp, week_view->client, + GTK_WIDGET (week_view)); + + switch (result) { + case EMPTY_COMP_REMOVE_LOCALLY: { + const char *uid; + + cal_component_get_uid (event->comp, &uid); + + e_week_view_foreach_event_with_uid (week_view, uid, + e_week_view_remove_event_cb, NULL); + gtk_widget_queue_draw (week_view->main_canvas); + e_week_view_check_layout (week_view); + goto out; } + + case EMPTY_COMP_REMOVED_FROM_SERVER: + goto out; + + case EMPTY_COMP_DO_NOT_REMOVE: + /* But we cannot keep an empty summary, so make the + * canvas item refresh itself from the text that the + * component already had. + */ + + gtk_object_ref (GTK_OBJECT (event->comp)); + e_week_view_update_event_cb (week_view, event_num, event->comp); + gtk_object_unref (GTK_OBJECT (event->comp)); + goto out; + + default: + g_assert_not_reached (); + } + + g_assert_not_reached (); + } + /* Only update the summary if necessary. */ cal_component_get_summary (event->comp, &summary); if (summary.value && !strcmp (text, summary.value)) { @@ -3088,6 +3128,8 @@ e_week_view_on_editing_stopped (EWeekView *week_view, g_message ("e_week_view_on_editing_stopped(): Could not update the object!"); } + out: + g_free (text); gtk_signal_emit (GTK_OBJECT (week_view), @@ -3351,7 +3393,7 @@ static EPopupMenu child_items [] = { e_week_view_on_delete_occurrence, NULL, MASK_RECURRING | MASK_EDITING }, { N_("Delete _All Occurrences"), NULL, e_week_view_on_delete_appointment, NULL, MASK_RECURRING | MASK_EDITING }, - + { NULL, NULL, NULL, NULL, 0 } }; @@ -3375,14 +3417,14 @@ e_week_view_show_popup_menu (EWeekView *week_view, * We could possibly set up another method of checking it. */ being_edited = FALSE; - + if (event_num == -1) { context_menu = main_items; } else { context_menu = child_items; event = &g_array_index (week_view->events, EWeekViewEvent, event_num); - if (cal_component_has_recurrences (event->comp)) + if (cal_component_has_recurrences (event->comp)) hide_mask |= MASK_SINGLE; else hide_mask |= MASK_RECURRING; @@ -3401,7 +3443,7 @@ e_week_view_on_new_appointment (GtkWidget *widget, gpointer data) EWeekView *week_view = E_WEEK_VIEW (data); time_t dtstart, dtend; struct icaltimetype itt; - + /* Edit a new event. If only one day is selected we set the time to the first 1/2-hour of the working day. */ if (week_view->selection_start_day == week_view->selection_end_day) { @@ -3428,7 +3470,7 @@ e_week_view_on_new_event (GtkWidget *widget, gpointer data) { EWeekView *week_view = E_WEEK_VIEW (data); time_t dtstart, dtend; - + dtstart = week_view->day_starts[week_view->selection_start_day]; dtend = week_view->day_starts[week_view->selection_end_day + 1]; gnome_calendar_new_appointment_for ( @@ -3511,7 +3553,7 @@ e_week_view_delete_event_internal (EWeekView *week_view, gint event_num) vtype = cal_component_get_vtype (event->comp); - if (delete_component_dialog (event->comp, 1, vtype, + if (delete_component_dialog (event->comp, FALSE, 1, vtype, GTK_WIDGET (week_view))) { const char *uid; diff --git a/calendar/gui/misc.c b/calendar/gui/misc.c new file mode 100644 index 0000000000..9f9aa77296 --- /dev/null +++ b/calendar/gui/misc.c @@ -0,0 +1,60 @@ +/* Evolution calendar - Miscellaneous utility functions + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "misc.h" + + + +/** + * string_is_empty: + * @value: A string. + * + * Returns whether a string is NULL, the empty string, or completely made up of + * whitespace characters. + * + * Return value: TRUE if the string is empty, FALSE otherwise. + **/ +gboolean +string_is_empty (const char *value) +{ + const char *p; + gboolean empty; + + empty = TRUE; + + if (value) { + p = value; + while (*p) { + if (!isspace ((unsigned char) *p)) { + empty = FALSE; + break; + } + p++; + } + } + return empty; + +} diff --git a/calendar/gui/misc.h b/calendar/gui/misc.h new file mode 100644 index 0000000000..8f4864a174 --- /dev/null +++ b/calendar/gui/misc.h @@ -0,0 +1,29 @@ +/* Evolution calendar - Miscellaneous utility functions + * + * Copyright (C) 2001 Ximian, Inc. + * + * Authors: Federico Mena-Quintero + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef MISC_H +#define MISC_H + +#include + +gboolean string_is_empty (const char *value); + +#endif -- cgit