From f1069c96d6e63f5f3f643080bb92bf29c20de4f6 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Wed, 28 Sep 2016 00:07:28 -0300 Subject: [PATCH] event: implement GInitable Since the event creation can fail, lets make it a GInitable so that we can fail during initialization. https://bugzilla.gnome.org/show_bug.cgi?id=763166 --- src/gcal-event.c | 95 +++++++++++++++++++++++++++++++++--- src/gcal-event.h | 12 ++++- src/gcal-manager.c | 14 +++++- src/gcal-quick-add-popover.c | 2 +- src/gcal-search-view.c | 17 ++++--- src/gcal-subscriber-view.c | 24 ++++++++- src/gcal-window.c | 2 +- src/gcal-year-view.c | 13 ++++- 8 files changed, 155 insertions(+), 24 deletions(-) diff --git a/src/gcal-event.c b/src/gcal-event.c index 408604b7..3f920e3e 100644 --- a/src/gcal-event.c +++ b/src/gcal-event.c @@ -48,9 +48,16 @@ struct _GcalEvent ECalComponent *component; ESource *source; + + gboolean is_valid : 1; + gboolean is_initialized : 1; + GError *initialization_error; }; -G_DEFINE_TYPE (GcalEvent, gcal_event, G_TYPE_OBJECT) +static void gcal_event_initable_iface_init (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (GcalEvent, gcal_event, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gcal_event_initable_iface_init)) enum { PROP_0, @@ -237,6 +244,23 @@ gcal_event_set_component_internal (GcalEvent *self, /* Setup start date */ e_cal_component_get_dtstart (component, &start); + + /* + * A NULL start date is invalid. We set something bogus to procceed, and make + * it set a GError and return NULL. + */ + if (!start.value) + { + self->is_valid = FALSE; + g_set_error (&self->initialization_error, + GCAL_EVENT_ERROR, + GCAL_EVENT_ERROR_INVALID_START_DATE, + "Event '%s' has an invalid start date", gcal_event_get_uid (self)); + + start.value = g_new0 (icaltimetype, 1); + *start.value = icaltime_today (); + } + date = icaltime_normalize (*start.value); zone_start = get_timezone_from_ical (&start); date_start = g_date_time_new (zone_start, @@ -300,6 +324,44 @@ gcal_event_set_component_internal (GcalEvent *self, } } +/* + * GInitable iface implementation + */ + +G_LOCK_DEFINE_STATIC (init_lock); + +static gboolean +gcal_event_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + GcalEvent *self; + + self = GCAL_EVENT (initable); + + G_LOCK (init_lock); + + if (self->is_initialized) + goto out; + + +out: + self->is_initialized = TRUE; + + if (!self->is_valid) + g_propagate_error (error, g_error_copy (self->initialization_error)); + + G_UNLOCK (init_lock); + + return self->is_valid; +} + +static void +gcal_event_initable_iface_init (GInitableIface *iface) +{ + iface->init = gcal_event_initable_init; +} + static void gcal_event_finalize (GObject *object) { @@ -593,27 +655,44 @@ gcal_event_init (GcalEvent *self) /* Alarms */ self->alarms = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + + self->is_valid = TRUE; +} + +/** + * gcal_event_error_quark: + * + * Error quark for event creating. + */ +GQuark +gcal_event_error_quark (void) +{ + return g_quark_from_static_string ("Invalid start date"); } /** * gcal_event_new: * @source: (nullable): an #ESource * @component: a #ECalComponent + * @error: (nullable): return location for a #GError * * Creates a new event which belongs to @source and * is represented by @component. New events will have * a %NULL @source. * - * Returns: (transfer full): a #GcalEvent + * Returns: (transfer full)(nullable): a #GcalEvent */ GcalEvent* -gcal_event_new (ESource *source, - ECalComponent *component) +gcal_event_new (ESource *source, + ECalComponent *component, + GError **error) { - return g_object_new (GCAL_TYPE_EVENT, - "source", source, - "component", component, - NULL); + return g_initable_new (GCAL_TYPE_EVENT, + NULL, + error, + "source", source, + "component", component, + NULL); } /** diff --git a/src/gcal-event.h b/src/gcal-event.h index 16dc19a2..ce21b22d 100644 --- a/src/gcal-event.h +++ b/src/gcal-event.h @@ -26,12 +26,22 @@ G_BEGIN_DECLS +typedef enum +{ + GCAL_EVENT_ERROR_INVALID_START_DATE +} GcalEventError; + +#define GCAL_EVENT_ERROR gcal_event_error_quark () + #define GCAL_TYPE_EVENT (gcal_event_get_type()) G_DECLARE_FINAL_TYPE (GcalEvent, gcal_event, GCAL, EVENT, GObject) +GQuark gcal_event_error_quark (void); + GcalEvent* gcal_event_new (ESource *source, - ECalComponent *component); + ECalComponent *component, + GError **error); gboolean gcal_event_get_all_day (GcalEvent *self); diff --git a/src/gcal-manager.c b/src/gcal-manager.c index 4f966346..fd25f215 100644 --- a/src/gcal-manager.c +++ b/src/gcal-manager.c @@ -274,10 +274,20 @@ gather_events (ECalDataModel *data_model, time_t instance_end, gpointer user_data) { - GList **result = user_data; GcalEvent *event; + GError *error; + GList **result; - event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp); + error = NULL; + result = user_data; + event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp, &error); + + if (error) + { + g_warning ("Error: %s", error->message); + g_clear_error (&error); + return TRUE; + } *result = g_list_append (*result, event);/* FIXME: add me sorted */ diff --git a/src/gcal-quick-add-popover.c b/src/gcal-quick-add-popover.c index e1298769..d3f61e94 100644 --- a/src/gcal-quick-add-popover.c +++ b/src/gcal-quick-add-popover.c @@ -465,7 +465,7 @@ edit_or_create_event (GcalQuickAddPopover *self, /* Create an ECalComponent from the data above */ component = build_component_from_details (summary, date_start, date_end); - event = gcal_event_new (source, component); + event = gcal_event_new (source, component, NULL); gcal_event_set_all_day (event, all_day); gcal_event_set_timezone (event, tz); diff --git a/src/gcal-search-view.c b/src/gcal-search-view.c index b8a13e3b..2c3a3c81 100644 --- a/src/gcal-search-view.c +++ b/src/gcal-search-view.c @@ -574,18 +574,21 @@ gcal_search_view_component_added (ECalDataModelSubscriber *subscriber, RowEventData *row_data; GcalEvent *event; + GError *error; gchar *uid; view = GCAL_SEARCH_VIEW (subscriber); - - e_cal_component_get_dtstart (comp, &dt); - - /* Protect against NULL start date */ - if (dt.value == NULL) - return; + error = NULL; /* event */ - event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp); + event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp, &error); + + if (error) + { + g_warning ("Error creating event: %s", error->message); + g_clear_error (&error); + return; + } /* insert row_data at the hash of events */ row_data = g_new0 (RowEventData, 1); diff --git a/src/gcal-subscriber-view.c b/src/gcal-subscriber-view.c index 550ad413..79bb8d06 100644 --- a/src/gcal-subscriber-view.c +++ b/src/gcal-subscriber-view.c @@ -370,8 +370,18 @@ gcal_subscriber_view_component_added (ECalDataModelSubscriber *subscriber, { GtkWidget *event_widget; GcalEvent *event; + GError *error; + + error = NULL; + event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp, &error); + + if (error) + { + g_message ("Error creating event: %s", error->message); + g_clear_error (&error); + return; + } - event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp); event_widget = gcal_event_widget_new (event); gcal_event_widget_set_read_only (GCAL_EVENT_WIDGET (event_widget), e_client_is_readonly (E_CLIENT (client))); @@ -390,9 +400,19 @@ gcal_subscriber_view_component_modified (ECalDataModelSubscriber *subscriber, GList *l; GtkWidget *new_widget; GcalEvent *event; + GError *error; + error = NULL; priv = gcal_subscriber_view_get_instance_private (GCAL_SUBSCRIBER_VIEW (subscriber)); - event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp); + event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp, &error); + + if (error) + { + g_message ("Error creating event: %s", error->message); + g_clear_error (&error); + return; + } + new_widget = gcal_event_widget_new (event); l = g_hash_table_lookup (priv->children, gcal_event_get_uid (event)); diff --git a/src/gcal-window.c b/src/gcal-window.c index 3864ce34..57ad3926 100644 --- a/src/gcal-window.c +++ b/src/gcal-window.c @@ -1061,7 +1061,7 @@ create_event_detailed_cb (GcalView *view, GcalEvent *event; comp = build_component_from_details ("", start_span, end_span); - event = gcal_event_new (gcal_manager_get_default_source (window->manager), comp); + event = gcal_event_new (gcal_manager_get_default_source (window->manager), comp, NULL); gcal_edit_dialog_set_event_is_new (GCAL_EDIT_DIALOG (window->edit_dialog), TRUE); gcal_edit_dialog_set_event (GCAL_EDIT_DIALOG (window->edit_dialog), event); diff --git a/src/gcal-year-view.c b/src/gcal-year-view.c index 83289bb8..7bf29798 100644 --- a/src/gcal-year-view.c +++ b/src/gcal-year-view.c @@ -1619,6 +1619,7 @@ gcal_year_view_component_added (ECalDataModelSubscriber *subscriber, GcalYearView *year_view = GCAL_YEAR_VIEW (subscriber); GcalEvent *event; + GError *error; GList **days_widgets_array; GList *l; gint i, days_span; @@ -1627,12 +1628,20 @@ gcal_year_view_component_added (ECalDataModelSubscriber *subscriber, time_t event_start, event_end, range_start, range_end; icaltimezone *zone; + error = NULL; + event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp, &error); + + if (error) + { + g_warning ("Error creating event: %s", error->message); + g_clear_error (&error); + return; + } + update_selected_dates_from_button_data (year_view); days_span = icaltime_day_of_year(*(year_view->end_selected_date)) - icaltime_day_of_year(*(year_view->start_selected_date)) + 1; days_widgets_array = g_new0 (GList*, days_span); - event = gcal_event_new (e_client_get_source (E_CLIENT (client)), comp); - /* check if event belongs to range */ zone = gcal_manager_get_system_timezone (year_view->manager); range_start = icaltime_as_timet_with_zone (*(year_view->start_selected_date), zone);