[gnome-calendar] subscriber: added protected internal structure
- From: Erick Pérez Castellanos <erickpc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar] subscriber: added protected internal structure
- Date: Fri, 9 Jan 2015 14:29:46 +0000 (UTC)
commit c1e68032c960fdab8b2c7198eb18b48fbe2e4100
Author: Erick Pérez Castellanos <erick red gmail com>
Date: Mon Dec 29 16:09:06 2014 -0500
subscriber: added protected internal structure
The idea here is to make GcalSubscriber handle the container
responsibilities of the view, and the view will handle only the drawing
an allocating, this would allow us to remove GcalView interface and
merge its methods in GcalSubscriber.
src/Makefile.am | 6 +-
src/gcal-subscriber-private.h | 59 ++++++
src/gcal-subscriber.c | 389 +++++++++++++++++++++++++++++++++++++++++
src/gcal-subscriber.h | 61 +++++++
4 files changed, 512 insertions(+), 3 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 6c9fc56..1111c5a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,9 +29,9 @@ gnome_calendar_SOURCES = \
gcal-window.c \
gcal-view.c \
gcal-view.h \
- gcal-subscriber-view.c \
- gcal-subscriber-view.h \
- gcal-subscriber-view-private.h \
+ gcal-subscriber.c \
+ gcal-subscriber.h \
+ gcal-subscriber-private.h \
gcal-month-view.c \
gcal-month-view.h \
gcal-week-view.c \
diff --git a/src/gcal-subscriber-private.h b/src/gcal-subscriber-private.h
new file mode 100644
index 0000000..fdfe884
--- /dev/null
+++ b/src/gcal-subscriber-private.h
@@ -0,0 +1,59 @@
+/*
+ * gcal-subscriber-private.h
+ *
+ * Copyright (C) 2014 - Erick Pérez Castellanos
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GCAL_SUBSCRIBER_PRIVATE_H__
+#define __GCAL_SUBSCRIBER_PRIVATE_H____
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+struct _GcalSubscriberPrivate
+{
+ /**
+ * Hash to keep children widgets (all of them, parent widgets and its parts if there's any),
+ * uuid as key and a list of all the instances of the event as value. Here, the first widget on the list is
+ * the master, and the rest are the parts. Note: that the master is a part itself, the first one
+ */
+ GHashTable *children;
+
+ /**
+ * Hash containig single-day events, day of the month as key and a list of the events that belongs to this
day
+ */
+ GHashTable *single_cell_children;
+
+ /**
+ * An organizaed list containig multiday events
+ * This one contains only parents events, to find out its parts @children will be used
+ */
+ GList *multi_cell_children;
+
+ /**
+ * Hash containing cells that who has overflow per list of hidden widgets.
+ */
+ GHashTable *overflow_cells;
+ /**
+ * Set containing the master widgets hidden for delete;
+ */
+ GHashTable *hidden_as_overflow;
+};
+
+G_END_DECLS
+
+#endif /* __GCAL_SUBSCRIBER_H__ */
diff --git a/src/gcal-subscriber.c b/src/gcal-subscriber.c
new file mode 100644
index 0000000..292cbab
--- /dev/null
+++ b/src/gcal-subscriber.c
@@ -0,0 +1,389 @@
+/* -*- mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * gcal-subscriber.c
+ *
+ * Copyright (C) 2014 - Erick Pérez Castellanos
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gcal-subscriber.h"
+#include "gcal-subscriber-private.h"
+
+#include "gcal-view.h"
+#include "gcal-event-widget.h"
+
+static void gcal_data_model_subscriber_interface_init (ECalDataModelSubscriberInterface *iface);
+
+static void gcal_subscriber_finalize (GObject *object);
+
+static void gcal_subscriber_add (GtkContainer *container,
+ GtkWidget *widget);
+
+static void gcal_subscriber_remove (GtkContainer *container,
+ GtkWidget *widget);
+
+static void gcal_subscriber_forall (GtkContainer *container,
+ gboolean
include_internals,
+ GtkCallback callback,
+ gpointer
callback_data);
+
+static gboolean gcal_subscriber_is_child_multicell (GcalSubscriber
*subscriber,
+ GcalEventWidget *child);
+
+static guint gcal_subscriber_get_child_cell (GcalSubscriber
*subscriber,
+ GcalEventWidget *child);
+
+static void gcal_subscriber_component_added (ECalDataModelSubscriber *subscriber,
+ ECalClient *client,
+ ECalComponent *comp);
+
+static void gcal_subscriber_component_modified (ECalDataModelSubscriber *subscriber,
+ ECalClient *client,
+ ECalComponent *comp);
+
+static void gcal_subscriber_component_removed (ECalDataModelSubscriber *subscriber,
+ ECalClient *client,
+ const gchar *uid,
+ const gchar *rid);
+
+static void gcal_subscriber_freeze (ECalDataModelSubscriber *subscriber);
+
+static void gcal_subscriber_thaw (ECalDataModelSubscriber *subscriber);
+
+G_DEFINE_TYPE_WITH_CODE (GcalSubscriber, gcal_subscriber, GTK_TYPE_CONTAINER,
+ G_ADD_PRIVATE (GcalSubscriber)
+ G_IMPLEMENT_INTERFACE (E_TYPE_CAL_DATA_MODEL_SUBSCRIBER,
+ gcal_data_model_subscriber_interface_init));
+
+
+static void
+gcal_subscriber_class_init (GcalSubscriberClass *klass)
+{
+ GtkContainerClass *container_class;
+
+ klass->is_child_multicell = gcal_subscriber_is_child_multicell;
+ klass->get_child_cell = gcal_subscriber_get_child_cell;
+
+ G_OBJECT_CLASS (klass)->finalize = gcal_subscriber_finalize;
+
+ container_class = GTK_CONTAINER_CLASS (klass);
+ container_class->add = gcal_subscriber_add;
+ container_class->remove = gcal_subscriber_remove;
+ container_class->forall = gcal_subscriber_forall;
+}
+
+static void
+gcal_subscriber_init (GcalSubscriber *self)
+{
+ GcalSubscriberPrivate *priv;
+
+ priv = gcal_subscriber_get_instance_private (self);
+ self->priv = priv;
+
+ priv->children = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_list_free);
+ priv->single_cell_children = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)
g_list_free);
+ priv->overflow_cells = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)
g_list_free);
+ priv->hidden_as_overflow = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+}
+
+static void
+gcal_data_model_subscriber_interface_init (ECalDataModelSubscriberInterface *iface)
+{
+ iface->component_added = gcal_subscriber_component_added;
+ iface->component_modified = gcal_subscriber_component_modified;
+ iface->component_removed = gcal_subscriber_component_removed;
+ iface->freeze = gcal_subscriber_freeze;
+ iface->thaw = gcal_subscriber_thaw;
+}
+
+static void
+gcal_subscriber_finalize (GObject *object)
+{
+ GcalSubscriberPrivate *priv;
+
+ priv = gcal_subscriber_get_instance_private (GCAL_SUBSCRIBER (object));
+
+ g_hash_table_destroy (priv->children);
+ g_hash_table_destroy (priv->single_cell_children);
+ g_hash_table_destroy (priv->overflow_cells);
+ g_hash_table_destroy (priv->hidden_as_overflow);
+
+ if (priv->multi_cell_children != NULL)
+ g_list_free (priv->multi_cell_children);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (gcal_subscriber_parent_class)->finalize (object);
+}
+
+static void
+gcal_subscriber_add (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GcalSubscriberPrivate *priv;
+ const gchar *uuid;
+ GList *l = NULL;
+
+ g_return_if_fail (GCAL_IS_EVENT_WIDGET (widget));
+ g_return_if_fail (gtk_widget_get_parent (widget) == NULL);
+ priv = gcal_subscriber_get_instance_private (GCAL_SUBSCRIBER (container));
+ uuid = gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET (widget));
+
+ /* inserting in all children hash */
+ if (g_hash_table_lookup (priv->children, uuid) != NULL)
+ {
+ g_warning ("Event with uuid: %s already added", uuid);
+ gtk_widget_destroy (widget);
+ return;
+ }
+ l = g_list_append (l, widget);
+ g_hash_table_insert (priv->children, g_strdup (uuid), l);
+
+ if (gcal_subscriber_is_child_multicell (GCAL_SUBSCRIBER (container), GCAL_EVENT_WIDGET (widget)))
+ {
+ priv->multi_cell_children = g_list_insert_sorted (priv->multi_cell_children, widget,
+ (GCompareFunc) gcal_event_widget_compare_by_length);
+ }
+ else
+ {
+ guint cell_idx = gcal_subscriber_get_child_cell (GCAL_SUBSCRIBER (container), GCAL_EVENT_WIDGET
(widget));
+ l = g_hash_table_lookup (priv->single_cell_children, GINT_TO_POINTER (cell_idx));
+ l = g_list_insert_sorted (l, widget, (GCompareFunc) gcal_event_widget_compare_by_start_date);
+
+ if (g_list_length (l) != 1)
+ {
+ g_hash_table_steal (priv->single_cell_children, GINT_TO_POINTER (cell_idx));
+ }
+ g_hash_table_insert (priv->single_cell_children, GINT_TO_POINTER (cell_idx), l);
+ }
+
+ /* setup child */
+ gtk_widget_set_parent (widget, GTK_WIDGET (container));
+ //g_signal_connect (widget, "activate", G_CALLBACK (event_opened), container);
+}
+
+static void
+gcal_subscriber_remove (GtkContainer *container,
+ GtkWidget *widget)
+{
+ GcalSubscriberPrivate *priv;
+ const gchar *uuid;
+
+ GList *l, *aux;
+ gboolean was_visible = FALSE;
+ GtkWidget *master_widget;
+
+ g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (container));
+ priv = gcal_subscriber_get_instance_private (GCAL_SUBSCRIBER (container));
+
+ uuid = gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET (widget));
+
+ l = g_hash_table_lookup (priv->children, uuid);
+ if (l != NULL)
+ {
+ master_widget = (GtkWidget*) l->data;
+
+ was_visible = gtk_widget_get_visible (widget);
+ gtk_widget_unparent (widget);
+
+ if (widget == master_widget)
+ {
+ if (gcal_subscriber_is_child_multicell (GCAL_SUBSCRIBER (container), GCAL_EVENT_WIDGET (widget)))
+ {
+ priv->multi_cell_children = g_list_remove (priv->multi_cell_children, widget);
+
+ aux = g_list_next (l);
+ if (aux != NULL)
+ {
+ l->next = NULL;
+ aux->prev = NULL;
+ g_list_foreach (aux, (GFunc) gtk_widget_unparent, NULL);
+ g_list_free (aux);
+ }
+ }
+ else
+ {
+ guint cell_idx = gcal_subscriber_get_child_cell (GCAL_SUBSCRIBER (container),
GCAL_EVENT_WIDGET (widget));
+
+ aux = g_hash_table_lookup (priv->single_cell_children, GINT_TO_POINTER (cell_idx));
+ aux = g_list_remove (g_list_copy (aux), widget);
+ if (aux == NULL)
+ g_hash_table_remove (priv->single_cell_children, GINT_TO_POINTER (cell_idx));
+ else
+ g_hash_table_replace (priv->single_cell_children, GINT_TO_POINTER (cell_idx), aux);
+ }
+ }
+
+ l = g_list_remove (g_list_copy (l), widget);
+ if (l == NULL)
+ g_hash_table_remove (priv->children, uuid);
+ else
+ g_hash_table_replace (priv->children, g_strdup (uuid), l);
+
+ g_hash_table_remove (priv->hidden_as_overflow, uuid);
+
+ if (was_visible)
+ gtk_widget_queue_resize (GTK_WIDGET (container));
+ }
+}
+
+static void
+gcal_subscriber_forall (GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data)
+{
+ GcalSubscriberPrivate *priv;
+ GList *l, *l2, *aux = NULL;
+
+ priv = gcal_subscriber_get_instance_private (GCAL_SUBSCRIBER (container));
+
+ l2 = g_hash_table_get_values (priv->children);
+ for (l = l2; l != NULL; l = g_list_next (l))
+ aux = g_list_concat (aux, g_list_reverse (g_list_copy (l->data)));
+ g_list_free (l2);
+
+ l = aux;
+ while (aux != NULL)
+ {
+ GtkWidget *widget = (GtkWidget*) aux->data;
+ aux = aux->next;
+
+ (*callback) (widget, callback_data);
+ }
+ g_list_free (l);
+}
+
+static gboolean
+gcal_subscriber_is_child_multicell (GcalSubscriber *subscriber,
+ GcalEventWidget *child)
+{
+ GcalSubscriberClass *klass;
+
+ g_return_val_if_fail (GCAL_IS_SUBSCRIBER (subscriber), FALSE);
+ g_return_val_if_fail (GCAL_IS_EVENT_WIDGET (child), FALSE);
+
+ klass = GCAL_SUBSCRIBER_GET_CLASS (subscriber);
+
+ if (klass->is_child_multicell)
+ return klass->is_child_multicell (subscriber, child);
+
+ return FALSE;
+}
+
+static guint
+gcal_subscriber_get_child_cell (GcalSubscriber *subscriber,
+ GcalEventWidget *child)
+{
+ GcalSubscriberClass *klass;
+
+ g_return_val_if_fail (GCAL_IS_SUBSCRIBER (subscriber), 0);
+ g_return_val_if_fail (GCAL_IS_EVENT_WIDGET (child), 0);
+
+ klass = GCAL_SUBSCRIBER_GET_CLASS (subscriber);
+
+ if (klass->get_child_cell)
+ return klass->get_child_cell (subscriber, child);
+
+ return 0;
+}
+
+/* ECalDataModelSubscriber interface API */
+static void
+gcal_subscriber_component_added (ECalDataModelSubscriber *subscriber,
+ ECalClient *client,
+ ECalComponent *comp)
+{
+ GtkWidget *event;
+ GcalEventData *data;
+
+ data = g_new0 (GcalEventData, 1);
+ data->source = e_client_get_source (E_CLIENT (client));
+ data->event_component = e_cal_component_clone (comp);
+
+ event = gcal_event_widget_new_from_data (data);
+ gcal_event_widget_set_read_only (GCAL_EVENT_WIDGET (event), e_client_is_readonly (E_CLIENT (client)));
+
+ g_free (data);
+
+ gtk_widget_show (event);
+ gtk_container_add (GTK_CONTAINER (subscriber), event);
+}
+
+static void
+gcal_subscriber_component_modified (ECalDataModelSubscriber *subscriber,
+ ECalClient *client,
+ ECalComponent *comp)
+{
+ GtkWidget *event;
+ GtkWidget *widget;
+ GcalEventData *data;
+
+ data = g_new0 (GcalEventData, 1);
+ data->source = e_client_get_source (E_CLIENT (client));
+ data->event_component = e_cal_component_clone (comp);
+
+ event = gcal_event_widget_new_from_data (data);
+ g_free (data);
+
+ widget =
+ gcal_view_get_by_uuid (
+ GCAL_VIEW (subscriber),
+ gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET (event)));
+
+ if (widget != NULL)
+ {
+ gtk_widget_destroy (widget);
+
+ gtk_widget_show (event);
+ gtk_container_add (GTK_CONTAINER (subscriber), event);
+ }
+}
+
+static void
+gcal_subscriber_component_removed (ECalDataModelSubscriber *subscriber,
+ ECalClient *client,
+ const gchar *uid,
+ const gchar *rid)
+{
+ GtkWidget *widget;
+ const gchar *sid;
+ gchar *uuid;
+
+ sid = e_source_get_uid (e_client_get_source (E_CLIENT (client)));
+
+ if (rid != NULL)
+ uuid = g_strdup_printf ("%s:%s:%s", sid, uid, rid);
+ else
+ uuid = g_strdup_printf ("%s:%s", sid, uid);
+
+ widget = gcal_view_get_by_uuid (GCAL_VIEW (subscriber), uuid);
+ if (widget != NULL)
+ gtk_widget_destroy (widget);
+ else
+ g_warning ("%s: Widget with uuid: %s not found",
+ G_STRFUNC, uuid);
+
+ g_free (uuid);
+}
+
+static void
+gcal_subscriber_freeze (ECalDataModelSubscriber *subscriber)
+{
+}
+
+static void
+gcal_subscriber_thaw (ECalDataModelSubscriber *subscriber)
+{
+}
diff --git a/src/gcal-subscriber.h b/src/gcal-subscriber.h
new file mode 100644
index 0000000..8878b11
--- /dev/null
+++ b/src/gcal-subscriber.h
@@ -0,0 +1,61 @@
+/*
+ * gcal-subscriber.h
+ *
+ * Copyright (C) 2014 - Erick Pérez Castellanos
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GCAL_SUBSCRIBER_H__
+#define __GCAL_SUBSCRIBER_H__
+
+#include "gcal-manager.h"
+#include "gcal-event-widget.h"
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GCAL_TYPE_SUBSCRIBER (gcal_subscriber_get_type ())
+#define GCAL_SUBSCRIBER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GCAL_TYPE_SUBSCRIBER,
GcalSubscriber))
+#define GCAL_SUBSCRIBER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GCAL_TYPE_SUBSCRIBER,
GcalSubscriberClass))
+#define GCAL_IS_SUBSCRIBER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GCAL_TYPE_SUBSCRIBER))
+#define GCAL_IS_SUBSCRIBER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GCAL_TYPE_SUBSCRIBER))
+#define GCAL_SUBSCRIBER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GCAL_TYPE_SUBSCRIBER,
GcalSubscriberClass))
+
+typedef struct _GcalSubscriber GcalSubscriber;
+typedef struct _GcalSubscriberClass GcalSubscriberClass;
+typedef struct _GcalSubscriberPrivate GcalSubscriberPrivate;
+
+struct _GcalSubscriber
+{
+ GtkContainer parent;
+
+ GcalSubscriberPrivate *priv;
+};
+
+struct _GcalSubscriberClass
+{
+ GtkContainerClass parent_class;
+
+ /*< public >*/
+ gboolean (*is_child_multicell) (GcalSubscriber *subscriber, GcalEventWidget *child);
+ guint (*get_child_cell) (GcalSubscriber *subscriber, GcalEventWidget *child);
+};
+
+GType gcal_subscriber_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GCAL_SUBSCRIBER_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]