diff --git a/src/views/gcal-month-view.c b/src/views/gcal-month-view.c index 3e8986c5..e7df1169 100644 --- a/src/views/gcal-month-view.c +++ b/src/views/gcal-month-view.c @@ -28,6 +28,7 @@ #include "gcal-month-cell.h" #include "gcal-month-popover.h" #include "gcal-month-view.h" +#include "gcal-timeline-subscriber.h" #include "gcal-utils.h" #include "gcal-view.h" @@ -143,13 +144,17 @@ static void on_month_cell_show_overflow_popover_cb (GcalMonthCell GtkWidget *button, GcalMonthView *self); +static void gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface); + G_DEFINE_TYPE_WITH_CODE (GcalMonthView, gcal_month_view, GTK_TYPE_CONTAINER, G_IMPLEMENT_INTERFACE (GCAL_TYPE_VIEW, gcal_view_interface_init) G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER, e_data_model_subscriber_interface_init) G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, - gtk_buildable_interface_init)); + gtk_buildable_interface_init) + G_IMPLEMENT_INTERFACE (GCAL_TYPE_TIMELINE_SUBSCRIBER, + gcal_timeline_subscriber_interface_init)); enum { @@ -1166,6 +1171,8 @@ gcal_month_view_set_date (GcalView *view, update_header_labels (self); update_month_cells (self); + gcal_timeline_subscriber_range_changed (GCAL_TIMELINE_SUBSCRIBER (view)); + GCAL_EXIT; } @@ -1284,6 +1291,126 @@ gtk_buildable_interface_init (GtkBuildableIface *iface) } +/* + * GcalTimelineSubscriber iface + */ + +static GDateTime* +gcal_month_view_get_range_start (GcalTimelineSubscriber *subscriber) +{ + GcalMonthView *self = GCAL_MONTH_VIEW (subscriber); + + return g_date_time_new_local (g_date_time_get_year (self->date), + g_date_time_get_month (self->date), + 1, 0, 0, 0); +} + +static GDateTime* +gcal_month_view_get_range_end (GcalTimelineSubscriber *subscriber) +{ + g_autoptr (GDateTime) month_start = NULL; + + month_start = gcal_month_view_get_range_start (subscriber); + return g_date_time_add_months (month_start, 1); +} + +static void +gcal_month_view_add_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + GcalMonthView *self; + GcalCalendar *calendar; + GtkWidget *event_widget; + + self = GCAL_MONTH_VIEW (subscriber); + calendar = gcal_event_get_calendar (event); + + event_widget = gcal_event_widget_new (self->context, event); + gcal_event_widget_set_read_only (GCAL_EVENT_WIDGET (event_widget), gcal_calendar_is_read_only (calendar)); + + gtk_widget_show (event_widget); + gtk_container_add (GTK_CONTAINER (subscriber), event_widget); + + self->pending_event_allocation = TRUE; +} + +static void +gcal_month_view_update_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + GcalMonthView *self; + GtkWidget *new_widget; + GList *l; + + GCAL_ENTRY; + + self = GCAL_MONTH_VIEW (subscriber); + + l = g_hash_table_lookup (self->children, gcal_event_get_uid (event)); + + if (!l) + { + g_warning ("%s: Widget with uuid: %s not found in view: %s", + G_STRFUNC, + gcal_event_get_uid (event), + gtk_widget_get_name (GTK_WIDGET (subscriber))); + return; + } + + /* Destroy the old event widget (split event widgets will be destroyed too) */ + gtk_widget_destroy (l->data); + + /* Create and add the new event widget */ + new_widget = gcal_event_widget_new (self->context, event); + gtk_widget_show (new_widget); + gtk_container_add (GTK_CONTAINER (subscriber), new_widget); + + self->pending_event_allocation = TRUE; + + GCAL_EXIT; +} + +static void +gcal_month_view_remove_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + GcalMonthView *self; + const gchar *uuid; + GList *l; + + GCAL_ENTRY; + + self = GCAL_MONTH_VIEW (subscriber); + uuid = gcal_event_get_uid (event); + l = g_hash_table_lookup (self->children, uuid); + + if (!l) + { + g_warning ("%s: Widget with uuid: %s not found in view: %s", + G_STRFUNC, + uuid, + gtk_widget_get_name (GTK_WIDGET (subscriber))); + GCAL_RETURN (); + } + + gtk_widget_destroy (l->data); + + self->pending_event_allocation = TRUE; + + GCAL_EXIT; +} + +static void +gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface) +{ + iface->get_range_start = gcal_month_view_get_range_start; + iface->get_range_end = gcal_month_view_get_range_end; + iface->add_event = gcal_month_view_add_event; + iface->update_event = gcal_month_view_update_event; + iface->remove_event = gcal_month_view_remove_event; +} + + /* * ECalDataModelSubscriber interface */ @@ -1296,7 +1423,6 @@ gcal_month_view_component_added (ECalDataModelSubscriber *subscriber, g_autoptr (GcalEvent) event = NULL; GcalMonthView *self; GcalCalendar *calendar; - GtkWidget *event_widget; GError *error; GCAL_ENTRY; @@ -1314,13 +1440,7 @@ gcal_month_view_component_added (ECalDataModelSubscriber *subscriber, GCAL_RETURN (); } - event_widget = gcal_event_widget_new (self->context, event); - gcal_event_widget_set_read_only (GCAL_EVENT_WIDGET (event_widget), e_client_is_readonly (E_CLIENT (client))); - - gtk_widget_show (event_widget); - gtk_container_add (GTK_CONTAINER (subscriber), event_widget); - - self->pending_event_allocation = TRUE; + gcal_month_view_add_event (GCAL_TIMELINE_SUBSCRIBER (self), event); GCAL_EXIT; } diff --git a/src/views/gcal-week-view.c b/src/views/gcal-week-view.c index d26a8a95..f66ff835 100644 --- a/src/views/gcal-week-view.c +++ b/src/views/gcal-week-view.c @@ -21,6 +21,7 @@ #include "gcal-debug.h" #include "gcal-enums.h" #include "gcal-event-widget.h" +#include "gcal-timeline-subscriber.h" #include "gcal-utils.h" #include "gcal-view.h" #include "gcal-week-header.h" @@ -63,6 +64,8 @@ static void gcal_view_interface_init (GcalViewInterf static void gcal_data_model_subscriber_interface_init (ECalDataModelSubscriberInterface *iface); +static void gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface); + enum { PROP_0, @@ -75,7 +78,9 @@ enum G_DEFINE_TYPE_WITH_CODE (GcalWeekView, gcal_week_view, GTK_TYPE_BOX, G_IMPLEMENT_INTERFACE (GCAL_TYPE_VIEW, gcal_view_interface_init) G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER, - gcal_data_model_subscriber_interface_init)); + gcal_data_model_subscriber_interface_init) + G_IMPLEMENT_INTERFACE (GCAL_TYPE_TIMELINE_SUBSCRIBER, + gcal_timeline_subscriber_interface_init)); /* Callbacks */ static void @@ -198,6 +203,8 @@ gcal_week_view_set_date (GcalView *view, schedule_position_scroll (self); + gcal_timeline_subscriber_range_changed (GCAL_TIMELINE_SUBSCRIBER (view)); + GCAL_EXIT; } @@ -334,6 +341,85 @@ update_hours_sidebar_size (GcalWeekView *self) g_object_unref (layout); } +/* + * GcalTimelineSubscriber iface + */ + +static GDateTime* +gcal_week_view_get_range_start (GcalTimelineSubscriber *subscriber) +{ + GcalWeekView *self = GCAL_WEEK_VIEW (subscriber); + + return gcal_date_time_get_start_of_week (self->date); +} + +static GDateTime* +gcal_week_view_get_range_end (GcalTimelineSubscriber *subscriber) +{ + GcalWeekView *self = GCAL_WEEK_VIEW (subscriber); + + return gcal_date_time_get_end_of_week (self->date); +} + +static void +gcal_week_view_add_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + GcalWeekView *self = GCAL_WEEK_VIEW (subscriber); + + GCAL_ENTRY; + + if (gcal_event_is_multiday (event) || gcal_event_get_all_day (event)) + gcal_week_header_add_event (GCAL_WEEK_HEADER (self->header), event); + else + gcal_week_grid_add_event (GCAL_WEEK_GRID (self->week_grid), event); + + GCAL_EXIT; +} + +static void +gcal_week_view_update_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + GcalWeekView *self = GCAL_WEEK_VIEW (subscriber); + const gchar *event_id; + + GCAL_ENTRY; + + event_id = gcal_event_get_uid (event); + gcal_week_header_remove_event (GCAL_WEEK_HEADER (self->header), event_id); + gcal_week_grid_remove_event (GCAL_WEEK_GRID (self->week_grid), event_id); + + gcal_week_view_add_event (subscriber, event); + + GCAL_EXIT; +} + +static void +gcal_week_view_remove_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + GcalWeekView *self = GCAL_WEEK_VIEW (subscriber); + const gchar *uuid = gcal_event_get_uid (event); + + GCAL_ENTRY; + + gcal_week_header_remove_event (GCAL_WEEK_HEADER (self->header), uuid); + gcal_week_grid_remove_event (GCAL_WEEK_GRID (self->week_grid), uuid); + + GCAL_EXIT; +} + +static void +gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface) +{ + iface->get_range_start = gcal_week_view_get_range_start; + iface->get_range_end = gcal_week_view_get_range_end; + iface->add_event = gcal_week_view_add_event; + iface->update_event = gcal_week_view_update_event; + iface->remove_event = gcal_week_view_remove_event; +} + /* ECalDataModelSubscriber implementation */ static void @@ -351,10 +437,7 @@ gcal_week_view_component_added (ECalDataModelSubscriber *subscriber, e_client_get_source (E_CLIENT (client))); event = gcal_event_new (calendar, comp, NULL); - if (gcal_event_is_multiday (event) || gcal_event_get_all_day (event)) - gcal_week_header_add_event (GCAL_WEEK_HEADER (self->header), event); - else - gcal_week_grid_add_event (GCAL_WEEK_GRID (self->week_grid), event); + gcal_week_view_add_event (GCAL_TIMELINE_SUBSCRIBER (subscriber), event); GCAL_EXIT; } diff --git a/src/views/gcal-year-view.c b/src/views/gcal-year-view.c index 0a264f94..f51f0d49 100644 --- a/src/views/gcal-year-view.c +++ b/src/views/gcal-year-view.c @@ -22,6 +22,7 @@ #include "gcal-clock.h" #include "gcal-context.h" #include "gcal-debug.h" +#include "gcal-timeline-subscriber.h" #include "gcal-year-view.h" #include "gcal-view.h" #include "gcal-utils.h" @@ -129,11 +130,15 @@ static void gcal_view_interface_init (GcalViewInterf static void gcal_data_model_subscriber_interface_init (ECalDataModelSubscriberInterface *iface); static void update_weather (GcalYearView *self); +static void gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface); + G_DEFINE_TYPE_WITH_CODE (GcalYearView, gcal_year_view, GTK_TYPE_BOX, G_IMPLEMENT_INTERFACE (GCAL_TYPE_VIEW, gcal_view_interface_init) G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER, - gcal_data_model_subscriber_interface_init)); + gcal_data_model_subscriber_interface_init) + G_IMPLEMENT_INTERFACE (GCAL_TYPE_TIMELINE_SUBSCRIBER, + gcal_timeline_subscriber_interface_init)); static gint compare_events (GcalEventWidget *widget1, @@ -1588,6 +1593,163 @@ navigator_drag_leave_cb (GcalYearView *self, gtk_widget_queue_draw (navigator); } +/* + * GcalTimelineSubscriber implementation + */ + +static GDateTime* +gcal_year_view_get_range_start (GcalTimelineSubscriber *subscriber) +{ + GcalYearView *self = GCAL_YEAR_VIEW (subscriber); + + return g_date_time_new_local (g_date_time_get_year (self->date), + 1, 1, 0, 0, 0); +} + +static GDateTime* +gcal_year_view_get_range_end (GcalTimelineSubscriber *subscriber) +{ + GcalYearView *self = GCAL_YEAR_VIEW (subscriber); + + return g_date_time_new_local (g_date_time_get_year (self->date) + 1, + 1, 1, 0, 0, 0); +} + +static void +gcal_year_view_add_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + GcalYearView *self; + GDateTime *event_start; + GDateTime *event_end; + guint start_month; + guint end_month; + guint i; + + GCAL_ENTRY; + + self = GCAL_YEAR_VIEW (subscriber); + + g_debug ("Caching event '%s' in Year view", gcal_event_get_uid (event)); + + event_start = gcal_event_get_date_start (event); + event_end = gcal_event_get_date_end (event); + + /* Calculate the start & end months */ + start_month = g_date_time_get_month (event_start) - 1; + end_month = g_date_time_get_month (event_end) - 1; + + if (g_date_time_get_year (event_start) < g_date_time_get_year (self->date)) + start_month = 0; + + if (g_date_time_get_year (event_end) > g_date_time_get_year (self->date)) + end_month = 11; + + /* Add the event to the cache */ + for (i = start_month; i <= end_month; i++) + g_ptr_array_add (self->events[i], g_object_ref (event)); + + update_sidebar (self); + + gtk_widget_queue_draw (GTK_WIDGET (self->navigator)); + + GCAL_EXIT; +} + +static void +gcal_year_view_remove_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + g_autoptr (GList) children = NULL; + GcalYearView *self; + GList *l; + const gchar *event_id; + guint n_children; + guint i; + + GCAL_ENTRY; + + self = GCAL_YEAR_VIEW (subscriber); + event_id = gcal_event_get_uid (event); + + n_children = 0; + children = gtk_container_get_children (GTK_CONTAINER (self->events_sidebar)); + + for (l = children; l != NULL; l = g_list_next (l)) + { + GcalEventWidget *child_widget; + GcalEvent *list_event; + + child_widget = GCAL_EVENT_WIDGET (gtk_bin_get_child (GTK_BIN (l->data))); + list_event = gcal_event_widget_get_event (child_widget); + + if (g_strcmp0 (event_id, gcal_event_get_uid (list_event)) == 0) + gtk_widget_destroy (GTK_WIDGET (l->data)); + else + n_children++; + } + + /* + * No children left visible, all the events were removed and now we have to show the + * 'No Events' placeholder. + */ + if (n_children == 0) + { + update_no_events_page (self); + gtk_stack_set_visible_child_name (GTK_STACK (self->navigator_stack), "no-events"); + } + + /* Also remove from the cached list of events */ + for (i = 0; i < 12; i++) + { + GPtrArray *events; + guint j; + + events = self->events[i]; + + for (j = 0; j < events->len; j++) + { + GcalEvent *cached_event; + + cached_event = g_ptr_array_index (events, j); + + if (!g_str_equal (gcal_event_get_uid (cached_event), event_id)) + continue; + + g_debug ("Removing event '%s' from Year view's cache", event_id); + g_ptr_array_remove (events, event); + } + } + + gtk_widget_queue_draw (GTK_WIDGET (self->navigator)); + + GCAL_EXIT; +} + +static void +gcal_year_view_update_event (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + GCAL_ENTRY; + + gcal_year_view_remove_event (subscriber, event); + gcal_year_view_add_event (subscriber, event); + + + GCAL_EXIT; +} + +static void +gcal_timeline_subscriber_interface_init (GcalTimelineSubscriberInterface *iface) +{ + iface->get_range_start = gcal_year_view_get_range_start; + iface->get_range_end = gcal_year_view_get_range_end; + iface->add_event = gcal_year_view_add_event; + iface->remove_event = gcal_year_view_remove_event; + iface->update_event = gcal_year_view_update_event; +} + + /* GcalView implementation */ static GDateTime* gcal_year_view_get_date (GcalView *view) @@ -1604,6 +1766,7 @@ gcal_year_view_set_date (GcalView *view, GCAL_ENTRY; update_date (GCAL_YEAR_VIEW (view), date); + gcal_timeline_subscriber_range_changed (GCAL_TIMELINE_SUBSCRIBER (view)); GCAL_EXIT; }