From 6ec3b5ae147cdf552c323ea66a0f22b753c6970f Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Sat, 18 Aug 2012 09:50:17 -0400 Subject: Add cal_shell_content_check_state(). --- modules/calendar/e-cal-shell-content.c | 214 +++++++++++++++++++++++++++++++ modules/calendar/e-cal-shell-content.h | 15 +-- modules/calendar/e-cal-shell-view.c | 222 ++++++++++----------------------- 3 files changed, 289 insertions(+), 162 deletions(-) (limited to 'modules/calendar') diff --git a/modules/calendar/e-cal-shell-content.c b/modules/calendar/e-cal-shell-content.c index b77bbfe397..5d8e7e6b8f 100644 --- a/modules/calendar/e-cal-shell-content.c +++ b/modules/calendar/e-cal-shell-content.c @@ -558,6 +558,219 @@ cal_shell_content_map (GtkWidget *widget) GTK_WIDGET_CLASS (e_cal_shell_content_parent_class)->map (widget); } +/* Helper for cal_shell_content_check_state() */ +static icalproperty * +cal_shell_content_get_attendee_prop (icalcomponent *icalcomp, + const gchar *address) +{ + icalproperty *prop; + + if (address == NULL || *address == '\0') + return NULL; + + prop = icalcomponent_get_first_property ( + icalcomp, ICAL_ATTENDEE_PROPERTY); + + while (prop != NULL) { + const gchar *attendee; + + attendee = icalproperty_get_attendee (prop); + + if (g_str_equal (itip_strip_mailto (attendee), address)) + return prop; + + prop = icalcomponent_get_next_property ( + icalcomp, ICAL_ATTENDEE_PROPERTY); + } + + return NULL; +} + +/* Helper for cal_shell_content_check_state() */ +static gboolean +cal_shell_content_icalcomp_is_delegated (icalcomponent *icalcomp, + const gchar *user_email) +{ + icalproperty *prop; + icalparameter *param; + const gchar *delto = NULL; + gboolean is_delegated = FALSE; + + prop = cal_shell_content_get_attendee_prop (icalcomp, user_email); + + if (prop != NULL) { + param = icalproperty_get_first_parameter ( + prop, ICAL_DELEGATEDTO_PARAMETER); + if (param != NULL) { + delto = icalparameter_get_delegatedto (param); + delto = itip_strip_mailto (delto); + } + } else + return FALSE; + + prop = cal_shell_content_get_attendee_prop (icalcomp, delto); + + if (prop != NULL) { + const gchar *delfrom = NULL; + icalparameter_partstat status = ICAL_PARTSTAT_NONE; + + param = icalproperty_get_first_parameter ( + prop, ICAL_DELEGATEDFROM_PARAMETER); + if (param != NULL) { + delfrom = icalparameter_get_delegatedfrom (param); + delfrom = itip_strip_mailto (delfrom); + } + param = icalproperty_get_first_parameter ( + prop, ICAL_PARTSTAT_PARAMETER); + if (param != NULL) + status = icalparameter_get_partstat (param); + is_delegated = + (status != ICAL_PARTSTAT_DECLINED) && + (g_strcmp0 (delfrom, user_email) == 0); + } + + return is_delegated; +} + +static guint32 +cal_shell_content_check_state (EShellContent *shell_content) +{ + EShell *shell; + EShellView *shell_view; + EShellBackend *shell_backend; + ESourceRegistry *registry; + ECalShellContent *cal_shell_content; + GnomeCalendar *calendar; + ECalendarView *calendar_view; + GnomeCalendarViewType view_type; + gboolean selection_is_editable = FALSE; + gboolean selection_is_instance = FALSE; + gboolean selection_is_meeting = FALSE; + gboolean selection_is_organizer = FALSE; + gboolean selection_is_recurring = FALSE; + gboolean selection_can_delegate = FALSE; + guint32 state = 0; + GList *selected; + GList *link; + guint n_selected; + + cal_shell_content = E_CAL_SHELL_CONTENT (shell_content); + + shell_view = e_shell_content_get_shell_view (shell_content); + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell = e_shell_backend_get_shell (shell_backend); + registry = e_shell_get_registry (shell); + + calendar = e_cal_shell_content_get_calendar (cal_shell_content); + view_type = gnome_calendar_get_view (calendar); + calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); + + selected = e_calendar_view_get_selected_events (calendar_view); + n_selected = g_list_length (selected); + + /* If we have a selection, assume it's + * editable until we learn otherwise. */ + if (n_selected > 0) + selection_is_editable = TRUE; + + for (link = selected; link != NULL; link = g_list_next (link)) { + ECalendarViewEvent *event = link->data; + ECalClient *client; + ECalComponent *comp; + gchar *user_email; + icalcomponent *icalcomp; + const gchar *capability; + gboolean cap_delegate_supported; + gboolean cap_delegate_to_many; + gboolean icalcomp_is_delegated; + gboolean read_only; + + if (!is_comp_data_valid (event)) + continue; + + client = event->comp_data->client; + icalcomp = event->comp_data->icalcomp; + + read_only = e_client_is_readonly (E_CLIENT (client)); + selection_is_editable &= !read_only; + + selection_is_instance |= + e_cal_util_component_is_instance (icalcomp); + + selection_is_meeting = + (n_selected == 1) && + e_cal_util_component_has_attendee (icalcomp); + + selection_is_recurring |= + e_cal_util_component_is_instance (icalcomp) || + e_cal_util_component_has_recurrences (icalcomp); + + /* XXX The rest of this is rather expensive and + * only applies if a single event is selected, + * so continue with the loop iteration if the + * rest of this is not applicable. */ + if (n_selected > 1) + continue; + + /* XXX This probably belongs in comp-util.c. */ + + comp = e_cal_component_new (); + e_cal_component_set_icalcomponent ( + comp, icalcomponent_new_clone (icalcomp)); + user_email = itip_get_comp_attendee ( + registry, comp, client); + + selection_is_organizer = + e_cal_util_component_has_organizer (icalcomp) && + itip_organizer_is_user (registry, comp, client); + + capability = CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED; + cap_delegate_supported = + e_client_check_capability ( + E_CLIENT (client), capability); + + capability = CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY; + cap_delegate_to_many = + e_client_check_capability ( + E_CLIENT (client), capability); + + icalcomp_is_delegated = + (user_email != NULL) && + cal_shell_content_icalcomp_is_delegated ( + icalcomp, user_email); + + selection_can_delegate = + cap_delegate_supported && + (cap_delegate_to_many || + (!selection_is_organizer && + !icalcomp_is_delegated)); + + g_free (user_email); + g_object_unref (comp); + } + + g_list_free (selected); + + if (n_selected == 1) + state |= E_CAL_SHELL_CONTENT_SELECTION_SINGLE; + if (n_selected > 1) + state |= E_CAL_SHELL_CONTENT_SELECTION_MULTIPLE; + if (selection_is_editable) + state |= E_CAL_SHELL_CONTENT_SELECTION_IS_EDITABLE; + if (selection_is_instance) + state |= E_CAL_SHELL_CONTENT_SELECTION_IS_INSTANCE; + if (selection_is_meeting) + state |= E_CAL_SHELL_CONTENT_SELECTION_IS_MEETING; + if (selection_is_organizer) + state |= E_CAL_SHELL_CONTENT_SELECTION_IS_ORGANIZER; + if (selection_is_recurring) + state |= E_CAL_SHELL_CONTENT_SELECTION_IS_RECURRING; + if (selection_can_delegate) + state |= E_CAL_SHELL_CONTENT_SELECTION_CAN_DELEGATE; + + return state; +} + static void cal_shell_content_focus_search_results (EShellContent *shell_content) { @@ -593,6 +806,7 @@ e_cal_shell_content_class_init (ECalShellContentClass *class) widget_class->map = cal_shell_content_map; shell_content_class = E_SHELL_CONTENT_CLASS (class); + shell_content_class->check_state = cal_shell_content_check_state; shell_content_class->focus_search_results = cal_shell_content_focus_search_results; g_object_class_install_property ( diff --git a/modules/calendar/e-cal-shell-content.h b/modules/calendar/e-cal-shell-content.h index 906fe80bc0..21e971b159 100644 --- a/modules/calendar/e-cal-shell-content.h +++ b/modules/calendar/e-cal-shell-content.h @@ -59,15 +59,12 @@ typedef struct _ECalShellContentPrivate ECalShellContentPrivate; enum { E_CAL_SHELL_CONTENT_SELECTION_SINGLE = 1 << 0, E_CAL_SHELL_CONTENT_SELECTION_MULTIPLE = 1 << 1, - E_CAL_SHELL_CONTENT_SELECTION_IS_ASSIGNABLE = 1 << 2, - E_CAL_SHELL_CONTENT_SELECTION_IS_COMPLETE = 1 << 3, - E_CAL_SHELL_CONTENT_SELECTION_IS_EDITABLE = 1 << 4, - E_CAL_SHELL_CONTENT_SELECTION_IS_MEETING = 1 << 5, - E_CAL_SHELL_CONTENT_SELECTION_IS_ORGANIZER = 1 << 6, - E_CAL_SHELL_CONTENT_SELECTION_IS_RECURRING = 1 << 7, - E_CAL_SHELL_CONTENT_SELECTION_CAN_ACCEPT = 1 << 8, - E_CAL_SHELL_CONTENT_SELECTION_CAN_DELEGATE = 1 << 9, - E_CAL_SHELL_CONTENT_SELECTION_CAN_SAVE = 1 << 10 + E_CAL_SHELL_CONTENT_SELECTION_IS_EDITABLE = 1 << 2, + E_CAL_SHELL_CONTENT_SELECTION_IS_INSTANCE = 1 << 3, + E_CAL_SHELL_CONTENT_SELECTION_IS_MEETING = 1 << 4, + E_CAL_SHELL_CONTENT_SELECTION_IS_ORGANIZER = 1 << 5, + E_CAL_SHELL_CONTENT_SELECTION_IS_RECURRING = 1 << 6, + E_CAL_SHELL_CONTENT_SELECTION_CAN_DELEGATE = 1 << 7 }; struct _ECalShellContent { diff --git a/modules/calendar/e-cal-shell-view.c b/modules/calendar/e-cal-shell-view.c index 7b90948f91..ef8b6c5e60 100644 --- a/modules/calendar/e-cal-shell-view.c +++ b/modules/calendar/e-cal-shell-view.c @@ -302,108 +302,41 @@ cal_shell_view_execute_search (EShellView *shell_view) e_shell_view_update_actions (shell_view); } -static icalproperty * -get_attendee_prop (icalcomponent *icalcomp, - const gchar *address) -{ - - icalproperty *prop; - - if (!(address && *address)) - return NULL; - - prop = icalcomponent_get_first_property ( - icalcomp, ICAL_ATTENDEE_PROPERTY); - - while (prop != NULL) { - const gchar *attendee = icalproperty_get_attendee (prop); - - if (g_str_equal (itip_strip_mailto (attendee), address)) - return prop; - - prop = icalcomponent_get_next_property ( - icalcomp, ICAL_ATTENDEE_PROPERTY); - } - - return NULL; -} - -static gboolean -is_delegated (icalcomponent *icalcomp, - const gchar *user_email) -{ - icalproperty *prop; - icalparameter *param; - const gchar *delto = NULL; - - prop = get_attendee_prop (icalcomp, user_email); - - if (prop != NULL) { - param = icalproperty_get_first_parameter ( - prop, ICAL_DELEGATEDTO_PARAMETER); - if (param != NULL) - delto = icalparameter_get_delegatedto (param); - } else - return FALSE; - - prop = get_attendee_prop (icalcomp, itip_strip_mailto (delto)); - - if (prop != NULL) { - const gchar *delfrom = NULL; - icalparameter_partstat status = ICAL_PARTSTAT_NONE; - - param = icalproperty_get_first_parameter ( - prop, ICAL_DELEGATEDFROM_PARAMETER); - if (param != NULL) - delfrom = icalparameter_get_delegatedfrom (param); - param = icalproperty_get_first_parameter ( - prop, ICAL_PARTSTAT_PARAMETER); - if (param != NULL) - status = icalparameter_get_partstat (param); - if ((delfrom != NULL && *delfrom != '\0') && - g_str_equal (itip_strip_mailto (delfrom), - user_email) && status != ICAL_PARTSTAT_DECLINED) - return TRUE; - } - - return FALSE; -} - static void cal_shell_view_update_actions (EShellView *shell_view) { ECalShellViewPrivate *priv; ECalShellContent *cal_shell_content; + EShellContent *shell_content; EShellSidebar *shell_sidebar; EShellWindow *shell_window; EShell *shell; ESource *source; ESourceRegistry *registry; - GnomeCalendarViewType view_type; GnomeCalendar *calendar; ECalModel *model; - ECalendarView *view; GtkAction *action; - GList *list, *iter; const gchar *model_sexp; gboolean is_searching; gboolean sensitive; guint32 state; - gint n_selected; /* Be descriptive. */ - gboolean editable = TRUE; - gboolean has_mail_identity; + gboolean any_events_selected; + gboolean has_mail_identity = FALSE; gboolean has_primary_source; gboolean primary_source_is_writable; gboolean primary_source_is_removable; gboolean primary_source_is_remote_deletable; gboolean primary_source_in_collection; - gboolean recurring = FALSE; - gboolean is_instance = FALSE; - gboolean is_meeting = FALSE; - gboolean is_delegatable = FALSE; - gboolean refresh_supported = FALSE; + gboolean multiple_events_selected; + gboolean selection_is_editable; + gboolean selection_is_instance; + gboolean selection_is_meeting; + gboolean selection_is_recurring; + gboolean selection_can_delegate; + gboolean single_event_selected; + gboolean refresh_supported; /* Chain up to parent's update_actions() method. */ E_SHELL_VIEW_CLASS (parent_class)->update_actions (shell_view); @@ -431,80 +364,37 @@ cal_shell_view_update_actions (EShellView *shell_view) registry = e_shell_get_registry (shell); source = e_source_registry_ref_default_mail_identity (registry); + has_mail_identity = (source != NULL); if (source != NULL) { has_mail_identity = TRUE; g_object_unref (source); - } else { - has_mail_identity = FALSE; } cal_shell_content = priv->cal_shell_content; calendar = e_cal_shell_content_get_calendar (cal_shell_content); - view_type = gnome_calendar_get_view (calendar); - view = gnome_calendar_get_calendar_view (calendar, view_type); model = gnome_calendar_get_model (calendar); model_sexp = e_cal_model_get_search_query (model); is_searching = model_sexp && *model_sexp && g_strcmp0 (model_sexp, "#t") != 0 && g_strcmp0 (model_sexp, "(contains? \"summary\" \"\")") != 0; - list = e_calendar_view_get_selected_events (view); - n_selected = g_list_length (list); - - for (iter = list; iter != NULL; iter = iter->next) { - ECalendarViewEvent *event = iter->data; - ECalClient *client; - ECalComponent *comp; - icalcomponent *icalcomp; - gchar *user_email = NULL; - gboolean user_org = FALSE; - gboolean read_only = TRUE; - - if (!is_comp_data_valid (event)) - continue; - - client = event->comp_data->client; - icalcomp = event->comp_data->icalcomp; - - read_only = e_client_is_readonly (E_CLIENT (client)); - editable = editable && !read_only; - - is_instance |= e_cal_util_component_is_instance (icalcomp); - - recurring |= - e_cal_util_component_is_instance (icalcomp) || - e_cal_util_component_has_recurrences (icalcomp); - - /* The following tests only apply if one event is selected. */ - if (iter != list || n_selected > 1) - continue; - - comp = e_cal_component_new (); - e_cal_component_set_icalcomponent ( - comp, icalcomponent_new_clone (icalcomp)); - user_email = itip_get_comp_attendee ( - registry, comp, client); - - is_meeting = e_cal_util_component_has_attendee (icalcomp); - - user_org = - e_cal_util_component_has_organizer (icalcomp) && - itip_organizer_is_user (registry, comp, client); - - is_delegatable = - e_client_check_capability ( - E_CLIENT (client), - CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED) && - (e_client_check_capability ( - E_CLIENT (client), - CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY) || - (!user_org && !is_delegated (icalcomp, user_email))); - - g_free (user_email); - g_object_unref (comp); - } - - g_list_free (list); + shell_content = e_shell_view_get_shell_content (shell_view); + state = e_shell_content_check_state (shell_content); + + single_event_selected = + (state & E_CAL_SHELL_CONTENT_SELECTION_SINGLE); + multiple_events_selected = + (state & E_CAL_SHELL_CONTENT_SELECTION_MULTIPLE); + selection_is_editable = + (state & E_CAL_SHELL_CONTENT_SELECTION_IS_EDITABLE); + selection_is_instance = + (state & E_CAL_SHELL_CONTENT_SELECTION_IS_INSTANCE); + selection_is_meeting = + (state & E_CAL_SHELL_CONTENT_SELECTION_IS_MEETING); + selection_is_recurring = + (state & E_CAL_SHELL_CONTENT_SELECTION_IS_RECURRING); + selection_can_delegate = + (state & E_CAL_SHELL_CONTENT_SELECTION_CAN_DELEGATE); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); state = e_shell_sidebar_check_state (shell_sidebar); @@ -522,6 +412,9 @@ cal_shell_view_update_actions (EShellView *shell_view) refresh_supported = (state & E_CAL_SHELL_SIDEBAR_SOURCE_SUPPORTS_REFRESH); + any_events_selected = + (single_event_selected || multiple_events_selected); + action = ACTION (CALENDAR_COPY); sensitive = has_primary_source; gtk_action_set_sensitive (action, sensitive); @@ -558,54 +451,77 @@ cal_shell_view_update_actions (EShellView *shell_view) action = ACTION (EVENT_DELEGATE); sensitive = - (n_selected == 1) && editable && - is_delegatable && is_meeting; + single_event_selected && + selection_is_editable && + selection_can_delegate && + selection_is_meeting; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_DELETE); - sensitive = (n_selected > 0) && editable && !recurring; + sensitive = + any_events_selected && + selection_is_editable && + !selection_is_recurring; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_DELETE_OCCURRENCE); - sensitive = (n_selected > 0) && editable && recurring; + sensitive = + any_events_selected && + selection_is_editable && + selection_is_recurring; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_DELETE_OCCURRENCE_ALL); - sensitive = (n_selected > 0) && editable && recurring; + sensitive = + any_events_selected && + selection_is_editable && + selection_is_recurring; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_FORWARD); - sensitive = (n_selected == 1); + sensitive = single_event_selected; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_OCCURRENCE_MOVABLE); sensitive = - (n_selected == 1) && editable && - recurring && is_instance; + single_event_selected && + selection_is_editable && + selection_is_recurring && + selection_is_instance; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_OPEN); - sensitive = (n_selected == 1); + sensitive = single_event_selected; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_PRINT); - sensitive = (n_selected == 1); + sensitive = single_event_selected; + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (EVENT_SAVE_AS); + sensitive = single_event_selected; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_SCHEDULE); - sensitive = (n_selected == 1) && editable && !is_meeting; + sensitive = + single_event_selected && + selection_is_editable && + !selection_is_meeting; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_SCHEDULE_APPOINTMENT); - sensitive = (n_selected == 1) && editable && is_meeting; + sensitive = + single_event_selected && + selection_is_editable && + selection_is_meeting; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_REPLY); - sensitive = (n_selected == 1) && is_meeting; + sensitive = single_event_selected && selection_is_meeting; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_REPLY_ALL); - sensitive = (n_selected == 1) && is_meeting; + sensitive = single_event_selected && selection_is_meeting; gtk_action_set_sensitive (action, sensitive); action = ACTION (EVENT_MEETING_NEW); -- cgit v1.2.3