[gnome-calendar/gnome-3-36] views: Implement GcalTimelineSubscriber



commit 85db5eb4387ddfc66b56a987a820a3a59e661c57
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Thu Mar 26 23:20:27 2020 -0300

    views: Implement GcalTimelineSubscriber

 src/views/gcal-month-view.c | 138 +++++++++++++++++++++++++++++++++---
 src/views/gcal-week-view.c  |  93 +++++++++++++++++++++++--
 src/views/gcal-year-view.c  | 165 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 381 insertions(+), 15 deletions(-)
---
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;
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]