evolution-3.6.4/modules/calendar/e-cal-shell-view-private.c

Location Tool Test ID Function Issue
e-cal-shell-view-private.c:938:3 clang-analyzer Value stored to 'success' is never read
e-cal-shell-view-private.c:938:3 clang-analyzer Value stored to 'success' is never read
   1 /*
   2  * e-cal-shell-view-private.c
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) version 3.
   8  *
   9  * This program is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * Lesser General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  16  *
  17  *
  18  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  19  *
  20  */
  21 
  22 #ifdef HAVE_CONFIG_H
  23 #include <config.h>
  24 #endif
  25 
  26 #include "e-util/e-util-private.h"
  27 
  28 #include "e-cal-shell-view-private.h"
  29 
  30 #include "calendar/gui/calendar-view-factory.h"
  31 #include "widgets/menus/gal-view-factory-etable.h"
  32 
  33 #define CHECK_NB	5
  34 
  35 /* be compatible with older e-d-s for MeeGo */
  36 #ifndef ETC_TIMEZONE
  37 #  define ETC_TIMEZONE        "/etc/timezone"
  38 #  define ETC_TIMEZONE_MAJ    "/etc/TIMEZONE"
  39 #  define ETC_RC_CONF         "/etc/rc.conf"
  40 #  define ETC_SYSCONFIG_CLOCK "/etc/sysconfig/clock"
  41 #  define ETC_CONF_D_CLOCK    "/etc/conf.d/clock"
  42 #  define ETC_LOCALTIME       "/etc/localtime"
  43 #endif
  44 
  45 static const gchar * files_to_check[CHECK_NB] = {
  46         ETC_TIMEZONE,
  47         ETC_TIMEZONE_MAJ,
  48         ETC_SYSCONFIG_CLOCK,
  49         ETC_CONF_D_CLOCK,
  50         ETC_LOCALTIME
  51 };
  52 
  53 static struct tm
  54 cal_shell_view_get_current_time (ECalendarItem *calitem,
  55                                  ECalShellView *cal_shell_view)
  56 {
  57 	ECalShellContent *cal_shell_content;
  58 	struct icaltimetype tt;
  59 	icaltimezone *timezone;
  60 	ECalModel *model;
  61 
  62 	cal_shell_content = cal_shell_view->priv->cal_shell_content;
  63 	model = e_cal_shell_content_get_model (cal_shell_content);
  64 	timezone = e_cal_model_get_timezone (model);
  65 
  66 	tt = icaltime_from_timet_with_zone (time (NULL), FALSE, timezone);
  67 
  68 	return icaltimetype_to_tm (&tt);
  69 }
  70 
  71 static void
  72 cal_shell_view_date_navigator_date_range_changed_cb (ECalShellView *cal_shell_view,
  73                                                      ECalendarItem *calitem)
  74 {
  75 	ECalShellContent *cal_shell_content;
  76 	GnomeCalendar *calendar;
  77 
  78 	cal_shell_content = cal_shell_view->priv->cal_shell_content;
  79 	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
  80 
  81 	gnome_calendar_update_query (calendar);
  82 }
  83 
  84 static void
  85 cal_shell_view_date_navigator_selection_changed_cb (ECalShellView *cal_shell_view,
  86                                                     ECalendarItem *calitem)
  87 {
  88 	ECalShellContent *cal_shell_content;
  89 	GnomeCalendarViewType switch_to;
  90 	GnomeCalendarViewType view_type;
  91 	GnomeCalendar *calendar;
  92 	ECalModel *model;
  93 	GDate start_date, end_date;
  94 	GDate new_start_date, new_end_date;
  95 	icaltimetype tt;
  96 	icaltimezone *timezone;
  97 	time_t start, end, new_time;
  98 	gboolean starts_on_week_start_day;
  99 	gint new_days_shown, old_days_shown;
 100 	gint week_start_day;
 101 
 102 	cal_shell_content = cal_shell_view->priv->cal_shell_content;
 103 	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
 104 
 105 	model = gnome_calendar_get_model (calendar);
 106 	view_type = gnome_calendar_get_view (calendar);
 107 	switch_to = view_type;
 108 
 109 	timezone = e_cal_model_get_timezone (model);
 110 	week_start_day = e_cal_model_get_week_start_day (model);
 111 	e_cal_model_get_time_range (model, &start, &end);
 112 
 113 	time_to_gdate_with_zone (&start_date, start, timezone);
 114 	time_to_gdate_with_zone (&end_date, end, timezone);
 115 
 116 	if (view_type == GNOME_CAL_MONTH_VIEW) {
 117 		EWeekView *week_view;
 118 		ECalendarView *calendar_view;
 119 		gboolean multi_week_view;
 120 		gboolean compress_weekend;
 121 
 122 		calendar_view = gnome_calendar_get_calendar_view (
 123 			calendar, GNOME_CAL_MONTH_VIEW);
 124 
 125 		week_view = E_WEEK_VIEW (calendar_view);
 126 		multi_week_view = e_week_view_get_multi_week_view (week_view);
 127 		compress_weekend = e_week_view_get_compress_weekend (week_view);
 128 
 129 		if (week_start_day == 0 && (!multi_week_view || compress_weekend))
 130 			g_date_add_days (&start_date, 1);
 131 	}
 132 
 133 	g_date_subtract_days (&end_date, 1);
 134 
 135 	e_calendar_item_get_selection (
 136 		calitem, &new_start_date, &new_end_date);
 137 
 138 	/* If the selection hasn't changed, just return. */
 139 	if (g_date_compare (&start_date, &new_start_date) == 0 &&
 140 		g_date_compare (&end_date, &new_end_date) == 0)
 141 		return;
 142 
 143 	old_days_shown =
 144 		g_date_get_julian (&end_date) -
 145 		g_date_get_julian (&start_date) + 1;
 146 	new_days_shown =
 147 		g_date_get_julian (&new_end_date) -
 148 		g_date_get_julian (&new_start_date) + 1;
 149 
 150 	/* If a complete week is selected we show the week view.
 151 	 * Note that if weekends are compressed and the week start
 152 	 * day is set to Sunday, we don't actually show complete
 153 	 * weeks in the week view, so this may need tweaking. */
 154 	starts_on_week_start_day =
 155 		(g_date_get_weekday (&new_start_date) % 7 == week_start_day);
 156 
 157 	/* Update selection to be in the new time range. */
 158 	tt = icaltime_null_time ();
 159 	tt.year = g_date_get_year (&new_start_date);
 160 	tt.month = g_date_get_month (&new_start_date);
 161 	tt.day = g_date_get_day (&new_start_date);
 162 	new_time = icaltime_as_timet_with_zone (tt, timezone);
 163 
 164 	/* Switch views as appropriate, and change the number of
 165 	 * days or weeks shown. */
 166 	if (view_type == GNOME_CAL_WORK_WEEK_VIEW && old_days_shown == new_days_shown) {
 167 		/* keep the work week view when has same days shown */
 168 		switch_to = GNOME_CAL_WORK_WEEK_VIEW;
 169 	} else if (new_days_shown > 9) {
 170 		if (view_type != GNOME_CAL_LIST_VIEW) {
 171 			ECalendarView *calendar_view;
 172 
 173 			calendar_view = gnome_calendar_get_calendar_view (
 174 				calendar, GNOME_CAL_MONTH_VIEW);
 175 			e_week_view_set_weeks_shown (
 176 				E_WEEK_VIEW (calendar_view),
 177 				(new_days_shown + 6) / 7);
 178 			switch_to = GNOME_CAL_MONTH_VIEW;
 179 		}
 180 	} else if (new_days_shown == 7 && starts_on_week_start_day) {
 181 		switch_to = GNOME_CAL_WEEK_VIEW;
 182 	} else if (new_days_shown == 1 && (view_type == GNOME_CAL_WORK_WEEK_VIEW || view_type == GNOME_CAL_WEEK_VIEW)) {
 183 		/* preserve week views when clicking on one day */
 184 		switch_to = view_type;
 185 	} else {
 186 		ECalendarView *calendar_view;
 187 
 188 		calendar_view = gnome_calendar_get_calendar_view (
 189 			calendar, GNOME_CAL_DAY_VIEW);
 190 		e_day_view_set_days_shown (
 191 			E_DAY_VIEW (calendar_view), new_days_shown);
 192 
 193 		if (new_days_shown != 5 || !starts_on_week_start_day)
 194 			switch_to = GNOME_CAL_DAY_VIEW;
 195 
 196 		else if (view_type != GNOME_CAL_WORK_WEEK_VIEW)
 197 			switch_to = GNOME_CAL_DAY_VIEW;
 198 	}
 199 
 200 	/* Make the views display things properly. */
 201 	gnome_calendar_update_view_times (calendar, new_time);
 202 	gnome_calendar_set_view (calendar, switch_to);
 203 	gnome_calendar_set_range_selected (calendar, TRUE);
 204 
 205 	gnome_calendar_notify_dates_shown_changed (calendar);
 206 
 207 	g_signal_handlers_block_by_func (
 208 		calitem,
 209 		cal_shell_view_date_navigator_selection_changed_cb, cal_shell_view);
 210 
 211 	/* make sure the selected days in the calendar matches shown days */
 212 	e_cal_model_get_time_range (model, &start, &end);
 213 
 214 	time_to_gdate_with_zone (&start_date, start, timezone);
 215 	time_to_gdate_with_zone (&end_date, end, timezone);
 216 
 217 	g_date_subtract_days (&end_date, 1);
 218 
 219 	e_calendar_item_set_selection (calitem, &start_date, &end_date);
 220 
 221 	g_signal_handlers_unblock_by_func (
 222 		calitem,
 223 		cal_shell_view_date_navigator_selection_changed_cb, cal_shell_view);
 224 }
 225 
 226 static gboolean
 227 cal_shell_view_date_navigator_scroll_event_cb (ECalShellView *cal_shell_view,
 228                                                GdkEventScroll *event,
 229                                                ECalendar *date_navigator)
 230 {
 231 	ECalendarItem *calitem;
 232 	GDate start_date, end_date;
 233 	GdkScrollDirection direction;
 234 
 235 	calitem = date_navigator->calitem;
 236 	if (!e_calendar_item_get_selection (calitem, &start_date, &end_date))
 237 		return FALSE;
 238 
 239 	direction = event->direction;
 240 
 241 	#if GTK_CHECK_VERSION(3,3,18)
 242 	if (direction == GDK_SCROLL_SMOOTH) {
 243 		static gdouble total_delta_y = 0.0;
 244 
 245 		total_delta_y += event->delta_y;
 246 
 247 		if (total_delta_y >= 1.0) {
 248 			total_delta_y = 0.0;
 249 			direction = GDK_SCROLL_DOWN;
 250 		} else if (total_delta_y <= -1.0) {
 251 			total_delta_y = 0.0;
 252 			direction = GDK_SCROLL_UP;
 253 		} else {
 254 			return FALSE;
 255 		}
 256 	}
 257 	#endif
 258 
 259 	switch (direction) {
 260 		case GDK_SCROLL_UP:
 261 			g_date_subtract_months (&start_date, 1);
 262 			g_date_subtract_months (&end_date, 1);
 263 			break;
 264 
 265 		case GDK_SCROLL_DOWN:
 266 			g_date_add_months (&start_date, 1);
 267 			g_date_add_months (&end_date, 1);
 268 			break;
 269 
 270 		default:
 271 			g_return_val_if_reached (FALSE);
 272 	}
 273 
 274 	/* XXX Does ECalendarItem emit a signal for this?  If so, maybe
 275 	 *     we could move this handler into ECalShellSidebar. */
 276 	e_calendar_item_set_selection (calitem, &start_date, &end_date);
 277 
 278 	cal_shell_view_date_navigator_selection_changed_cb (
 279 		cal_shell_view, calitem);
 280 
 281 	return TRUE;
 282 }
 283 
 284 static void
 285 cal_shell_view_popup_event_cb (EShellView *shell_view,
 286                                GdkEventButton *event)
 287 {
 288 	GList *list;
 289 	GnomeCalendar *calendar;
 290 	GnomeCalendarViewType view_type;
 291 	ECalendarView *view;
 292 	ECalShellViewPrivate *priv;
 293 	const gchar *widget_path;
 294 	gint n_selected;
 295 
 296 	priv = E_CAL_SHELL_VIEW_GET_PRIVATE (shell_view);
 297 
 298 	calendar = e_cal_shell_content_get_calendar (priv->cal_shell_content);
 299 
 300 	view_type = gnome_calendar_get_view (calendar);
 301 	view = gnome_calendar_get_calendar_view (calendar, view_type);
 302 
 303 	list = e_calendar_view_get_selected_events (view);
 304 	n_selected = g_list_length (list);
 305 	g_list_free (list);
 306 
 307 	if (n_selected <= 0)
 308 		widget_path = "/calendar-empty-popup";
 309 	else
 310 		widget_path = "/calendar-event-popup";
 311 
 312 	e_shell_view_show_popup_menu (shell_view, widget_path, event);
 313 }
 314 
 315 static gboolean
 316 cal_shell_view_selector_popup_event_cb (EShellView *shell_view,
 317                                         ESource *primary_source,
 318                                         GdkEventButton *event)
 319 {
 320 	const gchar *widget_path;
 321 
 322 	widget_path = "/calendar-popup";
 323 	e_shell_view_show_popup_menu (shell_view, widget_path, event);
 324 
 325 	return TRUE;
 326 }
 327 
 328 static void
 329 cal_shell_view_selector_client_added_cb (ECalShellView *cal_shell_view,
 330                                          ECalClient *client)
 331 {
 332 	ECalShellContent *cal_shell_content;
 333 	GnomeCalendar *calendar;
 334 	ECalModel *model;
 335 
 336 	cal_shell_content = cal_shell_view->priv->cal_shell_content;
 337 	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
 338 	model = gnome_calendar_get_model (calendar);
 339 
 340 	e_cal_model_add_client (model, client);
 341 
 342 	gnome_calendar_update_query (calendar);
 343 }
 344 
 345 static void
 346 cal_shell_view_selector_client_removed_cb (ECalShellView *cal_shell_view,
 347                                            ECalClient *client)
 348 {
 349 	ECalShellContent *cal_shell_content;
 350 	GnomeCalendar *calendar;
 351 	ECalModel *model;
 352 
 353 	cal_shell_content = cal_shell_view->priv->cal_shell_content;
 354 	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
 355 	model = gnome_calendar_get_model (calendar);
 356 
 357 	e_cal_model_remove_client (model, client);
 358 
 359 	gnome_calendar_update_query (calendar);
 360 }
 361 
 362 static void
 363 cal_shell_view_memopad_popup_event_cb (EShellView *shell_view,
 364                                        GdkEventButton *event)
 365 {
 366 	const gchar *widget_path;
 367 
 368 	widget_path = "/calendar-memopad-popup";
 369 	e_shell_view_show_popup_menu (shell_view, widget_path, event);
 370 }
 371 
 372 static void
 373 cal_shell_view_taskpad_popup_event_cb (EShellView *shell_view,
 374                                        GdkEventButton *event)
 375 {
 376 	const gchar *widget_path;
 377 
 378 	widget_path = "/calendar-taskpad-popup";
 379 	e_shell_view_show_popup_menu (shell_view, widget_path, event);
 380 }
 381 
 382 static void
 383 cal_shell_view_user_created_cb (ECalShellView *cal_shell_view,
 384                                 ECalClient *where_was_created,
 385                                 ECalendarView *calendar_view)
 386 {
 387 	ECalShellSidebar *cal_shell_sidebar;
 388 	ESource *source;
 389 
 390 	g_return_if_fail (where_was_created != NULL);
 391 
 392 	source = e_client_get_source (E_CLIENT (where_was_created));
 393 
 394 	cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar;
 395 	e_cal_shell_sidebar_add_source (cal_shell_sidebar, source);
 396 }
 397 
 398 static void
 399 cal_shell_view_load_view_collection (EShellViewClass *shell_view_class)
 400 {
 401 	GalViewCollection *collection;
 402 	GalViewFactory *factory;
 403 	ETableSpecification *spec;
 404 	const gchar *base_dir;
 405 	gchar *filename;
 406 
 407 	collection = shell_view_class->view_collection;
 408 
 409 	base_dir = EVOLUTION_ETSPECDIR;
 410 	spec = e_table_specification_new ();
 411 	filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL);
 412 	if (!e_table_specification_load_from_file (spec, filename))
 413 		g_critical (
 414 			"Unable to load ETable specification file "
 415 			"for calendars");
 416 	g_free (filename);
 417 
 418 	factory = calendar_view_factory_new (GNOME_CAL_DAY_VIEW);
 419 	gal_view_collection_add_factory (collection, factory);
 420 	g_object_unref (factory);
 421 
 422 	factory = calendar_view_factory_new (GNOME_CAL_WORK_WEEK_VIEW);
 423 	gal_view_collection_add_factory (collection, factory);
 424 	g_object_unref (factory);
 425 
 426 	factory = calendar_view_factory_new (GNOME_CAL_WEEK_VIEW);
 427 	gal_view_collection_add_factory (collection, factory);
 428 	g_object_unref (factory);
 429 
 430 	factory = calendar_view_factory_new (GNOME_CAL_MONTH_VIEW);
 431 	gal_view_collection_add_factory (collection, factory);
 432 	g_object_unref (factory);
 433 
 434 	factory = gal_view_factory_etable_new (spec);
 435 	gal_view_collection_add_factory (collection, factory);
 436 	g_object_unref (factory);
 437 	g_object_unref (spec);
 438 
 439 	gal_view_collection_load (collection);
 440 }
 441 
 442 static void
 443 cal_shell_view_notify_view_id_cb (ECalShellView *cal_shell_view)
 444 {
 445 	ECalShellContent *cal_shell_content;
 446 	GalViewInstance *view_instance;
 447 	const gchar *view_id;
 448 
 449 	cal_shell_content = cal_shell_view->priv->cal_shell_content;
 450 	view_instance =
 451 		e_cal_shell_content_get_view_instance (cal_shell_content);
 452 	view_id = e_shell_view_get_view_id (E_SHELL_VIEW (cal_shell_view));
 453 
 454 	/* A NULL view ID implies we're in a custom view.  But you can
 455 	 * only get to a custom view via the "Define Views" dialog, which
 456 	 * would have already modified the view instance appropriately.
 457 	 * Furthermore, there's no way to refer to a custom view by ID
 458 	 * anyway, since custom views have no IDs. */
 459 	if (view_id == NULL)
 460 		return;
 461 
 462 	gal_view_instance_set_current_view_id (view_instance, view_id);
 463 }
 464 
 465 void
 466 e_cal_shell_view_private_init (ECalShellView *cal_shell_view,
 467                                EShellViewClass *shell_view_class)
 468 {
 469 	if (!gal_view_collection_loaded (shell_view_class->view_collection))
 470 		cal_shell_view_load_view_collection (shell_view_class);
 471 
 472 	g_signal_connect (
 473 		cal_shell_view, "notify::view-id",
 474 		G_CALLBACK (cal_shell_view_notify_view_id_cb), NULL);
 475 }
 476 
 477 static void
 478 system_timezone_monitor_changed (GFileMonitor *handle,
 479                                  GFile *file,
 480                                  GFile *other_file,
 481                                  GFileMonitorEvent event,
 482                                  gpointer user_data)
 483 {
 484 	ECalShellView  *view = E_CAL_SHELL_VIEW (user_data);
 485 	ECalShellViewPrivate *priv = view->priv;
 486 	ECalShellContent *cal_shell_content;
 487 	icaltimezone *timezone = NULL, *current_zone = NULL;
 488 	EShellSettings *settings;
 489 	EShellBackend *shell_backend;
 490 	EShell *shell;
 491 	ECalModel *model;
 492 	const gchar *location;
 493 
 494 	if (event != G_FILE_MONITOR_EVENT_CHANGED &&
 495 	    event != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT &&
 496 	    event != G_FILE_MONITOR_EVENT_DELETED &&
 497 	    event != G_FILE_MONITOR_EVENT_CREATED)
 498 		return;
 499 
 500 	cal_shell_content = priv->cal_shell_content;
 501 	model = e_cal_shell_content_get_model (cal_shell_content);
 502 	current_zone = e_cal_model_get_timezone (model);
 503 	timezone = e_cal_util_get_system_timezone ();
 504 
 505 	if (!g_strcmp0 (
 506 		icaltimezone_get_tzid (timezone),
 507 		icaltimezone_get_tzid (current_zone)))
 508 		return;
 509 
 510 	shell_backend = e_shell_view_get_shell_backend ((EShellView *) view);
 511 	shell = e_shell_backend_get_shell (shell_backend);
 512 	settings = e_shell_get_shell_settings (shell);
 513 	location = icaltimezone_get_location (timezone);
 514 	if (location == NULL)
 515 		location = "UTC";
 516 
 517 	g_object_set (settings, "cal-timezone-string", location, NULL);
 518 	g_object_set (settings, "cal-timezone", timezone, NULL);
 519 }
 520 
 521 static void
 522 init_timezone_monitors (ECalShellView *view)
 523 {
 524 	ECalShellViewPrivate *priv = view->priv;
 525 	gint i;
 526 
 527 	for (i = 0; i < CHECK_NB; i++) {
 528 		GFile *file;
 529 
 530 		file = g_file_new_for_path (files_to_check[i]);
 531 		priv->monitors[i] = g_file_monitor_file (
 532 			file, G_FILE_MONITOR_NONE, NULL, NULL);
 533 		g_object_unref (file);
 534 
 535 		if (priv->monitors[i])
 536 			g_signal_connect_object (
 537 				priv->monitors[i], "changed",
 538 				G_CALLBACK (system_timezone_monitor_changed),
 539 				view, 0);
 540 	}
 541 }
 542 
 543 void
 544 e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view)
 545 {
 546 	ECalShellViewPrivate *priv = cal_shell_view->priv;
 547 	ECalShellContent *cal_shell_content;
 548 	ECalShellSidebar *cal_shell_sidebar;
 549 	EShellBackend *shell_backend;
 550 	EShellContent *shell_content;
 551 	EShellSidebar *shell_sidebar;
 552 	EShellWindow *shell_window;
 553 	EShellView *shell_view;
 554 	GnomeCalendar *calendar;
 555 	ECalendar *date_navigator;
 556 	EMemoTable *memo_table;
 557 	ETaskTable *task_table;
 558 	ESourceSelector *selector;
 559 	GtkWidget *widget;
 560 	ECalModel *model;
 561 	gint ii;
 562 
 563 	shell_view = E_SHELL_VIEW (cal_shell_view);
 564 	shell_backend = e_shell_view_get_shell_backend (shell_view);
 565 	shell_content = e_shell_view_get_shell_content (shell_view);
 566 	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
 567 	shell_window = e_shell_view_get_shell_window (shell_view);
 568 
 569 	e_shell_window_add_action_group (shell_window, "calendar");
 570 	e_shell_window_add_action_group (shell_window, "calendar-filter");
 571 
 572 	/* Cache these to avoid lots of awkward casting. */
 573 	priv->cal_shell_backend = g_object_ref (shell_backend);
 574 	priv->cal_shell_content = g_object_ref (shell_content);
 575 	priv->cal_shell_sidebar = g_object_ref (shell_sidebar);
 576 
 577 	cal_shell_content = E_CAL_SHELL_CONTENT (shell_content);
 578 	model = e_cal_shell_content_get_model (cal_shell_content);
 579 	calendar = e_cal_shell_content_get_calendar (cal_shell_content);
 580 	memo_table = e_cal_shell_content_get_memo_table (cal_shell_content);
 581 	task_table = e_cal_shell_content_get_task_table (cal_shell_content);
 582 
 583 	cal_shell_sidebar = E_CAL_SHELL_SIDEBAR (shell_sidebar);
 584 	selector = e_cal_shell_sidebar_get_selector (cal_shell_sidebar);
 585 	date_navigator = e_cal_shell_sidebar_get_date_navigator (cal_shell_sidebar);
 586 
 587 	/* Give GnomeCalendar a handle to the date navigator, memo and task table. */
 588 	gnome_calendar_set_date_navigator (calendar, date_navigator);
 589 	gnome_calendar_set_memo_table (
 590 		calendar, memo_table ? GTK_WIDGET (memo_table) : NULL);
 591 	gnome_calendar_set_task_table (
 592 		calendar, task_table ? GTK_WIDGET (task_table) : NULL);
 593 
 594 	e_calendar_item_set_get_time_callback (
 595 		date_navigator->calitem, (ECalendarItemGetTimeCallback)
 596 		cal_shell_view_get_current_time, cal_shell_view, NULL);
 597 
 598 	for (ii = 0; ii < GNOME_CAL_LAST_VIEW; ii++) {
 599 		ECalendarView *calendar_view;
 600 
 601 		calendar_view =
 602 			gnome_calendar_get_calendar_view (calendar, ii);
 603 
 604 		g_signal_connect_object (
 605 			calendar_view, "popup-event",
 606 			G_CALLBACK (cal_shell_view_popup_event_cb),
 607 			cal_shell_view, G_CONNECT_SWAPPED);
 608 
 609 		g_signal_connect_object (
 610 			calendar_view, "selection-changed",
 611 			G_CALLBACK (e_shell_view_update_actions),
 612 			cal_shell_view, G_CONNECT_SWAPPED);
 613 
 614 		g_signal_connect_object (
 615 			calendar_view, "user-created",
 616 			G_CALLBACK (cal_shell_view_user_created_cb),
 617 			cal_shell_view, G_CONNECT_SWAPPED);
 618 	}
 619 
 620 	g_signal_connect_object (
 621 		calendar, "dates-shown-changed",
 622 		G_CALLBACK (e_cal_shell_view_update_sidebar),
 623 		cal_shell_view, G_CONNECT_SWAPPED);
 624 
 625 	g_signal_connect_object (
 626 		model, "status-message",
 627 		G_CALLBACK (e_cal_shell_view_set_status_message),
 628 		cal_shell_view, G_CONNECT_SWAPPED);
 629 
 630 	g_signal_connect_object (
 631 		model, "notify::timezone",
 632 		G_CALLBACK (e_cal_shell_view_update_timezone),
 633 		cal_shell_view, G_CONNECT_SWAPPED);
 634 
 635 	g_signal_connect_object (
 636 		date_navigator, "scroll-event",
 637 		G_CALLBACK (cal_shell_view_date_navigator_scroll_event_cb),
 638 		cal_shell_view, G_CONNECT_SWAPPED);
 639 
 640 	g_signal_connect_object (
 641 		date_navigator->calitem, "date-range-changed",
 642 		G_CALLBACK (cal_shell_view_date_navigator_date_range_changed_cb),
 643 		cal_shell_view, G_CONNECT_SWAPPED);
 644 
 645 	g_signal_connect_object (
 646 		date_navigator->calitem, "selection-changed",
 647 		G_CALLBACK (cal_shell_view_date_navigator_selection_changed_cb),
 648 		cal_shell_view, G_CONNECT_SWAPPED);
 649 
 650 	g_signal_connect_object (
 651 		selector, "popup-event",
 652 		G_CALLBACK (cal_shell_view_selector_popup_event_cb),
 653 		cal_shell_view, G_CONNECT_SWAPPED);
 654 
 655 	g_signal_connect_object (
 656 		cal_shell_sidebar, "client-added",
 657 		G_CALLBACK (cal_shell_view_selector_client_added_cb),
 658 		cal_shell_view, G_CONNECT_SWAPPED);
 659 
 660 	g_signal_connect_object (
 661 		cal_shell_sidebar, "client-removed",
 662 		G_CALLBACK (cal_shell_view_selector_client_removed_cb),
 663 		cal_shell_view, G_CONNECT_SWAPPED);
 664 
 665 	if (memo_table)
 666 		g_signal_connect_object (
 667 			memo_table, "popup-event",
 668 			G_CALLBACK (cal_shell_view_memopad_popup_event_cb),
 669 			cal_shell_view, G_CONNECT_SWAPPED);
 670 
 671 	if (memo_table)
 672 		g_signal_connect_object (
 673 			memo_table, "selection-change",
 674 			G_CALLBACK (e_cal_shell_view_memopad_actions_update),
 675 			cal_shell_view, G_CONNECT_SWAPPED);
 676 
 677 	if (memo_table)
 678 		g_signal_connect_object (
 679 			memo_table, "status-message",
 680 			G_CALLBACK (e_cal_shell_view_memopad_set_status_message),
 681 			cal_shell_view, G_CONNECT_SWAPPED);
 682 
 683 	if (task_table)
 684 		g_signal_connect_object (
 685 			task_table, "popup-event",
 686 			G_CALLBACK (cal_shell_view_taskpad_popup_event_cb),
 687 			cal_shell_view, G_CONNECT_SWAPPED);
 688 
 689 	if (task_table)
 690 		g_signal_connect_object (
 691 			task_table, "status-message",
 692 			G_CALLBACK (e_cal_shell_view_taskpad_set_status_message),
 693 			cal_shell_view, G_CONNECT_SWAPPED);
 694 
 695 	if (task_table)
 696 		g_signal_connect_object (
 697 			task_table, "selection-change",
 698 			G_CALLBACK (e_cal_shell_view_taskpad_actions_update),
 699 			cal_shell_view, G_CONNECT_SWAPPED);
 700 
 701 	e_categories_add_change_hook (
 702 		(GHookFunc) e_cal_shell_view_update_search_filter,
 703 		cal_shell_view);
 704 
 705 	init_timezone_monitors (cal_shell_view);
 706 	e_cal_shell_view_actions_init (cal_shell_view);
 707 	e_cal_shell_view_update_sidebar (cal_shell_view);
 708 	e_cal_shell_view_update_search_filter (cal_shell_view);
 709 	e_cal_shell_view_update_timezone (cal_shell_view);
 710 
 711 	/* Express mode only: Bind the "New Calendar"
 712 	 * sidebar button to the appropriate action. */
 713 	widget = e_cal_shell_sidebar_get_new_calendar_button (cal_shell_sidebar);
 714 	if (widget != NULL)
 715 		gtk_activatable_set_related_action (
 716 			GTK_ACTIVATABLE (widget), ACTION (CALENDAR_NEW));
 717 
 718 	/* Keep the ECalModel in sync with the sidebar. */
 719 	g_object_bind_property (
 720 		shell_sidebar, "default-client",
 721 		model, "default-client",
 722 		G_BINDING_SYNC_CREATE);
 723 
 724 	/* Keep the toolbar view buttons in sync with the calendar. */
 725 	g_object_bind_property (
 726 		calendar, "view",
 727 		ACTION (CALENDAR_VIEW_DAY), "current-value",
 728 		G_BINDING_BIDIRECTIONAL |
 729 		G_BINDING_SYNC_CREATE);
 730 
 731 	/* Force the main calendar to update its default source. */
 732 	g_signal_emit_by_name (selector, "primary-selection-changed");
 733 }
 734 
 735 void
 736 e_cal_shell_view_private_dispose (ECalShellView *cal_shell_view)
 737 {
 738 	ECalShellViewPrivate *priv = cal_shell_view->priv;
 739 	gint i;
 740 
 741 	e_cal_shell_view_search_stop (cal_shell_view);
 742 
 743 	/* Calling ECalShellContent's save state from here,
 744 	 * because it is too late in its own dispose(). */
 745 	if (priv->cal_shell_content != NULL)
 746 		e_cal_shell_content_save_state (priv->cal_shell_content);
 747 
 748 	DISPOSE (priv->cal_shell_backend);
 749 	DISPOSE (priv->cal_shell_content);
 750 	DISPOSE (priv->cal_shell_sidebar);
 751 
 752 	if (priv->calendar_activity != NULL) {
 753 		/* XXX Activity is not cancellable. */
 754 		e_activity_set_state (
 755 			priv->calendar_activity, E_ACTIVITY_COMPLETED);
 756 		g_object_unref (priv->calendar_activity);
 757 		priv->calendar_activity = NULL;
 758 	}
 759 
 760 	if (priv->memopad_activity != NULL) {
 761 		/* XXX Activity is not cancellable. */
 762 		e_activity_set_state (
 763 			priv->memopad_activity, E_ACTIVITY_COMPLETED);
 764 		g_object_unref (priv->memopad_activity);
 765 		priv->memopad_activity = NULL;
 766 	}
 767 
 768 	if (priv->taskpad_activity != NULL) {
 769 		/* XXX Activity is not cancellable. */
 770 		e_activity_set_state (
 771 			priv->taskpad_activity, E_ACTIVITY_COMPLETED);
 772 		g_object_unref (priv->taskpad_activity);
 773 		priv->taskpad_activity = NULL;
 774 	}
 775 
 776 	for (i = 0; i < CHECK_NB; i++) {
 777 		g_object_unref (priv->monitors[i]);
 778 		priv->monitors[i] = NULL;
 779 	}
 780 }
 781 
 782 void
 783 e_cal_shell_view_private_finalize (ECalShellView *cal_shell_view)
 784 {
 785 	/* XXX Nothing to do? */
 786 }
 787 
 788 void
 789 e_cal_shell_view_open_event (ECalShellView *cal_shell_view,
 790                              ECalModelComponent *comp_data)
 791 {
 792 	EShell *shell;
 793 	EShellView *shell_view;
 794 	EShellWindow *shell_window;
 795 	ESourceRegistry *registry;
 796 	CompEditor *editor;
 797 	CompEditorFlags flags = 0;
 798 	ECalComponent *comp;
 799 	icalcomponent *clone;
 800 	icalproperty *prop;
 801 	const gchar *uid;
 802 
 803 	g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view));
 804 	g_return_if_fail (E_IS_CAL_MODEL_COMPONENT (comp_data));
 805 
 806 	shell_view = E_SHELL_VIEW (cal_shell_view);
 807 	shell_window = e_shell_view_get_shell_window (shell_view);
 808 	shell = e_shell_window_get_shell (shell_window);
 809 
 810 	registry = e_shell_get_registry (shell);
 811 
 812 	uid = icalcomponent_get_uid (comp_data->icalcomp);
 813 	editor = comp_editor_find_instance (uid);
 814 
 815 	if (editor != NULL)
 816 		goto exit;
 817 
 818 	comp = e_cal_component_new ();
 819 	clone = icalcomponent_new_clone (comp_data->icalcomp);
 820 	e_cal_component_set_icalcomponent (comp, clone);
 821 
 822 	prop = icalcomponent_get_first_property (
 823 		comp_data->icalcomp, ICAL_ATTENDEE_PROPERTY);
 824 	if (prop != NULL)
 825 		flags |= COMP_EDITOR_MEETING;
 826 
 827 	if (itip_organizer_is_user (registry, comp, comp_data->client))
 828 		flags |= COMP_EDITOR_USER_ORG;
 829 
 830 	if (itip_sentby_is_user (registry, comp, comp_data->client))
 831 		flags |= COMP_EDITOR_USER_ORG;
 832 
 833 	if (!e_cal_component_has_attendees (comp))
 834 		flags |= COMP_EDITOR_USER_ORG;
 835 
 836 	editor = event_editor_new (comp_data->client, shell, flags);
 837 	comp_editor_edit_comp (editor, comp);
 838 
 839 	g_object_unref (comp);
 840 
 841 exit:
 842 	gtk_window_present (GTK_WINDOW (editor));
 843 }
 844 
 845 void
 846 e_cal_shell_view_set_status_message (ECalShellView *cal_shell_view,
 847                                      const gchar *status_message,
 848                                      gdouble percent)
 849 {
 850 	EActivity *activity;
 851 	EShellView *shell_view;
 852 	EShellBackend *shell_backend;
 853 
 854 	g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view));
 855 
 856 	shell_view = E_SHELL_VIEW (cal_shell_view);
 857 	shell_backend = e_shell_view_get_shell_backend (shell_view);
 858 
 859 	activity = cal_shell_view->priv->calendar_activity;
 860 
 861 	if (status_message == NULL || *status_message == '\0') {
 862 		if (activity != NULL) {
 863 			e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
 864 			g_object_unref (activity);
 865 			activity = NULL;
 866 		}
 867 	} else if (activity == NULL) {
 868 		activity = e_activity_new ();
 869 		e_activity_set_percent (activity, percent);
 870 		e_activity_set_text (activity, status_message);
 871 		e_shell_backend_add_activity (shell_backend, activity);
 872 	} else {
 873 		e_activity_set_percent (activity, percent);
 874 		e_activity_set_text (activity, status_message);
 875 	}
 876 
 877 	cal_shell_view->priv->calendar_activity = activity;
 878 }
 879 
 880 struct ForeachTzidData
 881 {
 882 	ECalClient *source_client;
 883 	ECalClient *dest_client;
 884 };
 885 
 886 static void
 887 add_timezone_to_cal_cb (icalparameter *param,
 888                         gpointer data)
 889 {
 890 	struct ForeachTzidData *ftd = data;
 891 	icaltimezone *tz = NULL;
 892 	const gchar *tzid;
 893 
 894 	g_return_if_fail (ftd != NULL);
 895 	g_return_if_fail (ftd->source_client != NULL);
 896 	g_return_if_fail (ftd->dest_client != NULL);
 897 
 898 	tzid = icalparameter_get_tzid (param);
 899 	if (!tzid || !*tzid)
 900 		return;
 901 
 902 	if (e_cal_client_get_timezone_sync (ftd->source_client, tzid, &tz, NULL, NULL) && tz)
 903 		e_cal_client_add_timezone_sync (ftd->dest_client, tz, NULL, NULL);
 904 }
 905 
 906 void
 907 e_cal_shell_view_transfer_item_to (ECalShellView *cal_shell_view,
 908                                    ECalendarViewEvent *event,
 909                                    ECalClient *destination_client,
 910                                    gboolean remove)
 911 {
 912 	icalcomponent *icalcomp;
 913 	icalcomponent *icalcomp_clone;
 914 	icalcomponent *icalcomp_event;
 915 	gboolean success;
 916 	const gchar *uid;
 917 
 918 	/* XXX This function should be split up into
 919 	 *     smaller, more understandable pieces. */
 920 
 921 	g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view));
 922 	g_return_if_fail (event != NULL);
 923 	g_return_if_fail (E_IS_CAL_CLIENT (destination_client));
 924 
 925 	if (!is_comp_data_valid (event))
 926 		return;
 927 
 928 	icalcomp_event = event->comp_data->icalcomp;
 929 	uid = icalcomponent_get_uid (icalcomp_event);
 930 
 931 	/* Put the new object into the destination calendar. */
 932 
 933 	success = e_cal_client_get_object_sync (
 934 		destination_client, uid, NULL, &icalcomp, NULL, NULL);
 935 
 936 	if (success) {
 937 		icalcomponent_free (icalcomp);
 938 		success = e_cal_client_modify_object_sync (
Value stored to 'success' is never read
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

Value stored to 'success' is never read
(emitted by clang-analyzer)

TODO: a detailed trace is available in the data model (not yet rendered in this report)

939 destination_client, icalcomp_event, 940 CALOBJ_MOD_ALL, NULL, NULL); 941 942 /* do not delete the event when it was found in the calendar */ 943 return; 944 } else { 945 icalproperty *icalprop; 946 gchar *new_uid; 947 GError *error = NULL; 948 struct ForeachTzidData ftd; 949 950 ftd.source_client = event->comp_data->client; 951 ftd.dest_client = destination_client; 952 953 if (e_cal_util_component_is_instance (icalcomp_event)) { 954 success = e_cal_client_get_object_sync ( 955 event->comp_data->client, 956 uid, NULL, &icalcomp, NULL, NULL); 957 if (success) { 958 /* Use master object when working 959 * with a recurring event ... */ 960 icalcomp_clone = icalcomponent_new_clone (icalcomp); 961 icalcomponent_free (icalcomp); 962 } else { 963 /* ... or remove the recurrence ID ... */ 964 icalcomp_clone = 965 icalcomponent_new_clone (icalcomp_event); 966 if (e_cal_util_component_has_recurrences (icalcomp_clone)) { 967 /* ... for non-detached instances, 968 * to make it a master object. */ 969 icalprop = icalcomponent_get_first_property ( 970 icalcomp_clone, ICAL_RECURRENCEID_PROPERTY); 971 if (icalprop != NULL) 972 icalcomponent_remove_property ( 973 icalcomp_clone, icalprop); 974 } 975 } 976 } else 977 icalcomp_clone = 978 icalcomponent_new_clone (icalcomp_event); 979 980 icalprop = icalproperty_new_x ("1"); 981 icalproperty_set_x_name (icalprop, "X-EVOLUTION-MOVE-CALENDAR"); 982 icalcomponent_add_property (icalcomp_clone, icalprop); 983 984 if (!remove) { 985 /* Change the UID to avoid problems with 986 * duplicated UIDs. */ 987 new_uid = e_cal_component_gen_uid (); 988 icalcomponent_set_uid (icalcomp_clone, new_uid); 989 g_free (new_uid); 990 } 991 992 new_uid = NULL; 993 icalcomponent_foreach_tzid ( 994 icalcomp_clone, add_timezone_to_cal_cb, &ftd); 995 success = e_cal_client_create_object_sync ( 996 destination_client, icalcomp_clone, 997 &new_uid, NULL, &error); 998 if (!success) { 999 icalcomponent_free (icalcomp_clone); 1000 g_warning ( 1001 "%s: Failed to create object: %s", 1002 G_STRFUNC, error->message); 1003 g_error_free (error); 1004 return; 1005 } 1006 1007 icalcomponent_free (icalcomp_clone); 1008 g_free (new_uid); 1009 } 1010 1011 if (remove) { 1012 ECalClient *source_client = event->comp_data->client; 1013 1014 /* Remove the item from the source calendar. */ 1015 if (e_cal_util_component_is_instance (icalcomp_event) || 1016 e_cal_util_component_has_recurrences (icalcomp_event)) { 1017 icaltimetype icaltime; 1018 gchar *rid; 1019 1020 icaltime = 1021 icalcomponent_get_recurrenceid (icalcomp_event); 1022 if (!icaltime_is_null_time (icaltime)) 1023 rid = icaltime_as_ical_string_r (icaltime); 1024 else 1025 rid = NULL; 1026 e_cal_client_remove_object_sync ( 1027 source_client, uid, rid, 1028 CALOBJ_MOD_ALL, NULL, NULL); 1029 g_free (rid); 1030 } else 1031 e_cal_client_remove_object_sync ( 1032 source_client, uid, NULL, 1033 CALOBJ_MOD_THIS, NULL, NULL); 1034 } 1035 } 1036 1037 void 1038 e_cal_shell_view_update_sidebar (ECalShellView *cal_shell_view) 1039 { 1040 EShellView *shell_view; 1041 EShellSidebar *shell_sidebar; 1042 ECalShellContent *cal_shell_content; 1043 GnomeCalendar *calendar; 1044 GnomeCalendarViewType view_type; 1045 ECalendarView *calendar_view; 1046 ECalModel *model; 1047 time_t start_time, end_time; 1048 struct tm start_tm, end_tm; 1049 struct icaltimetype start_tt, end_tt; 1050 icaltimezone *timezone; 1051 gchar buffer[512] = { 0 }; 1052 gchar end_buffer[512] = { 0 }; 1053 1054 g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); 1055 1056 shell_view = E_SHELL_VIEW (cal_shell_view); 1057 shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); 1058 1059 cal_shell_content = cal_shell_view->priv->cal_shell_content; 1060 calendar = e_cal_shell_content_get_calendar (cal_shell_content); 1061 1062 model = gnome_calendar_get_model (calendar); 1063 timezone = e_cal_model_get_timezone (model); 1064 1065 view_type = gnome_calendar_get_view (calendar); 1066 calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); 1067 1068 if (!e_calendar_view_get_visible_time_range ( 1069 calendar_view, &start_time, &end_time)) { 1070 e_shell_sidebar_set_secondary_text (shell_sidebar, ""); 1071 return; 1072 } 1073 1074 start_tt = icaltime_from_timet_with_zone (start_time, FALSE, timezone); 1075 start_tm.tm_year = start_tt.year - 1900; 1076 start_tm.tm_mon = start_tt.month - 1; 1077 start_tm.tm_mday = start_tt.day; 1078 start_tm.tm_hour = start_tt.hour; 1079 start_tm.tm_min = start_tt.minute; 1080 start_tm.tm_sec = start_tt.second; 1081 start_tm.tm_isdst = -1; 1082 start_tm.tm_wday = time_day_of_week ( 1083 start_tt.day, start_tt.month - 1, start_tt.year); 1084 1085 /* Subtract one from end_time so we don't get an extra day. */ 1086 end_tt = icaltime_from_timet_with_zone (end_time - 1, FALSE, timezone); 1087 end_tm.tm_year = end_tt.year - 1900; 1088 end_tm.tm_mon = end_tt.month - 1; 1089 end_tm.tm_mday = end_tt.day; 1090 end_tm.tm_hour = end_tt.hour; 1091 end_tm.tm_min = end_tt.minute; 1092 end_tm.tm_sec = end_tt.second; 1093 end_tm.tm_isdst = -1; 1094 end_tm.tm_wday = time_day_of_week ( 1095 end_tt.day, end_tt.month - 1, end_tt.year); 1096 1097 switch (view_type) { 1098 case GNOME_CAL_DAY_VIEW: 1099 case GNOME_CAL_WORK_WEEK_VIEW: 1100 case GNOME_CAL_WEEK_VIEW: 1101 if (start_tm.tm_year == end_tm.tm_year && 1102 start_tm.tm_mon == end_tm.tm_mon && 1103 start_tm.tm_mday == end_tm.tm_mday) { 1104 e_utf8_strftime ( 1105 buffer, sizeof (buffer), 1106 _("%A %d %b %Y"), &start_tm); 1107 } else if (start_tm.tm_year == end_tm.tm_year) { 1108 e_utf8_strftime ( 1109 buffer, sizeof (buffer), 1110 _("%a %d %b"), &start_tm); 1111 e_utf8_strftime ( 1112 end_buffer, sizeof (end_buffer), 1113 _("%a %d %b %Y"), &end_tm); 1114 strcat (buffer, " - "); 1115 strcat (buffer, end_buffer); 1116 } else { 1117 e_utf8_strftime ( 1118 buffer, sizeof (buffer), 1119 _("%a %d %b %Y"), &start_tm); 1120 e_utf8_strftime ( 1121 end_buffer, sizeof (end_buffer), 1122 _("%a %d %b %Y"), &end_tm); 1123 strcat (buffer, " - "); 1124 strcat (buffer, end_buffer); 1125 } 1126 break; 1127 1128 case GNOME_CAL_MONTH_VIEW: 1129 case GNOME_CAL_LIST_VIEW: 1130 if (start_tm.tm_year == end_tm.tm_year) { 1131 if (start_tm.tm_mon == end_tm.tm_mon) { 1132 e_utf8_strftime ( 1133 buffer, 1134 sizeof (buffer), 1135 "%d", &start_tm); 1136 e_utf8_strftime ( 1137 end_buffer, 1138 sizeof (end_buffer), 1139 _("%d %b %Y"), &end_tm); 1140 strcat (buffer, " - "); 1141 strcat (buffer, end_buffer); 1142 } else { 1143 e_utf8_strftime ( 1144 buffer, 1145 sizeof (buffer), 1146 _("%d %b"), &start_tm); 1147 e_utf8_strftime ( 1148 end_buffer, 1149 sizeof (end_buffer), 1150 _("%d %b %Y"), &end_tm); 1151 strcat (buffer, " - "); 1152 strcat (buffer, end_buffer); 1153 } 1154 } else { 1155 e_utf8_strftime ( 1156 buffer, sizeof (buffer), 1157 _("%d %b %Y"), &start_tm); 1158 e_utf8_strftime ( 1159 end_buffer, sizeof (end_buffer), 1160 _("%d %b %Y"), &end_tm); 1161 strcat (buffer, " - "); 1162 strcat (buffer, end_buffer); 1163 } 1164 break; 1165 1166 default: 1167 g_return_if_reached (); 1168 } 1169 1170 e_shell_sidebar_set_secondary_text (shell_sidebar, buffer); 1171 } 1172 1173 void 1174 e_cal_shell_view_update_timezone (ECalShellView *cal_shell_view) 1175 { 1176 ECalShellContent *cal_shell_content; 1177 ECalShellSidebar *cal_shell_sidebar; 1178 icaltimezone *timezone; 1179 ECalModel *model; 1180 GList *clients, *iter; 1181 1182 cal_shell_content = cal_shell_view->priv->cal_shell_content; 1183 model = e_cal_shell_content_get_model (cal_shell_content); 1184 timezone = e_cal_model_get_timezone (model); 1185 1186 cal_shell_sidebar = cal_shell_view->priv->cal_shell_sidebar; 1187 clients = e_cal_shell_sidebar_get_clients (cal_shell_sidebar); 1188 1189 for (iter = clients; iter != NULL; iter = iter->next) { 1190 ECalClient *client = iter->data; 1191 1192 if (e_client_is_opened (E_CLIENT (client))) 1193 e_cal_client_set_default_timezone (client, timezone); 1194 } 1195 1196 g_list_free (clients); 1197 } 1198 1199 static gint 1200 cal_searching_get_search_range_years (ECalShellView *cal_shell_view) 1201 { 1202 EShellBackend *backend; 1203 EShellSettings *shell_settings; 1204 gint value; 1205 1206 backend = e_shell_view_get_shell_backend (E_SHELL_VIEW (cal_shell_view)); 1207 shell_settings = e_shell_get_shell_settings (e_shell_backend_get_shell (backend)); 1208 1209 value = e_shell_settings_get_int (shell_settings, "cal-search-range-years"); 1210 if (value <= 0) 1211 value = 10; 1212 1213 return value; 1214 } 1215 1216 static gint 1217 cal_time_t_ptr_compare (gconstpointer a, 1218 gconstpointer b) 1219 { 1220 const time_t *ta = a, *tb = b; 1221 1222 return (ta ? *ta : 0) - (tb ? *tb : 0); 1223 } 1224 1225 static void cal_iterate_searching (ECalShellView *cal_shell_view); 1226 1227 struct GenerateInstancesData { 1228 ECalClient *client; 1229 ECalShellView *cal_shell_view; 1230 GCancellable *cancellable; 1231 }; 1232 1233 static void 1234 cal_searching_instances_done_cb (gpointer user_data) 1235 { 1236 struct GenerateInstancesData *gid = user_data; 1237 1238 g_return_if_fail (gid != NULL); 1239 g_return_if_fail (gid->cal_shell_view != NULL); 1240 1241 if (!g_cancellable_is_cancelled (gid->cancellable)) { 1242 gid->cal_shell_view->priv->search_pending_count--; 1243 if (!gid->cal_shell_view->priv->search_pending_count) { 1244 gid->cal_shell_view->priv->search_hit_cache = 1245 g_slist_sort ( 1246 gid->cal_shell_view->priv->search_hit_cache, 1247 cal_time_t_ptr_compare); 1248 cal_iterate_searching (gid->cal_shell_view); 1249 } 1250 } 1251 1252 g_object_unref (gid->cancellable); 1253 g_free (gid); 1254 } 1255 1256 static gboolean 1257 cal_searching_got_instance_cb (ECalComponent *comp, 1258 time_t instance_start, 1259 time_t instance_end, 1260 gpointer user_data) 1261 { 1262 struct GenerateInstancesData *gid = user_data; 1263 ECalShellViewPrivate *priv; 1264 ECalComponentDateTime dt; 1265 time_t *value; 1266 1267 g_return_val_if_fail (gid != NULL, FALSE); 1268 1269 if (g_cancellable_is_cancelled (gid->cancellable)) 1270 return FALSE; 1271 1272 g_return_val_if_fail (gid->cal_shell_view != NULL, FALSE); 1273 g_return_val_if_fail (gid->cal_shell_view->priv != NULL, FALSE); 1274 1275 e_cal_component_get_dtstart (comp, &dt); 1276 1277 if (dt.tzid && dt.value) { 1278 icaltimezone *zone = NULL; 1279 if (!e_cal_client_get_timezone_sync (gid->client, dt.tzid, &zone, gid->cancellable, NULL)) { 1280 zone = NULL; 1281 } 1282 1283 if (g_cancellable_is_cancelled (gid->cancellable)) 1284 return FALSE; 1285 1286 if (zone) 1287 instance_start = icaltime_as_timet_with_zone (*dt.value, zone); 1288 } 1289 1290 e_cal_component_free_datetime (&dt); 1291 1292 priv = gid->cal_shell_view->priv; 1293 value = g_new (time_t, 1); 1294 *value = instance_start; 1295 if (!g_slist_find_custom (priv->search_hit_cache, value, cal_time_t_ptr_compare)) 1296 priv->search_hit_cache = g_slist_append (priv->search_hit_cache, value); 1297 else 1298 g_free (value); 1299 1300 return TRUE; 1301 } 1302 1303 static void 1304 cal_search_get_object_list_cb (GObject *source, 1305 GAsyncResult *result, 1306 gpointer user_data) 1307 { 1308 ECalClient *client = E_CAL_CLIENT (source); 1309 ECalShellView *cal_shell_view = user_data; 1310 GSList *icalcomps = NULL; 1311 GError *error = NULL; 1312 1313 g_return_if_fail (client != NULL); 1314 g_return_if_fail (result != NULL); 1315 g_return_if_fail (cal_shell_view != NULL); 1316 1317 if (!e_cal_client_get_object_list_finish (client, result, &icalcomps, &error) || !icalcomps) { 1318 if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) || 1319 g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { 1320 g_clear_error (&error); 1321 return; 1322 } 1323 1324 g_clear_error (&error); 1325 cal_shell_view->priv->search_pending_count--; 1326 if (!cal_shell_view->priv->search_pending_count) { 1327 cal_shell_view->priv->search_hit_cache = 1328 g_slist_sort ( 1329 cal_shell_view->priv->search_hit_cache, 1330 cal_time_t_ptr_compare); 1331 cal_iterate_searching (cal_shell_view); 1332 } 1333 } else { 1334 GSList *iter; 1335 GCancellable *cancellable; 1336 time_t start, end; 1337 1338 cancellable = e_activity_get_cancellable ( 1339 cal_shell_view->priv->searching_activity); 1340 start = time_add_day ( 1341 cal_shell_view->priv->search_time, 1342 (-1) * cal_shell_view->priv->search_direction); 1343 end = cal_shell_view->priv->search_time; 1344 if (start > end) { 1345 time_t tmp = start; 1346 start = end; 1347 end = tmp; 1348 } 1349 1350 for (iter = icalcomps; iter; iter = iter->next) { 1351 icalcomponent *icalcomp = iter->data; 1352 struct GenerateInstancesData *gid; 1353 1354 gid = g_new0 (struct GenerateInstancesData, 1); 1355 gid->client = client; 1356 gid->cal_shell_view = cal_shell_view; 1357 gid->cancellable = g_object_ref (cancellable); 1358 1359 e_cal_client_generate_instances_for_object ( 1360 client, icalcomp, start, end, cancellable, 1361 cal_searching_got_instance_cb, gid, 1362 cal_searching_instances_done_cb); 1363 } 1364 1365 e_cal_client_free_icalcomp_slist (icalcomps); 1366 } 1367 } 1368 1369 static gboolean 1370 cal_searching_check_candidates (ECalShellView *cal_shell_view) 1371 { 1372 ECalShellContent *cal_shell_content; 1373 GnomeCalendarViewType view_type; 1374 ECalendarView *calendar_view; 1375 GnomeCalendar *calendar; 1376 GSList *iter; 1377 time_t value, candidate = -1; 1378 1379 g_return_val_if_fail (cal_shell_view != NULL, FALSE); 1380 g_return_val_if_fail (cal_shell_view->priv != NULL, FALSE); 1381 1382 cal_shell_content = cal_shell_view->priv->cal_shell_content; 1383 calendar = e_cal_shell_content_get_calendar (cal_shell_content); 1384 view_type = gnome_calendar_get_view (calendar); 1385 calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); 1386 1387 if (!e_calendar_view_get_selected_time_range (calendar_view, &value, NULL)) 1388 return FALSE; 1389 1390 if (cal_shell_view->priv->search_direction > 0 && (view_type == GNOME_CAL_WEEK_VIEW || view_type == GNOME_CAL_MONTH_VIEW)) 1391 value = time_add_day (value, 1); 1392 1393 for (iter = cal_shell_view->priv->search_hit_cache; iter; iter = iter->next) { 1394 time_t cache = *((time_t *) iter->data); 1395 1396 /* list is sorted, once the search iteration is complete */ 1397 if (cache > value) { 1398 if (cal_shell_view->priv->search_direction > 0) 1399 candidate = cache; 1400 break; 1401 } else if (cal_shell_view->priv->search_direction < 0 && cache != value) 1402 candidate = cache; 1403 } 1404 1405 if (candidate > 0) { 1406 gnome_calendar_goto (calendar, candidate); 1407 return TRUE; 1408 } 1409 1410 return FALSE; 1411 } 1412 1413 static void 1414 cal_searching_update_alert (ECalShellView *cal_shell_view, 1415 const gchar *message) 1416 { 1417 ECalShellViewPrivate *priv; 1418 EShellContent *shell_content; 1419 EAlert *alert; 1420 1421 g_return_if_fail (cal_shell_view != NULL); 1422 g_return_if_fail (cal_shell_view->priv != NULL); 1423 1424 priv = cal_shell_view->priv; 1425 1426 if (priv->search_alert) { 1427 e_alert_response ( 1428 priv->search_alert, 1429 e_alert_get_default_response (priv->search_alert)); 1430 priv->search_alert = NULL; 1431 } 1432 1433 if (!message) 1434 return; 1435 1436 alert = e_alert_new ("calendar:search-error-generic", message, NULL); 1437 g_return_if_fail (alert != NULL); 1438 1439 priv->search_alert = alert; 1440 g_object_add_weak_pointer (G_OBJECT (alert), &priv->search_alert); 1441 e_alert_start_timer (priv->search_alert, 5); 1442 1443 shell_content = e_shell_view_get_shell_content ( 1444 E_SHELL_VIEW (cal_shell_view)); 1445 e_alert_sink_submit_alert ( 1446 E_ALERT_SINK (shell_content), priv->search_alert); 1447 g_object_unref (priv->search_alert); 1448 } 1449 1450 static void 1451 cal_iterate_searching (ECalShellView *cal_shell_view) 1452 { 1453 ECalShellViewPrivate *priv; 1454 GList *clients, *iter; 1455 ECalModel *model; 1456 time_t new_time, range1, range2; 1457 icaltimezone *timezone; 1458 const gchar *default_tzloc = NULL; 1459 GCancellable *cancellable; 1460 gchar *sexp, *start, *end; 1461 1462 g_return_if_fail (cal_shell_view != NULL); 1463 g_return_if_fail (cal_shell_view->priv != NULL); 1464 1465 priv = cal_shell_view->priv; 1466 g_return_if_fail (priv->search_direction != 0); 1467 g_return_if_fail (priv->search_pending_count == 0); 1468 1469 cal_searching_update_alert (cal_shell_view, NULL); 1470 1471 if (cal_searching_check_candidates (cal_shell_view)) { 1472 if (priv->searching_activity) { 1473 e_activity_set_state ( 1474 priv->searching_activity, 1475 E_ACTIVITY_COMPLETED); 1476 g_object_unref (priv->searching_activity); 1477 priv->searching_activity = NULL; 1478 } 1479 1480 return; 1481 } 1482 1483 if (!priv->searching_activity) { 1484 EShellBackend *shell_backend; 1485 1486 shell_backend = e_shell_view_get_shell_backend ( 1487 E_SHELL_VIEW (cal_shell_view)); 1488 1489 cancellable = g_cancellable_new (); 1490 priv->searching_activity = e_activity_new (); 1491 e_activity_set_cancellable ( 1492 priv->searching_activity, cancellable); 1493 e_activity_set_state ( 1494 priv->searching_activity, E_ACTIVITY_RUNNING); 1495 e_activity_set_text ( 1496 priv->searching_activity, 1497 priv->search_direction > 0 ? 1498 _("Searching next matching event") : 1499 _("Searching previous matching event")); 1500 1501 e_shell_backend_add_activity ( 1502 shell_backend, priv->searching_activity); 1503 } 1504 1505 new_time = time_add_day (priv->search_time, priv->search_direction); 1506 if (new_time > priv->search_max_time || new_time < priv->search_min_time) { 1507 gchar *alert_msg; 1508 gint range_years; 1509 1510 /* would get out of bounds, stop searching */ 1511 e_activity_set_state ( 1512 priv->searching_activity, E_ACTIVITY_COMPLETED); 1513 g_object_unref (priv->searching_activity); 1514 priv->searching_activity = NULL; 1515 1516 range_years = cal_searching_get_search_range_years (cal_shell_view); 1517 alert_msg = g_strdup_printf ( 1518 priv->search_direction > 0 ? 1519 ngettext ( 1520 "Cannot find matching event in the next %d year", 1521 "Cannot find matching event in the next %d years", 1522 range_years) : 1523 ngettext ( 1524 "Cannot find matching event in the previous %d year", 1525 "Cannot find matching event in the previous %d years", 1526 range_years), 1527 range_years); 1528 cal_searching_update_alert (cal_shell_view, alert_msg); 1529 g_free (alert_msg); 1530 1531 e_shell_view_update_actions (E_SHELL_VIEW (cal_shell_view)); 1532 1533 return; 1534 } 1535 1536 model = gnome_calendar_get_model ( 1537 e_cal_shell_content_get_calendar ( 1538 cal_shell_view->priv->cal_shell_content)); 1539 clients = e_cal_model_get_client_list (model); 1540 1541 if (!clients) { 1542 e_activity_set_state ( 1543 priv->searching_activity, E_ACTIVITY_COMPLETED); 1544 g_object_unref (priv->searching_activity); 1545 priv->searching_activity = NULL; 1546 1547 cal_searching_update_alert ( 1548 cal_shell_view, 1549 _("Cannot search with no active calendar")); 1550 1551 e_shell_view_update_actions (E_SHELL_VIEW (cal_shell_view)); 1552 1553 return; 1554 } 1555 1556 timezone = e_cal_model_get_timezone (model); 1557 range1 = priv->search_time; 1558 range2 = time_add_day (range1, priv->search_direction); 1559 if (range1 < range2) { 1560 start = isodate_from_time_t (time_day_begin (range1)); 1561 end = isodate_from_time_t (time_day_end (range2)); 1562 } else { 1563 start = isodate_from_time_t (time_day_begin (range2)); 1564 end = isodate_from_time_t (time_day_end (range1)); 1565 } 1566 1567 if (timezone && timezone != icaltimezone_get_utc_timezone ()) 1568 default_tzloc = icaltimezone_get_location (timezone); 1569 if (!default_tzloc) 1570 default_tzloc = ""; 1571 1572 sexp = g_strdup_printf ( 1573 "(and %s (occur-in-time-range? " 1574 "(make-time \"%s\") " 1575 "(make-time \"%s\") \"%s\"))", 1576 e_cal_model_get_search_query (model), start, end, default_tzloc); 1577 1578 g_free (start); 1579 g_free (end); 1580 1581 cancellable = e_activity_get_cancellable (priv->searching_activity); 1582 g_list_foreach (clients, (GFunc) g_object_ref, NULL); 1583 priv->search_pending_count = g_list_length (clients); 1584 priv->search_time = new_time; 1585 1586 for (iter = clients; iter; iter = iter->next) { 1587 ECalClient *client = iter->data; 1588 1589 e_cal_client_get_object_list ( 1590 client, sexp, cancellable, 1591 cal_search_get_object_list_cb, cal_shell_view); 1592 } 1593 1594 g_list_free_full (clients, g_object_unref); 1595 g_free (sexp); 1596 } 1597 1598 void 1599 e_cal_shell_view_search_events (ECalShellView *cal_shell_view, 1600 gboolean search_forward) 1601 { 1602 ECalShellViewPrivate *priv = cal_shell_view->priv; 1603 ECalShellContent *cal_shell_content; 1604 GnomeCalendarViewType view_type; 1605 ECalendarView *calendar_view; 1606 GnomeCalendar *calendar; 1607 time_t start_time = 0; 1608 gint range_years; 1609 1610 if (priv->searching_activity || !priv->search_direction) 1611 e_cal_shell_view_search_stop (cal_shell_view); 1612 1613 cal_shell_content = cal_shell_view->priv->cal_shell_content; 1614 calendar = e_cal_shell_content_get_calendar (cal_shell_content); 1615 view_type = gnome_calendar_get_view (calendar); 1616 calendar_view = gnome_calendar_get_calendar_view (calendar, view_type); 1617 1618 if (!e_calendar_view_get_selected_time_range (calendar_view, &start_time, NULL)) { 1619 e_shell_view_update_actions (E_SHELL_VIEW (cal_shell_view)); 1620 return; 1621 } 1622 1623 start_time = time_day_begin (start_time); 1624 if (priv->search_direction) { 1625 time_t cached_start, cached_end, tmp; 1626 1627 cached_start = priv->search_time; 1628 cached_end = time_add_day ( 1629 cached_start, (-1) * priv->search_direction); 1630 1631 if (priv->search_direction > 0) { 1632 tmp = cached_start; 1633 cached_start = cached_end; 1634 cached_end = tmp; 1635 } 1636 1637 /* clear cached results if searching out of cached bounds */ 1638 if (start_time < cached_start || start_time > cached_end) 1639 e_cal_shell_view_search_stop (cal_shell_view); 1640 } 1641 1642 priv->search_direction = search_forward ? +30 : -30; 1643 1644 if (cal_searching_check_candidates (cal_shell_view)) 1645 return; 1646 1647 range_years = cal_searching_get_search_range_years (cal_shell_view); 1648 1649 priv->search_pending_count = 0; 1650 priv->search_time = start_time; 1651 priv->search_min_time = start_time - (range_years * 365 * 24 * 60 * 60); 1652 priv->search_max_time = start_time + (range_years * 365 * 24 * 60 * 60); 1653 1654 if (priv->search_min_time < 0) 1655 priv->search_min_time = 0; 1656 if (priv->search_hit_cache) { 1657 g_slist_free_full (priv->search_hit_cache, g_free); 1658 priv->search_hit_cache = NULL; 1659 } 1660 1661 cal_iterate_searching (cal_shell_view); 1662 } 1663 1664 void 1665 e_cal_shell_view_search_stop (ECalShellView *cal_shell_view) 1666 { 1667 ECalShellViewPrivate *priv; 1668 1669 g_return_if_fail (cal_shell_view != NULL); 1670 g_return_if_fail (cal_shell_view->priv != NULL); 1671 1672 priv = cal_shell_view->priv; 1673 1674 cal_searching_update_alert (cal_shell_view, NULL); 1675 1676 if (priv->searching_activity) { 1677 g_cancellable_cancel ( 1678 e_activity_get_cancellable (priv->searching_activity)); 1679 e_activity_set_state ( 1680 priv->searching_activity, E_ACTIVITY_CANCELLED); 1681 g_object_unref (priv->searching_activity); 1682 priv->searching_activity = NULL; 1683 } 1684 1685 if (priv->search_hit_cache) { 1686 g_slist_free_full (priv->search_hit_cache, g_free); 1687 priv->search_hit_cache = NULL; 1688 } 1689 1690 priv->search_direction = 0; 1691 }