[gnome-calendar] month-view: rework internals data structures
- From: Erick Pérez Castellanos <erickpc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calendar] month-view: rework internals data structures
- Date: Thu, 18 Dec 2014 14:06:41 +0000 (UTC)
commit f5a08f24bb00ec274e6fdea817bde8f642b29207
Author: Erick Pérez Castellanos <erick red gmail com>
Date: Sat Dec 13 16:17:04 2014 -0500
month-view: rework internals data structures
Changed internals data structures in order to handle allocation of
multidays events properly.
Modified GtkContainer::add, GtkContainer::remove and
GtkContainer::forall according to this new internal structure.
Commented out GcalView::get_by_uuid since it might get deprecated.
src/gcal-month-view.c | 194 +++++++++++++++++++++++++++----------------------
1 files changed, 107 insertions(+), 87 deletions(-)
---
diff --git a/src/gcal-month-view.c b/src/gcal-month-view.c
index 0b019e3..c471b03 100644
--- a/src/gcal-month-view.c
+++ b/src/gcal-month-view.c
@@ -30,12 +30,27 @@
typedef struct
{
/**
- * This is where we keep the refs of the child widgets.
- * Every child added to the list placed in the position
- * of it corresponding month day.
- * The cell number of every month day is calculated elsewhere.
+ * 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
*/
- GList *days [31];
+ 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_day_children;
+
+ /**
+ * An organizaed list containig multiday events
+ * This one contains only parents events, to find out its parts @children will be used
+ */
+ GList *multiday_children;
+
+ /**
+ * Hash containing which days have overflow
+ */
+ GHashTable *overflown_days;
GdkWindow *event_window;
@@ -272,7 +287,6 @@ static void
gcal_month_view_init (GcalMonthView *self)
{
GcalMonthViewPrivate *priv;
- gint i;
gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
@@ -283,8 +297,10 @@ gcal_month_view_init (GcalMonthView *self)
priv->start_mark_cell = -1;
priv->end_mark_cell = -1;
- for (i = 0; i < 31; i++)
- priv->days[i] = NULL;
+ priv->children = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_list_free);
+ priv->single_day_children = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)
g_list_free);
+ priv->multiday_children = NULL;
+ priv->overflown_days = g_hash_table_new (g_direct_hash, g_direct_equal);
gtk_style_context_add_class (
gtk_widget_get_style_context (GTK_WIDGET (self)),
@@ -387,6 +403,13 @@ gcal_month_view_finalize (GObject *object)
GcalMonthViewPrivate *priv;
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (object));
+ g_hash_table_destroy (priv->children);
+ g_hash_table_destroy (priv->single_day_children);
+ g_hash_table_destroy (priv->overflown_days);
+
+ if (priv->multiday_children != NULL)
+ g_list_free (priv->multiday_children);
+
if (priv->date != NULL)
g_free (priv->date);
@@ -1079,54 +1102,59 @@ gcal_month_view_button_release (GtkWidget *widget,
return TRUE;
}
+/**
+ * gcal_month_view_add:
+ * @container:
+ * @widget:
+ *
+ * Since this is only called from inside { link GcalSubscriber} it's safe to assume that it's a master
widget what
+ * is being added here.
+ **/
static void
gcal_month_view_add (GtkContainer *container,
GtkWidget *widget)
{
GcalMonthViewPrivate *priv;
- GList *l;
- icaltimetype *date;
- GcalViewChild *new_child;
+ const gchar *uuid;
+ icaltimetype *date;
+ GList *l = NULL;
g_return_if_fail (GCAL_IS_EVENT_WIDGET (widget));
g_return_if_fail (gtk_widget_get_parent (widget) == NULL);
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (container));
+ uuid = gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET (widget));
- /* Check if it's already added for date */
- date = gcal_event_widget_get_date (GCAL_EVENT_WIDGET (widget));
-
- for (l = priv->days[date->day - 1]; l != NULL; l = l->next)
+ /* inserting in all children hash */
+ if (g_hash_table_lookup (priv->children, uuid) != NULL)
{
- GtkWidget *event;
+ 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);
- event = GTK_WIDGET (((GcalViewChild*) l->data)->widget);
- if (gcal_event_widget_equal (GCAL_EVENT_WIDGET (widget),
- GCAL_EVENT_WIDGET (event)))
- {
- //TODO: remove once the main-dev phase its over
- g_warning ("Trying to add an event with the same uuid to the view");
- g_free (date);
- gtk_widget_destroy (widget);
- return;
- }
+ if (gcal_event_widget_is_multiday (GCAL_EVENT_WIDGET (widget)))
+ {
+ priv->multiday_children = g_list_insert_sorted (priv->multiday_children, widget,
+ (GCompareFunc) gcal_event_widget_compare_by_length);
}
+ else
+ {
+ date = gcal_event_widget_get_date (GCAL_EVENT_WIDGET (widget));
- new_child = g_new0 (GcalViewChild, 1);
- new_child->widget = widget;
- new_child->hidden = FALSE;
+ l = g_hash_table_lookup (priv->single_day_children, GINT_TO_POINTER (date->day));
+ l = g_list_append (l, widget);
- priv->days[date->day - 1] =
- g_list_insert_sorted (priv->days[date->day - 1],
- new_child,
- gcal_compare_event_widget_by_date);
- gtk_widget_set_parent (widget, GTK_WIDGET (container));
+ if (g_list_length (l) == 1)
+ g_hash_table_insert (priv->children, GINT_TO_POINTER (date->day), l);
+
+ g_free (date);
+ }
- g_signal_connect (widget,
- "activate",
- G_CALLBACK (event_opened),
- container);
- g_free (date);
+ gtk_widget_set_parent (widget, GTK_WIDGET (container));
+ g_signal_connect (widget, "activate", G_CALLBACK (event_opened), container);
}
static void
@@ -1134,35 +1162,44 @@ gcal_month_view_remove (GtkContainer *container,
GtkWidget *widget)
{
GcalMonthViewPrivate *priv;
- gint i;
- GList *l;
+ GList *l, *aux;
+ gboolean was_visible = FALSE;
+ GtkWidget *master_widget;
g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (container));
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (container));
- for (i = 0; i < 31; i++)
+ l = g_hash_table_lookup (priv->children, gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET (widget)));
+ if (l != NULL)
{
- for (l = priv->days[i]; l != NULL; l = l->next)
- {
- GcalViewChild *child;
+ master_widget = (GtkWidget*) l->data;
- child = (GcalViewChild*) l->data;
- if (child->widget == widget)
+ if (widget == master_widget)
+ {
+ g_debug ("removing a master widget");
+ if (gcal_event_widget_is_multiday (GCAL_EVENT_WIDGET (widget)))
{
- gboolean was_visible;
+ priv->multiday_children = g_list_remove (priv->multiday_children, widget);
+ }
+ else
+ {
+ icaltimetype *date;
- was_visible = gtk_widget_get_visible (widget);
- gtk_widget_unparent (widget);
+ date = gcal_event_widget_get_date (GCAL_EVENT_WIDGET (widget));
+ aux = g_hash_table_lookup (priv->single_day_children, GINT_TO_POINTER (date->day));
+ aux = g_list_remove (aux, widget);
+ g_hash_table_replace (priv->single_day_children, GINT_TO_POINTER (date->day), aux);
+ }
+ }
- priv->days[i] = g_list_remove (priv->days[i], child);
- g_free (child);
+ l = g_list_remove (l, widget);
+ g_hash_table_replace (priv->children, (gchar*) gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET
(widget)), l);
- if (was_visible)
- gtk_widget_queue_resize (GTK_WIDGET (container));
+ was_visible = gtk_widget_get_visible (widget);
+ gtk_widget_unparent (widget);
- return;
- }
- }
+ if (was_visible)
+ gtk_widget_queue_resize (GTK_WIDGET (container));
}
}
@@ -1173,23 +1210,22 @@ gcal_month_view_forall (GtkContainer *container,
gpointer callback_data)
{
GcalMonthViewPrivate *priv;
- gint i;
- GList *l;
+ GList *l, *last;
priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (container));
- for (i = 0; i < 31; i++)
+ l = g_hash_table_get_values (priv->children);
+ while (l != NULL)
{
- l = priv->days[i];
+ last = g_list_last (l);
+ l = l->next;
- while (l)
+ while (last != NULL)
{
- GcalViewChild *child;
-
- child = (GcalViewChild*) l->data;
- l = l->next;
+ GtkWidget *widget = (GtkWidget*) last->data;
+ last = last->prev;
- (* callback) (child->widget, callback_data);
+ (*callback) (widget, callback_data);
}
}
}
@@ -1336,26 +1372,10 @@ static GtkWidget*
gcal_month_view_get_by_uuid (GcalView *view,
const gchar *uuid)
{
- GcalMonthViewPrivate *priv;
- gint i;
- GList *l;
-
- g_return_val_if_fail (GCAL_IS_MONTH_VIEW (view), NULL);
- priv = gcal_month_view_get_instance_private (GCAL_MONTH_VIEW (view));
-
- for (i = 0; i < 31; i++)
- {
- for (l = priv->days[i]; l != NULL; l = l->next)
- {
- GcalViewChild *child;
- const gchar* widget_uuid;
-
- child = (GcalViewChild*) l->data;
- widget_uuid = gcal_event_widget_peek_uuid (GCAL_EVENT_WIDGET (child->widget));
- if (g_strcmp0 (uuid, widget_uuid) == 0)
- return child->widget;
- }
- }
+ /* FIXME: this method is deprecated in favor of remove_by_uuid, hide_by_uuid, etc */
+ /* Since the view internally duplicates the widgets per uuid, doesn't have much sense to do this. */
+ /* One possible way could be: retrieve always the master widget, and hook some handlers into */
+ /* ::hide, ::delete, etc. etc. Not sure what's best tho. */
return NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]