1 /*
2 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
3 * Copyright (C) 2014 Red Hat, Inc. (www.redhat.com)
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "evolution-config.h"
19
20 #include <string.h>
21 #include <math.h>
22 #include <glib/gi18n-lib.h>
23
24 #include "calendar/gui/calendar-config.h"
25 #include "calendar/gui/calendar-view.h"
26 #include "calendar/gui/comp-util.h"
27 #include "calendar/gui/e-cal-list-view.h"
28 #include "calendar/gui/e-cal-model-calendar.h"
29 #include "calendar/gui/e-cal-model-memos.h"
30 #include "calendar/gui/e-cal-model-tasks.h"
31 #include "calendar/gui/e-calendar-view.h"
32 #include "calendar/gui/e-day-view.h"
33 #include "calendar/gui/e-month-view.h"
34 #include "calendar/gui/e-week-view.h"
35 #include "calendar/gui/itip-utils.h"
36 #include "calendar/gui/tag-calendar.h"
37
38 #include "e-cal-base-shell-sidebar.h"
39 #include "e-cal-shell-view-private.h"
40 #include "e-cal-shell-content.h"
41
42 #define E_CAL_SHELL_CONTENT_GET_PRIVATE(obj) \
43 (G_TYPE_INSTANCE_GET_PRIVATE \
44 ((obj), E_TYPE_CAL_SHELL_CONTENT, ECalShellContentPrivate))
45
46 struct _ECalShellContentPrivate {
47 GtkWidget *hpaned;
48 GtkWidget *vpaned;
49
50 GtkWidget *calendar_notebook;
51 GtkWidget *task_table;
52 ECalModel *task_model;
53 ECalDataModel *task_data_model;
54
55 GtkWidget *memo_table;
56 ECalModel *memo_model;
57 ECalDataModel *memo_data_model;
58
59 ECalModel *list_view_model;
60 ECalDataModel *list_view_data_model;
61
62 ETagCalendar *tag_calendar;
63 gulong datepicker_selection_changed_id;
64 gulong datepicker_range_moved_id;
65
66 ECalViewKind current_view;
67 ECalendarView *views[E_CAL_VIEW_KIND_LAST];
68 GDate view_start, view_end;
69 guint32 view_start_range_day_offset;
70 GDate last_range_start; /* because "date-range-changed" can be emit with no real change */
71
72 time_t previous_selected_start_time;
73 time_t previous_selected_end_time;
74
75 gulong current_view_id_changed_id;
76
77 gboolean initialized;
78 };
79
80 enum {
81 PROP_0,
82 PROP_CALENDAR_NOTEBOOK,
83 PROP_MEMO_TABLE,
84 PROP_TASK_TABLE,
85 PROP_CURRENT_VIEW_ID,
86 PROP_CURRENT_VIEW,
87 PROP_SHOW_TAG_VPANE
88 };
89
90 /* Used to indicate who has the focus within the calendar view. */
91 typedef enum {
92 FOCUS_CALENDAR_NOTEBOOK,
93 FOCUS_MEMO_TABLE,
94 FOCUS_TASK_TABLE,
95 FOCUS_OTHER
96 } FocusLocation;
97
G_DEFINE_DYNAMIC_TYPE(ECalShellContent,e_cal_shell_content,E_TYPE_CAL_BASE_SHELL_CONTENT)98 G_DEFINE_DYNAMIC_TYPE (ECalShellContent, e_cal_shell_content, E_TYPE_CAL_BASE_SHELL_CONTENT)
99
100 static time_t
101 convert_to_local_zone (time_t tm,
102 ICalTimezone *from_zone)
103 {
104 ICalTime *itt;
105 time_t tt;
106
107 itt = i_cal_time_new_from_timet_with_zone (tm, FALSE, from_zone);
108 tt = i_cal_time_as_timet (itt);
109 g_clear_object (&itt);
110
111 return tt;
112 }
113
114 static void
cal_shell_content_update_model_and_current_view_times(ECalShellContent * cal_shell_content,ECalModel * model,ECalendarItem * calitem,time_t view_start_tt,time_t view_end_tt,const GDate * view_start,const GDate * view_end)115 cal_shell_content_update_model_and_current_view_times (ECalShellContent *cal_shell_content,
116 ECalModel *model,
117 ECalendarItem *calitem,
118 time_t view_start_tt,
119 time_t view_end_tt,
120 const GDate *view_start,
121 const GDate *view_end)
122 {
123 ECalendarView *current_view;
124 EDayView *day_view = NULL;
125 gint day_view_selection_start_day = -1, day_view_selection_end_day = -1;
126 gint day_view_selection_start_row = -1, day_view_selection_end_row = -1;
127 gdouble day_view_scrollbar_position = 0.0;
128 gint syy, smm, sdd, eyy, emm, edd;
129 time_t visible_range_start, visible_range_end;
130 gboolean filters_updated = FALSE;
131 ICalTimezone *zone;
132 gchar *cal_filter;
133
134 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
135 g_return_if_fail (E_IS_CAL_MODEL (model));
136 g_return_if_fail (E_IS_CALENDAR_ITEM (calitem));
137
138 current_view = e_cal_shell_content_get_current_calendar_view (cal_shell_content);
139 g_return_if_fail (current_view != NULL);
140
141 zone = e_cal_model_get_timezone (model);
142 cal_filter = e_cal_data_model_dup_filter (e_cal_model_get_data_model (model));
143
144 if (E_IS_DAY_VIEW (current_view)) {
145 GtkAdjustment *adjustment;
146
147 day_view = E_DAY_VIEW (current_view);
148 day_view_selection_start_day = day_view->selection_start_day;
149 day_view_selection_end_day = day_view->selection_end_day;
150 day_view_selection_start_row = day_view->selection_start_row;
151 day_view_selection_end_row = day_view->selection_end_row;
152
153 adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (day_view->main_canvas));
154 day_view_scrollbar_position = gtk_adjustment_get_value (adjustment);
155 }
156
157 g_signal_handler_block (calitem, cal_shell_content->priv->datepicker_range_moved_id);
158 g_signal_handler_block (calitem, cal_shell_content->priv->datepicker_selection_changed_id);
159
160 visible_range_start = view_start_tt;
161 visible_range_end = view_end_tt;
162
163 e_calendar_view_precalc_visible_time_range (current_view, view_start_tt, view_end_tt, &visible_range_start, &visible_range_end);
164 if (view_start_tt != visible_range_start || view_end_tt != visible_range_end) {
165 time_t cmp_range_start = convert_to_local_zone (visible_range_start, zone);
166 time_t cmp_range_end = convert_to_local_zone (visible_range_end, zone);
167
168 if (view_start_tt != cmp_range_start ||
169 view_end_tt != cmp_range_end - 1) {
170 /* Calendar views update their inner time range during e_cal_model_set_time_range() call,
171 while they can change it if needed (like a clamp of a week view with a week start day
172 not being Monday */
173 GDate new_view_start, new_view_end;
174
175 /* Midnight means the next day, which is not desired here */
176 cmp_range_end--;
177 visible_range_end--;
178
179 /* These times are in the correct zone already */
180 time_to_gdate_with_zone (&new_view_start, cmp_range_start, NULL);
181 time_to_gdate_with_zone (&new_view_end, cmp_range_end, NULL);
182
183 e_calendar_item_set_selection (calitem, &new_view_start, &new_view_end);
184 e_cal_shell_content_update_filters (cal_shell_content, cal_filter, visible_range_start, visible_range_end);
185 e_calendar_view_set_selected_time_range (current_view, cmp_range_start, cmp_range_start);
186 filters_updated = TRUE;
187 view_start_tt = cmp_range_start;
188 view_end_tt = cmp_range_end;
189 }
190 }
191
192 if (!filters_updated) {
193 e_calendar_item_set_selection (calitem, view_start, view_end);
194 e_cal_shell_content_update_filters (cal_shell_content, cal_filter, view_start_tt, view_end_tt);
195 e_calendar_view_set_selected_time_range (current_view, view_start_tt, view_start_tt);
196 }
197
198 if (day_view && day_view_selection_start_day != -1 && day_view_selection_end_day != -1 &&
199 day_view_selection_start_row != -1 && day_view_selection_end_row != -1) {
200 GtkAdjustment *adjustment;
201
202 day_view->selection_start_day = day_view_selection_start_day;
203 day_view->selection_end_day = day_view_selection_end_day;
204 day_view->selection_start_row = day_view_selection_start_row;
205 day_view->selection_end_row = day_view_selection_end_row;
206
207 /* This is better than e_day_view_ensure_rows_visible(), because it keeps both
208 selection and the exact scrollbar position in the main canvas, which may not
209 always correspond to each other. */
210 adjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (day_view->main_canvas));
211 gtk_adjustment_set_value (adjustment, day_view_scrollbar_position);
212 }
213
214 gtk_widget_queue_draw (GTK_WIDGET (current_view));
215
216 g_free (cal_filter);
217
218 g_signal_handler_unblock (calitem, cal_shell_content->priv->datepicker_range_moved_id);
219 g_signal_handler_unblock (calitem, cal_shell_content->priv->datepicker_selection_changed_id);
220
221 if (e_calendar_item_get_date_range (calitem, &syy, &smm, &sdd, &eyy, &emm, &edd)) {
222 GDate range_start;
223
224 g_date_set_dmy (&range_start, sdd, smm + 1, syy);
225
226 cal_shell_content->priv->view_start_range_day_offset =
227 g_date_get_julian (&cal_shell_content->priv->view_start) - g_date_get_julian (&range_start);
228 }
229 }
230
231 static void
e_cal_shell_content_change_view(ECalShellContent * cal_shell_content,ECalViewKind to_view,const GDate * view_start,const GDate * view_end,gboolean force_change)232 e_cal_shell_content_change_view (ECalShellContent *cal_shell_content,
233 ECalViewKind to_view,
234 const GDate *view_start,
235 const GDate *view_end,
236 gboolean force_change)
237 {
238 EShellSidebar *shell_sidebar;
239 EShellView *shell_view;
240 ECalendar *calendar;
241 ECalModel *model;
242 ICalTimezone *zone;
243 time_t view_start_tt, view_end_tt;
244 gboolean view_changed = FALSE;
245 gint selected_days;
246
247 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
248 g_return_if_fail (to_view >= E_CAL_VIEW_KIND_DAY && to_view < E_CAL_VIEW_KIND_LAST);
249 g_return_if_fail (view_start != NULL);
250 g_return_if_fail (g_date_valid (view_start));
251 g_return_if_fail (view_end != NULL);
252 g_return_if_fail (g_date_valid (view_end));
253
254 shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content));
255 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
256 g_return_if_fail (E_IS_CAL_BASE_SHELL_SIDEBAR (shell_sidebar));
257
258 calendar = e_cal_base_shell_sidebar_get_date_navigator (E_CAL_BASE_SHELL_SIDEBAR (shell_sidebar));
259 g_return_if_fail (E_IS_CALENDAR (calendar));
260
261 model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
262 zone = e_cal_model_get_timezone (model);
263 view_start_tt = cal_comp_gdate_to_timet (view_start, zone);
264 view_end_tt = cal_comp_gdate_to_timet (view_end, zone);
265
266 if (to_view != cal_shell_content->priv->current_view) {
267 g_signal_handler_block (cal_shell_content, cal_shell_content->priv->current_view_id_changed_id);
268 e_cal_shell_content_set_current_view_id (cal_shell_content, to_view);
269 g_signal_handler_unblock (cal_shell_content, cal_shell_content->priv->current_view_id_changed_id);
270 view_changed = TRUE;
271 }
272
273 selected_days = g_date_get_julian (view_end) - g_date_get_julian (view_start) + 1;
274
275 if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_DAY) {
276 EDayView *day_view;
277
278 day_view = E_DAY_VIEW (cal_shell_content->priv->views[E_CAL_VIEW_KIND_DAY]);
279 e_day_view_set_days_shown (day_view, selected_days);
280 } else if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_MONTH) {
281 EWeekView *month_view;
282
283 month_view = E_WEEK_VIEW (cal_shell_content->priv->views[E_CAL_VIEW_KIND_MONTH]);
284 e_week_view_set_weeks_shown (month_view, selected_days / 7);
285 }
286
287 if (!force_change &&
288 g_date_valid (&cal_shell_content->priv->view_start) &&
289 g_date_valid (&cal_shell_content->priv->view_end) &&
290 g_date_compare (&cal_shell_content->priv->view_start, view_start) == 0 &&
291 g_date_compare (&cal_shell_content->priv->view_end, view_end) == 0) {
292 ECalendarItem *calitem = e_calendar_get_item (calendar);
293
294 if (view_changed)
295 cal_shell_content_update_model_and_current_view_times (
296 cal_shell_content, model, calitem, view_start_tt, view_end_tt, view_start, view_end);
297
298 g_signal_handler_block (calitem, cal_shell_content->priv->datepicker_range_moved_id);
299 g_signal_handler_block (calitem, cal_shell_content->priv->datepicker_selection_changed_id);
300
301 e_calendar_item_set_selection (calitem, view_start, view_end);
302
303 g_signal_handler_unblock (calitem, cal_shell_content->priv->datepicker_range_moved_id);
304 g_signal_handler_unblock (calitem, cal_shell_content->priv->datepicker_selection_changed_id);
305
306 return;
307 }
308
309 cal_shell_content->priv->view_start = *view_start;
310 cal_shell_content->priv->view_end = *view_end;
311
312 cal_shell_content_update_model_and_current_view_times (
313 cal_shell_content, model, e_calendar_get_item (calendar), view_start_tt, view_end_tt, view_start, view_end);
314 }
315
316 static void
cal_shell_content_clamp_for_whole_weeks(GDateWeekday week_start_day,GDate * sel_start,GDate * sel_end,gboolean saturday_as_sunday)317 cal_shell_content_clamp_for_whole_weeks (GDateWeekday week_start_day,
318 GDate *sel_start,
319 GDate *sel_end,
320 gboolean saturday_as_sunday)
321 {
322 GDateWeekday wday;
323 guint32 julian_start, julian_end;
324
325 g_return_if_fail (sel_start != NULL);
326 g_return_if_fail (sel_end != NULL);
327
328 wday = g_date_get_weekday (sel_start);
329
330 /* This is because the month/week view doesn't split weekends */
331 if (saturday_as_sunday && wday == G_DATE_SATURDAY && week_start_day == G_DATE_SUNDAY)
332 wday = G_DATE_SUNDAY;
333
334 if (week_start_day > wday) {
335 g_date_subtract_days (sel_start, wday);
336 wday = g_date_get_weekday (sel_start);
337 }
338
339 if (week_start_day < wday)
340 g_date_subtract_days (sel_start, wday - week_start_day);
341
342 julian_start = g_date_get_julian (sel_start);
343 julian_end = g_date_get_julian (sel_end);
344
345 if (((julian_end - julian_start + 1) % 7) != 0)
346 g_date_add_days (sel_end, 7 - ((julian_end - julian_start + 1) % 7));
347
348 julian_end = g_date_get_julian (sel_end);
349
350 /* Can show only up to 6 weeks */
351 if ((julian_end - julian_start + 1) / 7 > 6) {
352 *sel_end = *sel_start;
353 g_date_add_days (sel_end, (7 * 6) - 1);
354 }
355
356 if (g_date_compare (sel_start, sel_end) == 0)
357 g_date_add_days (sel_end, 6);
358 }
359
360 static gboolean
cal_shell_content_weekday_within(GDateWeekday start_wday,GDateWeekday end_wday,GDateWeekday test_wday)361 cal_shell_content_weekday_within (GDateWeekday start_wday,
362 GDateWeekday end_wday,
363 GDateWeekday test_wday)
364 {
365 gint ii;
366
367 if (start_wday <= end_wday)
368 return start_wday <= test_wday && test_wday <= end_wday;
369
370 for (ii = 0; ii < 7; ii++) {
371 if (start_wday == test_wday)
372 return TRUE;
373
374 if (start_wday == end_wday)
375 break;
376
377 start_wday = e_weekday_get_next (start_wday);
378 }
379
380 return FALSE;
381 }
382
383 static void
cal_shell_content_change_selection_in_current_view(ECalShellContent * cal_shell_content,time_t sel_start_tt,time_t sel_end_tt,ICalTimezone * zone)384 cal_shell_content_change_selection_in_current_view (ECalShellContent *cal_shell_content,
385 time_t sel_start_tt,
386 time_t sel_end_tt,
387 ICalTimezone *zone)
388 {
389 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
390
391 if (cal_shell_content->priv->current_view >= E_CAL_VIEW_KIND_DAY &&
392 cal_shell_content->priv->current_view < E_CAL_VIEW_KIND_LAST) {
393 ECalendarView *view;
394
395 view = cal_shell_content->priv->views[cal_shell_content->priv->current_view];
396
397 /* Preserve selected time (change only date) for these views */
398 if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_DAY ||
399 cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_WORKWEEK) {
400 time_t current_sel_start = (time_t) -1, current_sel_end = (time_t) -1;
401
402 if (e_calendar_view_get_selected_time_range (view, ¤t_sel_start, ¤t_sel_end)) {
403 ICalTime *itt;
404
405 itt = i_cal_time_new_from_timet_with_zone (current_sel_start, 0, zone);
406 current_sel_start = i_cal_time_as_timet_with_zone (itt, NULL);
407 g_clear_object (&itt);
408
409 itt = i_cal_time_new_from_timet_with_zone (current_sel_end, 0, zone);
410 current_sel_end = i_cal_time_as_timet_with_zone (itt, NULL);
411 g_clear_object (&itt);
412
413 sel_start_tt += current_sel_start % (24 * 60 * 60);
414 sel_end_tt += current_sel_end % (24 * 60 * 60);
415 }
416 }
417
418 e_calendar_view_set_selected_time_range (view, sel_start_tt, sel_end_tt);
419 }
420 }
421
422 static void
cal_shell_content_datepicker_selection_changed_cb(ECalendarItem * calitem,ECalShellContent * cal_shell_content)423 cal_shell_content_datepicker_selection_changed_cb (ECalendarItem *calitem,
424 ECalShellContent *cal_shell_content)
425 {
426 GDate sel_start, sel_end;
427 guint32 selected_days, start_julian, end_julian;
428 ICalTimezone *zone;
429 time_t sel_start_tt, sel_end_tt;
430
431 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
432 g_return_if_fail (E_IS_CALENDAR_ITEM (calitem));
433
434 g_date_clear (&sel_start, 1);
435 g_date_clear (&sel_end, 1);
436
437 if (!e_calendar_item_get_selection (calitem, &sel_start, &sel_end))
438 return;
439
440 start_julian = g_date_get_julian (&sel_start);
441 end_julian = g_date_get_julian (&sel_end);
442
443 g_return_if_fail (start_julian <= end_julian);
444
445 if (g_date_compare (&cal_shell_content->priv->view_start, &sel_start) == 0 &&
446 g_date_compare (&cal_shell_content->priv->view_end, &sel_end) == 0) {
447 /* No change in the selection range */
448 return;
449 }
450
451 zone = e_cal_model_get_timezone (e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content)));
452 sel_start_tt = cal_comp_gdate_to_timet (&sel_start, zone);
453 sel_end_tt = cal_comp_gdate_to_timet (&sel_end, zone);
454
455 selected_days = end_julian - start_julian + 1;
456 if (selected_days == 1) {
457 GDateWeekday sel_start_wday, sel_end_wday, cur_start_wday, cur_end_wday;
458
459 /* Clicked inside currently selected view range; do not do anything,
460 just make sure the days are selected again */
461 if (g_date_compare (&cal_shell_content->priv->view_start, &sel_start) <= 0 &&
462 g_date_compare (&sel_start, &cal_shell_content->priv->view_end) <= 0) {
463 sel_start = cal_shell_content->priv->view_start;
464 sel_end = cal_shell_content->priv->view_end;
465
466 e_calendar_item_set_selection (calitem, &sel_start, &sel_end);
467
468 cal_shell_content_change_selection_in_current_view (cal_shell_content, sel_start_tt, sel_end_tt, zone);
469 return;
470 }
471
472 sel_start_wday = g_date_get_weekday (&sel_start);
473 sel_end_wday = g_date_get_weekday (&sel_end);
474 cur_start_wday = g_date_get_weekday (&cal_shell_content->priv->view_start);
475 cur_end_wday = g_date_get_weekday (&cal_shell_content->priv->view_end);
476
477 if ((cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_WORKWEEK ||
478 (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_DAY &&
479 e_day_view_get_days_shown (E_DAY_VIEW (cal_shell_content->priv->views[E_CAL_VIEW_KIND_DAY])) != 1)) &&
480 cal_shell_content_weekday_within (cur_start_wday, cur_end_wday, sel_start_wday)) {
481 if (cur_start_wday < sel_start_wday) {
482 g_date_subtract_days (&sel_start, sel_start_wday - cur_start_wday);
483 } else if (cur_start_wday > sel_start_wday) {
484 g_date_subtract_days (&sel_start, 7 - (cur_start_wday - sel_start_wday));
485 }
486 sel_end = sel_start;
487 if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_DAY)
488 g_date_add_days (&sel_end, e_day_view_get_days_shown (E_DAY_VIEW (cal_shell_content->priv->views[E_CAL_VIEW_KIND_DAY])) - 1);
489 else
490 g_date_add_days (&sel_end, e_day_view_get_days_shown (E_DAY_VIEW (cal_shell_content->priv->views[E_CAL_VIEW_KIND_WORKWEEK])) - 1);
491
492 e_cal_shell_content_change_view (cal_shell_content, cal_shell_content->priv->current_view, &sel_start, &sel_end, FALSE);
493 } else if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_WEEK &&
494 cal_shell_content_weekday_within (cur_start_wday, cur_end_wday, sel_start_wday) &&
495 cal_shell_content_weekday_within (cur_start_wday, cur_end_wday, sel_end_wday)) {
496 if (cur_start_wday < sel_start_wday)
497 g_date_subtract_days (&sel_start, sel_start_wday - cur_start_wday);
498 sel_end = sel_start;
499 cal_shell_content_clamp_for_whole_weeks (calitem->week_start_day, &sel_start, &sel_end, TRUE);
500
501 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_WEEK, &sel_start, &sel_end, FALSE);
502 } else if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_MONTH ||
503 cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_LIST) {
504 /* whole month */
505 g_date_set_day (&sel_start, 1);
506 sel_end = sel_start;
507 g_date_set_day (&sel_end, g_date_get_days_in_month (g_date_get_month (&sel_start), g_date_get_year (&sel_start)) - 1);
508 cal_shell_content_clamp_for_whole_weeks (calitem->week_start_day, &sel_start, &sel_end, cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_MONTH);
509
510 e_cal_shell_content_change_view (cal_shell_content, cal_shell_content->priv->current_view, &sel_start, &sel_end, FALSE);
511 } else if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_WORKWEEK) {
512 cal_shell_content_clamp_for_whole_weeks (calitem->week_start_day, &sel_start, &sel_end, TRUE);
513 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_WEEK, &sel_start, &sel_end, FALSE);
514 } else {
515 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_DAY, &sel_start, &sel_end, FALSE);
516 }
517
518 cal_shell_content_change_selection_in_current_view (cal_shell_content, sel_start_tt, sel_end_tt, zone);
519 } else if (selected_days < 7) {
520 GDateWeekday first_work_wday;
521
522 first_work_wday = e_cal_model_get_work_day_first (e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content)));
523
524 if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_WORKWEEK &&
525 first_work_wday == g_date_get_weekday (&sel_start) &&
526 selected_days == e_day_view_get_days_shown (E_DAY_VIEW (cal_shell_content->priv->views[E_CAL_VIEW_KIND_WORKWEEK])))
527 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_WORKWEEK, &sel_start, &sel_end, FALSE);
528 else
529 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_DAY, &sel_start, &sel_end, FALSE);
530 } else if (selected_days == 7) {
531 GDateWeekday sel_start_wday;
532
533 sel_start_wday = g_date_get_weekday (&sel_start);
534
535 if (sel_start_wday == calitem->week_start_day &&
536 cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_DAY &&
537 e_day_view_get_days_shown (E_DAY_VIEW (cal_shell_content->priv->views[E_CAL_VIEW_KIND_DAY])) == 7) {
538 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_DAY, &sel_start, &sel_end, FALSE);
539 } else {
540 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_WEEK, &sel_start, &sel_end, FALSE);
541 }
542 } else {
543 if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_LIST) {
544 /* whole month */
545 g_date_set_day (&sel_start, 1);
546 sel_end = sel_start;
547 g_date_set_day (&sel_end, g_date_get_days_in_month (g_date_get_month (&sel_start), g_date_get_year (&sel_start)));
548 cal_shell_content_clamp_for_whole_weeks (calitem->week_start_day, &sel_start, &sel_end, FALSE);
549
550 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_LIST, &sel_start, &sel_end, FALSE);
551 } else {
552 cal_shell_content_clamp_for_whole_weeks (calitem->week_start_day, &sel_start, &sel_end,
553 cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_MONTH || cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_WEEK);
554 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_MONTH, &sel_start, &sel_end, FALSE);
555 }
556 }
557 }
558
559 static void
cal_shell_content_datepicker_range_moved_cb(ECalendarItem * calitem,ECalShellContent * cal_shell_content)560 cal_shell_content_datepicker_range_moved_cb (ECalendarItem *calitem,
561 ECalShellContent *cal_shell_content)
562 {
563 gint start_year, start_month, start_day, end_year, end_month, end_day;
564 GDate sel_start_date, sel_end_date, range_start_date;
565
566 g_return_if_fail (E_IS_CALENDAR_ITEM (calitem));
567 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
568
569 if (!e_calendar_item_get_date_range (calitem, &start_year, &start_month, &start_day, &end_year, &end_month, &end_day))
570 return;
571
572 g_date_set_dmy (&range_start_date, start_day, start_month + 1, start_year);
573
574 if (g_date_valid (&cal_shell_content->priv->last_range_start) &&
575 g_date_compare (&cal_shell_content->priv->last_range_start, &range_start_date) == 0) {
576 return;
577 }
578
579 cal_shell_content->priv->last_range_start = range_start_date;
580
581 g_date_clear (&sel_start_date, 1);
582 g_date_clear (&sel_end_date, 1);
583
584 if (cal_shell_content->priv->view_start_range_day_offset == (guint32) -1) {
585 sel_start_date = cal_shell_content->priv->view_start;
586 sel_end_date = cal_shell_content->priv->view_end;
587 cal_shell_content->priv->view_start_range_day_offset =
588 g_date_get_julian (&cal_shell_content->priv->view_start) - g_date_get_julian (&range_start_date);
589 } else {
590 gint view_days;
591
592 view_days = g_date_get_julian (&cal_shell_content->priv->view_end) - g_date_get_julian (&cal_shell_content->priv->view_start);
593
594 sel_start_date = range_start_date;
595 g_date_add_days (&sel_start_date, cal_shell_content->priv->view_start_range_day_offset);
596
597 sel_end_date = sel_start_date;
598 g_date_add_days (&sel_end_date, view_days);
599 }
600
601 g_signal_handler_block (calitem, cal_shell_content->priv->datepicker_range_moved_id);
602
603 e_calendar_item_set_selection (calitem, &sel_start_date, &sel_end_date);
604
605 g_signal_handler_unblock (calitem, cal_shell_content->priv->datepicker_range_moved_id);
606 }
607
608 static gboolean
cal_shell_content_datepicker_button_press_cb(ECalendar * calendar,GdkEvent * event,ECalShellContent * cal_shell_content)609 cal_shell_content_datepicker_button_press_cb (ECalendar *calendar,
610 GdkEvent *event,
611 ECalShellContent *cal_shell_content)
612 {
613 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), FALSE);
614
615 if (!event)
616 return FALSE;
617
618 if (event->type == GDK_2BUTTON_PRESS) {
619 ECalendarItem *calitem = e_calendar_get_item (calendar);
620 gdouble xwin = 0.0, ywin = 0.0;
621 GDate sel_start, sel_end;
622
623 /* Do that only if the double-click was above a day cell */
624 if (!gdk_event_get_coords (event, &xwin, &ywin) ||
625 !e_calendar_item_convert_position_to_date (calitem, xwin, ywin, &sel_start)) {
626 return FALSE;
627 }
628
629 g_date_clear (&sel_start, 1);
630 g_date_clear (&sel_end, 1);
631
632 if (!e_calendar_item_get_selection (calitem, &sel_start, &sel_end))
633 return FALSE;
634
635 /* Switch to a day view on a double-click */
636 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_DAY, &sel_start, &sel_start, FALSE);
637 }
638
639 return FALSE;
640 }
641
642 static void
cal_shell_content_current_view_id_changed_cb(ECalShellContent * cal_shell_content)643 cal_shell_content_current_view_id_changed_cb (ECalShellContent *cal_shell_content)
644 {
645 GDate sel_start, sel_end;
646 GDateWeekday work_day_first, week_start_day;
647 ECalModel *model;
648 gint ii;
649
650 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
651
652 model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
653 work_day_first = e_cal_model_get_work_day_first (model);
654 week_start_day = e_cal_model_get_week_start_day (model);
655
656 if (cal_shell_content->priv->previous_selected_start_time != -1 &&
657 cal_shell_content->priv->previous_selected_end_time != -1) {
658 ICalTimezone *zone;
659
660 zone = e_cal_model_get_timezone (model);
661 time_to_gdate_with_zone (&sel_start, cal_shell_content->priv->previous_selected_start_time, zone);
662 time_to_gdate_with_zone (&sel_end, cal_shell_content->priv->previous_selected_end_time, zone);
663 } else {
664 sel_start = cal_shell_content->priv->view_start;
665 sel_end = cal_shell_content->priv->view_end;
666 }
667
668 switch (cal_shell_content->priv->current_view) {
669 case E_CAL_VIEW_KIND_DAY:
670 /* Left the start & end being the current view start */
671 sel_end = sel_start;
672 break;
673 case E_CAL_VIEW_KIND_WORKWEEK:
674 cal_shell_content_clamp_for_whole_weeks (week_start_day, &sel_start, &sel_end, FALSE);
675 ii = 0;
676 while (g_date_get_weekday (&sel_start) != work_day_first && ii < 7) {
677 g_date_add_days (&sel_start, 1);
678 ii++;
679 }
680
681 sel_end = sel_start;
682 g_date_add_days (&sel_end, e_day_view_get_days_shown (E_DAY_VIEW (cal_shell_content->priv->views[E_CAL_VIEW_KIND_WORKWEEK])) - 1);
683 break;
684 case E_CAL_VIEW_KIND_WEEK:
685 sel_end = sel_start;
686 cal_shell_content_clamp_for_whole_weeks (week_start_day, &sel_start, &sel_end, TRUE);
687 break;
688 case E_CAL_VIEW_KIND_MONTH:
689 case E_CAL_VIEW_KIND_LIST:
690 if (!calendar_config_get_month_start_with_current_week ()) {
691 if (g_date_get_days_in_month (g_date_get_month (&sel_start), g_date_get_year (&sel_start)) - g_date_get_day (&sel_start) <= 7) {
692 /* Keep the sel_start unchanged, because it's within the last week of the month,
693 which can be covered by the mini-calendar. Setting to the first day of the month
694 may mean the mini-calendar would go back by one month. */
695 } else if (g_date_get_day (&sel_start) != 1 &&
696 (g_date_get_julian (&sel_end) - g_date_get_julian (&sel_start) + 1) / 7 >= 3 &&
697 g_date_get_month (&sel_start) != g_date_get_month (&sel_end)) {
698 g_date_set_day (&sel_start, 1);
699 g_date_add_months (&sel_start, 1);
700 } else {
701 g_date_set_day (&sel_start, 1);
702 }
703 }
704 sel_end = sel_start;
705 g_date_add_months (&sel_end, 1);
706 g_date_subtract_days (&sel_end, 1);
707 cal_shell_content_clamp_for_whole_weeks (week_start_day, &sel_start, &sel_end, cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_MONTH);
708 break;
709 default:
710 g_warn_if_reached ();
711 return;
712 }
713
714 /* Ensure a change */
715 e_cal_shell_content_change_view (cal_shell_content, cal_shell_content->priv->current_view, &sel_start, &sel_end, TRUE);
716
717 /* Try to preserve selection between the views */
718 if (cal_shell_content->priv->previous_selected_start_time != -1 &&
719 cal_shell_content->priv->previous_selected_end_time != -1) {
720 if (cal_shell_content->priv->current_view >= E_CAL_VIEW_KIND_DAY &&
721 cal_shell_content->priv->current_view < E_CAL_VIEW_KIND_LAST) {
722 ECalendarView *cal_view = cal_shell_content->priv->views[cal_shell_content->priv->current_view];
723
724 e_calendar_view_set_selected_time_range (cal_view,
725 cal_shell_content->priv->previous_selected_start_time,
726 cal_shell_content->priv->previous_selected_end_time);
727 }
728 }
729
730 cal_shell_content->priv->previous_selected_start_time = -1;
731 cal_shell_content->priv->previous_selected_end_time = -1;
732 }
733
734 static void
cal_shell_content_display_view_cb(ECalShellContent * cal_shell_content,GalView * gal_view)735 cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content,
736 GalView *gal_view)
737 {
738 ECalViewKind view_kind;
739 GType gal_view_type;
740
741 gal_view_type = G_OBJECT_TYPE (gal_view);
742
743 if (gal_view_type == GAL_TYPE_VIEW_ETABLE) {
744 ECalendarView *calendar_view;
745
746 view_kind = E_CAL_VIEW_KIND_LIST;
747 calendar_view = cal_shell_content->priv->views[view_kind];
748 gal_view_etable_attach_table (
749 GAL_VIEW_ETABLE (gal_view),
750 e_cal_list_view_get_table (E_CAL_LIST_VIEW (calendar_view)));
751
752 } else if (gal_view_type == GAL_TYPE_VIEW_CALENDAR_DAY) {
753 view_kind = E_CAL_VIEW_KIND_DAY;
754
755 } else if (gal_view_type == GAL_TYPE_VIEW_CALENDAR_WORK_WEEK) {
756 view_kind = E_CAL_VIEW_KIND_WORKWEEK;
757
758 } else if (gal_view_type == GAL_TYPE_VIEW_CALENDAR_WEEK) {
759 view_kind = E_CAL_VIEW_KIND_WEEK;
760
761 } else if (gal_view_type == GAL_TYPE_VIEW_CALENDAR_MONTH) {
762 view_kind = E_CAL_VIEW_KIND_MONTH;
763
764 } else {
765 g_return_if_reached ();
766 }
767
768 if (view_kind != E_CAL_VIEW_KIND_LIST) {
769 EShellView *shell_view;
770 EShellWindow *shell_window;
771
772 shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content));
773 shell_window = e_shell_view_get_shell_window (shell_view);
774
775 /* Reset these two filters, because they force the List View */
776 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (CALENDAR_FILTER_ACTIVE_APPOINTMENTS))) ||
777 gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS))))
778 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (ACTION (CALENDAR_FILTER_ANY_CATEGORY)), TRUE);
779 }
780
781 e_cal_shell_content_set_current_view_id (cal_shell_content, view_kind);
782 }
783
784 static void
cal_shell_content_notify_view_id_cb(ECalShellContent * cal_shell_content)785 cal_shell_content_notify_view_id_cb (ECalShellContent *cal_shell_content)
786 {
787 EShellContent *shell_content;
788 EShellView *shell_view;
789 GSettings *settings;
790 GtkWidget *paned;
791 const gchar *key;
792 const gchar *view_id;
793
794 settings = e_util_ref_settings ("org.gnome.evolution.calendar");
795 paned = cal_shell_content->priv->hpaned;
796
797 shell_content = E_SHELL_CONTENT (cal_shell_content);
798 shell_view = e_shell_content_get_shell_view (shell_content);
799 view_id = e_shell_view_get_view_id (shell_view);
800
801 if (view_id != NULL && strcmp (view_id, "Month_View") == 0)
802 key = "month-hpane-position";
803 else
804 key = "hpane-position";
805
806 g_settings_unbind (paned, "hposition");
807
808 g_settings_bind (
809 settings, key,
810 paned, "hposition",
811 G_SETTINGS_BIND_DEFAULT);
812
813 g_object_unref (settings);
814 }
815
816 static void
cal_shell_content_is_editing_changed_cb(gpointer cal_view_tasks_memos_table,GParamSpec * param,EShellView * shell_view)817 cal_shell_content_is_editing_changed_cb (gpointer cal_view_tasks_memos_table,
818 GParamSpec *param,
819 EShellView *shell_view)
820 {
821 g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
822
823 e_shell_view_update_actions (shell_view);
824 }
825
826 static gchar *
cal_shell_content_get_pad_state_filename(EShellContent * shell_content,ETable * table)827 cal_shell_content_get_pad_state_filename (EShellContent *shell_content,
828 ETable *table)
829 {
830 EShellBackend *shell_backend;
831 EShellView *shell_view;
832 const gchar *config_dir, *nick = NULL;
833
834 g_return_val_if_fail (shell_content != NULL, NULL);
835 g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
836 g_return_val_if_fail (table != NULL, NULL);
837 g_return_val_if_fail (E_IS_TABLE (table), NULL);
838
839 if (E_IS_TASK_TABLE (table))
840 nick = "TaskPad";
841 else if (E_IS_MEMO_TABLE (table))
842 nick = "MemoPad";
843
844 g_return_val_if_fail (nick != NULL, NULL);
845
846 shell_view = e_shell_content_get_shell_view (shell_content);
847 shell_backend = e_shell_view_get_shell_backend (shell_view);
848 config_dir = e_shell_backend_get_config_dir (shell_backend);
849
850 return g_build_filename (config_dir, nick, NULL);
851 }
852
853 static void
cal_shell_content_save_table_state(EShellContent * shell_content,ETable * table)854 cal_shell_content_save_table_state (EShellContent *shell_content,
855 ETable *table)
856 {
857 gchar *filename;
858
859 filename = cal_shell_content_get_pad_state_filename (
860 shell_content, table);
861 g_return_if_fail (filename != NULL);
862
863 e_table_save_state (table, filename);
864 g_free (filename);
865 }
866
867 static void
cal_shell_content_load_table_state(EShellContent * shell_content,ETable * table)868 cal_shell_content_load_table_state (EShellContent *shell_content,
869 ETable *table)
870 {
871 gchar *filename;
872
873 filename = cal_shell_content_get_pad_state_filename (shell_content, table);
874 g_return_if_fail (filename != NULL);
875
876 e_table_load_state (table, filename);
877 g_free (filename);
878 }
879
880 static ICalProperty *
cal_shell_content_get_attendee_prop(ICalComponent * icomp,const gchar * address)881 cal_shell_content_get_attendee_prop (ICalComponent *icomp,
882 const gchar *address)
883 {
884 ICalProperty *prop;
885
886 if (address == NULL || *address == '\0')
887 return NULL;
888
889 for (prop = i_cal_component_get_first_property (icomp, I_CAL_ATTENDEE_PROPERTY);
890 prop;
891 g_object_unref (prop), prop = i_cal_component_get_next_property (icomp, I_CAL_ATTENDEE_PROPERTY)) {
892 const gchar *attendee;
893
894 attendee = itip_strip_mailto (i_cal_property_get_attendee (prop));
895
896 if (attendee && g_ascii_strcasecmp (attendee, address) == 0)
897 return prop;
898 }
899
900 return NULL;
901 }
902
903 static gboolean
cal_shell_content_icomp_is_delegated(ICalComponent * icomp,const gchar * user_email)904 cal_shell_content_icomp_is_delegated (ICalComponent *icomp,
905 const gchar *user_email)
906 {
907 ICalProperty *prop;
908 ICalParameter *param;
909 gchar *delto = NULL;
910 gboolean is_delegated = FALSE;
911
912 prop = cal_shell_content_get_attendee_prop (icomp, user_email);
913
914 if (prop) {
915 param = i_cal_property_get_first_parameter (prop, I_CAL_DELEGATEDTO_PARAMETER);
916 if (param) {
917 delto = g_strdup (itip_strip_mailto (i_cal_parameter_get_delegatedto (param)));
918 g_object_unref (param);
919 }
920
921 g_object_unref (prop);
922 } else
923 return FALSE;
924
925 prop = cal_shell_content_get_attendee_prop (icomp, delto);
926
927 if (prop) {
928 gchar *delfrom = NULL;
929 ICalParameterPartstat partstat = I_CAL_PARTSTAT_NONE;
930
931 param = i_cal_property_get_first_parameter (prop, I_CAL_DELEGATEDFROM_PARAMETER);
932 if (param) {
933 delfrom = g_strdup (itip_strip_mailto (i_cal_parameter_get_delegatedfrom (param)));
934 g_object_unref (param);
935 }
936
937 param = i_cal_property_get_first_parameter (prop, I_CAL_PARTSTAT_PARAMETER);
938 if (param) {
939 partstat = i_cal_parameter_get_partstat (param);
940 g_object_unref (param);
941 }
942
943 is_delegated = delfrom && user_email &&
944 partstat != I_CAL_PARTSTAT_DECLINED &&
945 g_ascii_strcasecmp (delfrom, user_email) == 0;
946
947 g_object_unref (prop);
948 g_free (delfrom);
949 }
950
951 g_free (delto);
952
953 return is_delegated;
954 }
955
956 static guint32
cal_shell_content_check_state(EShellContent * shell_content)957 cal_shell_content_check_state (EShellContent *shell_content)
958 {
959 EShell *shell;
960 EShellView *shell_view;
961 EShellBackend *shell_backend;
962 ESourceRegistry *registry;
963 ECalShellContent *cal_shell_content;
964 ECalendarView *calendar_view;
965 gboolean selection_is_editable = FALSE;
966 gboolean selection_is_instance = FALSE;
967 gboolean selection_is_meeting = FALSE;
968 gboolean selection_is_organizer = FALSE;
969 gboolean selection_is_attendee = FALSE;
970 gboolean selection_is_recurring = FALSE;
971 gboolean selection_can_delegate = FALSE;
972 gboolean this_and_future_supported = FALSE;
973 guint32 state = 0;
974 GList *selected;
975 GList *link;
976 guint n_selected;
977
978 cal_shell_content = E_CAL_SHELL_CONTENT (shell_content);
979
980 shell_view = e_shell_content_get_shell_view (shell_content);
981 shell_backend = e_shell_view_get_shell_backend (shell_view);
982 shell = e_shell_backend_get_shell (shell_backend);
983 registry = e_shell_get_registry (shell);
984
985 calendar_view = e_cal_shell_content_get_current_calendar_view (cal_shell_content);
986
987 selected = e_calendar_view_get_selected_events (calendar_view);
988 n_selected = g_list_length (selected);
989
990 /* If we have a selection, assume it's
991 * editable until we learn otherwise. */
992 if (n_selected > 0)
993 selection_is_editable = TRUE;
994
995 for (link = selected; link != NULL; link = g_list_next (link)) {
996 ECalendarViewEvent *event = link->data;
997 ECalClient *client;
998 ECalComponent *comp;
999 gchar *user_email;
1000 ICalComponent *icomp;
1001 const gchar *capability;
1002 gboolean cap_delegate_supported;
1003 gboolean cap_delegate_to_many;
1004 gboolean icomp_is_delegated;
1005 gboolean read_only;
1006
1007 if (!is_comp_data_valid (event))
1008 continue;
1009
1010 client = event->comp_data->client;
1011 icomp = event->comp_data->icalcomp;
1012
1013 read_only = e_client_is_readonly (E_CLIENT (client));
1014 selection_is_editable &= !read_only;
1015
1016 selection_is_instance |=
1017 e_cal_util_component_is_instance (icomp);
1018
1019 selection_is_meeting =
1020 (n_selected == 1) &&
1021 e_cal_util_component_has_attendee (icomp);
1022
1023 selection_is_recurring |=
1024 e_cal_util_component_is_instance (icomp) ||
1025 e_cal_util_component_has_recurrences (icomp);
1026
1027 /* XXX The rest of this is rather expensive and
1028 * only applies if a single event is selected,
1029 * so continue with the loop iteration if the
1030 * rest of this is not applicable. */
1031 if (n_selected > 1)
1032 continue;
1033
1034 /* XXX This probably belongs in comp-util.c. */
1035
1036 comp = e_cal_component_new_from_icalcomponent (i_cal_component_clone (icomp));
1037 user_email = itip_get_comp_attendee (registry, comp, client);
1038
1039 selection_is_organizer =
1040 e_cal_util_component_has_organizer (icomp) &&
1041 itip_organizer_is_user (registry, comp, client);
1042
1043 capability = E_CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED;
1044 cap_delegate_supported =
1045 e_client_check_capability (
1046 E_CLIENT (client), capability);
1047
1048 capability = E_CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY;
1049 cap_delegate_to_many =
1050 e_client_check_capability (
1051 E_CLIENT (client), capability);
1052
1053 this_and_future_supported = !e_client_check_capability (
1054 E_CLIENT (client), E_CAL_STATIC_CAPABILITY_NO_THISANDFUTURE);
1055
1056 icomp_is_delegated = user_email != NULL &&
1057 cal_shell_content_icomp_is_delegated (icomp, user_email);
1058
1059 selection_can_delegate =
1060 cap_delegate_supported &&
1061 (cap_delegate_to_many ||
1062 (!selection_is_organizer &&
1063 !icomp_is_delegated));
1064
1065 selection_is_attendee = !selection_is_organizer &&
1066 selection_is_meeting &&
1067 !icomp_is_delegated &&
1068 itip_attendee_is_user (registry, comp, client);
1069
1070 g_free (user_email);
1071 g_object_unref (comp);
1072 }
1073
1074 g_list_free (selected);
1075
1076 if (n_selected == 1)
1077 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_SINGLE;
1078 if (n_selected > 1)
1079 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_MULTIPLE;
1080 if (selection_is_editable)
1081 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_EDITABLE;
1082 if (selection_is_instance)
1083 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_INSTANCE;
1084 if (selection_is_meeting)
1085 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_MEETING;
1086 if (selection_is_organizer)
1087 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_ORGANIZER;
1088 if (selection_is_attendee)
1089 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_ATTENDEE;
1090 if (selection_is_recurring)
1091 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_IS_RECURRING;
1092 if (selection_can_delegate)
1093 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_CAN_DELEGATE;
1094 if (this_and_future_supported)
1095 state |= E_CAL_BASE_SHELL_CONTENT_SELECTION_THIS_AND_FUTURE_SUPPORTED;
1096
1097 return state;
1098 }
1099
1100 static void
cal_shell_content_focus_search_results(EShellContent * shell_content)1101 cal_shell_content_focus_search_results (EShellContent *shell_content)
1102 {
1103 ECalendarView *calendar_view;
1104
1105 calendar_view = e_cal_shell_content_get_current_calendar_view (E_CAL_SHELL_CONTENT (shell_content));
1106
1107 gtk_widget_grab_focus (GTK_WIDGET (calendar_view));
1108 }
1109
1110 static time_t
cal_shell_content_get_default_time(ECalModel * model,gpointer user_data)1111 cal_shell_content_get_default_time (ECalModel *model,
1112 gpointer user_data)
1113 {
1114 ECalShellContent *cal_shell_content = user_data;
1115 ICalTimezone *zone;
1116 ICalTime *itt;
1117 time_t tt;
1118
1119 g_return_val_if_fail (model != NULL, 0);
1120 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), 0);
1121
1122 if (e_cal_shell_content_get_current_view_id (cal_shell_content) != E_CAL_VIEW_KIND_LIST) {
1123 ECalendarView *cal_view;
1124 time_t selected_start = (time_t) 0, selected_end = (time_t) 0;
1125
1126 cal_view = e_cal_shell_content_get_current_calendar_view (cal_shell_content);
1127
1128 if (cal_view && e_calendar_view_get_selected_time_range (cal_view, &selected_start, &selected_end))
1129 return selected_start;
1130 }
1131
1132 zone = e_cal_model_get_timezone (model);
1133 itt = i_cal_time_new_current_with_zone (zone);
1134 tt = i_cal_time_as_timet_with_zone (itt, zone);
1135 g_clear_object (&itt);
1136
1137 return tt;
1138 }
1139
1140 static void
update_adjustment(ECalShellContent * cal_shell_content,GtkAdjustment * adjustment,EWeekView * week_view,gboolean move_by_week)1141 update_adjustment (ECalShellContent *cal_shell_content,
1142 GtkAdjustment *adjustment,
1143 EWeekView *week_view,
1144 gboolean move_by_week)
1145 {
1146 GDate start_date, end_date;
1147 GDate first_day_shown;
1148 ECalModel *model;
1149 gint week_offset;
1150 ICalTime *start_tt = NULL;
1151 ICalTimezone *timezone;
1152 time_t lower;
1153 guint32 old_first_day_julian, new_first_day_julian;
1154 gdouble value;
1155
1156 e_week_view_get_first_day_shown (week_view, &first_day_shown);
1157
1158 /* If we don't have a valid date set yet, just return. */
1159 if (!g_date_valid (&first_day_shown))
1160 return;
1161
1162 value = gtk_adjustment_get_value (adjustment);
1163
1164 /* Determine the first date shown. */
1165 start_date = week_view->base_date;
1166 week_offset = floor (value + 0.5);
1167
1168 if (week_offset > 0)
1169 g_date_add_days (&start_date, week_offset * 7);
1170 else
1171 g_date_subtract_days (&start_date, week_offset * (-7));
1172
1173 /* Convert the old & new first days shown to julian values. */
1174 old_first_day_julian = g_date_get_julian (&first_day_shown);
1175 new_first_day_julian = g_date_get_julian (&start_date);
1176
1177 /* If we are already showing the date, just return. */
1178 if (old_first_day_julian == new_first_day_julian)
1179 return;
1180
1181 /* Convert it to a time_t. */
1182 start_tt = i_cal_time_new_null_time ();
1183 i_cal_time_set_date (start_tt,
1184 g_date_get_year (&start_date),
1185 g_date_get_month (&start_date),
1186 g_date_get_day (&start_date));
1187
1188 model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
1189 timezone = e_cal_model_get_timezone (model);
1190 lower = i_cal_time_as_timet_with_zone (start_tt, timezone);
1191 g_clear_object (&start_tt);
1192
1193 end_date = start_date;
1194 if (move_by_week) {
1195 g_date_add_days (&end_date, 7 - 1);
1196 } else {
1197 g_date_add_days (&end_date, 7 * e_week_view_get_weeks_shown (week_view) - 1);
1198 }
1199
1200 e_week_view_set_update_base_date (week_view, FALSE);
1201 e_cal_shell_content_change_view (cal_shell_content, cal_shell_content->priv->current_view, &start_date, &end_date, FALSE);
1202 e_calendar_view_set_selected_time_range (E_CALENDAR_VIEW (week_view), lower, lower);
1203 e_week_view_set_update_base_date (week_view, TRUE);
1204 }
1205
1206 static void
week_view_adjustment_changed_cb(GtkAdjustment * adjustment,ECalShellContent * cal_shell_content)1207 week_view_adjustment_changed_cb (GtkAdjustment *adjustment,
1208 ECalShellContent *cal_shell_content)
1209 {
1210 ECalendarView *view;
1211
1212 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
1213
1214 view = cal_shell_content->priv->views[E_CAL_VIEW_KIND_WEEK];
1215 update_adjustment (cal_shell_content, adjustment, E_WEEK_VIEW (view), TRUE);
1216 }
1217
1218 static void
month_view_adjustment_changed_cb(GtkAdjustment * adjustment,ECalShellContent * cal_shell_content)1219 month_view_adjustment_changed_cb (GtkAdjustment *adjustment,
1220 ECalShellContent *cal_shell_content)
1221 {
1222 ECalendarView *view;
1223
1224 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
1225
1226 view = cal_shell_content->priv->views[E_CAL_VIEW_KIND_MONTH];
1227 update_adjustment (cal_shell_content, adjustment, E_WEEK_VIEW (view), FALSE);
1228 }
1229
1230 static void
cal_shell_content_notify_work_day_cb(ECalModel * model,GParamSpec * param,ECalShellContent * cal_shell_content)1231 cal_shell_content_notify_work_day_cb (ECalModel *model,
1232 GParamSpec *param,
1233 ECalShellContent *cal_shell_content)
1234 {
1235 GDateWeekday work_day_first, work_day_last;
1236
1237 g_return_if_fail (E_IS_CAL_MODEL (model));
1238 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
1239
1240 if (cal_shell_content->priv->current_view != E_CAL_VIEW_KIND_WORKWEEK)
1241 return;
1242
1243 work_day_first = e_cal_model_get_work_day_first (model);
1244 work_day_last = e_cal_model_get_work_day_last (model);
1245
1246 if (work_day_first == g_date_get_weekday (&cal_shell_content->priv->view_start) &&
1247 work_day_last == g_date_get_weekday (&cal_shell_content->priv->view_end))
1248 return;
1249
1250 cal_shell_content->priv->previous_selected_start_time = -1;
1251 cal_shell_content->priv->previous_selected_end_time = -1;
1252
1253 /* This makes sure that the selection in the datepicker corresponds
1254 to the time range used in the Work Week view */
1255 cal_shell_content_current_view_id_changed_cb (cal_shell_content);
1256 }
1257
1258 static void
cal_shell_content_notify_week_start_day_cb(ECalModel * model,GParamSpec * param,ECalShellContent * cal_shell_content)1259 cal_shell_content_notify_week_start_day_cb (ECalModel *model,
1260 GParamSpec *param,
1261 ECalShellContent *cal_shell_content)
1262 {
1263 g_return_if_fail (E_IS_CAL_MODEL (model));
1264 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
1265
1266 cal_shell_content->priv->previous_selected_start_time = -1;
1267 cal_shell_content->priv->previous_selected_end_time = -1;
1268
1269 /* This makes sure that the selection in the datepicker corresponds
1270 to the time range used in the current view */
1271 cal_shell_content_current_view_id_changed_cb (cal_shell_content);
1272 }
1273
1274 static void
cal_shell_content_move_view_range_cb(ECalendarView * cal_view,ECalendarViewMoveType move_type,gint64 exact_date,ECalShellContent * cal_shell_content)1275 cal_shell_content_move_view_range_cb (ECalendarView *cal_view,
1276 ECalendarViewMoveType move_type,
1277 gint64 exact_date,
1278 ECalShellContent *cal_shell_content)
1279 {
1280 g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view));
1281 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
1282
1283 if (!cal_view->in_focus)
1284 return;
1285
1286 e_cal_shell_content_move_view_range (cal_shell_content, move_type, (time_t) exact_date);
1287 }
1288
1289 static void
cal_shell_content_clear_all_in_list_view(ECalShellContent * cal_shell_content)1290 cal_shell_content_clear_all_in_list_view (ECalShellContent *cal_shell_content)
1291 {
1292 ECalDataModelSubscriber *subscriber;
1293
1294 subscriber = E_CAL_DATA_MODEL_SUBSCRIBER (cal_shell_content->priv->list_view_model);
1295
1296 e_cal_data_model_unsubscribe (cal_shell_content->priv->list_view_data_model, subscriber);
1297 e_cal_model_remove_all_objects (cal_shell_content->priv->list_view_model);
1298 e_cal_data_model_remove_all_clients (cal_shell_content->priv->list_view_data_model);
1299 e_cal_data_model_subscribe (cal_shell_content->priv->list_view_data_model, subscriber, 0, 0);
1300 }
1301
1302 static void
cal_shell_content_client_opened_cb(ECalBaseShellSidebar * cal_base_shell_sidebar,EClient * client,gpointer user_data)1303 cal_shell_content_client_opened_cb (ECalBaseShellSidebar *cal_base_shell_sidebar,
1304 EClient *client,
1305 gpointer user_data)
1306 {
1307 ECalShellContent *cal_shell_content = user_data;
1308 ESourceSelector *source_selector;
1309 ESource *source;
1310
1311 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
1312
1313 if (cal_shell_content->priv->current_view != E_CAL_VIEW_KIND_LIST || !E_IS_CAL_CLIENT (client))
1314 return;
1315
1316 source_selector = e_cal_base_shell_sidebar_get_selector (cal_base_shell_sidebar);
1317 source = e_source_selector_ref_primary_selection (source_selector);
1318
1319 /* It can happen that the previously opening calendar finished its open
1320 after the current calendar, in which case this would replace the data,
1321 thus ensure the opened calendar is the correct calendar. */
1322 if (source == e_client_get_source (client)) {
1323 cal_shell_content_clear_all_in_list_view (cal_shell_content);
1324 e_cal_data_model_add_client (cal_shell_content->priv->list_view_data_model, E_CAL_CLIENT (client));
1325 }
1326
1327 g_clear_object (&source);
1328 }
1329
1330 static void
cal_shell_content_update_list_view(ECalShellContent * cal_shell_content)1331 cal_shell_content_update_list_view (ECalShellContent *cal_shell_content)
1332 {
1333 ECalBaseShellSidebar *cal_base_shell_sidebar;
1334 ESourceSelector *source_selector;
1335 ECalClient *client;
1336 ESource *source;
1337
1338 cal_base_shell_sidebar = E_CAL_BASE_SHELL_SIDEBAR (e_shell_view_get_shell_sidebar (
1339 e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content))));
1340
1341 source_selector = e_cal_base_shell_sidebar_get_selector (cal_base_shell_sidebar);
1342
1343 source = e_source_selector_ref_primary_selection (source_selector);
1344 if (!source)
1345 return;
1346
1347 e_cal_model_set_default_source_uid (cal_shell_content->priv->list_view_model, e_source_get_uid (source));
1348
1349 client = e_cal_data_model_ref_client (cal_shell_content->priv->list_view_data_model, e_source_get_uid (source));
1350
1351 if (!client)
1352 e_cal_base_shell_sidebar_open_source (cal_base_shell_sidebar, source, cal_shell_content_client_opened_cb, cal_shell_content);
1353
1354 g_clear_object (&client);
1355 g_clear_object (&source);
1356 }
1357
1358 static void
cal_shell_content_primary_selection_changed_cb(ESourceSelector * selector,gpointer user_data)1359 cal_shell_content_primary_selection_changed_cb (ESourceSelector *selector,
1360 gpointer user_data)
1361 {
1362 ECalShellContent *cal_shell_content = user_data;
1363
1364 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
1365
1366 if (cal_shell_content->priv->current_view == E_CAL_VIEW_KIND_LIST)
1367 cal_shell_content_update_list_view (cal_shell_content);
1368 }
1369
1370 static void
cal_shell_content_foreign_client_opened_cb(ECalBaseShellSidebar * cal_base_shell_sidebar,ECalClient * client,ECalModel * model)1371 cal_shell_content_foreign_client_opened_cb (ECalBaseShellSidebar *cal_base_shell_sidebar,
1372 ECalClient *client,
1373 ECalModel *model)
1374 {
1375 g_return_if_fail (E_IS_CAL_CLIENT (client));
1376 g_return_if_fail (E_IS_CAL_MODEL (model));
1377
1378 e_cal_data_model_add_client (e_cal_model_get_data_model (model), client);
1379 }
1380
1381 static void
cal_shell_content_foreign_client_closed_cb(ECalBaseShellSidebar * cal_base_shell_sidebar,ESource * source,ECalModel * model)1382 cal_shell_content_foreign_client_closed_cb (ECalBaseShellSidebar *cal_base_shell_sidebar,
1383 ESource *source,
1384 ECalModel *model)
1385 {
1386 g_return_if_fail (E_IS_SOURCE (source));
1387 g_return_if_fail (E_IS_CAL_MODEL (model));
1388
1389 e_cal_data_model_remove_client (e_cal_model_get_data_model (model), e_source_get_uid (source));
1390 }
1391
1392 static void
cal_shell_content_setup_foreign_sources(EShellWindow * shell_window,const gchar * view_name,const gchar * extension_name,ECalModel * model)1393 cal_shell_content_setup_foreign_sources (EShellWindow *shell_window,
1394 const gchar *view_name,
1395 const gchar *extension_name,
1396 ECalModel *model)
1397 {
1398 EShellSidebar *foreign_sidebar;
1399 EShellContent *foreign_content;
1400 EShellView *foreign_view;
1401 ECalModel *foreign_model;
1402 gboolean is_new_view;
1403
1404 g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1405 g_return_if_fail (E_IS_CAL_MODEL (model));
1406
1407 is_new_view = e_shell_window_peek_shell_view (shell_window, view_name) == NULL;
1408
1409 foreign_view = e_shell_window_get_shell_view (shell_window, view_name);
1410 g_return_if_fail (E_IS_SHELL_VIEW (foreign_view));
1411
1412 foreign_sidebar = e_shell_view_get_shell_sidebar (foreign_view);
1413 g_return_if_fail (E_IS_CAL_BASE_SHELL_SIDEBAR (foreign_sidebar));
1414
1415 if (is_new_view) {
1416 /* Preselect default source, when the view was not created yet */
1417 ESourceSelector *source_selector;
1418 ESourceRegistry *registry;
1419 ESource *source;
1420
1421 source_selector = e_cal_base_shell_sidebar_get_selector (E_CAL_BASE_SHELL_SIDEBAR (foreign_sidebar));
1422 registry = e_source_selector_get_registry (source_selector);
1423 source = e_source_registry_ref_default_for_extension_name (registry, extension_name);
1424
1425 if (source)
1426 e_source_selector_set_primary_selection (source_selector, source);
1427
1428 g_clear_object (&source);
1429 }
1430
1431 g_signal_connect_object (foreign_sidebar, "client-opened",
1432 G_CALLBACK (cal_shell_content_foreign_client_opened_cb), model, 0);
1433 g_signal_connect_object (foreign_sidebar, "client-closed",
1434 G_CALLBACK (cal_shell_content_foreign_client_closed_cb), model, 0);
1435
1436 foreign_content = e_shell_view_get_shell_content (foreign_view);
1437 foreign_model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (foreign_content));
1438
1439 e_binding_bind_property (
1440 foreign_model, "default-source-uid",
1441 model, "default-source-uid",
1442 G_BINDING_SYNC_CREATE);
1443
1444 g_signal_connect_object (model, "row-appended",
1445 G_CALLBACK (e_cal_base_shell_view_model_row_appended), foreign_view, G_CONNECT_SWAPPED);
1446
1447 /* This makes sure that the local models for memos and tasks
1448 in the calendar view get populated with the same sources
1449 as those in the respective views. */
1450
1451 e_cal_base_shell_sidebar_ensure_sources_open (E_CAL_BASE_SHELL_SIDEBAR (foreign_sidebar));
1452 }
1453
1454 static void
cal_shell_content_view_created(ECalBaseShellContent * cal_base_shell_content)1455 cal_shell_content_view_created (ECalBaseShellContent *cal_base_shell_content)
1456 {
1457 ECalShellContent *cal_shell_content;
1458 EShellView *shell_view;
1459 EShellWindow *shell_window;
1460 EShellSidebar *shell_sidebar;
1461 GalViewInstance *view_instance;
1462 ECalendar *calendar;
1463 ECalModel *model;
1464 ECalDataModel *data_model;
1465 GDate date;
1466 time_t today;
1467
1468 cal_shell_content = E_CAL_SHELL_CONTENT (cal_base_shell_content);
1469 cal_shell_content->priv->current_view = E_CAL_VIEW_KIND_DAY;
1470
1471 today = time (NULL);
1472 g_date_clear (&date, 1);
1473 g_date_set_time_t (&date, today);
1474
1475 shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content));
1476 shell_window = e_shell_view_get_shell_window (shell_view);
1477 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
1478 g_return_if_fail (E_IS_CAL_BASE_SHELL_SIDEBAR (shell_sidebar));
1479
1480 calendar = e_cal_base_shell_sidebar_get_date_navigator (E_CAL_BASE_SHELL_SIDEBAR (shell_sidebar));
1481 g_return_if_fail (E_IS_CALENDAR (calendar));
1482
1483 model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
1484 e_calendar_item_set_selection (e_calendar_get_item (calendar), &date, &date);
1485 e_cal_model_set_time_range (model, today, today);
1486
1487 /* Show everything known by default in the task and memo pads */
1488 e_cal_model_set_time_range (cal_shell_content->priv->memo_model, 0, 0);
1489 e_cal_model_set_time_range (cal_shell_content->priv->task_model, 0, 0);
1490 e_cal_model_set_time_range (cal_shell_content->priv->list_view_model, 0, 0);
1491
1492 g_signal_connect (e_cal_base_shell_sidebar_get_selector (E_CAL_BASE_SHELL_SIDEBAR (shell_sidebar)), "primary-selection-changed",
1493 G_CALLBACK (cal_shell_content_primary_selection_changed_cb), cal_shell_content);
1494
1495 cal_shell_content->priv->datepicker_selection_changed_id =
1496 g_signal_connect (e_calendar_get_item (calendar), "selection-changed",
1497 G_CALLBACK (cal_shell_content_datepicker_selection_changed_cb), cal_shell_content);
1498 cal_shell_content->priv->datepicker_range_moved_id =
1499 g_signal_connect (e_calendar_get_item (calendar), "date-range-moved",
1500 G_CALLBACK (cal_shell_content_datepicker_range_moved_cb), cal_shell_content);
1501
1502 g_signal_connect_after (calendar, "button-press-event",
1503 G_CALLBACK (cal_shell_content_datepicker_button_press_cb), cal_shell_content);
1504
1505 data_model = e_cal_base_shell_content_get_data_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
1506 cal_shell_content->priv->tag_calendar = e_tag_calendar_new (calendar);
1507 e_tag_calendar_subscribe (cal_shell_content->priv->tag_calendar, data_model);
1508
1509 /* Intentionally not using e_signal_connect_notify() here, no need to filter
1510 out "false" notifications, it's dealt with them in another way */
1511 cal_shell_content->priv->current_view_id_changed_id = g_signal_connect (
1512 cal_shell_content, "notify::current-view-id",
1513 G_CALLBACK (cal_shell_content_current_view_id_changed_cb), NULL);
1514
1515 /* List of selected Task/Memo sources is taken from respective views,
1516 which are loaded if necessary. */
1517 cal_shell_content_setup_foreign_sources (shell_window, "memos", E_SOURCE_EXTENSION_MEMO_LIST,
1518 cal_shell_content->priv->memo_model);
1519
1520 cal_shell_content_setup_foreign_sources (shell_window, "tasks", E_SOURCE_EXTENSION_TASK_LIST,
1521 cal_shell_content->priv->task_model);
1522
1523 /* Finally load the view instance */
1524 view_instance = e_shell_view_get_view_instance (shell_view);
1525 gal_view_instance_load (view_instance);
1526
1527 /* Keep the toolbar view buttons in sync with the calendar. */
1528 e_binding_bind_property (
1529 cal_shell_content, "current-view-id",
1530 ACTION (CALENDAR_VIEW_DAY), "current-value",
1531 G_BINDING_BIDIRECTIONAL |
1532 G_BINDING_SYNC_CREATE);
1533
1534 e_signal_connect_notify (
1535 model, "notify::work-day-monday",
1536 G_CALLBACK (cal_shell_content_notify_work_day_cb), cal_shell_content);
1537
1538 e_signal_connect_notify (
1539 model, "notify::work-day-tuesday",
1540 G_CALLBACK (cal_shell_content_notify_work_day_cb), cal_shell_content);
1541
1542 e_signal_connect_notify (
1543 model, "notify::work-day-wednesday",
1544 G_CALLBACK (cal_shell_content_notify_work_day_cb), cal_shell_content);
1545
1546 e_signal_connect_notify (
1547 model, "notify::work-day-thursday",
1548 G_CALLBACK (cal_shell_content_notify_work_day_cb), cal_shell_content);
1549
1550 e_signal_connect_notify (
1551 model, "notify::work-day-friday",
1552 G_CALLBACK (cal_shell_content_notify_work_day_cb), cal_shell_content);
1553
1554 e_signal_connect_notify (
1555 model, "notify::work-day-saturday",
1556 G_CALLBACK (cal_shell_content_notify_work_day_cb), cal_shell_content);
1557
1558 e_signal_connect_notify (
1559 model, "notify::work-day-sunday",
1560 G_CALLBACK (cal_shell_content_notify_work_day_cb), cal_shell_content);
1561
1562 e_signal_connect_notify (
1563 model, "notify::week-start-day",
1564 G_CALLBACK (cal_shell_content_notify_week_start_day_cb), cal_shell_content);
1565
1566 cal_shell_content->priv->initialized = TRUE;
1567 }
1568
1569 static void
e_cal_shell_content_create_calendar_views(ECalShellContent * cal_shell_content)1570 e_cal_shell_content_create_calendar_views (ECalShellContent *cal_shell_content)
1571 {
1572 EShellView *shell_view;
1573 ECalModel *model;
1574 ECalendarView *calendar_view;
1575 GtkAdjustment *adjustment;
1576 time_t today;
1577 gint ii;
1578
1579 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
1580 g_return_if_fail (cal_shell_content->priv->calendar_notebook != NULL);
1581 g_return_if_fail (cal_shell_content->priv->views[0] == NULL);
1582
1583 model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
1584
1585 /* Day View */
1586 calendar_view = e_day_view_new (model);
1587 cal_shell_content->priv->views[E_CAL_VIEW_KIND_DAY] = calendar_view;
1588 g_object_ref_sink (calendar_view);
1589
1590 /* Work Week View */
1591 calendar_view = e_day_view_new (model);
1592 e_day_view_set_work_week_view (E_DAY_VIEW (calendar_view), TRUE);
1593 e_day_view_set_days_shown (E_DAY_VIEW (calendar_view), 5);
1594 cal_shell_content->priv->views[E_CAL_VIEW_KIND_WORKWEEK] = calendar_view;
1595 g_object_ref_sink (calendar_view);
1596
1597 /* Week View */
1598 calendar_view = e_week_view_new (model);
1599 cal_shell_content->priv->views[E_CAL_VIEW_KIND_WEEK] = calendar_view;
1600 g_object_ref_sink (calendar_view);
1601
1602 adjustment = gtk_range_get_adjustment (
1603 GTK_RANGE (E_WEEK_VIEW (calendar_view)->vscrollbar));
1604 g_signal_connect (
1605 adjustment, "value-changed",
1606 G_CALLBACK (week_view_adjustment_changed_cb), cal_shell_content);
1607
1608 /* Month View */
1609 calendar_view = e_month_view_new (model);
1610 e_week_view_set_multi_week_view (E_WEEK_VIEW (calendar_view), TRUE);
1611 e_week_view_set_weeks_shown (E_WEEK_VIEW (calendar_view), 6);
1612 cal_shell_content->priv->views[E_CAL_VIEW_KIND_MONTH] = calendar_view;
1613 g_object_ref_sink (calendar_view);
1614
1615 adjustment = gtk_range_get_adjustment (
1616 GTK_RANGE (E_WEEK_VIEW (calendar_view)->vscrollbar));
1617 g_signal_connect (
1618 adjustment, "value-changed",
1619 G_CALLBACK (month_view_adjustment_changed_cb), cal_shell_content);
1620
1621 /* List View */
1622 calendar_view = e_cal_list_view_new (cal_shell_content->priv->list_view_model);
1623 cal_shell_content->priv->views[E_CAL_VIEW_KIND_LIST] = calendar_view;
1624 g_object_ref_sink (calendar_view);
1625
1626 shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content));
1627 today = time (NULL);
1628
1629 for (ii = 0; ii < E_CAL_VIEW_KIND_LAST; ii++) {
1630 calendar_view = cal_shell_content->priv->views[ii];
1631
1632 calendar_view->in_focus = ii == cal_shell_content->priv->current_view;
1633
1634 e_calendar_view_set_selected_time_range (calendar_view, today, today);
1635
1636 e_signal_connect_notify (
1637 calendar_view, "notify::is-editing",
1638 G_CALLBACK (cal_shell_content_is_editing_changed_cb), shell_view);
1639
1640 g_signal_connect (
1641 calendar_view, "move-view-range",
1642 G_CALLBACK (cal_shell_content_move_view_range_cb), cal_shell_content);
1643
1644 gtk_notebook_append_page (
1645 GTK_NOTEBOOK (cal_shell_content->priv->calendar_notebook),
1646 GTK_WIDGET (calendar_view), NULL);
1647 gtk_widget_show (GTK_WIDGET (calendar_view));
1648 }
1649 }
1650
1651 static void
cal_shell_content_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)1652 cal_shell_content_set_property (GObject *object,
1653 guint property_id,
1654 const GValue *value,
1655 GParamSpec *pspec)
1656 {
1657 switch (property_id) {
1658 case PROP_CURRENT_VIEW_ID:
1659 e_cal_shell_content_set_current_view_id (E_CAL_SHELL_CONTENT (object),
1660 g_value_get_int (value));
1661 return;
1662 case PROP_SHOW_TAG_VPANE:
1663 e_cal_shell_content_set_show_tag_vpane (E_CAL_SHELL_CONTENT (object),
1664 g_value_get_boolean (value));
1665 return;
1666 }
1667
1668 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1669 }
1670
1671 static void
cal_shell_content_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)1672 cal_shell_content_get_property (GObject *object,
1673 guint property_id,
1674 GValue *value,
1675 GParamSpec *pspec)
1676 {
1677 switch (property_id) {
1678 case PROP_CALENDAR_NOTEBOOK:
1679 g_value_set_object (
1680 value, e_cal_shell_content_get_calendar_notebook (
1681 E_CAL_SHELL_CONTENT (object)));
1682 return;
1683
1684 case PROP_MEMO_TABLE:
1685 g_value_set_object (
1686 value, e_cal_shell_content_get_memo_table (
1687 E_CAL_SHELL_CONTENT (object)));
1688 return;
1689
1690 case PROP_TASK_TABLE:
1691 g_value_set_object (
1692 value, e_cal_shell_content_get_task_table (
1693 E_CAL_SHELL_CONTENT (object)));
1694 return;
1695
1696 case PROP_CURRENT_VIEW_ID:
1697 g_value_set_int (value,
1698 e_cal_shell_content_get_current_view_id (E_CAL_SHELL_CONTENT (object)));
1699 return;
1700
1701 case PROP_CURRENT_VIEW:
1702 g_value_set_object (value,
1703 e_cal_shell_content_get_current_calendar_view (E_CAL_SHELL_CONTENT (object)));
1704 return;
1705
1706 case PROP_SHOW_TAG_VPANE:
1707 g_value_set_boolean (value,
1708 e_cal_shell_content_get_show_tag_vpane (E_CAL_SHELL_CONTENT (object)));
1709 return;
1710 }
1711
1712 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
1713 }
1714
1715 static void
cal_shell_content_dispose(GObject * object)1716 cal_shell_content_dispose (GObject *object)
1717 {
1718 ECalShellContent *cal_shell_content = E_CAL_SHELL_CONTENT (object);
1719 gint ii;
1720
1721 if (cal_shell_content->priv->task_data_model) {
1722 e_cal_data_model_set_disposing (cal_shell_content->priv->task_data_model, TRUE);
1723 e_cal_data_model_unsubscribe (cal_shell_content->priv->task_data_model,
1724 E_CAL_DATA_MODEL_SUBSCRIBER (cal_shell_content->priv->task_model));
1725 }
1726
1727 if (cal_shell_content->priv->memo_data_model) {
1728 e_cal_data_model_set_disposing (cal_shell_content->priv->memo_data_model, TRUE);
1729 e_cal_data_model_unsubscribe (cal_shell_content->priv->memo_data_model,
1730 E_CAL_DATA_MODEL_SUBSCRIBER (cal_shell_content->priv->memo_model));
1731 }
1732
1733 if (cal_shell_content->priv->list_view_data_model) {
1734 e_cal_data_model_set_disposing (cal_shell_content->priv->list_view_data_model, TRUE);
1735 e_cal_data_model_unsubscribe (cal_shell_content->priv->list_view_data_model,
1736 E_CAL_DATA_MODEL_SUBSCRIBER (cal_shell_content->priv->list_view_model));
1737 }
1738
1739 if (cal_shell_content->priv->tag_calendar) {
1740 ECalDataModel *data_model;
1741
1742 data_model = e_cal_base_shell_content_get_data_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
1743 e_cal_data_model_set_disposing (data_model, TRUE);
1744 e_tag_calendar_unsubscribe (cal_shell_content->priv->tag_calendar, data_model);
1745 g_clear_object (&cal_shell_content->priv->tag_calendar);
1746 }
1747
1748 for (ii = 0; ii < E_CAL_VIEW_KIND_LAST; ii++) {
1749 g_clear_object (&(cal_shell_content->priv->views[ii]));
1750 }
1751
1752 g_clear_object (&cal_shell_content->priv->hpaned);
1753 g_clear_object (&cal_shell_content->priv->vpaned);
1754 g_clear_object (&cal_shell_content->priv->calendar_notebook);
1755 g_clear_object (&cal_shell_content->priv->task_table);
1756 g_clear_object (&cal_shell_content->priv->task_model);
1757 g_clear_object (&cal_shell_content->priv->task_data_model);
1758 g_clear_object (&cal_shell_content->priv->memo_table);
1759 g_clear_object (&cal_shell_content->priv->memo_model);
1760 g_clear_object (&cal_shell_content->priv->memo_data_model);
1761 g_clear_object (&cal_shell_content->priv->list_view_model);
1762 g_clear_object (&cal_shell_content->priv->list_view_data_model);
1763
1764 /* Chain up to parent's dispose() method. */
1765 G_OBJECT_CLASS (e_cal_shell_content_parent_class)->dispose (object);
1766 }
1767
1768 static void
cal_shell_content_constructed(GObject * object)1769 cal_shell_content_constructed (GObject *object)
1770 {
1771 ECalShellContent *cal_shell_content;
1772 EShellContent *shell_content;
1773 EShellView *shell_view;
1774 EShellWindow *shell_window;
1775 EShell *shell;
1776 GalViewInstance *view_instance;
1777 GSettings *settings;
1778 GtkWidget *container;
1779 GtkWidget *widget;
1780 gchar *markup;
1781
1782 /* Chain up to parent's constructed() method. */
1783 G_OBJECT_CLASS (e_cal_shell_content_parent_class)->constructed (object);
1784
1785 cal_shell_content = E_CAL_SHELL_CONTENT (object);
1786 shell_content = E_SHELL_CONTENT (cal_shell_content);
1787 shell_view = e_shell_content_get_shell_view (shell_content);
1788 shell_window = e_shell_view_get_shell_window (shell_view);
1789 shell = e_shell_window_get_shell (shell_window);
1790
1791 cal_shell_content->priv->memo_data_model =
1792 e_cal_base_shell_content_create_new_data_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
1793 cal_shell_content->priv->memo_model =
1794 e_cal_model_memos_new (cal_shell_content->priv->memo_data_model, e_shell_get_registry (shell), shell);
1795
1796 cal_shell_content->priv->task_data_model =
1797 e_cal_base_shell_content_create_new_data_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
1798 cal_shell_content->priv->task_model =
1799 e_cal_model_tasks_new (cal_shell_content->priv->task_data_model, e_shell_get_registry (shell), shell);
1800
1801 cal_shell_content->priv->list_view_data_model =
1802 e_cal_base_shell_content_create_new_data_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
1803 cal_shell_content->priv->list_view_model =
1804 e_cal_model_calendar_new (cal_shell_content->priv->list_view_data_model, e_shell_get_registry (shell), shell);
1805
1806 e_binding_bind_property (
1807 cal_shell_content->priv->memo_model, "timezone",
1808 cal_shell_content->priv->memo_data_model, "timezone",
1809 G_BINDING_SYNC_CREATE);
1810
1811 e_binding_bind_property (
1812 cal_shell_content->priv->task_model, "timezone",
1813 cal_shell_content->priv->task_data_model, "timezone",
1814 G_BINDING_SYNC_CREATE);
1815
1816 e_binding_bind_property (
1817 cal_shell_content->priv->list_view_model, "timezone",
1818 cal_shell_content->priv->list_view_data_model, "timezone",
1819 G_BINDING_SYNC_CREATE);
1820
1821 /* Build content widgets. */
1822
1823 container = GTK_WIDGET (object);
1824
1825 widget = e_paned_new (GTK_ORIENTATION_HORIZONTAL);
1826 gtk_container_add (GTK_CONTAINER (container), widget);
1827 cal_shell_content->priv->hpaned = g_object_ref (widget);
1828 gtk_widget_show (widget);
1829
1830 container = cal_shell_content->priv->hpaned;
1831
1832 widget = gtk_notebook_new ();
1833 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
1834 gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE);
1835 gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE);
1836 cal_shell_content->priv->calendar_notebook = g_object_ref (widget);
1837 gtk_widget_show (widget);
1838
1839 widget = e_paned_new (GTK_ORIENTATION_VERTICAL);
1840 e_paned_set_fixed_resize (E_PANED (widget), FALSE);
1841 gtk_paned_pack2 (GTK_PANED (container), widget, FALSE, TRUE);
1842 cal_shell_content->priv->vpaned = g_object_ref (widget);
1843 gtk_widget_show (widget);
1844
1845 container = cal_shell_content->priv->calendar_notebook;
1846
1847 e_cal_shell_content_create_calendar_views (cal_shell_content);
1848
1849 e_binding_bind_property (
1850 cal_shell_content, "current-view-id",
1851 cal_shell_content->priv->calendar_notebook, "page",
1852 G_BINDING_SYNC_CREATE);
1853
1854 container = cal_shell_content->priv->vpaned;
1855
1856 widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1857 gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, TRUE);
1858 gtk_widget_show (widget);
1859
1860 container = widget;
1861
1862 widget = gtk_label_new (NULL);
1863 markup = g_strdup_printf ("<b>%s</b>", _("Tasks"));
1864 gtk_label_set_markup (GTK_LABEL (widget), markup);
1865 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0);
1866 gtk_widget_show (widget);
1867 g_free (markup);
1868
1869 widget = gtk_scrolled_window_new (NULL, NULL);
1870 gtk_scrolled_window_set_policy (
1871 GTK_SCROLLED_WINDOW (widget),
1872 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1873 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
1874 gtk_widget_show (widget);
1875
1876 container = widget;
1877
1878 widget = e_task_table_new (shell_view, cal_shell_content->priv->task_model);
1879 gtk_container_add (GTK_CONTAINER (container), widget);
1880 cal_shell_content->priv->task_table = g_object_ref (widget);
1881 gtk_widget_show (widget);
1882
1883 cal_shell_content_load_table_state (shell_content, E_TABLE (widget));
1884
1885 g_signal_connect_swapped (
1886 widget, "open-component",
1887 G_CALLBACK (e_cal_shell_view_taskpad_open_task),
1888 shell_view);
1889
1890 e_signal_connect_notify (
1891 widget, "notify::is-editing",
1892 G_CALLBACK (cal_shell_content_is_editing_changed_cb), shell_view);
1893
1894 container = cal_shell_content->priv->vpaned;
1895
1896 widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
1897 gtk_paned_pack2 (GTK_PANED (container), widget, TRUE, TRUE);
1898 gtk_widget_show (widget);
1899
1900 container = widget;
1901
1902 widget = gtk_label_new (NULL);
1903 markup = g_strdup_printf ("<b>%s</b>", _("Memos"));
1904 gtk_label_set_markup (GTK_LABEL (widget), markup);
1905 gtk_box_pack_start (GTK_BOX (container), widget, FALSE, TRUE, 0);
1906 gtk_widget_show (widget);
1907 g_free (markup);
1908
1909 widget = gtk_scrolled_window_new (NULL, NULL);
1910 gtk_scrolled_window_set_policy (
1911 GTK_SCROLLED_WINDOW (widget),
1912 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1913 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
1914 gtk_widget_show (widget);
1915
1916 container = widget;
1917
1918 widget = e_memo_table_new (shell_view, cal_shell_content->priv->memo_model);
1919 gtk_container_add (GTK_CONTAINER (container), widget);
1920 cal_shell_content->priv->memo_table = g_object_ref (widget);
1921 gtk_widget_show (widget);
1922
1923 cal_shell_content_load_table_state (shell_content, E_TABLE (widget));
1924
1925 e_cal_model_set_default_time_func (cal_shell_content->priv->memo_model, cal_shell_content_get_default_time, cal_shell_content);
1926
1927 g_signal_connect_swapped (
1928 widget, "open-component",
1929 G_CALLBACK (e_cal_shell_view_memopad_open_memo),
1930 shell_view);
1931
1932 e_signal_connect_notify (
1933 widget, "notify::is-editing",
1934 G_CALLBACK (cal_shell_content_is_editing_changed_cb), shell_view);
1935
1936 /* Prepare the view instance. */
1937
1938 view_instance = e_shell_view_new_view_instance (shell_view, NULL);
1939 g_signal_connect_swapped (
1940 view_instance, "display-view",
1941 G_CALLBACK (cal_shell_content_display_view_cb),
1942 object);
1943 /* Actual load happens at cal_shell_content_view_created() */
1944 e_shell_view_set_view_instance (shell_view, view_instance);
1945 g_object_unref (view_instance);
1946
1947 e_signal_connect_notify_swapped (
1948 shell_view, "notify::view-id",
1949 G_CALLBACK (cal_shell_content_notify_view_id_cb),
1950 cal_shell_content);
1951
1952 settings = e_util_ref_settings ("org.gnome.evolution.calendar");
1953
1954 g_settings_bind (
1955 settings, "tag-vpane-position",
1956 cal_shell_content->priv->vpaned, "proportion",
1957 G_SETTINGS_BIND_DEFAULT);
1958
1959 g_settings_bind (
1960 settings, "show-tag-vpane",
1961 cal_shell_content, "show-tag-vpane",
1962 G_SETTINGS_BIND_DEFAULT);
1963
1964 g_object_unref (settings);
1965
1966 /* Cannot access shell sidebar here, thus rely on cal_shell_content_view_created()
1967 with exact widget settings which require it */
1968 }
1969
1970 static void
e_cal_shell_content_class_init(ECalShellContentClass * class)1971 e_cal_shell_content_class_init (ECalShellContentClass *class)
1972 {
1973 GObjectClass *object_class;
1974 EShellContentClass *shell_content_class;
1975 ECalBaseShellContentClass *cal_base_shell_content_class;
1976
1977 g_type_class_add_private (class, sizeof (ECalShellContentPrivate));
1978
1979 object_class = G_OBJECT_CLASS (class);
1980 object_class->set_property = cal_shell_content_set_property;
1981 object_class->get_property = cal_shell_content_get_property;
1982 object_class->dispose = cal_shell_content_dispose;
1983 object_class->constructed = cal_shell_content_constructed;
1984
1985 shell_content_class = E_SHELL_CONTENT_CLASS (class);
1986 shell_content_class->check_state = cal_shell_content_check_state;
1987 shell_content_class->focus_search_results = cal_shell_content_focus_search_results;
1988
1989 cal_base_shell_content_class = E_CAL_BASE_SHELL_CONTENT_CLASS (class);
1990 cal_base_shell_content_class->new_cal_model = e_cal_model_calendar_new;
1991 cal_base_shell_content_class->view_created = cal_shell_content_view_created;
1992
1993 g_object_class_install_property (
1994 object_class,
1995 PROP_CALENDAR_NOTEBOOK,
1996 g_param_spec_object (
1997 "calendar-notebook",
1998 NULL,
1999 NULL,
2000 GTK_TYPE_NOTEBOOK,
2001 G_PARAM_READABLE));
2002
2003 g_object_class_install_property (
2004 object_class,
2005 PROP_MEMO_TABLE,
2006 g_param_spec_object (
2007 "memo-table",
2008 NULL,
2009 NULL,
2010 E_TYPE_MEMO_TABLE,
2011 G_PARAM_READABLE));
2012
2013 g_object_class_install_property (
2014 object_class,
2015 PROP_TASK_TABLE,
2016 g_param_spec_object (
2017 "task-table",
2018 NULL,
2019 NULL,
2020 E_TYPE_TASK_TABLE,
2021 G_PARAM_READABLE));
2022
2023 g_object_class_install_property (
2024 object_class,
2025 PROP_CURRENT_VIEW_ID,
2026 g_param_spec_int (
2027 "current-view-id",
2028 "Current Calendar View ID",
2029 NULL,
2030 E_CAL_VIEW_KIND_DAY,
2031 E_CAL_VIEW_KIND_LAST - 1,
2032 E_CAL_VIEW_KIND_DAY,
2033 G_PARAM_READWRITE));
2034
2035 g_object_class_install_property (
2036 object_class,
2037 PROP_CURRENT_VIEW,
2038 g_param_spec_object (
2039 "current-view",
2040 "Current Calendar View",
2041 NULL,
2042 E_TYPE_CALENDAR_VIEW,
2043 G_PARAM_READABLE));
2044
2045 g_object_class_install_property (
2046 object_class,
2047 PROP_SHOW_TAG_VPANE,
2048 g_param_spec_boolean (
2049 "show-tag-vpane",
2050 NULL,
2051 NULL,
2052 TRUE,
2053 G_PARAM_READWRITE));
2054 }
2055
2056 static void
e_cal_shell_content_class_finalize(ECalShellContentClass * class)2057 e_cal_shell_content_class_finalize (ECalShellContentClass *class)
2058 {
2059 }
2060
2061 static void
e_cal_shell_content_init(ECalShellContent * cal_shell_content)2062 e_cal_shell_content_init (ECalShellContent *cal_shell_content)
2063 {
2064 time_t now;
2065
2066 cal_shell_content->priv = E_CAL_SHELL_CONTENT_GET_PRIVATE (cal_shell_content);
2067 g_date_clear (&cal_shell_content->priv->view_start, 1);
2068 g_date_clear (&cal_shell_content->priv->view_end, 1);
2069 g_date_clear (&cal_shell_content->priv->last_range_start, 1);
2070
2071 now = time (NULL);
2072 g_date_set_time_t (&cal_shell_content->priv->view_start, now);
2073 g_date_set_time_t (&cal_shell_content->priv->view_end, now);
2074
2075 cal_shell_content->priv->view_start_range_day_offset = (guint32) -1;
2076 cal_shell_content->priv->previous_selected_start_time = -1;
2077 cal_shell_content->priv->previous_selected_end_time = -1;
2078 cal_shell_content->priv->initialized = FALSE;
2079 }
2080
2081 void
e_cal_shell_content_type_register(GTypeModule * type_module)2082 e_cal_shell_content_type_register (GTypeModule *type_module)
2083 {
2084 /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
2085 * function, so we have to wrap it with a public function in
2086 * order to register types from a separate compilation unit. */
2087 e_cal_shell_content_register_type (type_module);
2088 }
2089
2090 GtkWidget *
e_cal_shell_content_new(EShellView * shell_view)2091 e_cal_shell_content_new (EShellView *shell_view)
2092 {
2093 g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
2094
2095 return g_object_new (
2096 E_TYPE_CAL_SHELL_CONTENT,
2097 "shell-view", shell_view, NULL);
2098 }
2099
2100 gboolean
e_cal_shell_content_get_initialized(ECalShellContent * cal_shell_content)2101 e_cal_shell_content_get_initialized (ECalShellContent *cal_shell_content)
2102 {
2103 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), FALSE);
2104
2105 return cal_shell_content->priv->initialized;
2106 }
2107
2108 GtkNotebook *
e_cal_shell_content_get_calendar_notebook(ECalShellContent * cal_shell_content)2109 e_cal_shell_content_get_calendar_notebook (ECalShellContent *cal_shell_content)
2110 {
2111 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL);
2112
2113 return GTK_NOTEBOOK (cal_shell_content->priv->calendar_notebook);
2114 }
2115
2116 EMemoTable *
e_cal_shell_content_get_memo_table(ECalShellContent * cal_shell_content)2117 e_cal_shell_content_get_memo_table (ECalShellContent *cal_shell_content)
2118 {
2119 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL);
2120
2121 return E_MEMO_TABLE (cal_shell_content->priv->memo_table);
2122 }
2123
2124 ETaskTable *
e_cal_shell_content_get_task_table(ECalShellContent * cal_shell_content)2125 e_cal_shell_content_get_task_table (ECalShellContent *cal_shell_content)
2126 {
2127 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL);
2128
2129 return E_TASK_TABLE (cal_shell_content->priv->task_table);
2130 }
2131
2132 EShellSearchbar *
e_cal_shell_content_get_searchbar(ECalShellContent * cal_shell_content)2133 e_cal_shell_content_get_searchbar (ECalShellContent *cal_shell_content)
2134 {
2135 EShellView *shell_view;
2136 EShellContent *shell_content;
2137 GtkWidget *widget;
2138
2139 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL);
2140
2141 shell_content = E_SHELL_CONTENT (cal_shell_content);
2142 shell_view = e_shell_content_get_shell_view (shell_content);
2143 widget = e_shell_view_get_searchbar (shell_view);
2144
2145 return E_SHELL_SEARCHBAR (widget);
2146 }
2147
2148 static void
cal_shell_content_resubscribe(ECalendarView * cal_view,ECalModel * model)2149 cal_shell_content_resubscribe (ECalendarView *cal_view,
2150 ECalModel *model)
2151 {
2152 ECalDataModel *data_model;
2153 ECalDataModelSubscriber *subscriber;
2154 time_t range_start, range_end;
2155 gboolean is_tasks_or_memos;
2156
2157 g_return_if_fail (E_IS_CALENDAR_VIEW (cal_view));
2158 g_return_if_fail (E_IS_CAL_MODEL (model));
2159
2160 data_model = e_cal_model_get_data_model (model);
2161 subscriber = E_CAL_DATA_MODEL_SUBSCRIBER (model);
2162 is_tasks_or_memos = e_cal_model_get_component_kind (model) == I_CAL_VJOURNAL_COMPONENT ||
2163 e_cal_model_get_component_kind (model) == I_CAL_VTODO_COMPONENT;
2164
2165 if ((!is_tasks_or_memos && e_calendar_view_get_visible_time_range (cal_view, &range_start, &range_end)) ||
2166 e_cal_data_model_get_subscriber_range (data_model, subscriber, &range_start, &range_end)) {
2167 e_cal_data_model_unsubscribe (data_model, subscriber);
2168 e_cal_model_remove_all_objects (model);
2169
2170 if (is_tasks_or_memos)
2171 e_cal_data_model_subscribe (data_model, subscriber, range_start, range_end);
2172 }
2173 }
2174
2175 /* Only helper function */
2176 static void
cal_shell_content_switch_list_view(ECalShellContent * cal_shell_content,ECalViewKind from_view_kind,ECalViewKind to_view_kind)2177 cal_shell_content_switch_list_view (ECalShellContent *cal_shell_content,
2178 ECalViewKind from_view_kind,
2179 ECalViewKind to_view_kind)
2180 {
2181 EShellView *shell_view;
2182 EShellSidebar *shell_sidebar;
2183 ECalBaseShellSidebar *cal_base_shell_sidebar;
2184 ECalendar *date_navigator;
2185 ESourceSelector *source_selector;
2186 ECalModel *model;
2187 gchar *cal_filter;
2188
2189 g_return_if_fail (from_view_kind != to_view_kind);
2190
2191 if (to_view_kind != E_CAL_VIEW_KIND_LIST &&
2192 from_view_kind != E_CAL_VIEW_KIND_LIST)
2193 return;
2194
2195 shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content));
2196 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
2197 cal_base_shell_sidebar = E_CAL_BASE_SHELL_SIDEBAR (shell_sidebar);
2198 date_navigator = e_cal_base_shell_sidebar_get_date_navigator (cal_base_shell_sidebar);
2199 source_selector = e_cal_base_shell_sidebar_get_selector (cal_base_shell_sidebar);
2200
2201 gtk_widget_set_visible (GTK_WIDGET (date_navigator), to_view_kind != E_CAL_VIEW_KIND_LIST);
2202 e_source_selector_set_show_toggles (source_selector, to_view_kind != E_CAL_VIEW_KIND_LIST);
2203
2204 model = e_calendar_view_get_model (cal_shell_content->priv->views[from_view_kind]);
2205 cal_filter = e_cal_data_model_dup_filter (e_cal_model_get_data_model (model));
2206 if (cal_filter) {
2207 model = e_calendar_view_get_model (cal_shell_content->priv->views[to_view_kind]);
2208 e_cal_data_model_set_filter (e_cal_model_get_data_model (model), cal_filter);
2209 g_free (cal_filter);
2210 }
2211
2212 /* The list view is activated */
2213 if (to_view_kind == E_CAL_VIEW_KIND_LIST) {
2214 cal_shell_content_update_list_view (cal_shell_content);
2215 /* The list view is deactivated */
2216 } else if (from_view_kind == E_CAL_VIEW_KIND_LIST) {
2217 cal_shell_content_clear_all_in_list_view (cal_shell_content);
2218 e_cal_base_shell_sidebar_ensure_sources_open (cal_base_shell_sidebar);
2219 }
2220 }
2221
2222 void
e_cal_shell_content_set_current_view_id(ECalShellContent * cal_shell_content,ECalViewKind view_kind)2223 e_cal_shell_content_set_current_view_id (ECalShellContent *cal_shell_content,
2224 ECalViewKind view_kind)
2225 {
2226 EShellView *shell_view;
2227 time_t start_time = -1, end_time = -1;
2228 gint ii;
2229
2230 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2231 g_return_if_fail (view_kind >= E_CAL_VIEW_KIND_DAY && view_kind < E_CAL_VIEW_KIND_LAST);
2232
2233 if (cal_shell_content->priv->current_view == view_kind)
2234 return;
2235
2236 if (cal_shell_content->priv->current_view >= E_CAL_VIEW_KIND_DAY &&
2237 cal_shell_content->priv->current_view < E_CAL_VIEW_KIND_LAST) {
2238 ECalendarView *cal_view = cal_shell_content->priv->views[cal_shell_content->priv->current_view];
2239
2240 if (!e_calendar_view_get_selected_time_range (cal_view, &start_time, &end_time)) {
2241 start_time = -1;
2242 end_time = -1;
2243 }
2244
2245 e_calendar_view_destroy_tooltip (cal_view);
2246 }
2247
2248 cal_shell_content->priv->previous_selected_start_time = start_time;
2249 cal_shell_content->priv->previous_selected_end_time = end_time;
2250
2251 for (ii = 0; ii < E_CAL_VIEW_KIND_LAST; ii++) {
2252 ECalendarView *cal_view = cal_shell_content->priv->views[ii];
2253 gboolean in_focus = ii == view_kind;
2254 gboolean focus_changed;
2255
2256 if (!cal_view) {
2257 g_warn_if_reached ();
2258 continue;
2259 }
2260
2261 focus_changed = (cal_view->in_focus ? 1 : 0) != (in_focus ? 1 : 0);
2262
2263 cal_view->in_focus = in_focus;
2264
2265 if (ii == E_CAL_VIEW_KIND_LIST)
2266 continue;
2267
2268 if (focus_changed && in_focus) {
2269 /* Currently focused view changed. Any events within the common time
2270 range are not shown in the newly focused view, thus make sure it'll
2271 contain all what it should have. */
2272 ECalModel *model;
2273
2274 model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
2275
2276 /* This may not cause any queries to backends with events,
2277 because the time range should be always within the one
2278 shown in the date picker. */
2279 cal_shell_content_resubscribe (cal_view, model);
2280
2281 if (cal_shell_content->priv->task_table) {
2282 ETaskTable *task_table;
2283
2284 task_table = E_TASK_TABLE (cal_shell_content->priv->task_table);
2285 cal_shell_content_resubscribe (cal_view, e_task_table_get_model (task_table));
2286 }
2287
2288 if (cal_shell_content->priv->memo_table) {
2289 EMemoTable *memo_table;
2290
2291 memo_table = E_MEMO_TABLE (cal_shell_content->priv->memo_table);
2292 cal_shell_content_resubscribe (cal_view, e_memo_table_get_model (memo_table));
2293 }
2294 }
2295 }
2296
2297 cal_shell_content_switch_list_view (cal_shell_content, cal_shell_content->priv->current_view, view_kind);
2298
2299 cal_shell_content->priv->current_view = view_kind;
2300
2301 g_object_notify (G_OBJECT (cal_shell_content), "current-view-id");
2302
2303 gtk_widget_queue_draw (GTK_WIDGET (cal_shell_content->priv->views[cal_shell_content->priv->current_view]));
2304
2305 shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content));
2306 e_shell_view_update_actions (shell_view);
2307 e_cal_shell_view_update_sidebar (E_CAL_SHELL_VIEW (shell_view));
2308 }
2309
2310 ECalViewKind
e_cal_shell_content_get_current_view_id(ECalShellContent * cal_shell_content)2311 e_cal_shell_content_get_current_view_id (ECalShellContent *cal_shell_content)
2312 {
2313 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), E_CAL_VIEW_KIND_LAST);
2314
2315 return cal_shell_content->priv->current_view;
2316 }
2317
2318 ECalendarView *
e_cal_shell_content_get_calendar_view(ECalShellContent * cal_shell_content,ECalViewKind view_kind)2319 e_cal_shell_content_get_calendar_view (ECalShellContent *cal_shell_content,
2320 ECalViewKind view_kind)
2321 {
2322 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL);
2323 g_return_val_if_fail (view_kind >= E_CAL_VIEW_KIND_DAY && view_kind < E_CAL_VIEW_KIND_LAST, NULL);
2324
2325 return cal_shell_content->priv->views[view_kind];
2326 }
2327
2328 ECalendarView *
e_cal_shell_content_get_current_calendar_view(ECalShellContent * cal_shell_content)2329 e_cal_shell_content_get_current_calendar_view (ECalShellContent *cal_shell_content)
2330 {
2331 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL);
2332
2333 return e_cal_shell_content_get_calendar_view (cal_shell_content,
2334 e_cal_shell_content_get_current_view_id (cal_shell_content));
2335 }
2336
2337 void
e_cal_shell_content_save_state(ECalShellContent * cal_shell_content)2338 e_cal_shell_content_save_state (ECalShellContent *cal_shell_content)
2339 {
2340 ECalShellContentPrivate *priv;
2341
2342 g_return_if_fail (cal_shell_content != NULL);
2343 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2344
2345 priv = cal_shell_content->priv;
2346
2347 if (priv->task_table != NULL)
2348 cal_shell_content_save_table_state (
2349 E_SHELL_CONTENT (cal_shell_content),
2350 E_TABLE (priv->task_table));
2351
2352 if (priv->memo_table != NULL)
2353 cal_shell_content_save_table_state (
2354 E_SHELL_CONTENT (cal_shell_content),
2355 E_TABLE (priv->memo_table));
2356 }
2357
2358 void
e_cal_shell_content_get_current_range(ECalShellContent * cal_shell_content,time_t * range_start,time_t * range_end)2359 e_cal_shell_content_get_current_range (ECalShellContent *cal_shell_content,
2360 time_t *range_start,
2361 time_t *range_end)
2362 {
2363 ICalTimezone *zone;
2364
2365 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2366 g_return_if_fail (range_start != NULL);
2367 g_return_if_fail (range_end != NULL);
2368
2369 zone = e_cal_data_model_get_timezone (e_cal_base_shell_content_get_data_model (
2370 E_CAL_BASE_SHELL_CONTENT (cal_shell_content)));
2371
2372 *range_start = cal_comp_gdate_to_timet (&(cal_shell_content->priv->view_start), zone);
2373 *range_end = cal_comp_gdate_to_timet (&(cal_shell_content->priv->view_end), zone);
2374 }
2375
2376 void
e_cal_shell_content_get_current_range_dates(ECalShellContent * cal_shell_content,GDate * range_start,GDate * range_end)2377 e_cal_shell_content_get_current_range_dates (ECalShellContent *cal_shell_content,
2378 GDate *range_start,
2379 GDate *range_end)
2380 {
2381 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2382 g_return_if_fail (range_start != NULL);
2383 g_return_if_fail (range_end != NULL);
2384
2385 *range_start = cal_shell_content->priv->view_start;
2386 *range_end = cal_shell_content->priv->view_end;
2387 }
2388
2389 static void
cal_shell_content_move_view_range_relative(ECalShellContent * cal_shell_content,gint direction)2390 cal_shell_content_move_view_range_relative (ECalShellContent *cal_shell_content,
2391 gint direction)
2392 {
2393 GDate start, end;
2394
2395 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2396 g_return_if_fail (direction != 0);
2397
2398 start = cal_shell_content->priv->view_start;
2399 end = cal_shell_content->priv->view_end;
2400
2401 switch (cal_shell_content->priv->current_view) {
2402 case E_CAL_VIEW_KIND_DAY:
2403 if (direction > 0) {
2404 g_date_add_days (&start, direction);
2405 g_date_add_days (&end, direction);
2406 } else {
2407 g_date_subtract_days (&start, direction * -1);
2408 g_date_subtract_days (&end, direction * -1);
2409 }
2410 break;
2411 case E_CAL_VIEW_KIND_WORKWEEK:
2412 case E_CAL_VIEW_KIND_WEEK:
2413 if (direction > 0) {
2414 g_date_add_days (&start, direction * 7);
2415 g_date_add_days (&end, direction * 7);
2416 } else {
2417 g_date_subtract_days (&start, direction * -7);
2418 g_date_subtract_days (&end, direction * -7);
2419 }
2420 break;
2421 case E_CAL_VIEW_KIND_MONTH:
2422 case E_CAL_VIEW_KIND_LIST:
2423 if (g_date_get_day (&start) != 1) {
2424 g_date_add_months (&start, 1);
2425 g_date_set_day (&start, 1);
2426 }
2427 if (direction > 0)
2428 g_date_add_months (&start, direction);
2429 else
2430 g_date_subtract_months (&start, direction * -1);
2431 end = start;
2432 g_date_set_day (&end, g_date_get_days_in_month (g_date_get_month (&start), g_date_get_year (&start)));
2433 g_date_add_days (&end, 6);
2434 break;
2435 case E_CAL_VIEW_KIND_LAST:
2436 return;
2437 }
2438
2439 e_cal_shell_content_change_view (cal_shell_content, cal_shell_content->priv->current_view, &start, &end, FALSE);
2440 }
2441
2442 void
e_cal_shell_content_move_view_range(ECalShellContent * cal_shell_content,ECalendarViewMoveType move_type,time_t exact_date)2443 e_cal_shell_content_move_view_range (ECalShellContent *cal_shell_content,
2444 ECalendarViewMoveType move_type,
2445 time_t exact_date)
2446 {
2447 ECalendar *calendar;
2448 ECalDataModel *data_model;
2449 EShellSidebar *shell_sidebar;
2450 EShellView *shell_view;
2451 ICalTime *tt;
2452 ICalTimezone *zone;
2453 GDate date;
2454
2455 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2456
2457 shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content));
2458 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
2459 g_return_if_fail (E_IS_CAL_BASE_SHELL_SIDEBAR (shell_sidebar));
2460
2461 calendar = e_cal_base_shell_sidebar_get_date_navigator (E_CAL_BASE_SHELL_SIDEBAR (shell_sidebar));
2462 g_return_if_fail (E_IS_CALENDAR (calendar));
2463 g_return_if_fail (e_calendar_get_item (calendar) != NULL);
2464
2465 data_model = e_cal_base_shell_content_get_data_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
2466 zone = e_cal_data_model_get_timezone (data_model);
2467
2468 switch (move_type) {
2469 case E_CALENDAR_VIEW_MOVE_PREVIOUS:
2470 cal_shell_content_move_view_range_relative (cal_shell_content, -1);
2471 break;
2472 case E_CALENDAR_VIEW_MOVE_NEXT:
2473 cal_shell_content_move_view_range_relative (cal_shell_content, +1);
2474 break;
2475 case E_CALENDAR_VIEW_MOVE_TO_TODAY:
2476 tt = i_cal_time_new_current_with_zone (zone);
2477 g_date_set_dmy (&date, i_cal_time_get_day (tt), i_cal_time_get_month (tt), i_cal_time_get_year (tt));
2478 g_clear_object (&tt);
2479 /* one-day selection takes care of the view range move with left view kind */
2480 e_calendar_item_set_selection (e_calendar_get_item (calendar), &date, &date);
2481 break;
2482 case E_CALENDAR_VIEW_MOVE_TO_EXACT_DAY:
2483 time_to_gdate_with_zone (&date, exact_date, zone);
2484 e_cal_shell_content_change_view (cal_shell_content, E_CAL_VIEW_KIND_DAY, &date, &date, FALSE);
2485 break;
2486 }
2487 }
2488
2489 static void
cal_shell_content_update_model_filter(ECalDataModel * data_model,ECalModel * model,const gchar * filter,time_t range_start,time_t range_end)2490 cal_shell_content_update_model_filter (ECalDataModel *data_model,
2491 ECalModel *model,
2492 const gchar *filter,
2493 time_t range_start,
2494 time_t range_end)
2495 {
2496 time_t tmp_start, tmp_end;
2497
2498 g_return_if_fail (E_IS_CAL_DATA_MODEL (data_model));
2499 g_return_if_fail (E_IS_CAL_MODEL (model));
2500
2501 e_cal_data_model_freeze_views_update (data_model);
2502 if (filter != NULL)
2503 e_cal_data_model_set_filter (data_model, filter);
2504 e_cal_model_set_time_range (model, range_start, range_end);
2505
2506 if (!e_cal_data_model_get_subscriber_range (data_model, E_CAL_DATA_MODEL_SUBSCRIBER (model), &tmp_start, &tmp_end)) {
2507 e_cal_data_model_subscribe (data_model, E_CAL_DATA_MODEL_SUBSCRIBER (model), range_start, range_end);
2508 }
2509
2510 e_cal_data_model_thaw_views_update (data_model);
2511 }
2512
2513 void
e_cal_shell_content_update_tasks_filter(ECalShellContent * cal_shell_content,const gchar * cal_filter)2514 e_cal_shell_content_update_tasks_filter (ECalShellContent *cal_shell_content,
2515 const gchar *cal_filter)
2516 {
2517 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2518
2519 if (cal_shell_content->priv->task_table) {
2520 ETaskTable *task_table;
2521 ECalDataModel *data_model;
2522 ECalModel *model;
2523 gchar *hide_completed_tasks_sexp;
2524 gboolean hide_cancelled_tasks;
2525
2526 /* Set the query on the task pad. */
2527
2528 task_table = E_TASK_TABLE (cal_shell_content->priv->task_table);
2529 model = e_task_table_get_model (task_table);
2530 data_model = e_cal_model_get_data_model (model);
2531
2532 hide_completed_tasks_sexp = calendar_config_get_hide_completed_tasks_sexp (FALSE);
2533 hide_cancelled_tasks = calendar_config_get_hide_cancelled_tasks ();
2534
2535 if (hide_completed_tasks_sexp != NULL) {
2536 if (cal_filter && *cal_filter) {
2537 gchar *filter;
2538
2539 filter = g_strdup_printf ("(and %s %s%s%s)", hide_completed_tasks_sexp,
2540 hide_cancelled_tasks ? CALENDAR_CONFIG_NOT_CANCELLED_TASKS_SEXP : "",
2541 hide_cancelled_tasks ? " " : "",
2542 cal_filter);
2543 cal_shell_content_update_model_filter (data_model, model, filter, 0, 0);
2544 g_free (filter);
2545 } else if (hide_cancelled_tasks) {
2546 gchar *filter;
2547
2548 filter = g_strdup_printf ("(and %s %s)", hide_completed_tasks_sexp,
2549 CALENDAR_CONFIG_NOT_CANCELLED_TASKS_SEXP);
2550 cal_shell_content_update_model_filter (data_model, model, filter, 0, 0);
2551 g_free (filter);
2552 } else {
2553 cal_shell_content_update_model_filter (data_model, model, hide_completed_tasks_sexp, 0, 0);
2554 }
2555 } else if (hide_cancelled_tasks) {
2556 if (cal_filter && *cal_filter) {
2557 gchar *filter;
2558
2559 filter = g_strdup_printf ("(and %s %s)", CALENDAR_CONFIG_NOT_CANCELLED_TASKS_SEXP, cal_filter);
2560 cal_shell_content_update_model_filter (data_model, model, filter, 0, 0);
2561 g_free (filter);
2562 } else {
2563 cal_shell_content_update_model_filter (data_model, model, CALENDAR_CONFIG_NOT_CANCELLED_TASKS_SEXP, 0, 0);
2564 }
2565 } else {
2566 cal_shell_content_update_model_filter (data_model, model, (cal_filter && *cal_filter) ? cal_filter : "#t", 0, 0);
2567 }
2568
2569 g_free (hide_completed_tasks_sexp);
2570 }
2571 }
2572
2573 void
e_cal_shell_content_update_filters(ECalShellContent * cal_shell_content,const gchar * cal_filter,time_t start_range,time_t end_range)2574 e_cal_shell_content_update_filters (ECalShellContent *cal_shell_content,
2575 const gchar *cal_filter,
2576 time_t start_range,
2577 time_t end_range)
2578 {
2579 ECalDataModel *data_model;
2580 ECalModel *model;
2581
2582 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2583
2584 if (!cal_filter)
2585 return;
2586
2587 if (e_cal_shell_content_get_current_view_id (cal_shell_content) == E_CAL_VIEW_KIND_LIST) {
2588 data_model = cal_shell_content->priv->list_view_data_model;
2589 model = cal_shell_content->priv->list_view_model;
2590 start_range = 0;
2591 end_range = 0;
2592 } else {
2593 data_model = e_cal_base_shell_content_get_data_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
2594 model = e_cal_base_shell_content_get_model (E_CAL_BASE_SHELL_CONTENT (cal_shell_content));
2595 }
2596
2597 cal_shell_content_update_model_filter (data_model, model, cal_filter, start_range, end_range);
2598 e_cal_shell_content_update_tasks_filter (cal_shell_content, cal_filter);
2599
2600 if (cal_shell_content->priv->memo_table) {
2601 EMemoTable *memo_table;
2602
2603 /* Set the query on the memo pad. */
2604
2605 memo_table = E_MEMO_TABLE (cal_shell_content->priv->memo_table);
2606 model = e_memo_table_get_model (memo_table);
2607 data_model = e_cal_model_get_data_model (model);
2608
2609 if (start_range != 0 && end_range != 0) {
2610 ICalTimezone *zone;
2611 const gchar *default_tzloc = NULL;
2612 time_t end = end_range;
2613 gchar *filter;
2614 gchar *iso_start;
2615 gchar *iso_end;
2616
2617 zone = e_cal_data_model_get_timezone (data_model);
2618 if (zone && zone != i_cal_timezone_get_utc_timezone ())
2619 default_tzloc = i_cal_timezone_get_location (zone);
2620 if (!default_tzloc)
2621 default_tzloc = "";
2622
2623 if (start_range != (time_t) 0 && end_range != (time_t) 0) {
2624 end = time_day_end_with_zone (end_range, zone);
2625 }
2626
2627 iso_start = isodate_from_time_t (start_range);
2628 iso_end = isodate_from_time_t (end);
2629
2630 filter = g_strdup_printf (
2631 "(and (or (not (has-start?)) "
2632 "(occur-in-time-range? (make-time \"%s\") "
2633 "(make-time \"%s\") \"%s\")) %s)",
2634 iso_start, iso_end, default_tzloc, cal_filter);
2635
2636 cal_shell_content_update_model_filter (data_model, model, filter, 0, 0);
2637
2638 g_free (filter);
2639 g_free (iso_start);
2640 g_free (iso_end);
2641 } else {
2642 cal_shell_content_update_model_filter (data_model, model, *cal_filter ? cal_filter : "#t", 0, 0);
2643 }
2644 }
2645 }
2646
2647 ECalDataModel *
e_cal_shell_content_get_list_view_data_model(ECalShellContent * cal_shell_content)2648 e_cal_shell_content_get_list_view_data_model (ECalShellContent *cal_shell_content)
2649 {
2650 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), NULL);
2651
2652 return cal_shell_content->priv->list_view_data_model;
2653 }
2654
2655 void
e_cal_shell_content_set_show_tag_vpane(ECalShellContent * cal_shell_content,gboolean show)2656 e_cal_shell_content_set_show_tag_vpane (ECalShellContent *cal_shell_content,
2657 gboolean show)
2658 {
2659 g_return_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content));
2660
2661 if ((gtk_widget_get_visible (cal_shell_content->priv->vpaned) ? 1 : 0) == (show ? 1 : 0))
2662 return;
2663
2664 gtk_widget_set_visible (cal_shell_content->priv->vpaned, show);
2665
2666 if (show) {
2667 if (cal_shell_content->priv->task_data_model)
2668 e_cal_data_model_thaw_views_update (cal_shell_content->priv->task_data_model);
2669
2670 if (cal_shell_content->priv->memo_data_model)
2671 e_cal_data_model_thaw_views_update (cal_shell_content->priv->memo_data_model);
2672 } else {
2673 if (cal_shell_content->priv->task_data_model)
2674 e_cal_data_model_freeze_views_update (cal_shell_content->priv->task_data_model);
2675
2676 if (cal_shell_content->priv->memo_data_model)
2677 e_cal_data_model_freeze_views_update (cal_shell_content->priv->memo_data_model);
2678 }
2679
2680 g_object_notify (G_OBJECT (cal_shell_content), "show-tag-vpane");
2681 }
2682
2683 gboolean
e_cal_shell_content_get_show_tag_vpane(ECalShellContent * cal_shell_content)2684 e_cal_shell_content_get_show_tag_vpane (ECalShellContent *cal_shell_content)
2685 {
2686 g_return_val_if_fail (E_IS_CAL_SHELL_CONTENT (cal_shell_content), FALSE);
2687
2688 return gtk_widget_get_visible (cal_shell_content->priv->vpaned);
2689 }
2690