evolution-3.6.4/calendar/gui/dialogs/schedule-page.c

Location Tool Test ID Function Issue
schedule-page.c:147:12 clang-analyzer Dereference of null pointer (loaded from field 'value')
schedule-page.c:147:12 clang-analyzer Dereference of null pointer (loaded from field 'value')
  1 /*
  2  * Evolution calendar - Scheduling page
  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  * Authors:
 19  *		Federico Mena-Quintero <federico@ximian.com>
 20  *      Miguel de Icaza <miguel@ximian.com>
 21  *      Seth Alves <alves@hungry.com>
 22  *      JP Rosevear <jpr@ximian.com>
 23  *
 24  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 25  *
 26  */
 27 
 28 #ifdef HAVE_CONFIG_H
 29 #include <config.h>
 30 #endif
 31 
 32 #include <gtk/gtk.h>
 33 #include <glib/gi18n.h>
 34 #include <e-util/e-util-private.h>
 35 #include <misc/e-dateedit.h>
 36 #include "../e-meeting-time-sel.h"
 37 #include "../itip-utils.h"
 38 #include "comp-editor-util.h"
 39 #include "e-delegate-dialog.h"
 40 #include "schedule-page.h"
 41 
 42 #define SCHEDULE_PAGE_GET_PRIVATE(obj) \
 43 	(G_TYPE_INSTANCE_GET_PRIVATE \
 44 	((obj), TYPE_SCHEDULE_PAGE, SchedulePagePrivate))
 45 
 46 /* Private part of the SchedulePage structure */
 47 struct _SchedulePagePrivate {
 48 	GtkBuilder *builder;
 49 
 50 	/* Widgets from the UI file */
 51 	GtkWidget *main;
 52 
 53 	/* Model */
 54 	EMeetingStore *model;
 55 
 56 	/* Selector */
 57 	EMeetingTimeSelector *sel;
 58 
 59 	/* The timezone we use. Note that we use the same timezone for the
 60 	 * start and end date. We convert the end date if it is passed in in
 61 	 * another timezone. */
 62 	icaltimezone *zone;
 63 };
 64 
 65 static void times_changed_cb (GtkWidget *widget, SchedulePage *spage);
 66 
 67 G_DEFINE_TYPE (SchedulePage, schedule_page, TYPE_COMP_EDITOR_PAGE)
 68 
 69 static void
 70 sensitize_widgets (SchedulePage *spage)
 71 {
 72 	SchedulePagePrivate *priv = spage->priv;
 73 	CompEditor *editor;
 74 	ECalClient *client;
 75 
 76 	editor = comp_editor_page_get_editor (COMP_EDITOR_PAGE (spage));
 77 	client = comp_editor_get_client (editor);
 78 
 79 	e_meeting_time_selector_set_read_only (
 80 		priv->sel, e_client_is_readonly (E_CLIENT (client)));
 81 }
 82 
 83 /* Set date/time */
 84 static void
 85 update_time (SchedulePage *spage,
 86              ECalComponentDateTime *start_date,
 87              ECalComponentDateTime *end_date)
 88 {
 89 	SchedulePagePrivate *priv = spage->priv;
 90 	CompEditor *editor;
 91 	struct icaltimetype start_tt, end_tt;
 92 	icaltimezone *start_zone = NULL, *end_zone = NULL;
 93 	ECalClient *client;
 94 	gboolean all_day;
 95 
 96 	editor = comp_editor_page_get_editor (COMP_EDITOR_PAGE (spage));
 97 	client = comp_editor_get_client (editor);
 98 
 99 	if (start_date->tzid) {
100 		/* Note that if we are creating a new event, the timezones may not be
101 		 * on the server, so we try to get the builtin timezone with the TZID
102 		 * first. */
103 		start_zone = icaltimezone_get_builtin_timezone_from_tzid (start_date->tzid);
104 		if (!start_zone) {
105 			GError *error = NULL;
106 
107 			e_cal_client_get_timezone_sync (
108 				client, start_date->tzid,
109 				&start_zone, NULL, &error);
110 
111 			if (error != NULL) {
112 				/* FIXME: Handle error better. */
113 				g_warning (
114 					"Couldn't get timezone '%s' from server: %s",
115 					start_date->tzid ? start_date->tzid : "",
116 					error->message);
117 				g_error_free (error);
118 			}
119 		}
120 	}
121 
122 	if (end_date->tzid) {
123 		end_zone = icaltimezone_get_builtin_timezone_from_tzid (end_date->tzid);
124 		if (!end_zone) {
125 			GError *error = NULL;
126 
127 			e_cal_client_get_timezone_sync (
128 				client, end_date->tzid,
129 				&end_zone, NULL, &error);
130 
131 			if (error != NULL) {
132 				/* FIXME: Handle error better. */
133 				g_warning (
134 					"Couldn't get timezone '%s' from server: %s",
135 					end_date->tzid ? end_date->tzid : "",
136 					error->message);
137 				g_error_free (error);
138 			}
139 		}
140 	}
141 
142 	start_tt = *start_date->value;
143 	if (!end_date->value && start_tt.is_date) {
144 		end_tt = start_tt;
145 		icaltime_adjust (&end_tt, 1, 0, 0, 0);
146 	} else {
147 		end_tt = *end_date->value;
Dereference of null pointer (loaded from field 'value')
(emitted by clang-analyzer)

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

Dereference of null pointer (loaded from field 'value')
(emitted by clang-analyzer)

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

148 } 149 150 /* If the end zone is not the same as the start zone, we convert it. */ 151 priv->zone = start_zone; 152 if (start_zone != end_zone) { 153 icaltimezone_convert_time (&end_tt, end_zone, start_zone); 154 } 155 e_meeting_store_set_timezone (priv->model, priv->zone); 156 157 all_day = (start_tt.is_date && end_tt.is_date) ? TRUE : FALSE; 158 159 /* For All Day Events, if DTEND is after DTSTART, we subtract 1 day 160 * from it. */ 161 if (all_day) { 162 if (icaltime_compare_date_only (end_tt, start_tt) > 0) { 163 icaltime_adjust (&end_tt, -1, 0, 0, 0); 164 } 165 } 166 167 e_date_edit_set_date ( 168 E_DATE_EDIT (priv->sel->start_date_edit), start_tt.year, 169 start_tt.month, start_tt.day); 170 e_date_edit_set_time_of_day ( 171 E_DATE_EDIT (priv->sel->start_date_edit), 172 start_tt.hour, start_tt.minute); 173 174 e_date_edit_set_date ( 175 E_DATE_EDIT (priv->sel->end_date_edit), end_tt.year, 176 end_tt.month, end_tt.day); 177 e_date_edit_set_time_of_day ( 178 E_DATE_EDIT (priv->sel->end_date_edit), 179 end_tt.hour, end_tt.minute); 180 181 } 182 183 static void 184 schedule_page_dispose (GObject *object) 185 { 186 SchedulePagePrivate *priv; 187 188 priv = SCHEDULE_PAGE_GET_PRIVATE (object); 189 190 if (priv->main != NULL) { 191 g_object_unref (priv->main); 192 priv->main = NULL; 193 } 194 195 if (priv->builder != NULL) { 196 g_object_unref (priv->builder); 197 priv->builder = NULL; 198 } 199 200 if (priv->model != NULL) { 201 g_object_unref (priv->model); 202 priv->model = NULL; 203 } 204 205 /* Chain up to parent's dispose() method. */ 206 G_OBJECT_CLASS (schedule_page_parent_class)->dispose (object); 207 } 208 209 static GtkWidget * 210 schedule_page_get_widget (CompEditorPage *page) 211 { 212 SchedulePage *spage; 213 SchedulePagePrivate *priv; 214 215 spage = SCHEDULE_PAGE (page); 216 priv = spage->priv; 217 218 return priv->main; 219 } 220 221 static void 222 schedule_page_focus_main_widget (CompEditorPage *page) 223 { 224 SchedulePage *spage; 225 SchedulePagePrivate *priv; 226 227 spage = SCHEDULE_PAGE (page); 228 priv = spage->priv; 229 230 gtk_widget_grab_focus (GTK_WIDGET (priv->sel)); 231 } 232 233 static gboolean 234 schedule_page_fill_widgets (CompEditorPage *page, 235 ECalComponent *comp) 236 { 237 SchedulePage *spage; 238 ECalComponentDateTime start_date, end_date; 239 gboolean validated = TRUE; 240 241 spage = SCHEDULE_PAGE (page); 242 243 /* Start and end times */ 244 e_cal_component_get_dtstart (comp, &start_date); 245 e_cal_component_get_dtend (comp, &end_date); 246 if (!start_date.value) 247 validated = FALSE; 248 else if (!end_date.value) 249 validated = FALSE; 250 else 251 update_time (spage, &start_date, &end_date); 252 253 e_cal_component_free_datetime (&start_date); 254 e_cal_component_free_datetime (&end_date); 255 256 sensitize_widgets (spage); 257 258 return validated; 259 } 260 261 static gboolean 262 schedule_page_fill_component (CompEditorPage *page, 263 ECalComponent *comp) 264 { 265 return TRUE; 266 } 267 268 static void 269 schedule_page_set_dates (CompEditorPage *page, 270 CompEditorPageDates *dates) 271 { 272 SchedulePage *spage; 273 274 spage = SCHEDULE_PAGE (page); 275 276 comp_editor_page_set_updating (page, TRUE); 277 update_time (spage, dates->start, dates->end); 278 comp_editor_page_set_updating (page, FALSE); 279 } 280 281 static void 282 schedule_page_class_init (SchedulePageClass *class) 283 { 284 GObjectClass *object_class; 285 CompEditorPageClass *editor_page_class; 286 287 g_type_class_add_private (class, sizeof (SchedulePagePrivate)); 288 289 object_class = G_OBJECT_CLASS (class); 290 object_class->dispose = schedule_page_dispose; 291 292 editor_page_class = COMP_EDITOR_PAGE_CLASS (class); 293 editor_page_class->get_widget = schedule_page_get_widget; 294 editor_page_class->focus_main_widget = schedule_page_focus_main_widget; 295 editor_page_class->fill_widgets = schedule_page_fill_widgets; 296 editor_page_class->fill_component = schedule_page_fill_component; 297 editor_page_class->set_dates = schedule_page_set_dates; 298 } 299 300 static void 301 schedule_page_init (SchedulePage *spage) 302 { 303 spage->priv = SCHEDULE_PAGE_GET_PRIVATE (spage); 304 } 305 306 /* Gets the widgets from the XML file and returns if they are all available. */ 307 static gboolean 308 get_widgets (SchedulePage *spage) 309 { 310 CompEditorPage *page = COMP_EDITOR_PAGE (spage); 311 SchedulePagePrivate *priv; 312 GSList *accel_groups; 313 GtkWidget *toplevel; 314 GtkWidget *parent; 315 316 priv = spage->priv; 317 318 #define GW(name) e_builder_get_widget (priv->builder, name) 319 320 priv->main = GW ("schedule-page"); 321 if (!priv->main) 322 return FALSE; 323 324 /* Get the GtkAccelGroup from the toplevel window, so we can install 325 * it when the notebook page is mapped. */ 326 toplevel = gtk_widget_get_toplevel (priv->main); 327 accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel)); 328 if (accel_groups) 329 page->accel_group = g_object_ref (accel_groups->data); 330 331 g_object_ref (priv->main); 332 parent = gtk_widget_get_parent (priv->main); 333 gtk_container_remove (GTK_CONTAINER (parent), priv->main); 334 335 #undef GW 336 337 return TRUE; 338 } 339 340 static gboolean 341 init_widgets (SchedulePage *spage) 342 { 343 SchedulePagePrivate *priv; 344 345 priv = spage->priv; 346 347 g_signal_connect ( 348 priv->sel, "changed", 349 G_CALLBACK (times_changed_cb), spage); 350 351 return TRUE; 352 } 353 354 void 355 schedule_page_set_meeting_time (SchedulePage *spage, 356 icaltimetype *start_tt, 357 icaltimetype *end_tt) 358 { 359 SchedulePagePrivate *priv; 360 gboolean all_day; 361 362 priv = spage->priv; 363 364 all_day = (start_tt->is_date && end_tt->is_date) ? TRUE : FALSE; 365 366 if (all_day) { 367 if (icaltime_compare_date_only (*end_tt, *start_tt) > 0) { 368 icaltime_adjust (end_tt, -1, 0, 0, 0); 369 } 370 } 371 372 e_meeting_time_selector_set_meeting_time ( 373 priv->sel, start_tt->year, start_tt->month, 374 start_tt->day, start_tt->hour, start_tt->minute, 375 end_tt->year, end_tt->month, end_tt->day, 376 end_tt->hour, end_tt->minute); 377 e_meeting_time_selector_set_all_day (priv->sel, all_day); 378 379 } 380 381 /** 382 * schedule_page_construct: 383 * @spage: An schedule page. 384 * 385 * Constructs an schedule page by loading its Glade data. 386 * 387 * Return value: The same object as @spage, or NULL if the widgets could not 388 * be created. 389 **/ 390 SchedulePage * 391 schedule_page_construct (SchedulePage *spage, 392 EMeetingStore *ems) 393 { 394 SchedulePagePrivate *priv = spage->priv; 395 CompEditor *editor; 396 397 editor = comp_editor_page_get_editor (COMP_EDITOR_PAGE (spage)); 398 399 priv->builder = gtk_builder_new (); 400 e_load_ui_builder_definition (priv->builder, "schedule-page.ui"); 401 402 if (!get_widgets (spage)) { 403 g_message ( 404 "schedule_page_construct(): " 405 "Could not find all widgets in the XML file!"); 406 return NULL; 407 } 408 409 /* Model */ 410 g_object_ref (ems); 411 priv->model = ems; 412 413 /* Selector */ 414 priv->sel = E_MEETING_TIME_SELECTOR (e_meeting_time_selector_new (ems)); 415 gtk_widget_set_size_request ((GtkWidget *) priv->sel, -1, 400); 416 e_meeting_time_selector_set_working_hours ( 417 priv->sel, 418 comp_editor_get_work_day_start_hour (editor), 419 comp_editor_get_work_day_start_minute (editor), 420 comp_editor_get_work_day_end_hour (editor), 421 comp_editor_get_work_day_end_minute (editor)); 422 gtk_widget_show (GTK_WIDGET (priv->sel)); 423 gtk_box_pack_start (GTK_BOX (priv->main), GTK_WIDGET (priv->sel), TRUE, TRUE, 6); 424 425 if (!init_widgets (spage)) { 426 g_message ( 427 "schedule_page_construct(): " 428 "Could not initialize the widgets!"); 429 return NULL; 430 } 431 432 g_signal_connect_swapped ( 433 editor, "notify::client", 434 G_CALLBACK (sensitize_widgets), spage); 435 436 return spage; 437 } 438 439 /** 440 * schedule_page_new: 441 * 442 * Creates a new schedule page. 443 * 444 * Return value: A newly-created schedule page, or NULL if the page could 445 * not be created. 446 **/ 447 SchedulePage * 448 schedule_page_new (EMeetingStore *ems, 449 CompEditor *editor) 450 { 451 SchedulePage *spage; 452 453 spage = g_object_new (TYPE_SCHEDULE_PAGE, "editor", editor, NULL); 454 if (!schedule_page_construct (spage, ems)) { 455 g_object_unref (spage); 456 g_return_val_if_reached (NULL); 457 } 458 459 return spage; 460 } 461 462 void 463 schedule_page_update_free_busy (SchedulePage *spage) 464 { 465 SchedulePagePrivate *priv; 466 467 g_return_if_fail (spage != NULL); 468 g_return_if_fail (IS_SCHEDULE_PAGE (spage)); 469 470 priv = spage->priv; 471 472 e_meeting_time_selector_refresh_free_busy (priv->sel, 0, TRUE); 473 } 474 475 void 476 schedule_page_set_name_selector (SchedulePage *spage, 477 ENameSelector *name_selector) 478 { 479 SchedulePagePrivate *priv; 480 481 g_return_if_fail (spage != NULL); 482 g_return_if_fail (IS_SCHEDULE_PAGE (spage)); 483 484 priv = spage->priv; 485 486 e_meeting_list_view_set_name_selector (priv->sel->list_view, name_selector); 487 } 488 489 static void 490 times_changed_cb (GtkWidget *widget, 491 SchedulePage *spage) 492 { 493 SchedulePagePrivate *priv; 494 CompEditorPageDates dates; 495 CompEditor *editor; 496 ECalComponentDateTime start_dt, end_dt; 497 struct icaltimetype start_tt = icaltime_null_time (); 498 struct icaltimetype end_tt = icaltime_null_time (); 499 500 priv = spage->priv; 501 502 if (comp_editor_page_get_updating (COMP_EDITOR_PAGE (spage))) 503 return; 504 505 editor = comp_editor_page_get_editor (COMP_EDITOR_PAGE (spage)); 506 507 e_date_edit_get_date ( 508 E_DATE_EDIT (priv->sel->start_date_edit), 509 &start_tt.year, 510 &start_tt.month, 511 &start_tt.day); 512 e_date_edit_get_time_of_day ( 513 E_DATE_EDIT (priv->sel->start_date_edit), 514 &start_tt.hour, 515 &start_tt.minute); 516 e_date_edit_get_date ( 517 E_DATE_EDIT (priv->sel->end_date_edit), 518 &end_tt.year, 519 &end_tt.month, 520 &end_tt.day); 521 e_date_edit_get_time_of_day ( 522 E_DATE_EDIT (priv->sel->end_date_edit), 523 &end_tt.hour, 524 &end_tt.minute); 525 526 start_dt.value = &start_tt; 527 end_dt.value = &end_tt; 528 529 if (e_date_edit_get_show_time (E_DATE_EDIT (priv->sel->start_date_edit))) { 530 /* We set the start and end to the same timezone. */ 531 start_dt.tzid = icaltimezone_get_tzid (priv->zone); 532 end_dt.tzid = start_dt.tzid; 533 } else { 534 /* For All-Day Events, we set the timezone to NULL, and add 535 * 1 day to DTEND. */ 536 start_dt.value->is_date = TRUE; 537 start_dt.tzid = NULL; 538 end_dt.value->is_date = TRUE; 539 icaltime_adjust (&end_tt, 1, 0, 0, 0); 540 end_dt.tzid = NULL; 541 } 542 543 dates.start = &start_dt; 544 dates.end = &end_dt; 545 dates.due = NULL; 546 dates.complete = NULL; 547 548 comp_editor_page_notify_dates_changed (COMP_EDITOR_PAGE (spage), &dates); 549 comp_editor_set_changed (editor, TRUE); 550 }