views/week-grid: Port to GListModel

And, while at it, rewrite the layout algorithm to operate on blocks of
overlapping events, and segmented columns. Like the month view row,
layouts blocks are invalidated at any point in time, but recalculated
immediately before a relayout happens.

The reason for doing such a massive rewrite while in the middle of the
port to GListModel is because it's easier to handle GListModel data
with this approach, than with the previous approach of storing it all
in a GcalRangeTree.

Closes: https://gitlab.gnome.org/GNOME/gnome-calendar/-/issues/1153
Part-of: <https://gitlab.gnome.org/GNOME/gnome-calendar/-/merge_requests/742>
This commit is contained in:
Georges Basile Stavracas Neto
2026-05-03 16:57:53 +00:00
committed by Marge Bot
parent 5fe24582d4
commit fa03c6f9af
3 changed files with 416 additions and 218 deletions
+413 -186
View File
@@ -30,6 +30,7 @@
#include "gcal-utils.h"
#include "gcal-view-private.h"
#include "gcal-event-widget.h"
#include "gcal-event-list.h"
#include "gcal-range-tree.h"
#include <glib/gi18n.h>
@@ -43,12 +44,6 @@ typedef struct
gint drop_cell;
} DropData;
typedef struct
{
GtkWidget *widget;
GcalEvent *event;
} ChildData;
struct _GcalWeekGrid
{
GtkWidget parent;
@@ -59,7 +54,11 @@ struct _GcalWeekGrid
GDateTime *active_date;
GcalRangeTree *events;
GPtrArray *layout_blocks;
GtkFilterListModel *filter_model;
GtkSortListModel *sort_model;
gboolean layout_blocks_valid;
/*
* These fields are "cells" rather than minutes. Each cell
@@ -78,6 +77,12 @@ struct _GcalWeekGrid
} dnd;
};
static void on_event_widget_activated_cb (GcalEventWidget *widget,
GcalWeekGrid *self);
static gboolean widget_tick_cb (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data);
G_DEFINE_TYPE (GcalWeekGrid, gcal_week_grid, GTK_TYPE_WIDGET);
@@ -89,10 +94,18 @@ enum
static guint signals[LAST_SIGNAL] = { 0, };
/*
* Auxiliary methods
* ChildData
*/
typedef struct
{
GtkWidget *widget;
GcalEvent *event;
uint32_t n_columns;
} ChildData;
static ChildData*
child_data_new (GtkWidget *widget,
GcalEvent *event)
@@ -102,6 +115,7 @@ child_data_new (GtkWidget *widget,
data = g_new (ChildData, 1);
data->widget = widget;
data->event = g_object_ref (event);
data->n_columns = 1;
return data;
}
@@ -119,79 +133,323 @@ child_data_free (gpointer data)
g_free (child_data);
}
static inline gint
uint16_compare (gconstpointer a,
gconstpointer b)
/*
* LayoutBlock
*/
typedef struct
{
return GPOINTER_TO_UINT (*(gint*)a) - GPOINTER_TO_UINT (*(gint*)b);
GcalRange *range;
GPtrArray *columns; /* GcalRangeTree<ChildData> */
} LayoutBlock;
static void
layout_block_free (gpointer data)
{
LayoutBlock *layout_block = data;
if (!layout_block)
return;
g_clear_pointer (&layout_block->range, gcal_range_unref);
g_clear_pointer (&layout_block->columns, g_ptr_array_unref);
g_free (layout_block);
}
static inline guint
get_event_index (GcalRangeTree *tree,
GcalRange *range)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (LayoutBlock, layout_block_free)
static ChildData *
layout_block_add_event (LayoutBlock *layout_block,
GcalEvent *event)
{
g_autoptr (GPtrArray) array = NULL;
gint idx, i;
GcalRange *event_range = NULL;
ChildData *child_data = NULL;
size_t column = 0;
idx = 0;
array = gcal_range_tree_get_data_at_range (tree, range);
g_assert (layout_block != NULL);
g_assert (GCAL_IS_EVENT (event));
if (!array)
return 0;
event_range = gcal_event_get_range (event);
g_ptr_array_sort (array, uint16_compare);
for (i = 0; array && i < array->len; i++)
do
{
if (idx == GPOINTER_TO_INT (g_ptr_array_index (array, i)))
idx++;
GcalRangeTree *column_data = NULL;
if (column >= layout_block->columns->len)
{
column_data = gcal_range_tree_new_with_free_func (child_data_free);
g_ptr_array_insert (layout_block->columns, column, column_data);
}
else
break;
}
{
column_data = g_ptr_array_index (layout_block->columns, column);
}
return idx;
g_assert (column_data != NULL);
if (!gcal_range_tree_has_entries_at_range (column_data, event_range))
{
g_autoptr (GcalRange) new_block_range = NULL;
child_data = child_data_new (NULL, event);
gcal_range_tree_add_range (column_data, event_range, child_data);
new_block_range = gcal_range_union (layout_block->range, event_range);
g_clear_pointer (&layout_block->range, gcal_range_unref);
layout_block->range = g_steal_pointer (&new_block_range);
break;
}
column++;
}
while (TRUE);
g_assert (child_data != NULL);
return child_data;
}
static guint
count_overlaps_at_range (GcalRangeTree *self,
GcalRange *range)
/*
* Auxiliary methods
*/
static void
add_event_to_block (GcalWeekGrid *self,
LayoutBlock *layout_block,
GcalEvent *event)
{
g_autoptr (GDateTime) start = NULL;
g_autoptr (GDateTime) end = NULL;
guint64 counter;
gint minutes;
gint i;
ChildData *child_data;
g_return_val_if_fail (self, 0);
g_assert (GCAL_IS_WEEK_GRID (self));
g_assert (layout_block != NULL);
g_assert (GCAL_IS_EVENT (event));
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;
child_data = layout_block_add_event (layout_block, event);
for (i = 0; i < minutes; i++)
child_data->widget = g_object_new (GCAL_TYPE_EVENT_WIDGET,
"event", event,
"orientation", GTK_ORIENTATION_VERTICAL,
"timestamp-policy", GCAL_TIMESTAMP_POLICY_START,
NULL);
g_signal_connect (child_data->widget, "activate", G_CALLBACK (on_event_widget_activated_cb), self);
gtk_widget_set_parent (child_data->widget, GTK_WIDGET (self));
}
static void
expand_event_widgets_in_blocks (GcalWeekGrid *self)
{
for (size_t block_index = 0; block_index < self->layout_blocks->len; block_index++)
{
g_autoptr (GcalRange) minute_range = NULL;
guint n_events;
g_autoptr (GDateTime) block_range_start = NULL;
LayoutBlock *layout_block = NULL;
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);
layout_block = g_ptr_array_index (self->layout_blocks, block_index);
g_assert (layout_block != NULL);
g_assert (layout_block->columns != NULL);
if (n_events == 0)
break;
for (size_t column_index = 0; column_index < layout_block->columns->len; column_index++)
{
g_autoptr (GPtrArray) children_data = NULL;
GcalRangeTree *block_column;
counter = MAX (counter, n_events);
block_column = g_ptr_array_index (layout_block->columns, column_index);
g_assert (block_column != NULL);
children_data = gcal_range_tree_get_all_data (block_column);
g_assert (children_data != NULL);
for (size_t child_data_index = 0; child_data_index < children_data->len; child_data_index++)
{
GcalRange *event_range;
ChildData *child_data;
child_data = g_ptr_array_index (children_data, child_data_index);
event_range = gcal_event_get_range (child_data->event);
for (size_t next_column_index = column_index + 1;
next_column_index < layout_block->columns->len;
next_column_index++)
{
GcalRangeTree *next_column = g_ptr_array_index (layout_block->columns, next_column_index);
if (gcal_range_tree_has_entries_at_range (next_column, event_range))
break;
child_data->n_columns++;
}
}
}
}
}
static void
recalculate_layout_blocks (GcalWeekGrid *self)
{
g_autoptr (GcalRangeTree) blocks_by_range = NULL;
size_t n_events = 0;
GCAL_ENTRY;
g_assert (GCAL_IS_WEEK_GRID (self));
g_assert (self->layout_blocks != NULL);
blocks_by_range = gcal_range_tree_new ();
/* Remove all blocks */
g_ptr_array_set_size (self->layout_blocks, 0);
/* First pass: create all layout blocks, all event widgets will have 1 column of width */
n_events = g_list_model_get_n_items (G_LIST_MODEL (self->sort_model));
for (size_t i = 0; i < n_events; i++)
{
g_autoptr (GPtrArray) blocks_at_range = NULL;
g_autoptr (GcalRange) old_block_range = NULL;
g_autoptr (GcalRange) new_block_range = NULL;
g_autoptr (GcalEvent) event = NULL;
LayoutBlock *layout_block = NULL;
GcalRange *event_range;
event = g_list_model_get_item (G_LIST_MODEL (self->sort_model), i);
g_assert (GCAL_IS_EVENT (event));
event_range = gcal_event_get_range (event);
blocks_at_range = gcal_range_tree_get_data_at_range (blocks_by_range, event_range);
g_assert (blocks_at_range == NULL || blocks_at_range->len == 1);
if (!blocks_at_range)
{
layout_block = g_new0 (LayoutBlock, 1);
layout_block->range = gcal_range_ref (event_range);
layout_block->columns = g_ptr_array_new_with_free_func ((GDestroyNotify) gcal_range_tree_unref);
gcal_range_tree_add_range (blocks_by_range, layout_block->range, layout_block);
g_ptr_array_add (self->layout_blocks, layout_block);
}
else
{
layout_block = g_ptr_array_index (blocks_at_range, 0);
}
g_assert (layout_block != NULL);
old_block_range = gcal_range_ref (layout_block->range);
add_event_to_block (self, layout_block, event);
new_block_range = gcal_range_ref (layout_block->range);
if (gcal_range_calculate_overlap (old_block_range, new_block_range, NULL) != GCAL_RANGE_EQUAL)
{
gcal_range_tree_remove_range (blocks_by_range, old_block_range, layout_block);
gcal_range_tree_add_range (blocks_by_range, new_block_range, layout_block);
}
}
return counter;
/* Second pass: expand event widgets to fill in empty space */
expand_event_widgets_in_blocks (self);
self->layout_blocks_valid = TRUE;
GCAL_EXIT;
}
static void
invalidate_layout_blocks (GcalWeekGrid *self)
{
GCAL_ENTRY;
if (!self->layout_blocks_valid)
GCAL_RETURN ();
if (gtk_widget_get_mapped (GTK_WIDGET (self)))
{
gtk_widget_add_tick_callback (GTK_WIDGET (self), widget_tick_cb, self, NULL);
gtk_widget_queue_allocate (GTK_WIDGET (self));
}
self->layout_blocks_valid = FALSE;
GCAL_EXIT;
}
/*
* Callbacks
*/
static gboolean
widget_tick_cb (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
GcalWeekGrid *self = (GcalWeekGrid *) widget;
GCAL_ENTRY;
g_assert (GCAL_IS_WEEK_GRID (self));
recalculate_layout_blocks (self);
GCAL_RETURN (G_SOURCE_REMOVE);
}
static int
compare_events_cb (gconstpointer a,
gconstpointer b,
gpointer user_data)
{
GDateTime *event_a_start;
GDateTime *event_b_start;
GDateTime *event_a_end;
GDateTime *event_b_end;
GcalEvent *event_a;
GcalEvent *event_b;
int result;
event_a = (GcalEvent *) a;
event_b = (GcalEvent *) b;
event_a_start = gcal_event_get_date_start (event_a);
event_b_start = gcal_event_get_date_start (event_b);
result = g_date_time_compare (event_a_start, event_b_start);
if (result != 0)
return result;
event_a_end = gcal_event_get_date_end (event_a);
event_b_end = gcal_event_get_date_end (event_b);
result = g_date_time_compare (event_a_end, event_b_end);
if (result != 0)
return -result;
return 0;
}
static gboolean
event_is_timed_single_day_func (gpointer item,
gpointer user_data)
{
GcalEvent *event = (GcalEvent *) item;
g_assert (GCAL_IS_EVENT (event));
return !gcal_event_get_all_day (event) && !gcal_event_is_multiday (event);
}
static void
events_changed_cb (GListModel *model,
unsigned int position,
unsigned int removed,
unsigned int added,
GcalWeekGrid *self)
{
invalidate_layout_blocks (self);
}
static void
on_click_gesture_pressed_cb (GtkGestureClick *click_gesture,
gint n_press,
@@ -507,8 +765,8 @@ gcal_week_grid_dispose (GObject *object)
{
GcalWeekGrid *self = GCAL_WEEK_GRID (object);
g_clear_pointer (&self->layout_blocks, g_ptr_array_unref);
g_clear_pointer (&self->dnd.widget, gtk_widget_unparent);
g_clear_pointer (&self->events, gcal_range_tree_unref);
g_clear_pointer (&self->now_strip, gtk_widget_unparent);
g_clear_pointer (&self->selection.widget, gtk_widget_unparent);
@@ -521,6 +779,8 @@ gcal_week_grid_finalize (GObject *object)
GcalWeekGrid *self = GCAL_WEEK_GRID (object);
gcal_clear_date_time (&self->active_date);
g_clear_object (&self->filter_model);
g_clear_object (&self->sort_model);
G_OBJECT_CLASS (gcal_week_grid_parent_class)->finalize (object);
}
@@ -561,6 +821,19 @@ get_today_column (GcalWeekGrid *self)
return days_diff;
}
static void
gcal_week_grid_map (GtkWidget *widget)
{
GcalWeekGrid *self = (GcalWeekGrid *) widget;
g_assert (GCAL_IS_WEEK_GRID (self));
GTK_WIDGET_CLASS (gcal_week_grid_parent_class)->map (widget);
if (!self->layout_blocks_valid)
recalculate_layout_blocks (self);
}
static void
gcal_week_grid_measure (GtkWidget *widget,
GtkOrientation orientation,
@@ -580,7 +853,6 @@ static void
gcal_week_grid_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot)
{
g_autoptr (GPtrArray) widgets = NULL;
GcalWeekGrid *self;
gint width, height;
@@ -595,12 +867,19 @@ gcal_week_grid_snapshot (GtkWidget *widget,
gtk_widget_snapshot_child (widget, self->selection.widget, snapshot);
gtk_widget_snapshot_child (widget, self->dnd.widget, snapshot);
widgets = gcal_range_tree_get_all_data (self->events);
for (guint i = 0; i < widgets->len; i++)
/* Then, event widgets */
for (GtkWidget *child = gtk_widget_get_first_child (widget);
child;
child = gtk_widget_get_next_sibling (child))
{
ChildData *child_data = g_ptr_array_index (widgets, i);
if (child == self->selection.widget ||
child == self->dnd.widget ||
child == self->now_strip)
{
continue;
}
gtk_widget_snapshot_child (widget, child_data->widget, snapshot);
gtk_widget_snapshot_child (widget, child, snapshot);
}
gtk_widget_snapshot_child (widget, self->now_strip, snapshot);
@@ -614,7 +893,6 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
{
GcalWeekGrid *self = GCAL_WEEK_GRID (widget);
g_autoptr (GDateTime) week_start = NULL;
GcalRangeTree *overlaps;
gboolean ltr;
gdouble minutes_height;
gdouble column_width;
@@ -697,101 +975,87 @@ gcal_week_grid_size_allocate (GtkWidget *widget,
baseline);
}
/* Temporary range tree to hold positioned events' indexes */
overlaps = gcal_range_tree_new ();
week_start = gcal_date_time_get_start_of_week (self->active_date);
/*
* Iterate through weekdays; we don't have to worry about events that
* jump between days because they're already handled by GcalWeekHeader.
*/
for (size_t i = 0; i < N_WEEKDAYS; i++)
/* Event widgets */
for (size_t block_index = 0; block_index < self->layout_blocks->len; block_index++)
{
g_autoptr (GcalRange) day_range = NULL;
GPtrArray *widgets_data;
guint j;
g_autoptr (GDateTime) block_range_start = NULL;
LayoutBlock *layout_block = NULL;
double block_column_width;
int block_weekday;
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);
layout_block = g_ptr_array_index (self->layout_blocks, block_index);
g_assert (layout_block != NULL);
g_assert (layout_block->columns != NULL);
for (j = 0; widgets_data && j < widgets_data->len; j++)
block_range_start = gcal_range_get_start (layout_block->range);
block_weekday = gcal_date_time_compare_date (block_range_start, week_start);
g_assert (block_weekday >= 0 && block_weekday < 7);
block_column_width = column_width / (double) layout_block->columns->len - 1;
for (size_t block_column_index = 0; block_column_index < layout_block->columns->len; block_column_index++)
{
g_autoptr (GDateTime) event_start = NULL;
g_autoptr (GDateTime) event_end = NULL;
GtkAllocation child_allocation;
GtkWidget *event_widget;
GcalRange *event_range;
ChildData *data;
guint64 events_at_range;
gint event_minutes;
gint minimum_width;
gint minimum_height;
gint widget_index;
gint offset;
gint event_height;
gint event_width;
gint x;
gint y;
g_autoptr (GPtrArray) children_data = NULL;
GcalRangeTree *block_column;
data = g_ptr_array_index (widgets_data, j);
event_widget = data->widget;
block_column = g_ptr_array_index (layout_block->columns, block_column_index);
g_assert (block_column != NULL);
if (!gtk_widget_should_layout (event_widget))
continue;
children_data = gcal_range_tree_get_all_data (block_column);
g_assert (children_data != NULL);
event_range = gcal_event_get_range (data->event);
event_start = g_date_time_to_local (gcal_event_get_date_start (data->event));
event_end = g_date_time_to_local (gcal_event_get_date_end (data->event));
for (size_t child_data_index = 0; child_data_index < children_data->len; child_data_index++)
{
g_autoptr (GDateTime) event_start = NULL;
g_autoptr (GDateTime) event_end = NULL;
GtkAllocation child_allocation;
GtkWidget *event_widget;
ChildData *child_data;
gint event_minutes;
gint minimum_width;
gint minimum_height;
gint event_height;
gint event_width;
gint x;
gint y;
/* The total number of events available in this range */
events_at_range = count_overlaps_at_range (self->events, event_range);
child_data = g_ptr_array_index (children_data, child_data_index);
event_widget = child_data->widget;
/* The real horizontal position of this event */
widget_index = get_event_index (overlaps, event_range);
if (!gtk_widget_should_layout (event_widget))
continue;
event_minutes = g_date_time_difference (event_end, event_start) / G_TIME_SPAN_MINUTE;
event_start = g_date_time_to_local (gcal_event_get_date_start (child_data->event));
event_end = g_date_time_to_local (gcal_event_get_date_end (child_data->event));
event_minutes = g_date_time_difference (event_end, event_start) / G_TIME_SPAN_MINUTE;
/* Compute the height of the widget */
gtk_widget_measure (event_widget, GTK_ORIENTATION_VERTICAL, -1, &minimum_height, NULL, NULL, NULL);
event_height = event_minutes * minutes_height;
event_height = MAX (minimum_height, event_height);
/* Compute the height of the widget */
gtk_widget_measure (event_widget, GTK_ORIENTATION_VERTICAL, -1, &minimum_height, NULL, NULL, NULL);
event_height = event_minutes * minutes_height;
event_height = MAX (minimum_height, event_height);
/* Compute the width of the widget */
gtk_widget_measure (event_widget, GTK_ORIENTATION_HORIZONTAL, event_height, &minimum_width, NULL, NULL, NULL);
event_width = column_width / events_at_range;
event_width = MAX (minimum_width, event_width);
/* Compute the width of the widget */
gtk_widget_measure (event_widget, GTK_ORIENTATION_HORIZONTAL, event_height, &minimum_width, NULL, NULL, NULL);
event_width = MAX (minimum_width, block_column_width * child_data->n_columns);
offset = event_width * widget_index;
y = (g_date_time_get_hour (event_start) * 60 + g_date_time_get_minute (event_start)) * minutes_height;
x = column_width * block_weekday + block_column_width * block_column_index + 1;
if (!ltr)
x = width - (x + event_width);
y = (g_date_time_get_hour (event_start) * 60 + g_date_time_get_minute (event_start)) * minutes_height;
if (ltr)
x = column_width * i + offset + 1;
else
x = width - event_width - (column_width * i + offset + 1);
/* Setup the child position and size */
child_allocation.x = x;
child_allocation.y = y;
child_allocation.width = event_width;
child_allocation.height = event_height;
/* Setup the child position and size */
child_allocation.x = x;
child_allocation.y = y;
child_allocation.width = event_width;
child_allocation.height = event_height;
gtk_widget_size_allocate (event_widget, &child_allocation, baseline);
/*
* 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_range, GUINT_TO_POINTER (widget_index));
gtk_widget_size_allocate (event_widget, &child_allocation, baseline);
}
}
g_clear_pointer (&widgets_data, g_ptr_array_unref);
}
g_clear_pointer (&overlaps, gcal_range_tree_unref);
/* Today column */
today_column = get_today_column (GCAL_WEEK_GRID (widget));
@@ -841,6 +1105,7 @@ gcal_week_grid_class_init (GcalWeekGridClass *klass)
object_class->get_property = gcal_week_grid_get_property;
object_class->set_property = gcal_week_grid_set_property;
widget_class->map = gcal_week_grid_map;
widget_class->measure = gcal_week_grid_measure;
widget_class->size_allocate = gcal_week_grid_size_allocate;
widget_class->snapshot = gcal_week_grid_snapshot;
@@ -860,6 +1125,7 @@ static void
gcal_week_grid_init (GcalWeekGrid *self)
{
GcalContext *context = gcal_application_get_context (GCAL_DEFAULT_APPLICATION);
GtkCustomFilter *filter;
GtkDropTarget *drop_target;
GtkGesture *click_gesture;
AdwStyleManager *manager;
@@ -875,7 +1141,13 @@ gcal_week_grid_init (GcalWeekGrid *self)
gtk_widget_set_visible (self->dnd.widget, FALSE);
gtk_widget_set_parent (self->dnd.widget, GTK_WIDGET (self));
self->events = gcal_range_tree_new_with_free_func (child_data_free);
self->layout_blocks = g_ptr_array_new_with_free_func (layout_block_free);
filter = gtk_custom_filter_new (event_is_timed_single_day_func, NULL, NULL);
self->filter_model = gtk_filter_list_model_new (NULL, GTK_FILTER (g_steal_pointer (&filter)));
self->sort_model = gtk_sort_list_model_new (G_LIST_MODEL (g_object_ref (self->filter_model)),
GTK_SORTER (gtk_custom_sorter_new (compare_events_cb, NULL, NULL)));
g_signal_connect (self->sort_model, "items-changed", G_CALLBACK (events_changed_cb), self);
self->now_strip = adw_bin_new ();
gtk_widget_add_css_class (self->now_strip, "now-strip");
@@ -915,57 +1187,13 @@ gcal_week_grid_init (GcalWeekGrid *self)
G_CONNECT_SWAPPED);
}
/* Public API */
void
gcal_week_grid_add_event (GcalWeekGrid *self,
GcalEvent *event)
gcal_week_grid_set_model (GcalWeekGrid *self,
GListModel *model)
{
GtkWidget *widget;
g_assert (GCAL_IS_WEEK_GRID (self));
g_return_if_fail (GCAL_IS_WEEK_GRID (self));
g_object_ref (event);
widget = g_object_new (GCAL_TYPE_EVENT_WIDGET,
"event", event,
"orientation", GTK_ORIENTATION_VERTICAL,
"timestamp-policy", GCAL_TIMESTAMP_POLICY_START,
NULL);
gcal_range_tree_add_range (self->events,
gcal_event_get_range (event),
child_data_new (widget, event));
g_signal_connect (widget, "activate", G_CALLBACK (on_event_widget_activated_cb), self);
gtk_widget_set_parent (widget, GTK_WIDGET (self));
}
void
gcal_week_grid_remove_event (GcalWeekGrid *self,
const gchar *uid)
{
g_autoptr (GPtrArray) widgets = NULL;
guint i;
g_return_if_fail (GCAL_IS_WEEK_GRID (self));
widgets = gcal_range_tree_get_all_data (self->events);
for (i = 0; widgets && i < widgets->len; i++)
{
ChildData *data;
GcalEvent *event;
data = g_ptr_array_index (widgets, i);
event = gcal_event_widget_get_event (GCAL_EVENT_WIDGET (data->widget));
if (g_strcmp0 (gcal_event_get_uid (event), uid) != 0)
continue;
gcal_range_tree_remove_range (self->events, gcal_event_get_range (event), data);
gtk_widget_queue_allocate (GTK_WIDGET (self));
}
gtk_filter_list_model_set_model (self->filter_model, model);
}
GList*
@@ -998,7 +1226,6 @@ gcal_week_grid_set_date (GcalWeekGrid *self,
{
gcal_set_date_time (&self->active_date, date);
gtk_widget_queue_resize (GTK_WIDGET (self));
gtk_widget_queue_draw (GTK_WIDGET (self));
invalidate_layout_blocks (self);
}
+2 -5
View File
@@ -33,11 +33,8 @@ G_DECLARE_FINAL_TYPE (GcalWeekGrid, gcal_week_grid, GCAL, WEEK_GRID, GtkWidget)
void gcal_week_grid_set_first_weekday (GcalWeekGrid *week_grid,
gint nr_day);
void gcal_week_grid_add_event (GcalWeekGrid *self,
GcalEvent *event);
void gcal_week_grid_remove_event (GcalWeekGrid *self,
const gchar *uid);
void gcal_week_grid_set_model (GcalWeekGrid *self,
GListModel *model);
GList* gcal_week_grid_get_children_by_uuid (GcalWeekGrid *self,
GcalRecurrenceModType mod,
+1 -27
View File
@@ -494,14 +494,6 @@ static void
gcal_week_view_add_event (GcalTimelineSubscriber *subscriber,
GcalEvent *event)
{
GcalWeekView *self = GCAL_WEEK_VIEW (subscriber);
GCAL_ENTRY;
if (!gcal_event_is_multiday (event) && !gcal_event_get_all_day (event))
gcal_week_grid_add_event (GCAL_WEEK_GRID (self->week_grid), event);
GCAL_EXIT;
}
static void
@@ -509,31 +501,12 @@ gcal_week_view_update_event (GcalTimelineSubscriber *subscriber,
GcalEvent *old_event,
GcalEvent *event)
{
GcalWeekView *self = GCAL_WEEK_VIEW (subscriber);
const gchar *event_id;
GCAL_ENTRY;
event_id = gcal_event_get_uid (old_event);
gcal_week_grid_remove_event (GCAL_WEEK_GRID (self->week_grid), event_id);
gcal_week_view_add_event (subscriber, event);
GCAL_EXIT;
}
static void
gcal_week_view_remove_event (GcalTimelineSubscriber *subscriber,
GcalEvent *event)
{
GcalWeekView *self = GCAL_WEEK_VIEW (subscriber);
const gchar *uuid = gcal_event_get_uid (event);
GCAL_ENTRY;
gcal_week_grid_remove_event (GCAL_WEEK_GRID (self->week_grid), uuid);
GCAL_EXIT;
}
static void
@@ -547,6 +520,7 @@ gcal_week_view_set_model (GcalTimelineSubscriber *subscriber,
self = GCAL_WEEK_VIEW (subscriber);
gcal_week_header_set_model (GCAL_WEEK_HEADER (self->header), model);
gcal_week_grid_set_model (GCAL_WEEK_GRID (self->week_grid), model);
GCAL_EXIT;
}