range-tree: Use GcalRange
This commit is contained in:
+97
-160
@@ -1,6 +1,6 @@
|
|||||||
/* gcal-range-tree.c
|
/* gcal-range-tree.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
* Copyright (C) 2016-2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* 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 *left;
|
||||||
struct _Node *right;
|
struct _Node *right;
|
||||||
GDateTime *start;
|
GcalRange *range;
|
||||||
GDateTime *end;
|
|
||||||
GDateTime *max;
|
GDateTime *max;
|
||||||
guint16 hits;
|
guint16 hits;
|
||||||
gint64 height;
|
gint64 height;
|
||||||
@@ -74,8 +73,7 @@ destroy_tree (Node *n)
|
|||||||
destroy_tree (n->left);
|
destroy_tree (n->left);
|
||||||
destroy_tree (n->right);
|
destroy_tree (n->right);
|
||||||
|
|
||||||
gcal_clear_date_time (&n->start);
|
g_clear_pointer (&n->range, gcal_range_unref);
|
||||||
gcal_clear_date_time (&n->end);
|
|
||||||
gcal_clear_date_time (&n->max);
|
gcal_clear_date_time (&n->max);
|
||||||
|
|
||||||
g_ptr_array_unref (n->data_array);
|
g_ptr_array_unref (n->data_array);
|
||||||
@@ -100,71 +98,16 @@ balance (Node *n)
|
|||||||
return n ? height (n->left) - height (n->right) : 0;
|
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*
|
static Node*
|
||||||
node_new (GDateTime *start,
|
node_new (GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data,
|
gpointer data,
|
||||||
GDestroyNotify destroy_func)
|
GDestroyNotify destroy_func)
|
||||||
{
|
{
|
||||||
Node *n;
|
Node *n;
|
||||||
|
|
||||||
n = g_new0 (Node, 1);
|
n = g_new0 (Node, 1);
|
||||||
n->start = g_date_time_ref (start);
|
n->range = gcal_range_ref (range);
|
||||||
n->end = g_date_time_ref (end);
|
n->max = gcal_range_get_end (range);
|
||||||
n->max = g_date_time_ref (end);
|
|
||||||
n->height = 1;
|
n->height = 1;
|
||||||
n->hits = 1;
|
n->hits = 1;
|
||||||
|
|
||||||
@@ -246,31 +189,30 @@ rebalance (Node *n)
|
|||||||
|
|
||||||
static Node*
|
static Node*
|
||||||
insert (Node *n,
|
insert (Node *n,
|
||||||
GDateTime *start,
|
GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data,
|
gpointer data,
|
||||||
GDestroyNotify destroy_func)
|
GDestroyNotify destroy_func)
|
||||||
{
|
{
|
||||||
|
g_autoptr (GDateTime) range_end = NULL;
|
||||||
gint result;
|
gint result;
|
||||||
|
|
||||||
if (!n)
|
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)
|
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)
|
else if (result > 0)
|
||||||
n->right = insert (n->right, start, end, data, destroy_func);
|
n->right = insert (n->right, range, data, destroy_func);
|
||||||
else
|
else
|
||||||
return hit_node (n, data);
|
return hit_node (n, data);
|
||||||
|
|
||||||
|
range_end = gcal_range_get_end (range);
|
||||||
|
|
||||||
/* Update the current node's maximum subrange value */
|
/* Update the current node's maximum subrange value */
|
||||||
if (!n->max || g_date_time_compare (end, n->max) > 0)
|
if (!n->max || g_date_time_compare (range_end, n->max) > 0)
|
||||||
{
|
gcal_set_date_time (&n->max, range_end);
|
||||||
gcal_clear_date_time (&n->max);
|
|
||||||
n->max = g_date_time_ref (end);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rebalance (n);
|
return rebalance (n);
|
||||||
}
|
}
|
||||||
@@ -327,19 +269,32 @@ delete_node (Node *n,
|
|||||||
|
|
||||||
static Node*
|
static Node*
|
||||||
remove_node (Node *n,
|
remove_node (Node *n,
|
||||||
GDateTime *start,
|
GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
|
GcalRangePosition position;
|
||||||
|
|
||||||
if (!n)
|
if (!n)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (is_interval_lower (n, start, end))
|
gcal_range_calculate_overlap (range, n->range, &position);
|
||||||
n->left = remove_node (n->left, start, end, data);
|
|
||||||
else if (is_interval_higher (n, start, end))
|
switch (position)
|
||||||
n->right = remove_node (n->right, start, end, data);
|
{
|
||||||
else
|
case GCAL_RANGE_BEFORE:
|
||||||
return delete_node (n, data);
|
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);
|
return rebalance (n);
|
||||||
}
|
}
|
||||||
@@ -354,7 +309,7 @@ run_traverse_func (Node *n,
|
|||||||
|
|
||||||
for (i = 0; i < n->hits; i++)
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,8 +354,7 @@ traverse (Node *n,
|
|||||||
|
|
||||||
/* Internal traverse functions */
|
/* Internal traverse functions */
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
gather_all_data (GDateTime *start,
|
gather_all_data (GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -412,71 +366,66 @@ gather_all_data (GDateTime *start,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
gather_data_at_range (GDateTime *start,
|
gather_data_at_range (GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
struct {
|
GcalRangePosition position;
|
||||||
GDateTime *start, *end;
|
GcalRangeOverlap overlap;
|
||||||
GPtrArray **array;
|
|
||||||
} *range = user_data;
|
|
||||||
|
|
||||||
/* Since we're traversing in order, stop here */
|
struct {
|
||||||
if (compare_intervals (range->start, range->end, start, end) > 0 &&
|
GcalRange *range;
|
||||||
g_date_time_compare (start, range->end) >= 0)
|
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 (!*gather_data->array)
|
||||||
* If the current range doesn't overlap but we're before the desired range, keep
|
*gather_data->array = g_ptr_array_new ();
|
||||||
* traversing the tree
|
|
||||||
*/
|
|
||||||
if (g_date_time_compare (range->start, end) >= 0)
|
|
||||||
return GCAL_TRAVERSE_CONTINUE;
|
|
||||||
|
|
||||||
if (!*range->array)
|
g_ptr_array_add (*gather_data->array, data);
|
||||||
*range->array = g_ptr_array_new ();
|
|
||||||
|
|
||||||
g_ptr_array_add (*range->array, data);
|
|
||||||
|
|
||||||
return GCAL_TRAVERSE_CONTINUE;
|
return GCAL_TRAVERSE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
count_entries_at_range (GDateTime *start,
|
count_entries_at_range (GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
struct {
|
GcalRangePosition position;
|
||||||
GDateTime *start, *end;
|
GcalRangeOverlap overlap;
|
||||||
guint64 counter;
|
|
||||||
} *range = user_data;
|
|
||||||
|
|
||||||
/* Since we're traversing in order, stop here */
|
struct {
|
||||||
if (compare_intervals (range->start, range->end, start, end) > 0 &&
|
GcalRange *range;
|
||||||
g_date_time_compare (start, range->end) >= 0)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
gather_data->counter++;
|
||||||
* 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++;
|
|
||||||
|
|
||||||
return GCAL_TRAVERSE_CONTINUE;
|
return GCAL_TRAVERSE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
remove_data_func (GDateTime *start,
|
remove_data_func (GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -487,7 +436,7 @@ remove_data_func (GDateTime *start,
|
|||||||
|
|
||||||
if (remove_data->data == data)
|
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;
|
return GCAL_TRAVERSE_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,8 +556,7 @@ gcal_range_tree_unref (GcalRangeTree *self)
|
|||||||
/**
|
/**
|
||||||
* gcal_range_tree_add_range:
|
* gcal_range_tree_add_range:
|
||||||
* @self: a #GcalRangeTree
|
* @self: a #GcalRangeTree
|
||||||
* @start: start of the interval
|
* @range: a #GcalRange
|
||||||
* @end: end of the interval
|
|
||||||
* @data: user data
|
* @data: user data
|
||||||
*
|
*
|
||||||
* Adds the range into @self, and attach @data do it. It is
|
* Adds the range into @self, and attach @data do it. It is
|
||||||
@@ -618,37 +566,32 @@ gcal_range_tree_unref (GcalRangeTree *self)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gcal_range_tree_add_range (GcalRangeTree *self,
|
gcal_range_tree_add_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
g_return_if_fail (self);
|
g_return_if_fail (self);
|
||||||
g_return_if_fail (end && start);
|
g_return_if_fail (range);
|
||||||
g_return_if_fail (g_date_time_compare (end, start) >= 0);
|
|
||||||
|
|
||||||
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:
|
* gcal_range_tree_remove_range:
|
||||||
* @self: a #GcalRangeTree
|
* @self: a #GcalRangeTree
|
||||||
* @start: the start of the range
|
* @range: a #GcalRange
|
||||||
* @end: the end of the range
|
|
||||||
* @data: user data
|
* @data: user data
|
||||||
*
|
*
|
||||||
* Removes (or decreases the reference count) of the given interval.
|
* Removes (or decreases the reference count) of the given interval.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gcal_range_tree_remove_range (GcalRangeTree *self,
|
gcal_range_tree_remove_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
g_return_if_fail (self);
|
g_return_if_fail (self);
|
||||||
g_return_if_fail (end && start);
|
g_return_if_fail (range);
|
||||||
g_return_if_fail (g_date_time_compare (end, start) >= 0);
|
|
||||||
|
|
||||||
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:
|
* gcal_range_tree_get_data_at_range:
|
||||||
* @self: a #GcalRangeTree
|
* @self: a #GcalRangeTree
|
||||||
* @start: inclusive start of the range
|
* @range: a #GcalRange
|
||||||
* @end: exclusive end of the range
|
|
||||||
*
|
*
|
||||||
* 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()
|
* Returns: (transfer full): a #GPtrArray. Unref with g_ptr_array_unref()
|
||||||
* when finished.
|
* when finished.
|
||||||
*/
|
*/
|
||||||
GPtrArray*
|
GPtrArray*
|
||||||
gcal_range_tree_get_data_at_range (GcalRangeTree *self,
|
gcal_range_tree_get_data_at_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range)
|
||||||
GDateTime *end)
|
|
||||||
{
|
{
|
||||||
GPtrArray *data;
|
GPtrArray *data;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GDateTime *start, *end;
|
GcalRange *range;
|
||||||
GPtrArray **array;
|
GPtrArray **array;
|
||||||
} range = { start, end, &data };
|
} gather_data = { range, &data };
|
||||||
|
|
||||||
g_return_val_if_fail (self, NULL);
|
g_return_val_if_fail (self, NULL);
|
||||||
g_return_val_if_fail (end && start, NULL);
|
g_return_val_if_fail (range, NULL);
|
||||||
g_return_val_if_fail (g_date_time_compare (end, start) >= 0, NULL);
|
|
||||||
|
|
||||||
data = 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;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -751,8 +691,7 @@ gcal_range_tree_get_data_at_range (GcalRangeTree *self,
|
|||||||
/**
|
/**
|
||||||
* gcal_range_tree_count_entries_at_range:
|
* gcal_range_tree_count_entries_at_range:
|
||||||
* @self: a #GcalRangeTree
|
* @self: a #GcalRangeTree
|
||||||
* @start: start of the range
|
* @range: a #GcalRange
|
||||||
* @end: end of the range
|
|
||||||
*
|
*
|
||||||
* Counts the number of entries available in the given
|
* Counts the number of entries available in the given
|
||||||
* range.
|
* range.
|
||||||
@@ -761,19 +700,17 @@ gcal_range_tree_get_data_at_range (GcalRangeTree *self,
|
|||||||
*/
|
*/
|
||||||
guint64
|
guint64
|
||||||
gcal_range_tree_count_entries_at_range (GcalRangeTree *self,
|
gcal_range_tree_count_entries_at_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range)
|
||||||
GDateTime *end)
|
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
GDateTime *start, *end;
|
GcalRange *range;
|
||||||
guint64 counter;
|
guint64 counter;
|
||||||
} range = { start, end, 0 };
|
} gather_data = { range, 0 };
|
||||||
|
|
||||||
g_return_val_if_fail (self, 0);
|
g_return_val_if_fail (self, 0);
|
||||||
g_return_val_if_fail (end && start, 0);
|
g_return_val_if_fail (range, 0);
|
||||||
g_return_val_if_fail (g_date_time_compare (end, start) >= 0, 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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "gcal-range.h"
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
@@ -37,8 +39,7 @@ typedef struct _GcalRangeTree GcalRangeTree;
|
|||||||
*
|
*
|
||||||
* Returns: %TRUE to stop traversing, %FALSE to continue traversing
|
* Returns: %TRUE to stop traversing, %FALSE to continue traversing
|
||||||
*/
|
*/
|
||||||
typedef gboolean (*GcalRangeTraverseFunc) (GDateTime *start,
|
typedef gboolean (*GcalRangeTraverseFunc) (GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gpointer user_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_unref (GcalRangeTree *self);
|
||||||
|
|
||||||
void gcal_range_tree_add_range (GcalRangeTree *self,
|
void gcal_range_tree_add_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
|
||||||
void gcal_range_tree_remove_range (GcalRangeTree *self,
|
void gcal_range_tree_remove_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data);
|
gpointer data);
|
||||||
|
|
||||||
void gcal_range_tree_remove_data (GcalRangeTree *self,
|
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_all_data (GcalRangeTree *self);
|
||||||
|
|
||||||
GPtrArray* gcal_range_tree_get_data_at_range (GcalRangeTree *self,
|
GPtrArray* gcal_range_tree_get_data_at_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range);
|
||||||
GDateTime *end);
|
|
||||||
|
|
||||||
guint64 gcal_range_tree_count_entries_at_range (GcalRangeTree *self,
|
guint64 gcal_range_tree_count_entries_at_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range);
|
||||||
GDateTime *end);
|
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GcalRangeTree, gcal_range_tree_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GcalRangeTree, gcal_range_tree_unref)
|
||||||
|
|
||||||
|
|||||||
+59
-54
@@ -308,20 +308,27 @@ update_range (GcalTimeline *self)
|
|||||||
static void
|
static void
|
||||||
calculate_changed_events (GcalTimeline *self,
|
calculate_changed_events (GcalTimeline *self,
|
||||||
GcalTimelineSubscriber *subscriber,
|
GcalTimelineSubscriber *subscriber,
|
||||||
GDateTime *old_range_start,
|
GcalRange *old_range,
|
||||||
GDateTime *old_range_end,
|
GcalRange *new_range)
|
||||||
GDateTime *new_range_start,
|
|
||||||
GDateTime *new_range_end)
|
|
||||||
{
|
{
|
||||||
g_autoptr (GPtrArray) subscriber_array = NULL;
|
g_autoptr (GPtrArray) subscriber_array = NULL;
|
||||||
g_autoptr (GPtrArray) events_to_remove = NULL;
|
g_autoptr (GPtrArray) events_to_remove = NULL;
|
||||||
g_autoptr (GPtrArray) events_to_add = 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 range_diff;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
events_to_add = g_ptr_array_new ();
|
events_to_add = g_ptr_array_new ();
|
||||||
events_to_remove = 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 */
|
/* Start ranges diff */
|
||||||
range_diff = g_date_time_compare (old_range_start, new_range_start);
|
range_diff = g_date_time_compare (old_range_start, new_range_start);
|
||||||
if (range_diff != 0)
|
if (range_diff != 0)
|
||||||
@@ -330,15 +337,19 @@ calculate_changed_events (GcalTimeline *self,
|
|||||||
|
|
||||||
if (range_diff < 0)
|
if (range_diff < 0)
|
||||||
{
|
{
|
||||||
|
g_autoptr (GcalRange) range = gcal_range_new (old_range_start, new_range_start, GCAL_RANGE_DEFAULT);
|
||||||
|
|
||||||
/* Removed */
|
/* 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)
|
if (events)
|
||||||
g_ptr_array_extend (events_to_remove, events, NULL, NULL);
|
g_ptr_array_extend (events_to_remove, events, NULL, NULL);
|
||||||
}
|
}
|
||||||
else if (range_diff > 0)
|
else if (range_diff > 0)
|
||||||
{
|
{
|
||||||
|
g_autoptr (GcalRange) range = gcal_range_new (new_range_start, old_range_start, GCAL_RANGE_DEFAULT);
|
||||||
|
|
||||||
/* Added */
|
/* 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)
|
if (events)
|
||||||
g_ptr_array_extend (events_to_add, events, NULL, NULL);
|
g_ptr_array_extend (events_to_add, events, NULL, NULL);
|
||||||
}
|
}
|
||||||
@@ -352,13 +363,17 @@ calculate_changed_events (GcalTimeline *self,
|
|||||||
|
|
||||||
if (range_diff < 0)
|
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)
|
if (events)
|
||||||
g_ptr_array_extend (events_to_add, events, NULL, NULL);
|
g_ptr_array_extend (events_to_add, events, NULL, NULL);
|
||||||
}
|
}
|
||||||
else if (range_diff > 0)
|
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)
|
if (events)
|
||||||
g_ptr_array_extend (events_to_remove, events, NULL, NULL);
|
g_ptr_array_extend (events_to_remove, events, NULL, NULL);
|
||||||
}
|
}
|
||||||
@@ -403,6 +418,7 @@ static void
|
|||||||
add_cached_events_to_subscriber (GcalTimeline *self,
|
add_cached_events_to_subscriber (GcalTimeline *self,
|
||||||
GcalTimelineSubscriber *subscriber)
|
GcalTimelineSubscriber *subscriber)
|
||||||
{
|
{
|
||||||
|
g_autoptr (GcalRange) subscriber_range = NULL;
|
||||||
g_autoptr (GDateTime) subscriber_start = NULL;
|
g_autoptr (GDateTime) subscriber_start = NULL;
|
||||||
g_autoptr (GDateTime) subscriber_end = NULL;
|
g_autoptr (GDateTime) subscriber_end = NULL;
|
||||||
g_autoptr (GPtrArray) subscriber_array = 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_start = gcal_timeline_subscriber_get_range_start (subscriber);
|
||||||
subscriber_end = gcal_timeline_subscriber_get_range_end (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 ();
|
subscriber_array = g_ptr_array_new ();
|
||||||
g_ptr_array_add (subscriber_array, subscriber);
|
g_ptr_array_add (subscriber_array, subscriber);
|
||||||
@@ -441,8 +458,8 @@ static void
|
|||||||
update_subscriber_range (GcalTimeline *self,
|
update_subscriber_range (GcalTimeline *self,
|
||||||
GcalTimelineSubscriber *subscriber)
|
GcalTimelineSubscriber *subscriber)
|
||||||
{
|
{
|
||||||
g_autoptr (GDateTime) new_range_start = NULL;
|
g_autoptr (GcalRange) old_range = NULL;
|
||||||
g_autoptr (GDateTime) new_range_end = NULL;
|
g_autoptr (GcalRange) new_range = NULL;
|
||||||
SubscriberData *subscriber_data;
|
SubscriberData *subscriber_data;
|
||||||
|
|
||||||
|
|
||||||
@@ -451,26 +468,23 @@ update_subscriber_range (GcalTimeline *self,
|
|||||||
subscriber_data = g_hash_table_lookup (self->subscribers, subscriber);
|
subscriber_data = g_hash_table_lookup (self->subscribers, subscriber);
|
||||||
g_assert (subscriber_data != NULL);
|
g_assert (subscriber_data != NULL);
|
||||||
|
|
||||||
new_range_start = gcal_timeline_subscriber_get_range_start (subscriber);
|
old_range = gcal_range_new (subscriber_data->range_start, subscriber_data->range_end, GCAL_RANGE_DEFAULT);
|
||||||
new_range_end = gcal_timeline_subscriber_get_range_end (subscriber);
|
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 */
|
/* Diff new and old event ranges */
|
||||||
calculate_changed_events (self,
|
calculate_changed_events (self, subscriber, old_range, new_range);
|
||||||
subscriber,
|
|
||||||
subscriber_data->range_start,
|
|
||||||
subscriber_data->range_end,
|
|
||||||
new_range_start,
|
|
||||||
new_range_end);
|
|
||||||
|
|
||||||
/* Update the subscriber range */
|
/* Update the subscriber range */
|
||||||
gcal_range_tree_remove_data (self->subscriber_ranges, subscriber);
|
gcal_range_tree_remove_data (self->subscriber_ranges, subscriber);
|
||||||
gcal_range_tree_add_range (self->subscriber_ranges,
|
gcal_range_tree_add_range (self->subscriber_ranges, new_range, subscriber);
|
||||||
new_range_start,
|
|
||||||
new_range_end,
|
|
||||||
subscriber);
|
|
||||||
|
|
||||||
gcal_set_date_time (&subscriber_data->range_start, new_range_start);
|
gcal_clear_date_time (&subscriber_data->range_start);
|
||||||
gcal_set_date_time (&subscriber_data->range_end, new_range_end);
|
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;
|
GCAL_EXIT;
|
||||||
}
|
}
|
||||||
@@ -499,16 +513,14 @@ on_calendar_monitor_event_added_cb (GcalCalendarMonitor *monitor,
|
|||||||
GcalTimeline *self)
|
GcalTimeline *self)
|
||||||
{
|
{
|
||||||
g_autoptr (GPtrArray) subscribers_at_range = NULL;
|
g_autoptr (GPtrArray) subscribers_at_range = NULL;
|
||||||
GDateTime *event_start;
|
GcalRange *event_range;
|
||||||
GDateTime *event_end;
|
|
||||||
|
|
||||||
GCAL_ENTRY;
|
GCAL_ENTRY;
|
||||||
|
|
||||||
event_start = gcal_event_get_date_start (event);
|
event_range = gcal_event_get_range (event);
|
||||||
event_end = gcal_event_get_date_end (event);
|
|
||||||
|
|
||||||
/* Add to all subscribers within the event range */
|
/* 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)
|
if (subscribers_at_range)
|
||||||
queue_event_data (self, ADD_EVENT, subscribers_at_range, event, NULL, TRUE);
|
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)
|
GcalTimeline *self)
|
||||||
{
|
{
|
||||||
g_autoptr (GPtrArray) subscribers_at_range = NULL;
|
g_autoptr (GPtrArray) subscribers_at_range = NULL;
|
||||||
GDateTime *event_start;
|
GcalRange *event_range;
|
||||||
GDateTime *event_end;
|
|
||||||
|
|
||||||
GCAL_ENTRY;
|
GCAL_ENTRY;
|
||||||
|
|
||||||
/* Add the updated event to the (potentially new) range */
|
/* Add the updated event to the (potentially new) range */
|
||||||
event_start = gcal_event_get_date_start (event);
|
event_range = gcal_event_get_range (event);
|
||||||
event_end = gcal_event_get_date_end (event);
|
|
||||||
|
|
||||||
/* Add to all subscribers within the event range */
|
/* 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)
|
if (subscribers_at_range)
|
||||||
queue_event_data (self, UPDATE_EVENT, subscribers_at_range, event, old_event, TRUE);
|
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)
|
GcalTimeline *self)
|
||||||
{
|
{
|
||||||
g_autoptr (GPtrArray) subscribers_at_range = NULL;
|
g_autoptr (GPtrArray) subscribers_at_range = NULL;
|
||||||
GDateTime *event_start;
|
GcalRange *event_range;
|
||||||
GDateTime *event_end;
|
|
||||||
|
|
||||||
GCAL_ENTRY;
|
GCAL_ENTRY;
|
||||||
|
|
||||||
event_start = gcal_event_get_date_start (event);
|
event_range = gcal_event_get_range (event);
|
||||||
event_end = gcal_event_get_date_end (event);
|
|
||||||
|
|
||||||
/* Add to all subscribers within the event range */
|
/* 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)
|
if (subscribers_at_range)
|
||||||
queue_event_data (self, REMOVE_EVENT, subscribers_at_range, event, NULL, TRUE);
|
queue_event_data (self, REMOVE_EVENT, subscribers_at_range, event, NULL, TRUE);
|
||||||
@@ -623,8 +631,7 @@ timeline_source_dispatch (GSource *source,
|
|||||||
{
|
{
|
||||||
TimelineSource *timeline_source;
|
TimelineSource *timeline_source;
|
||||||
GcalTimeline *self;
|
GcalTimeline *self;
|
||||||
GDateTime *event_start;
|
GcalRange *event_range;
|
||||||
GDateTime *event_end;
|
|
||||||
QueueData *queue_data;
|
QueueData *queue_data;
|
||||||
GcalEvent *event;
|
GcalEvent *event;
|
||||||
gint i;
|
gint i;
|
||||||
@@ -636,8 +643,7 @@ timeline_source_dispatch (GSource *source,
|
|||||||
queue_data = g_queue_pop_head (self->event_queue);
|
queue_data = g_queue_pop_head (self->event_queue);
|
||||||
|
|
||||||
event = queue_data->event;
|
event = queue_data->event;
|
||||||
event_start = gcal_event_get_date_start (event);
|
event_range = gcal_event_get_range (event);
|
||||||
event_end = gcal_event_get_date_end (event);
|
|
||||||
|
|
||||||
switch (queue_data->queue_event)
|
switch (queue_data->queue_event)
|
||||||
{
|
{
|
||||||
@@ -647,7 +653,7 @@ timeline_source_dispatch (GSource *source,
|
|||||||
gcal_event_get_uid (event));
|
gcal_event_get_uid (event));
|
||||||
|
|
||||||
if (queue_data->update_range_tree)
|
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++)
|
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)
|
if (queue_data->update_range_tree)
|
||||||
{
|
{
|
||||||
GDateTime *old_event_start;
|
GcalRange *old_event_range;
|
||||||
GDateTime *old_event_end;
|
|
||||||
|
|
||||||
/* Remove the old event */
|
/* Remove the old event */
|
||||||
old_event_start = gcal_event_get_date_start (queue_data->old_event);
|
old_event_range = gcal_event_get_range (queue_data->old_event);
|
||||||
old_event_end = gcal_event_get_date_end (queue_data->old_event);
|
|
||||||
|
|
||||||
gcal_range_tree_remove_range (self->events, old_event_start, old_event_end, queue_data->old_event);
|
gcal_range_tree_remove_range (self->events, old_event_range, queue_data->old_event);
|
||||||
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++)
|
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)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1007,13 +1011,14 @@ gcal_timeline_get_events_at_range (GcalTimeline *self,
|
|||||||
GDateTime *range_end)
|
GDateTime *range_end)
|
||||||
{
|
{
|
||||||
g_autoptr (GPtrArray) events_at_range = NULL;
|
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 (GCAL_IS_TIMELINE (self), NULL);
|
||||||
g_return_val_if_fail (range_start != NULL, NULL);
|
g_return_val_if_fail (range_start != NULL, NULL);
|
||||||
g_return_val_if_fail (range_end != 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);
|
return g_steal_pointer (&events_at_range);
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-59
@@ -1,6 +1,6 @@
|
|||||||
/* gcal-week-grid.c
|
/* gcal-week-grid.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
* Copyright (C) 2016-2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
|
||||||
* Vamsi Krishna Gollapudi <pandu.sonu@yahoo.com>
|
* Vamsi Krishna Gollapudi <pandu.sonu@yahoo.com>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -127,14 +127,13 @@ uint16_compare (gconstpointer a,
|
|||||||
|
|
||||||
static inline guint
|
static inline guint
|
||||||
get_event_index (GcalRangeTree *tree,
|
get_event_index (GcalRangeTree *tree,
|
||||||
GDateTime *start,
|
GcalRange *range)
|
||||||
GDateTime *end)
|
|
||||||
{
|
{
|
||||||
g_autoptr (GPtrArray) array;
|
g_autoptr (GPtrArray) array;
|
||||||
gint idx, i;
|
gint idx, i;
|
||||||
|
|
||||||
i = idx = 0;
|
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)
|
if (!array)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -154,59 +153,35 @@ get_event_index (GcalRangeTree *tree,
|
|||||||
|
|
||||||
static guint
|
static guint
|
||||||
count_overlaps_at_range (GcalRangeTree *self,
|
count_overlaps_at_range (GcalRangeTree *self,
|
||||||
GDateTime *start,
|
GcalRange *range)
|
||||||
GDateTime *end)
|
|
||||||
{
|
{
|
||||||
|
g_autoptr (GDateTime) start = NULL;
|
||||||
|
g_autoptr (GDateTime) end = NULL;
|
||||||
guint64 counter;
|
guint64 counter;
|
||||||
|
gint minutes;
|
||||||
|
gint i;
|
||||||
|
|
||||||
g_return_val_if_fail (self, 0);
|
g_return_val_if_fail (self, 0);
|
||||||
|
|
||||||
counter = 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;
|
guint n_events;
|
||||||
|
|
||||||
start_plus_one = g_date_time_add_minutes (start, 1);
|
minute_range = gcal_range_new_take (g_date_time_add_minutes (start, i),
|
||||||
n_events = gcal_range_tree_count_entries_at_range (self, start, start_plus_one);
|
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)
|
if (n_events == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
counter = MAX (counter, n_events);
|
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;
|
return counter;
|
||||||
@@ -589,20 +564,21 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < 7; i++)
|
for (i = 0; i < 7; i++)
|
||||||
{
|
{
|
||||||
g_autoptr (GDateTime) day_start = NULL;
|
g_autoptr (GcalRange) day_range = NULL;
|
||||||
g_autoptr (GDateTime) day_end = NULL;
|
|
||||||
GPtrArray *widgets_data;
|
GPtrArray *widgets_data;
|
||||||
guint j;
|
guint j;
|
||||||
|
|
||||||
day_start = g_date_time_add_days (week_start, i);
|
day_range = gcal_range_new_take (g_date_time_add_days (week_start, i),
|
||||||
day_end = g_date_time_add_days (day_start, 1);
|
g_date_time_add_days (week_start, i + 1),
|
||||||
widgets_data = gcal_range_tree_get_data_at_range (self->events, day_start, day_end);
|
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++)
|
for (j = 0; widgets_data && j < widgets_data->len; j++)
|
||||||
{
|
{
|
||||||
GtkStyleContext *context;
|
GtkStyleContext *context;
|
||||||
GtkAllocation child_allocation;
|
GtkAllocation child_allocation;
|
||||||
GtkWidget *event_widget;
|
GtkWidget *event_widget;
|
||||||
|
GcalRange *event_range;
|
||||||
GDateTime *event_start;
|
GDateTime *event_start;
|
||||||
GDateTime *event_end;
|
GDateTime *event_end;
|
||||||
ChildData *data;
|
ChildData *data;
|
||||||
@@ -617,15 +593,16 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
|
|||||||
|
|
||||||
data = g_ptr_array_index (widgets_data, j);
|
data = g_ptr_array_index (widgets_data, j);
|
||||||
event_widget = data->widget;
|
event_widget = data->widget;
|
||||||
|
event_range = gcal_event_get_range (data->event);
|
||||||
event_start = gcal_event_get_date_start (data->event);
|
event_start = gcal_event_get_date_start (data->event);
|
||||||
event_end = gcal_event_get_date_end (data->event);
|
event_end = gcal_event_get_date_end (data->event);
|
||||||
context = gtk_widget_get_style_context (event_widget);
|
context = gtk_widget_get_style_context (event_widget);
|
||||||
|
|
||||||
/* The total number of events available in this range */
|
/* 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 */
|
/* 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 complains about that */
|
||||||
gtk_widget_get_preferred_height (event_widget, NULL, &natural_height);
|
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
|
* 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.
|
* know how many events are already positioned in the current column.
|
||||||
*/
|
*/
|
||||||
gcal_range_tree_add_range (overlaps,
|
gcal_range_tree_add_range (overlaps, event_range, GUINT_TO_POINTER (widget_index));
|
||||||
event_start,
|
|
||||||
event_end,
|
|
||||||
GUINT_TO_POINTER (widget_index));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_pointer (&widgets_data, g_ptr_array_unref);
|
g_clear_pointer (&widgets_data, g_ptr_array_unref);
|
||||||
@@ -1114,8 +1088,7 @@ gcal_week_grid_add_event (GcalWeekGrid *self,
|
|||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
gcal_range_tree_add_range (self->events,
|
gcal_range_tree_add_range (self->events,
|
||||||
gcal_event_get_date_start (event),
|
gcal_event_get_range (event),
|
||||||
gcal_event_get_date_end (event),
|
|
||||||
child_data_new (widget, event));
|
child_data_new (widget, event));
|
||||||
|
|
||||||
setup_event_widget (self, widget);
|
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)
|
if (g_strcmp0 (gcal_event_get_uid (event), uid) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
gcal_range_tree_remove_range (self->events,
|
gcal_range_tree_remove_range (self->events, gcal_event_get_range (event), data);
|
||||||
gcal_event_get_date_start (event),
|
|
||||||
gcal_event_get_date_end (event),
|
|
||||||
data);
|
|
||||||
destroy_event_widget (self, data->widget);
|
destroy_event_widget (self, data->widget);
|
||||||
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
gtk_widget_queue_allocate (GTK_WIDGET (self));
|
||||||
g_object_unref (event);
|
g_object_unref (event);
|
||||||
|
|||||||
+33
-26
@@ -37,6 +37,7 @@ static void
|
|||||||
range_tree_insert (void)
|
range_tree_insert (void)
|
||||||
{
|
{
|
||||||
g_autoptr (GcalRangeTree) range_tree = NULL;
|
g_autoptr (GcalRangeTree) range_tree = NULL;
|
||||||
|
g_autoptr (GcalRange) range = NULL;
|
||||||
g_autoptr (GDateTime) start = NULL;
|
g_autoptr (GDateTime) start = NULL;
|
||||||
g_autoptr (GDateTime) end = 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);
|
start = g_date_time_new_local (2020, 3, 17, 9, 30, 0);
|
||||||
end = g_date_time_add_hours (start, 1);
|
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);
|
gcal_range_tree_add_range (range_tree, range, (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);
|
||||||
|
|
||||||
gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0x8badf00d);
|
gcal_range_tree_add_range (range_tree, range, (gpointer) 0x8badf00d);
|
||||||
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_add_range (range_tree, start, end, (gpointer) 0x0badcafe);
|
gcal_range_tree_add_range (range_tree, range, (gpointer) 0x0badcafe);
|
||||||
g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 3);
|
g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************************************/
|
/*********************************************************************************************************************/
|
||||||
@@ -73,8 +75,7 @@ static struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
traverse_func (GDateTime *start,
|
traverse_func (GcalRange *range,
|
||||||
GDateTime *end,
|
|
||||||
gpointer data,
|
gpointer data,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
@@ -96,13 +97,13 @@ range_tree_traverse (void)
|
|||||||
utc = g_time_zone_new_utc ();
|
utc = g_time_zone_new_utc ();
|
||||||
for (i = 0; i < G_N_ELEMENTS (ranges); i++)
|
for (i = 0; i < G_N_ELEMENTS (ranges); i++)
|
||||||
{
|
{
|
||||||
g_autoptr (GDateTime) start = NULL;
|
g_autoptr (GcalRange) range = NULL;
|
||||||
g_autoptr (GDateTime) end = NULL;
|
|
||||||
|
|
||||||
start = g_date_time_new_from_iso8601 (ranges[i].start, utc);
|
range = gcal_range_new_take (g_date_time_new_from_iso8601 (ranges[i].start, utc),
|
||||||
end = g_date_time_new_from_iso8601 (ranges[i].end, 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);
|
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 (GcalRangeTree) range_tree = NULL;
|
||||||
g_autoptr (GDateTime) range_start = NULL;
|
g_autoptr (GDateTime) range_start = NULL;
|
||||||
g_autoptr (GDateTime) range_end = 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) start = NULL;
|
||||||
g_autoptr (GDateTime) end = 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);
|
start = g_date_time_new_local (2020, 3, 17, 9, 30, 0);
|
||||||
end = g_date_time_add_hours (start, 1);
|
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);
|
gcal_range_tree_add_range (range_tree, range1, (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, range1), ==, 1);
|
||||||
|
|
||||||
range_start = g_date_time_new_local (2020, 3, 20, 9, 30, 0);
|
range_start = g_date_time_new_local (2020, 3, 20, 9, 30, 0);
|
||||||
range_end = g_date_time_add_hours (range_start, 1);
|
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)
|
range_tree_remove_data (void)
|
||||||
{
|
{
|
||||||
g_autoptr (GcalRangeTree) range_tree = NULL;
|
g_autoptr (GcalRangeTree) range_tree = NULL;
|
||||||
|
g_autoptr (GcalRange) range = NULL;
|
||||||
g_autoptr (GDateTime) start = NULL;
|
g_autoptr (GDateTime) start = NULL;
|
||||||
g_autoptr (GDateTime) end = 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);
|
start = g_date_time_new_local (2020, 3, 17, 9, 30, 0);
|
||||||
end = g_date_time_add_hours (start, 1);
|
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);
|
gcal_range_tree_add_range (range_tree, range, (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);
|
||||||
|
|
||||||
gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xdeadbeef);
|
gcal_range_tree_add_range (range_tree, range, (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_add_range (range_tree, start, end, (gpointer) 0xbadcafe);
|
gcal_range_tree_add_range (range_tree, range, (gpointer) 0xbadcafe);
|
||||||
g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 3);
|
g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, range), ==, 3);
|
||||||
|
|
||||||
/* Remove the 2 deadbeefs */
|
/* Remove the 2 deadbeefs */
|
||||||
gcal_range_tree_remove_data (range_tree, (gpointer) 0xdeadbeef);
|
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);
|
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 */
|
/* Try again */
|
||||||
gcal_range_tree_remove_data (range_tree, (gpointer) 0xdeadbeef);
|
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 */
|
/* Remove bad cafe */
|
||||||
gcal_range_tree_remove_data (range_tree, (gpointer) 0xbadcafe);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************************************/
|
/*********************************************************************************************************************/
|
||||||
|
|||||||
Reference in New Issue
Block a user