1 /*
2  * ECalListView - display calendar events in an ETable.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; if not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authors:
17  *		Hans Petter Jansson  <hpj@ximian.com>
18  *
19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20  */
21 
22 #include "evolution-config.h"
23 
24 #include "e-cal-list-view.h"
25 #include "ea-calendar.h"
26 
27 #include <math.h>
28 #include <time.h>
29 #include <sys/stat.h>
30 #include <gtk/gtk.h>
31 #include <glib/gi18n.h>
32 #include <glib/gstdio.h>
33 #include <gdk/gdkkeysyms.h>
34 
35 #include "e-cal-model-calendar.h"
36 #include "e-cell-date-edit-text.h"
37 #include "comp-util.h"
38 #include "itip-utils.h"
39 #include "calendar-config.h"
40 #include "misc.h"
41 
42 struct _ECalListViewPrivate {
43 	/* The main display table */
44 	ETable *table;
45 
46 	/* The last ECalendarViewEvent we returned from e_cal_list_view_get_selected_events(), to be freed */
47 	ECalendarViewEvent *cursor_event;
48 };
49 
50 enum {
51 	PROP_0,
52 	PROP_IS_EDITING
53 };
54 
55 /* The icons to represent the event. */
56 static const gchar *icon_names[] = {
57 	"x-office-calendar",
58 	"stock_people",
59 	"view-refresh"
60 };
61 
62 static void      e_cal_list_view_dispose                (GObject *object);
63 
64 static GList    *e_cal_list_view_get_selected_events    (ECalendarView *cal_view);
65 static gboolean  e_cal_list_view_get_selected_time_range (ECalendarView *cal_view, time_t *start_time, time_t *end_time);
66 static gboolean  e_cal_list_view_get_visible_time_range (ECalendarView *cal_view, time_t *start_time,
67 							 time_t *end_time);
68 
69 static gboolean  e_cal_list_view_popup_menu             (GtkWidget *widget);
70 
71 static gboolean  e_cal_list_view_on_table_double_click   (GtkWidget *table, gint row, gint col,
72 							 GdkEvent *event, gpointer data);
73 static gboolean  e_cal_list_view_on_table_right_click   (GtkWidget *table, gint row, gint col,
74 							 GdkEvent *event, gpointer data);
75 static gboolean e_cal_list_view_on_table_key_press	(ETable *table, gint row, gint col,
76 							 GdkEvent *event, gpointer data);
77 static gboolean  e_cal_list_view_on_table_white_space_event (ETable *table, GdkEvent *event, gpointer data);
78 static void e_cal_list_view_cursor_change_cb (ETable *etable, gint row, gpointer data);
79 
G_DEFINE_TYPE(ECalListView,e_cal_list_view,E_TYPE_CALENDAR_VIEW)80 G_DEFINE_TYPE (ECalListView, e_cal_list_view, E_TYPE_CALENDAR_VIEW)
81 
82 static void
83 e_cal_list_view_get_property (GObject *object,
84                               guint property_id,
85                               GValue *value,
86                               GParamSpec *pspec)
87 {
88 	ECalListView *eclv = E_CAL_LIST_VIEW (object);
89 
90 	switch (property_id) {
91 	case PROP_IS_EDITING:
92 		g_value_set_boolean (value, e_cal_list_view_is_editing (eclv));
93 		break;
94 	default:
95 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
96 		break;
97 	}
98 }
99 
100 static gchar *
e_cal_list_view_get_description_text(ECalendarView * cal_view)101 e_cal_list_view_get_description_text (ECalendarView *cal_view)
102 {
103 	ECalModel *model;
104 	GString *string;
105 	const gchar *format;
106 	gint n_rows;
107 	gint n_selected;
108 
109 	g_return_val_if_fail (E_IS_CAL_LIST_VIEW (cal_view), NULL);
110 
111 	model = e_calendar_view_get_model (cal_view);
112 	n_rows = e_table_model_row_count (E_TABLE_MODEL (model));
113 	n_selected = e_table_selected_count (e_cal_list_view_get_table (E_CAL_LIST_VIEW (cal_view)));
114 	string = g_string_sized_new (64);
115 
116 	format = ngettext ("%d appointment", "%d appointments", n_rows);
117 	g_string_append_printf (string, format, n_rows);
118 
119 	if (n_selected > 0) {
120 		format = _("%d selected");
121 		g_string_append_len (string, ", ", 2);
122 		g_string_append_printf (string, format, n_selected);
123 	}
124 
125 	return g_string_free (string, FALSE);
126 }
127 
128 static void
e_cal_list_view_class_init(ECalListViewClass * class)129 e_cal_list_view_class_init (ECalListViewClass *class)
130 {
131 	GObjectClass *object_class;
132 	GtkWidgetClass *widget_class;
133 	ECalendarViewClass *view_class;
134 
135 	object_class = (GObjectClass *) class;
136 	widget_class = (GtkWidgetClass *) class;
137 	view_class = (ECalendarViewClass *) class;
138 
139 	g_type_class_add_private (class, sizeof (ECalListViewPrivate));
140 
141 	/* Method override */
142 	object_class->dispose = e_cal_list_view_dispose;
143 	object_class->get_property = e_cal_list_view_get_property;
144 
145 	widget_class->popup_menu = e_cal_list_view_popup_menu;
146 
147 	view_class->get_selected_events = e_cal_list_view_get_selected_events;
148 	view_class->get_selected_time_range = e_cal_list_view_get_selected_time_range;
149 	view_class->get_visible_time_range = e_cal_list_view_get_visible_time_range;
150 	view_class->get_description_text = e_cal_list_view_get_description_text;
151 
152 	g_object_class_override_property (
153 		object_class,
154 		PROP_IS_EDITING,
155 		"is-editing");
156 }
157 
158 static void
e_cal_list_view_init(ECalListView * cal_list_view)159 e_cal_list_view_init (ECalListView *cal_list_view)
160 {
161 	cal_list_view->priv = G_TYPE_INSTANCE_GET_PRIVATE (cal_list_view, E_TYPE_CAL_LIST_VIEW, ECalListViewPrivate);
162 
163 	cal_list_view->priv->table = NULL;
164 	cal_list_view->priv->cursor_event = NULL;
165 }
166 
167 /* Returns the current time, for the ECellDateEdit items. */
168 static struct tm
get_current_time_cb(ECellDateEdit * ecde,gpointer data)169 get_current_time_cb (ECellDateEdit *ecde,
170                      gpointer data)
171 {
172 	ECalListView *cal_list_view = data;
173 	ICalTimezone *zone;
174 	ICalTime *tt;
175 	struct tm tmp_tm;
176 
177 	zone = e_calendar_view_get_timezone (E_CALENDAR_VIEW (cal_list_view));
178 	tt = i_cal_time_new_from_timet_with_zone (time (NULL), FALSE, zone);
179 
180 	tmp_tm = e_cal_util_icaltime_to_tm (tt);
181 
182 	g_clear_object (&tt);
183 
184 	return tmp_tm;
185 }
186 
187 static void
e_cal_list_view_table_editing_changed_cb(ETable * table,GParamSpec * param,ECalListView * eclv)188 e_cal_list_view_table_editing_changed_cb (ETable *table,
189                                           GParamSpec *param,
190                                           ECalListView *eclv)
191 {
192 	g_return_if_fail (E_IS_CAL_LIST_VIEW (eclv));
193 
194 	g_object_notify (G_OBJECT (eclv), "is-editing");
195 }
196 
197 static void
setup_e_table(ECalListView * cal_list_view)198 setup_e_table (ECalListView *cal_list_view)
199 {
200 	ECalModel *model;
201 	ETableExtras *extras;
202 	ETableSpecification *specification;
203 	GList *strings;
204 	ECell *cell, *popup_cell;
205 	GtkWidget *container;
206 	GtkWidget *widget;
207 	gchar *etspecfile;
208 	GError *local_error = NULL;
209 
210 	model = e_calendar_view_get_model (E_CALENDAR_VIEW (cal_list_view));
211 
212 	/* Create the header columns */
213 
214 	extras = e_table_extras_new ();
215 
216 	cell = e_cell_toggle_new (icon_names, G_N_ELEMENTS (icon_names));
217 	g_object_set (cell,
218 		"bg-color-column", E_CAL_MODEL_FIELD_COLOR,
219 		NULL);
220 	e_table_extras_add_cell (extras, "icon", cell);
221 	g_object_unref (cell);
222 
223 	e_table_extras_add_icon_name (extras, "icon", "x-office-calendar");
224 
225 	/* Normal string fields */
226 
227 	cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
228 	g_object_set (
229 		cell,
230 		"bg_color_column", E_CAL_MODEL_FIELD_COLOR,
231 		"strikeout_column", E_CAL_MODEL_FIELD_CANCELLED,
232 		NULL);
233 
234 	e_table_extras_add_cell (extras, "calstring", cell);
235 	g_object_unref (cell);
236 
237 	/* Date fields */
238 
239 	cell = e_cell_date_edit_text_new (NULL, GTK_JUSTIFY_LEFT);
240 	g_object_set (
241 		cell,
242 		"bg_color_column", E_CAL_MODEL_FIELD_COLOR,
243 		"strikeout_column", E_CAL_MODEL_FIELD_CANCELLED,
244 		NULL);
245 
246 	e_binding_bind_property (
247 		model, "timezone",
248 		cell, "timezone",
249 		G_BINDING_BIDIRECTIONAL |
250 		G_BINDING_SYNC_CREATE);
251 
252 	e_binding_bind_property (
253 		model, "use-24-hour-format",
254 		cell, "use-24-hour-format",
255 		G_BINDING_BIDIRECTIONAL |
256 		G_BINDING_SYNC_CREATE);
257 
258 	popup_cell = e_cell_date_edit_new ();
259 	e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell);
260 	g_object_unref (cell);
261 
262 	e_binding_bind_property (
263 		model, "use-24-hour-format",
264 		popup_cell, "use-24-hour-format",
265 		G_BINDING_BIDIRECTIONAL |
266 		G_BINDING_SYNC_CREATE);
267 
268 	e_table_extras_add_cell (extras, "dateedit", popup_cell);
269 	g_object_unref (popup_cell);
270 
271 	gtk_widget_hide (E_CELL_DATE_EDIT (popup_cell)->none_button);
272 
273 	e_cell_date_edit_set_get_time_callback (
274 		E_CELL_DATE_EDIT (popup_cell),
275 		get_current_time_cb,
276 		cal_list_view, NULL);
277 
278 	/* Combo fields */
279 
280 	cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
281 	g_object_set (
282 		cell,
283 		"bg_color_column", E_CAL_MODEL_FIELD_COLOR,
284 		"strikeout_column", E_CAL_MODEL_FIELD_CANCELLED,
285 		"editable", FALSE,
286 		NULL);
287 
288 	popup_cell = e_cell_combo_new ();
289 	e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell);
290 	g_object_unref (cell);
291 
292 	strings = NULL;
293 	strings = g_list_append (strings, (gchar *) _("Public"));
294 	strings = g_list_append (strings, (gchar *) _("Private"));
295 	strings = g_list_append (strings, (gchar *) _("Confidential"));
296 	e_cell_combo_set_popdown_strings (
297 		E_CELL_COMBO (popup_cell),
298 		strings);
299 	g_list_free (strings);
300 
301 	e_table_extras_add_cell (extras, "classification", popup_cell);
302 	g_object_unref (popup_cell);
303 
304 	/* Status field. */
305 	cell = e_cell_text_new (NULL, GTK_JUSTIFY_LEFT);
306 	g_object_set (
307 		cell,
308 		"bg_color_column", E_CAL_MODEL_FIELD_COLOR,
309 		"strikeout_column", E_CAL_MODEL_FIELD_CANCELLED,
310 		NULL);
311 
312 	popup_cell = e_cell_combo_new ();
313 	e_cell_popup_set_child (E_CELL_POPUP (popup_cell), cell);
314 	g_object_unref (cell);
315 
316 	strings = cal_comp_util_get_status_list_for_kind (e_cal_model_get_component_kind (model));
317 	e_cell_combo_set_popdown_strings (
318 		E_CELL_COMBO (popup_cell),
319 		strings);
320 	g_list_free (strings);
321 
322 	e_table_extras_add_cell (extras, "calstatus", popup_cell);
323 	g_object_unref (popup_cell);
324 
325 	/* Sorting */
326 
327 	e_table_extras_add_compare (
328 		extras, "date-compare",
329 		e_cell_date_edit_compare_cb);
330 	e_table_extras_add_compare (
331 		extras, "status-compare",
332 		e_cal_model_util_status_compare_cb);
333 
334 	/* set proper format component for a default 'date' cell renderer */
335 	cell = e_table_extras_get_cell (extras, "date");
336 	e_cell_date_set_format_component (E_CELL_DATE (cell), "calendar");
337 
338 	/* Create table view */
339 
340 	container = GTK_WIDGET (cal_list_view);
341 
342 	widget = gtk_scrolled_window_new (NULL, NULL);
343 	gtk_scrolled_window_set_policy (
344 		GTK_SCROLLED_WINDOW (widget),
345 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
346 	gtk_grid_attach (GTK_GRID (container), widget, 0, 1, 2, 2);
347 	g_object_set (G_OBJECT (widget),
348 		"hexpand", TRUE,
349 		"vexpand", TRUE,
350 		"halign", GTK_ALIGN_FILL,
351 		"valign", GTK_ALIGN_FILL,
352 		NULL);
353 	gtk_widget_show (widget);
354 
355 	container = widget;
356 
357 	etspecfile = g_build_filename (
358 		EVOLUTION_ETSPECDIR, "e-cal-list-view.etspec", NULL);
359 	specification = e_table_specification_new (etspecfile, &local_error);
360 
361 	/* Failure here is fatal. */
362 	if (local_error != NULL) {
363 		g_error ("%s: %s", etspecfile, local_error->message);
364 		g_return_if_reached ();
365 	}
366 
367 	widget = e_table_new (E_TABLE_MODEL (model), extras, specification);
368 	g_object_set (G_OBJECT (widget), "uniform-row-height", TRUE, NULL);
369 	gtk_container_add (GTK_CONTAINER (container), widget);
370 	cal_list_view->priv->table = E_TABLE (widget);
371 	gtk_widget_show (widget);
372 
373 	g_object_unref (specification);
374 	g_object_unref (extras);
375 	g_free (etspecfile);
376 
377 	/* Connect signals */
378 	g_signal_connect (
379 		cal_list_view->priv->table, "double_click",
380 		G_CALLBACK (e_cal_list_view_on_table_double_click),
381 		cal_list_view);
382 	g_signal_connect (
383 		cal_list_view->priv->table, "right-click",
384 		G_CALLBACK (e_cal_list_view_on_table_right_click),
385 		cal_list_view);
386 	g_signal_connect (
387 		cal_list_view->priv->table, "key-press",
388 		G_CALLBACK (e_cal_list_view_on_table_key_press),
389 		cal_list_view);
390 	g_signal_connect (
391 		cal_list_view->priv->table, "white-space-event",
392 		G_CALLBACK (e_cal_list_view_on_table_white_space_event),
393 		cal_list_view);
394 	g_signal_connect_after (
395 		cal_list_view->priv->table, "cursor_change",
396 		G_CALLBACK (e_cal_list_view_cursor_change_cb),
397 		cal_list_view);
398 	e_signal_connect_notify_after (
399 		cal_list_view->priv->table, "notify::is-editing",
400 		G_CALLBACK (e_cal_list_view_table_editing_changed_cb),
401 		cal_list_view);
402 }
403 
404 /**
405  * e_cal_list_view_new:
406  * @Returns: a new #ECalListView.
407  *
408  * Creates a new #ECalListView.
409  **/
410 ECalendarView *
e_cal_list_view_new(ECalModel * model)411 e_cal_list_view_new (ECalModel *model)
412 {
413 	ECalendarView *cal_list_view;
414 
415 	cal_list_view = g_object_new (
416 		E_TYPE_CAL_LIST_VIEW, "model", model, NULL);
417 	setup_e_table (E_CAL_LIST_VIEW (cal_list_view));
418 
419 	return cal_list_view;
420 }
421 
422 static void
e_cal_list_view_dispose(GObject * object)423 e_cal_list_view_dispose (GObject *object)
424 {
425 	ECalListView *cal_list_view;
426 
427 	cal_list_view = E_CAL_LIST_VIEW (object);
428 
429 	g_clear_pointer (&cal_list_view->priv->cursor_event, g_free);
430 
431 	if (cal_list_view->priv->table) {
432 		gtk_widget_destroy (GTK_WIDGET (cal_list_view->priv->table));
433 		cal_list_view->priv->table = NULL;
434 	}
435 
436 	/* Chain up to parent's dispose() method. */
437 	G_OBJECT_CLASS (e_cal_list_view_parent_class)->dispose (object);
438 }
439 
440 static void
e_cal_list_view_show_popup_menu(ECalListView * cal_list_view,GdkEvent * event)441 e_cal_list_view_show_popup_menu (ECalListView *cal_list_view,
442                                  GdkEvent *event)
443 {
444 	e_calendar_view_popup_event (E_CALENDAR_VIEW (cal_list_view), event);
445 }
446 
447 static gboolean
e_cal_list_view_popup_menu(GtkWidget * widget)448 e_cal_list_view_popup_menu (GtkWidget *widget)
449 {
450 	ECalListView *cal_list_view = E_CAL_LIST_VIEW (widget);
451 
452 	e_cal_list_view_show_popup_menu (cal_list_view, NULL);
453 	return TRUE;
454 }
455 
456 static void
e_cal_list_view_open_at_row(ECalListView * cal_list_view,gint row)457 e_cal_list_view_open_at_row (ECalListView *cal_list_view,
458 			     gint row)
459 {
460 	ECalModelComponent *comp_data;
461 
462 	g_return_if_fail (E_IS_CAL_LIST_VIEW (cal_list_view));
463 
464 	comp_data = e_cal_model_get_component_at (e_calendar_view_get_model (E_CALENDAR_VIEW (cal_list_view)), row);
465 	g_warn_if_fail (comp_data != NULL);
466 	if (!comp_data)
467 		return;
468 
469 	e_calendar_view_edit_appointment (E_CALENDAR_VIEW (cal_list_view), comp_data->client, comp_data->icalcomp, EDIT_EVENT_AUTODETECT);
470 }
471 
472 static gboolean
e_cal_list_view_on_table_double_click(GtkWidget * table,gint row,gint col,GdkEvent * event,gpointer data)473 e_cal_list_view_on_table_double_click (GtkWidget *table,
474                                        gint row,
475                                        gint col,
476                                        GdkEvent *event,
477                                        gpointer data)
478 {
479 	e_cal_list_view_open_at_row (data, row);
480 
481 	return TRUE;
482 }
483 
484 static gboolean
e_cal_list_view_on_table_right_click(GtkWidget * table,gint row,gint col,GdkEvent * event,gpointer data)485 e_cal_list_view_on_table_right_click (GtkWidget *table,
486                                       gint row,
487                                       gint col,
488                                       GdkEvent *event,
489                                       gpointer data)
490 {
491 	ECalListView *cal_list_view = E_CAL_LIST_VIEW (data);
492 
493 	e_cal_list_view_show_popup_menu (cal_list_view, event);
494 
495 	return TRUE;
496 }
497 
498 static gboolean
e_cal_list_view_on_table_key_press(ETable * table,gint row,gint col,GdkEvent * event,gpointer data)499 e_cal_list_view_on_table_key_press (ETable *table,
500 				    gint row,
501 				    gint col,
502 				    GdkEvent *event,
503 				    gpointer data)
504 {
505 	if (event && event->type == GDK_KEY_PRESS &&
506 	    (event->key.keyval == GDK_KEY_Return || event->key.keyval == GDK_KEY_KP_Enter) &&
507 	    (event->key.state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)) == 0 &&
508 	    !e_table_is_editing (table)) {
509 		e_cal_list_view_open_at_row (data, row);
510 		return TRUE;
511 	}
512 
513 	return FALSE;
514 }
515 
516 static gboolean
e_cal_list_view_on_table_white_space_event(ETable * table,GdkEvent * event,gpointer user_data)517 e_cal_list_view_on_table_white_space_event (ETable *table,
518 					    GdkEvent *event,
519 					    gpointer user_data)
520 {
521 	ECalListView *cal_list_view = user_data;
522 	guint event_button = 0;
523 
524 	g_return_val_if_fail (E_IS_CAL_LIST_VIEW (cal_list_view), FALSE);
525 	g_return_val_if_fail (event != NULL, FALSE);
526 
527 	if (event->type == GDK_BUTTON_PRESS &&
528 	    gdk_event_get_button (event, &event_button) &&
529 	    event_button == 3) {
530 		GtkWidget *table_canvas;
531 
532 		table_canvas = GTK_WIDGET (table->table_canvas);
533 
534 		if (!gtk_widget_has_focus (table_canvas))
535 			gtk_widget_grab_focus (table_canvas);
536 
537 		e_cal_list_view_show_popup_menu (cal_list_view, event);
538 
539 		return TRUE;
540 	}
541 
542 	return FALSE;
543 }
544 
545 static void
e_cal_list_view_cursor_change_cb(ETable * etable,gint row,gpointer data)546 e_cal_list_view_cursor_change_cb (ETable *etable,
547                                   gint row,
548                                   gpointer data)
549 {
550 	ECalListView *cal_list_view = E_CAL_LIST_VIEW (data);
551 
552 	g_signal_emit_by_name (cal_list_view, "selection_changed");
553 }
554 
555 static gboolean
e_cal_list_view_get_selected_time_range(ECalendarView * cal_view,time_t * start_time,time_t * end_time)556 e_cal_list_view_get_selected_time_range (ECalendarView *cal_view,
557                                          time_t *start_time,
558                                          time_t *end_time)
559 {
560 	GList *selected;
561 	ICalTimezone *zone;
562 
563 	selected = e_calendar_view_get_selected_events (cal_view);
564 	if (selected) {
565 		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
566 		ECalComponent *comp;
567 
568 		if (!is_comp_data_valid (event))
569 			return FALSE;
570 
571 		comp = e_cal_component_new ();
572 		e_cal_component_set_icalcomponent (comp, i_cal_component_clone (event->comp_data->icalcomp));
573 		if (start_time) {
574 			ECalComponentDateTime *dt;
575 
576 			dt = e_cal_component_get_dtstart (comp);
577 
578 			if (dt) {
579 				if (e_cal_component_datetime_get_tzid (dt)) {
580 					zone = i_cal_component_get_timezone (e_cal_component_get_icalcomponent (comp), e_cal_component_datetime_get_tzid (dt));
581 				} else {
582 					zone = NULL;
583 				}
584 				*start_time = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value (dt), zone);
585 			} else {
586 				*start_time = (time_t) 0;
587 			}
588 
589 			e_cal_component_datetime_free (dt);
590 		}
591 		if (end_time) {
592 			ECalComponentDateTime *dt;
593 
594 			dt = e_cal_component_get_dtend (comp);
595 
596 			if (dt) {
597 				if (e_cal_component_datetime_get_tzid (dt)) {
598 					zone = i_cal_component_get_timezone (e_cal_component_get_icalcomponent (comp), e_cal_component_datetime_get_tzid (dt));
599 				} else {
600 					zone = NULL;
601 				}
602 				*end_time = i_cal_time_as_timet_with_zone (e_cal_component_datetime_get_value (dt), zone);
603 			} else {
604 				*end_time = (time_t) 0;
605 			}
606 
607 			e_cal_component_datetime_free (dt);
608 		}
609 
610 		g_object_unref (comp);
611 		g_list_free (selected);
612 
613 		return TRUE;
614 	}
615 
616 	return FALSE;
617 }
618 
619 static GList *
e_cal_list_view_get_selected_events(ECalendarView * cal_view)620 e_cal_list_view_get_selected_events (ECalendarView *cal_view)
621 {
622 	GList *event_list = NULL;
623 	gint   cursor_row;
624 
625 	g_clear_pointer (&E_CAL_LIST_VIEW (cal_view)->priv->cursor_event, g_free);
626 
627 	cursor_row = e_table_get_cursor_row (
628 		E_CAL_LIST_VIEW (cal_view)->priv->table);
629 
630 	if (cursor_row >= 0) {
631 		ECalendarViewEvent *event;
632 
633 		event = E_CAL_LIST_VIEW (cal_view)->priv->cursor_event = g_new0 (ECalendarViewEvent, 1);
634 		event->comp_data =
635 			e_cal_model_get_component_at (
636 				e_calendar_view_get_model (cal_view),
637 				cursor_row);
638 		event_list = g_list_prepend (event_list, event);
639 	}
640 
641 	return event_list;
642 }
643 
644 static gboolean
e_cal_list_view_get_visible_time_range(ECalendarView * cal_view,time_t * start_time,time_t * end_time)645 e_cal_list_view_get_visible_time_range (ECalendarView *cal_view,
646                                         time_t *start_time,
647                                         time_t *end_time)
648 {
649 	/* No time range */
650 	return FALSE;
651 }
652 
653 ETable *
e_cal_list_view_get_table(ECalListView * cal_list_view)654 e_cal_list_view_get_table (ECalListView *cal_list_view)
655 {
656 	g_return_val_if_fail (E_IS_CAL_LIST_VIEW (cal_list_view), NULL);
657 
658 	return cal_list_view->priv->table;
659 }
660 
661 gboolean
e_cal_list_view_is_editing(ECalListView * eclv)662 e_cal_list_view_is_editing (ECalListView *eclv)
663 {
664 	g_return_val_if_fail (E_IS_CAL_LIST_VIEW (eclv), FALSE);
665 
666 	return eclv->priv->table && e_table_is_editing (eclv->priv->table);
667 }
668