From 3efbc2436cc04f943d0c89ccf07c6ffdb8c2eede Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Mon, 13 Apr 2020 10:30:23 -0300 Subject: [PATCH] range-tree: Use GcalRange --- src/core/gcal-range-tree.c | 257 ++++++++++++++----------------------- src/core/gcal-range-tree.h | 17 +-- src/core/gcal-timeline.c | 113 ++++++++-------- src/views/gcal-week-grid.c | 88 +++++-------- tests/test-range-tree.c | 59 +++++---- 5 files changed, 225 insertions(+), 309 deletions(-) diff --git a/src/core/gcal-range-tree.c b/src/core/gcal-range-tree.c index ad77488c..59b66c6c 100644 --- a/src/core/gcal-range-tree.c +++ b/src/core/gcal-range-tree.c @@ -1,6 +1,6 @@ /* gcal-range-tree.c * - * Copyright (C) 2016 Georges Basile Stavracas Neto + * Copyright (C) 2016-2020 Georges Basile Stavracas Neto * * 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 @@ -46,8 +46,7 @@ typedef struct _Node { struct _Node *left; struct _Node *right; - GDateTime *start; - GDateTime *end; + GcalRange *range; GDateTime *max; guint16 hits; gint64 height; @@ -74,8 +73,7 @@ destroy_tree (Node *n) destroy_tree (n->left); destroy_tree (n->right); - gcal_clear_date_time (&n->start); - gcal_clear_date_time (&n->end); + g_clear_pointer (&n->range, gcal_range_unref); gcal_clear_date_time (&n->max); g_ptr_array_unref (n->data_array); @@ -100,71 +98,16 @@ balance (Node *n) return n ? height (n->left) - height (n->right) : 0; } -/* - * Compares the ranges A [a_start, a_end] and B [b_start, b_end]. A is - * less rangy than B when either it starts before B, or starts at the - * same point but ends before B. - * - * Some examples: - * - * 1. [-----A----] = 0 - * [-----B----] - * - * 2. [----A----] = 1 - * [----B----] - * - * 3. [------A-----] = -1 - * [----B----] - * - * 4. [----A----] = -1 - * [----B----] - * - * This is *not* comparing the sizes of the ranges. - */ -static inline gboolean -compare_intervals (GDateTime *a_start, - GDateTime *a_end, - GDateTime *b_start, - GDateTime *b_end) -{ - gint result = g_date_time_compare (b_start, a_start); - - if (result == 0) - result = g_date_time_compare (b_end, a_end); - - return result; -} - -static inline gboolean -is_interval_lower (Node *n, - GDateTime *start, - GDateTime *end) -{ - gint a_compare = g_date_time_compare (start, n->start); - return a_compare < 0 || (a_compare == 0 && g_date_time_compare (end, n->end) < 0); -} - -static inline gboolean -is_interval_higher (Node *n, - GDateTime *start, - GDateTime *end) -{ - gint a_compare = g_date_time_compare (start, n->start); - return a_compare > 0 || (a_compare == 0 && g_date_time_compare (end, n->end) > 0); -} - static Node* -node_new (GDateTime *start, - GDateTime *end, +node_new (GcalRange *range, gpointer data, GDestroyNotify destroy_func) { Node *n; n = g_new0 (Node, 1); - n->start = g_date_time_ref (start); - n->end = g_date_time_ref (end); - n->max = g_date_time_ref (end); + n->range = gcal_range_ref (range); + n->max = gcal_range_get_end (range); n->height = 1; n->hits = 1; @@ -246,31 +189,30 @@ rebalance (Node *n) static Node* insert (Node *n, - GDateTime *start, - GDateTime *end, + GcalRange *range, gpointer data, GDestroyNotify destroy_func) { + g_autoptr (GDateTime) range_end = NULL; gint result; if (!n) - return node_new (start, end, data, destroy_func); + return node_new (range, data, destroy_func); - result = compare_intervals (n->start, n->end, start, end); + result = gcal_range_compare (range, n->range); if (result < 0) - n->left = insert (n->left, start, end, data, destroy_func); + n->left = insert (n->left, range, data, destroy_func); else if (result > 0) - n->right = insert (n->right, start, end, data, destroy_func); + n->right = insert (n->right, range, data, destroy_func); else return hit_node (n, data); + range_end = gcal_range_get_end (range); + /* Update the current node's maximum subrange value */ - if (!n->max || g_date_time_compare (end, n->max) > 0) - { - gcal_clear_date_time (&n->max); - n->max = g_date_time_ref (end); - } + if (!n->max || g_date_time_compare (range_end, n->max) > 0) + gcal_set_date_time (&n->max, range_end); return rebalance (n); } @@ -327,19 +269,32 @@ delete_node (Node *n, static Node* remove_node (Node *n, - GDateTime *start, - GDateTime *end, + GcalRange *range, gpointer data) { + GcalRangePosition position; + if (!n) return NULL; - if (is_interval_lower (n, start, end)) - n->left = remove_node (n->left, start, end, data); - else if (is_interval_higher (n, start, end)) - n->right = remove_node (n->right, start, end, data); - else - return delete_node (n, data); + gcal_range_calculate_overlap (range, n->range, &position); + + switch (position) + { + case GCAL_RANGE_BEFORE: + n->left = remove_node (n->left, range, data); + break; + + case GCAL_RANGE_MATCH: + return delete_node (n, data); + + case GCAL_RANGE_AFTER: + n->right = remove_node (n->right, range, data); + break; + + default: + g_assert_not_reached (); + } return rebalance (n); } @@ -354,7 +309,7 @@ run_traverse_func (Node *n, for (i = 0; i < n->hits; i++) { - if (func (n->start, n->end, g_ptr_array_index (n->data_array, i), user_data)) + if (func (n->range, g_ptr_array_index (n->data_array, i), user_data)) return TRUE; } @@ -399,8 +354,7 @@ traverse (Node *n, /* Internal traverse functions */ static inline gboolean -gather_all_data (GDateTime *start, - GDateTime *end, +gather_all_data (GcalRange *range, gpointer data, gpointer user_data) { @@ -412,71 +366,66 @@ gather_all_data (GDateTime *start, } static inline gboolean -gather_data_at_range (GDateTime *start, - GDateTime *end, +gather_data_at_range (GcalRange *range, gpointer data, gpointer user_data) { - struct { - GDateTime *start, *end; - GPtrArray **array; - } *range = user_data; + GcalRangePosition position; + GcalRangeOverlap overlap; - /* Since we're traversing in order, stop here */ - if (compare_intervals (range->start, range->end, start, end) > 0 && - g_date_time_compare (start, range->end) >= 0) + struct { + GcalRange *range; + GPtrArray **array; + } *gather_data = user_data; + + overlap = gcal_range_calculate_overlap (range, gather_data->range, &position); + + if (overlap == GCAL_RANGE_NO_OVERLAP) { - return GCAL_TRAVERSE_STOP; + if (position == GCAL_RANGE_BEFORE) + return GCAL_TRAVERSE_CONTINUE; + if (position == GCAL_RANGE_AFTER) + return GCAL_TRAVERSE_STOP; } - /* - * If the current range doesn't overlap but we're before the desired range, keep - * traversing the tree - */ - if (g_date_time_compare (range->start, end) >= 0) - return GCAL_TRAVERSE_CONTINUE; + if (!*gather_data->array) + *gather_data->array = g_ptr_array_new (); - if (!*range->array) - *range->array = g_ptr_array_new (); - - g_ptr_array_add (*range->array, data); + g_ptr_array_add (*gather_data->array, data); return GCAL_TRAVERSE_CONTINUE; } static inline gboolean -count_entries_at_range (GDateTime *start, - GDateTime *end, +count_entries_at_range (GcalRange *range, gpointer data, gpointer user_data) { - struct { - GDateTime *start, *end; - guint64 counter; - } *range = user_data; + GcalRangePosition position; + GcalRangeOverlap overlap; - /* Since we're traversing in order, stop here */ - if (compare_intervals (range->start, range->end, start, end) > 0 && - g_date_time_compare (start, range->end) >= 0) + struct { + GcalRange *range; + guint64 counter; + } *gather_data = user_data; + + overlap = gcal_range_calculate_overlap (range, gather_data->range, &position); + + if (overlap == GCAL_RANGE_NO_OVERLAP) { - return GCAL_TRAVERSE_STOP; + if (position == GCAL_RANGE_BEFORE) + return GCAL_TRAVERSE_CONTINUE; + if (position == GCAL_RANGE_AFTER) + return GCAL_TRAVERSE_STOP; } - /* - * If the current range doesn't overlap but we're before the desired range, keep - * traversing the tree - */ - if (g_date_time_compare (range->start, end) >= 0) - return GCAL_TRAVERSE_CONTINUE; - - range->counter++; + gather_data->counter++; return GCAL_TRAVERSE_CONTINUE; } static inline gboolean -remove_data_func (GDateTime *start, - GDateTime *end, +remove_data_func (GcalRange *range, gpointer data, gpointer user_data) { @@ -487,7 +436,7 @@ remove_data_func (GDateTime *start, if (remove_data->data == data) { - gcal_range_tree_remove_range (remove_data->range_tree, start, end, data); + gcal_range_tree_remove_range (remove_data->range_tree, range, data); return GCAL_TRAVERSE_STOP; } @@ -607,8 +556,7 @@ gcal_range_tree_unref (GcalRangeTree *self) /** * gcal_range_tree_add_range: * @self: a #GcalRangeTree - * @start: start of the interval - * @end: end of the interval + * @range: a #GcalRange * @data: user data * * Adds the range into @self, and attach @data do it. It is @@ -618,37 +566,32 @@ gcal_range_tree_unref (GcalRangeTree *self) */ void gcal_range_tree_add_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end, + GcalRange *range, gpointer data) { g_return_if_fail (self); - g_return_if_fail (end && start); - g_return_if_fail (g_date_time_compare (end, start) >= 0); + g_return_if_fail (range); - self->root = insert (self->root, start, end, data, self->destroy_func); + self->root = insert (self->root, range, data, self->destroy_func); } /** * gcal_range_tree_remove_range: * @self: a #GcalRangeTree - * @start: the start of the range - * @end: the end of the range + * @range: a #GcalRange * @data: user data * * Removes (or decreases the reference count) of the given interval. */ void gcal_range_tree_remove_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end, + GcalRange *range, gpointer data) { g_return_if_fail (self); - g_return_if_fail (end && start); - g_return_if_fail (g_date_time_compare (end, start) >= 0); + g_return_if_fail (range); - self->root = remove_node (self->root, start, end, data); + self->root = remove_node (self->root, range, data); } /** @@ -717,33 +660,30 @@ gcal_range_tree_get_all_data (GcalRangeTree *self) /** * gcal_range_tree_get_data_at_range: * @self: a #GcalRangeTree - * @start: inclusive start of the range - * @end: exclusive end of the range + * @range: a #GcalRange * - * Retrieves the data of every node between @start and @end. + * Retrieves the data of every node within @range. * * Returns: (transfer full): a #GPtrArray. Unref with g_ptr_array_unref() * when finished. */ GPtrArray* gcal_range_tree_get_data_at_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end) + GcalRange *range) { GPtrArray *data; struct { - GDateTime *start, *end; + GcalRange *range; GPtrArray **array; - } range = { start, end, &data }; + } gather_data = { range, &data }; g_return_val_if_fail (self, NULL); - g_return_val_if_fail (end && start, NULL); - g_return_val_if_fail (g_date_time_compare (end, start) >= 0, NULL); + g_return_val_if_fail (range, NULL); data = NULL; - gcal_range_tree_traverse (self, G_IN_ORDER, gather_data_at_range, &range); + gcal_range_tree_traverse (self, G_IN_ORDER, gather_data_at_range, &gather_data); return data; } @@ -751,8 +691,7 @@ gcal_range_tree_get_data_at_range (GcalRangeTree *self, /** * gcal_range_tree_count_entries_at_range: * @self: a #GcalRangeTree - * @start: start of the range - * @end: end of the range + * @range: a #GcalRange * * Counts the number of entries available in the given * range. @@ -761,19 +700,17 @@ gcal_range_tree_get_data_at_range (GcalRangeTree *self, */ guint64 gcal_range_tree_count_entries_at_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end) + GcalRange *range) { struct { - GDateTime *start, *end; + GcalRange *range; guint64 counter; - } range = { start, end, 0 }; + } gather_data = { range, 0 }; g_return_val_if_fail (self, 0); - g_return_val_if_fail (end && start, 0); - g_return_val_if_fail (g_date_time_compare (end, start) >= 0, 0); + g_return_val_if_fail (range, 0); - gcal_range_tree_traverse (self, G_IN_ORDER, count_entries_at_range, &range); + gcal_range_tree_traverse (self, G_IN_ORDER, count_entries_at_range, &gather_data); - return range.counter; + return gather_data.counter; } diff --git a/src/core/gcal-range-tree.h b/src/core/gcal-range-tree.h index b5e1bbc5..9bfa5f8a 100644 --- a/src/core/gcal-range-tree.h +++ b/src/core/gcal-range-tree.h @@ -18,6 +18,8 @@ #pragma once +#include "gcal-range.h" + #include G_BEGIN_DECLS @@ -37,8 +39,7 @@ typedef struct _GcalRangeTree GcalRangeTree; * * Returns: %TRUE to stop traversing, %FALSE to continue traversing */ -typedef gboolean (*GcalRangeTraverseFunc) (GDateTime *start, - GDateTime *end, +typedef gboolean (*GcalRangeTraverseFunc) (GcalRange *range, gpointer data, gpointer user_data); @@ -58,13 +59,11 @@ GcalRangeTree* gcal_range_tree_ref (GcalRangeTree void gcal_range_tree_unref (GcalRangeTree *self); void gcal_range_tree_add_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end, + GcalRange *range, gpointer data); void gcal_range_tree_remove_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end, + GcalRange *range, gpointer data); void gcal_range_tree_remove_data (GcalRangeTree *self, @@ -78,12 +77,10 @@ void gcal_range_tree_traverse (GcalRangeTree GPtrArray* gcal_range_tree_get_all_data (GcalRangeTree *self); GPtrArray* gcal_range_tree_get_data_at_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end); + GcalRange *range); guint64 gcal_range_tree_count_entries_at_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end); + GcalRange *range); G_DEFINE_AUTOPTR_CLEANUP_FUNC (GcalRangeTree, gcal_range_tree_unref) diff --git a/src/core/gcal-timeline.c b/src/core/gcal-timeline.c index d630e6a4..5732a313 100644 --- a/src/core/gcal-timeline.c +++ b/src/core/gcal-timeline.c @@ -308,20 +308,27 @@ update_range (GcalTimeline *self) static void calculate_changed_events (GcalTimeline *self, GcalTimelineSubscriber *subscriber, - GDateTime *old_range_start, - GDateTime *old_range_end, - GDateTime *new_range_start, - GDateTime *new_range_end) + GcalRange *old_range, + GcalRange *new_range) { g_autoptr (GPtrArray) subscriber_array = NULL; g_autoptr (GPtrArray) events_to_remove = NULL; g_autoptr (GPtrArray) events_to_add = NULL; + g_autoptr (GDateTime) old_range_start = NULL; + g_autoptr (GDateTime) old_range_end = NULL; + g_autoptr (GDateTime) new_range_start = NULL; + g_autoptr (GDateTime) new_range_end = NULL; gint range_diff; gint i; events_to_add = g_ptr_array_new (); events_to_remove = g_ptr_array_new (); + old_range_start = gcal_range_get_start (old_range); + old_range_end = gcal_range_get_end (old_range); + new_range_start = gcal_range_get_start (new_range); + new_range_end = gcal_range_get_end (new_range); + /* Start ranges diff */ range_diff = g_date_time_compare (old_range_start, new_range_start); if (range_diff != 0) @@ -330,15 +337,19 @@ calculate_changed_events (GcalTimeline *self, if (range_diff < 0) { + g_autoptr (GcalRange) range = gcal_range_new (old_range_start, new_range_start, GCAL_RANGE_DEFAULT); + /* Removed */ - events = gcal_range_tree_get_data_at_range (self->events, old_range_start, new_range_start); + events = gcal_range_tree_get_data_at_range (self->events, range); if (events) g_ptr_array_extend (events_to_remove, events, NULL, NULL); } else if (range_diff > 0) { + g_autoptr (GcalRange) range = gcal_range_new (new_range_start, old_range_start, GCAL_RANGE_DEFAULT); + /* Added */ - events = gcal_range_tree_get_data_at_range (self->events, new_range_start, old_range_start); + events = gcal_range_tree_get_data_at_range (self->events, range); if (events) g_ptr_array_extend (events_to_add, events, NULL, NULL); } @@ -352,13 +363,17 @@ calculate_changed_events (GcalTimeline *self, if (range_diff < 0) { - events = gcal_range_tree_get_data_at_range (self->events, old_range_end, new_range_end); + g_autoptr (GcalRange) range = gcal_range_new (old_range_end, new_range_end, GCAL_RANGE_DEFAULT); + + events = gcal_range_tree_get_data_at_range (self->events, range); if (events) g_ptr_array_extend (events_to_add, events, NULL, NULL); } else if (range_diff > 0) { - events = gcal_range_tree_get_data_at_range (self->events, new_range_end, old_range_end); + g_autoptr (GcalRange) range = gcal_range_new (new_range_end, old_range_end, GCAL_RANGE_DEFAULT); + + events = gcal_range_tree_get_data_at_range (self->events, range); if (events) g_ptr_array_extend (events_to_remove, events, NULL, NULL); } @@ -403,6 +418,7 @@ static void add_cached_events_to_subscriber (GcalTimeline *self, GcalTimelineSubscriber *subscriber) { + g_autoptr (GcalRange) subscriber_range = NULL; g_autoptr (GDateTime) subscriber_start = NULL; g_autoptr (GDateTime) subscriber_end = NULL; g_autoptr (GPtrArray) subscriber_array = NULL; @@ -413,8 +429,9 @@ add_cached_events_to_subscriber (GcalTimeline *self, subscriber_start = gcal_timeline_subscriber_get_range_start (subscriber); subscriber_end = gcal_timeline_subscriber_get_range_end (subscriber); + subscriber_range = gcal_range_new (subscriber_start, subscriber_end, GCAL_RANGE_DEFAULT); - events_to_add = gcal_range_tree_get_data_at_range (self->events, subscriber_start, subscriber_end); + events_to_add = gcal_range_tree_get_data_at_range (self->events, subscriber_range); subscriber_array = g_ptr_array_new (); g_ptr_array_add (subscriber_array, subscriber); @@ -441,8 +458,8 @@ static void update_subscriber_range (GcalTimeline *self, GcalTimelineSubscriber *subscriber) { - g_autoptr (GDateTime) new_range_start = NULL; - g_autoptr (GDateTime) new_range_end = NULL; + g_autoptr (GcalRange) old_range = NULL; + g_autoptr (GcalRange) new_range = NULL; SubscriberData *subscriber_data; @@ -451,26 +468,23 @@ update_subscriber_range (GcalTimeline *self, subscriber_data = g_hash_table_lookup (self->subscribers, subscriber); g_assert (subscriber_data != NULL); - new_range_start = gcal_timeline_subscriber_get_range_start (subscriber); - new_range_end = gcal_timeline_subscriber_get_range_end (subscriber); + old_range = gcal_range_new (subscriber_data->range_start, subscriber_data->range_end, GCAL_RANGE_DEFAULT); + new_range = gcal_range_new_take (gcal_timeline_subscriber_get_range_start (subscriber), + gcal_timeline_subscriber_get_range_end (subscriber), + GCAL_RANGE_DEFAULT); /* Diff new and old event ranges */ - calculate_changed_events (self, - subscriber, - subscriber_data->range_start, - subscriber_data->range_end, - new_range_start, - new_range_end); + calculate_changed_events (self, subscriber, old_range, new_range); /* Update the subscriber range */ gcal_range_tree_remove_data (self->subscriber_ranges, subscriber); - gcal_range_tree_add_range (self->subscriber_ranges, - new_range_start, - new_range_end, - subscriber); + gcal_range_tree_add_range (self->subscriber_ranges, new_range, subscriber); - gcal_set_date_time (&subscriber_data->range_start, new_range_start); - gcal_set_date_time (&subscriber_data->range_end, new_range_end); + gcal_clear_date_time (&subscriber_data->range_start); + subscriber_data->range_start = gcal_range_get_start (new_range); + + gcal_clear_date_time (&subscriber_data->range_end); + subscriber_data->range_end = gcal_range_get_end (new_range); GCAL_EXIT; } @@ -499,16 +513,14 @@ on_calendar_monitor_event_added_cb (GcalCalendarMonitor *monitor, GcalTimeline *self) { g_autoptr (GPtrArray) subscribers_at_range = NULL; - GDateTime *event_start; - GDateTime *event_end; + GcalRange *event_range; GCAL_ENTRY; - event_start = gcal_event_get_date_start (event); - event_end = gcal_event_get_date_end (event); + event_range = gcal_event_get_range (event); /* Add to all subscribers within the event range */ - subscribers_at_range = gcal_range_tree_get_data_at_range (self->subscriber_ranges, event_start, event_end); + subscribers_at_range = gcal_range_tree_get_data_at_range (self->subscriber_ranges, event_range); if (subscribers_at_range) queue_event_data (self, ADD_EVENT, subscribers_at_range, event, NULL, TRUE); @@ -523,17 +535,15 @@ on_calendar_monitor_event_updated_cb (GcalCalendarMonitor *monitor, GcalTimeline *self) { g_autoptr (GPtrArray) subscribers_at_range = NULL; - GDateTime *event_start; - GDateTime *event_end; + GcalRange *event_range; GCAL_ENTRY; /* Add the updated event to the (potentially new) range */ - event_start = gcal_event_get_date_start (event); - event_end = gcal_event_get_date_end (event); + event_range = gcal_event_get_range (event); /* Add to all subscribers within the event range */ - subscribers_at_range = gcal_range_tree_get_data_at_range (self->subscriber_ranges, event_start, event_end); + subscribers_at_range = gcal_range_tree_get_data_at_range (self->subscriber_ranges, event_range); if (subscribers_at_range) queue_event_data (self, UPDATE_EVENT, subscribers_at_range, event, old_event, TRUE); @@ -547,16 +557,14 @@ on_calendar_monitor_event_removed_cb (GcalCalendarMonitor *monitor, GcalTimeline *self) { g_autoptr (GPtrArray) subscribers_at_range = NULL; - GDateTime *event_start; - GDateTime *event_end; + GcalRange *event_range; GCAL_ENTRY; - event_start = gcal_event_get_date_start (event); - event_end = gcal_event_get_date_end (event); + event_range = gcal_event_get_range (event); /* Add to all subscribers within the event range */ - subscribers_at_range = gcal_range_tree_get_data_at_range (self->subscriber_ranges, event_start, event_end); + subscribers_at_range = gcal_range_tree_get_data_at_range (self->subscriber_ranges, event_range); if (subscribers_at_range) queue_event_data (self, REMOVE_EVENT, subscribers_at_range, event, NULL, TRUE); @@ -623,8 +631,7 @@ timeline_source_dispatch (GSource *source, { TimelineSource *timeline_source; GcalTimeline *self; - GDateTime *event_start; - GDateTime *event_end; + GcalRange *event_range; QueueData *queue_data; GcalEvent *event; gint i; @@ -636,8 +643,7 @@ timeline_source_dispatch (GSource *source, queue_data = g_queue_pop_head (self->event_queue); event = queue_data->event; - event_start = gcal_event_get_date_start (event); - event_end = gcal_event_get_date_end (event); + event_range = gcal_event_get_range (event); switch (queue_data->queue_event) { @@ -647,7 +653,7 @@ timeline_source_dispatch (GSource *source, gcal_event_get_uid (event)); if (queue_data->update_range_tree) - gcal_range_tree_add_range (self->events, event_start, event_end, g_object_ref (event)); + gcal_range_tree_add_range (self->events, event_range, g_object_ref (event)); for (i = 0; queue_data->subscribers && i < queue_data->subscribers->len; i++) { @@ -668,15 +674,13 @@ timeline_source_dispatch (GSource *source, if (queue_data->update_range_tree) { - GDateTime *old_event_start; - GDateTime *old_event_end; + GcalRange *old_event_range; /* Remove the old event */ - old_event_start = gcal_event_get_date_start (queue_data->old_event); - old_event_end = gcal_event_get_date_end (queue_data->old_event); + old_event_range = gcal_event_get_range (queue_data->old_event); - gcal_range_tree_remove_range (self->events, old_event_start, old_event_end, queue_data->old_event); - gcal_range_tree_add_range (self->events, event_start, event_end, g_object_ref (event)); + gcal_range_tree_remove_range (self->events, old_event_range, queue_data->old_event); + gcal_range_tree_add_range (self->events, event_range, g_object_ref (event)); } for (i = 0; queue_data->subscribers && i < queue_data->subscribers->len; i++) @@ -703,7 +707,7 @@ timeline_source_dispatch (GSource *source, } if (queue_data->update_range_tree) - gcal_range_tree_remove_range (self->events, event_start, event_end, event); + gcal_range_tree_remove_range (self->events, event_range, event); break; } @@ -1007,13 +1011,14 @@ gcal_timeline_get_events_at_range (GcalTimeline *self, GDateTime *range_end) { g_autoptr (GPtrArray) events_at_range = NULL; + g_autoptr (GcalRange) range = NULL; g_return_val_if_fail (GCAL_IS_TIMELINE (self), NULL); g_return_val_if_fail (range_start != NULL, NULL); g_return_val_if_fail (range_end != NULL, NULL); - g_return_val_if_fail (g_date_time_compare (range_start, range_end) < 0, NULL); - events_at_range = gcal_range_tree_get_data_at_range (self->events, range_start, range_end); + range = gcal_range_new (range_start, range_end, GCAL_RANGE_DEFAULT); + events_at_range = gcal_range_tree_get_data_at_range (self->events, range); return g_steal_pointer (&events_at_range); } diff --git a/src/views/gcal-week-grid.c b/src/views/gcal-week-grid.c index 5e2b7ab2..7a06774e 100644 --- a/src/views/gcal-week-grid.c +++ b/src/views/gcal-week-grid.c @@ -1,6 +1,6 @@ /* gcal-week-grid.c * - * Copyright (C) 2016 Georges Basile Stavracas Neto + * Copyright (C) 2016-2020 Georges Basile Stavracas Neto * Vamsi Krishna Gollapudi * * This program is free software: you can redistribute it and/or modify @@ -127,14 +127,13 @@ uint16_compare (gconstpointer a, static inline guint get_event_index (GcalRangeTree *tree, - GDateTime *start, - GDateTime *end) + GcalRange *range) { g_autoptr (GPtrArray) array; gint idx, i; i = idx = 0; - array = gcal_range_tree_get_data_at_range (tree, start, end); + array = gcal_range_tree_get_data_at_range (tree, range); if (!array) return 0; @@ -154,59 +153,35 @@ get_event_index (GcalRangeTree *tree, static guint count_overlaps_at_range (GcalRangeTree *self, - GDateTime *start, - GDateTime *end) + GcalRange *range) { + g_autoptr (GDateTime) start = NULL; + g_autoptr (GDateTime) end = NULL; guint64 counter; + gint minutes; + gint i; g_return_val_if_fail (self, 0); counter = 0; + start = gcal_range_get_start (range); + end = gcal_range_get_end (range); + minutes = g_date_time_difference (end, start) / G_TIME_SPAN_MINUTE; - while (g_date_time_compare (start, end) < 0) + for (i = 0; i < minutes; i++) { - g_autoptr (GDateTime) start_plus_one = NULL; + g_autoptr (GcalRange) minute_range = NULL; guint n_events; - start_plus_one = g_date_time_add_minutes (start, 1); - n_events = gcal_range_tree_count_entries_at_range (self, start, start_plus_one); + minute_range = gcal_range_new_take (g_date_time_add_minutes (start, i), + g_date_time_add_minutes (start, i + 1), + GCAL_RANGE_DEFAULT); + n_events = gcal_range_tree_count_entries_at_range (self, minute_range); if (n_events == 0) break; counter = MAX (counter, n_events); - - start = g_steal_pointer (&start_plus_one); - } - - return counter; -} - -static guint -count_overlaps_of_event (GcalRangeTree *self, - GDateTime *day_start, - GDateTime *day_end, - GDateTime *event_start, - GDateTime *event_end) -{ - guint64 counter; - - counter = count_overlaps_at_range (self, event_start, day_end); - - while (g_date_time_compare (event_start, day_start) > 0) - { - g_autoptr (GDateTime) start_minus_one = NULL; - guint n_events; - - start_minus_one = g_date_time_add_minutes (event_start, -1); - n_events = gcal_range_tree_count_entries_at_range (self, start_minus_one, event_start); - - if (n_events == 0) - break; - - counter = MAX (counter, n_events); - - event_start = g_date_time_add_minutes (event_start, 1); } return counter; @@ -589,20 +564,21 @@ gcal_week_grid_size_allocate (GtkWidget *widget, */ for (i = 0; i < 7; i++) { - g_autoptr (GDateTime) day_start = NULL; - g_autoptr (GDateTime) day_end = NULL; + g_autoptr (GcalRange) day_range = NULL; GPtrArray *widgets_data; guint j; - day_start = g_date_time_add_days (week_start, i); - day_end = g_date_time_add_days (day_start, 1); - widgets_data = gcal_range_tree_get_data_at_range (self->events, day_start, day_end); + day_range = gcal_range_new_take (g_date_time_add_days (week_start, i), + g_date_time_add_days (week_start, i + 1), + GCAL_RANGE_DEFAULT); + widgets_data = gcal_range_tree_get_data_at_range (self->events, day_range); for (j = 0; widgets_data && j < widgets_data->len; j++) { GtkStyleContext *context; GtkAllocation child_allocation; GtkWidget *event_widget; + GcalRange *event_range; GDateTime *event_start; GDateTime *event_end; ChildData *data; @@ -617,15 +593,16 @@ gcal_week_grid_size_allocate (GtkWidget *widget, data = g_ptr_array_index (widgets_data, j); event_widget = data->widget; + event_range = gcal_event_get_range (data->event); event_start = gcal_event_get_date_start (data->event); event_end = gcal_event_get_date_end (data->event); context = gtk_widget_get_style_context (event_widget); /* The total number of events available in this range */ - events_at_range = count_overlaps_of_event (self->events, day_start, day_end, event_start, event_end); + events_at_range = count_overlaps_at_range (self->events, event_range); /* The real horizontal position of this event */ - widget_index = get_event_index (overlaps, event_start, event_end); + widget_index = get_event_index (overlaps, event_range); /* Gtk complains about that */ gtk_widget_get_preferred_height (event_widget, NULL, &natural_height); @@ -663,10 +640,7 @@ gcal_week_grid_size_allocate (GtkWidget *widget, * Add the current event to the temporary overlaps tree so we have a way to * know how many events are already positioned in the current column. */ - gcal_range_tree_add_range (overlaps, - event_start, - event_end, - GUINT_TO_POINTER (widget_index)); + gcal_range_tree_add_range (overlaps, event_range, GUINT_TO_POINTER (widget_index)); } g_clear_pointer (&widgets_data, g_ptr_array_unref); @@ -1114,8 +1088,7 @@ gcal_week_grid_add_event (GcalWeekGrid *self, NULL); gcal_range_tree_add_range (self->events, - gcal_event_get_date_start (event), - gcal_event_get_date_end (event), + gcal_event_get_range (event), child_data_new (widget, event)); setup_event_widget (self, widget); @@ -1146,10 +1119,7 @@ gcal_week_grid_remove_event (GcalWeekGrid *self, if (g_strcmp0 (gcal_event_get_uid (event), uid) != 0) continue; - gcal_range_tree_remove_range (self->events, - gcal_event_get_date_start (event), - gcal_event_get_date_end (event), - data); + gcal_range_tree_remove_range (self->events, gcal_event_get_range (event), data); destroy_event_widget (self, data->widget); gtk_widget_queue_allocate (GTK_WIDGET (self)); g_object_unref (event); diff --git a/tests/test-range-tree.c b/tests/test-range-tree.c index 8315b435..ddc7e8a8 100644 --- a/tests/test-range-tree.c +++ b/tests/test-range-tree.c @@ -37,6 +37,7 @@ static void range_tree_insert (void) { g_autoptr (GcalRangeTree) range_tree = NULL; + g_autoptr (GcalRange) range = NULL; g_autoptr (GDateTime) start = NULL; g_autoptr (GDateTime) end = NULL; @@ -45,15 +46,16 @@ range_tree_insert (void) start = g_date_time_new_local (2020, 3, 17, 9, 30, 0); end = g_date_time_add_hours (start, 1); + range = gcal_range_new (start, end, GCAL_RANGE_DEFAULT); - gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xdeadbeef); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 1); + gcal_range_tree_add_range (range_tree, range, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 1); - gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0x8badf00d); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 2); + gcal_range_tree_add_range (range_tree, range, (gpointer) 0x8badf00d); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 2); - gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0x0badcafe); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 3); + gcal_range_tree_add_range (range_tree, range, (gpointer) 0x0badcafe); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 3); } /*********************************************************************************************************************/ @@ -73,8 +75,7 @@ static struct { }; static gboolean -traverse_func (GDateTime *start, - GDateTime *end, +traverse_func (GcalRange *range, gpointer data, gpointer user_data) { @@ -96,13 +97,13 @@ range_tree_traverse (void) utc = g_time_zone_new_utc (); for (i = 0; i < G_N_ELEMENTS (ranges); i++) { - g_autoptr (GDateTime) start = NULL; - g_autoptr (GDateTime) end = NULL; + g_autoptr (GcalRange) range = NULL; - start = g_date_time_new_from_iso8601 (ranges[i].start, utc); - end = g_date_time_new_from_iso8601 (ranges[i].end, utc); + range = gcal_range_new_take (g_date_time_new_from_iso8601 (ranges[i].start, utc), + g_date_time_new_from_iso8601 (ranges[i].end, utc), + GCAL_RANGE_DEFAULT); - gcal_range_tree_add_range (range_tree, start, end, GINT_TO_POINTER (i)); + gcal_range_tree_add_range (range_tree, range, GINT_TO_POINTER (i)); } gcal_range_tree_traverse (range_tree, G_PRE_ORDER, traverse_func, NULL); @@ -118,6 +119,8 @@ range_tree_smaller_range (void) g_autoptr (GcalRangeTree) range_tree = NULL; g_autoptr (GDateTime) range_start = NULL; g_autoptr (GDateTime) range_end = NULL; + g_autoptr (GcalRange) range1 = NULL; + g_autoptr (GcalRange) range2 = NULL; g_autoptr (GDateTime) start = NULL; g_autoptr (GDateTime) end = NULL; @@ -126,14 +129,16 @@ range_tree_smaller_range (void) start = g_date_time_new_local (2020, 3, 17, 9, 30, 0); end = g_date_time_add_hours (start, 1); + range1 = gcal_range_new (start, end, GCAL_RANGE_DEFAULT); - gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xdeadbeef); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 1); + gcal_range_tree_add_range (range_tree, range1, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range1), ==, 1); range_start = g_date_time_new_local (2020, 3, 20, 9, 30, 0); range_end = g_date_time_add_hours (range_start, 1); + range2 = gcal_range_new (range_start, range_end, GCAL_RANGE_DEFAULT); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range_start, range_end), ==, 0); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range2), ==, 0); } /*********************************************************************************************************************/ @@ -142,6 +147,7 @@ static void range_tree_remove_data (void) { g_autoptr (GcalRangeTree) range_tree = NULL; + g_autoptr (GcalRange) range = NULL; g_autoptr (GDateTime) start = NULL; g_autoptr (GDateTime) end = NULL; @@ -150,30 +156,31 @@ range_tree_remove_data (void) start = g_date_time_new_local (2020, 3, 17, 9, 30, 0); end = g_date_time_add_hours (start, 1); + range = gcal_range_new (start, end, GCAL_RANGE_DEFAULT); - gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xdeadbeef); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 1); + gcal_range_tree_add_range (range_tree, range, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 1); - gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xdeadbeef); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 2); + gcal_range_tree_add_range (range_tree, range, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 2); - gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xbadcafe); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 3); + gcal_range_tree_add_range (range_tree, range, (gpointer) 0xbadcafe); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 3); /* Remove the 2 deadbeefs */ gcal_range_tree_remove_data (range_tree, (gpointer) 0xdeadbeef); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 2); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 2); gcal_range_tree_remove_data (range_tree, (gpointer) 0xdeadbeef); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 1); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 1); /* Try again */ gcal_range_tree_remove_data (range_tree, (gpointer) 0xdeadbeef); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 1); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 1); /* Remove bad cafe */ gcal_range_tree_remove_data (range_tree, (gpointer) 0xbadcafe); - g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 0); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 0); } /*********************************************************************************************************************/