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