evolution-3.6.4/shell/e-shell-window.c

No issues found

   1 /*
   2  * e-shell-window.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 /**
  23  * SECTION: e-shell-window
  24  * @short_description: the main window
  25  * @include: shell/e-shell-window.h
  26  **/
  27 
  28 #ifdef HAVE_CONFIG_H
  29 #include <config.h>
  30 #endif
  31 
  32 #include "e-shell-window-private.h"
  33 
  34 enum {
  35 	PROP_0,
  36 	PROP_ACTIVE_VIEW,
  37 	PROP_ALERT_BAR,
  38 	PROP_FOCUS_TRACKER,
  39 	PROP_GEOMETRY,
  40 	PROP_SAFE_MODE,
  41 	PROP_SHELL,
  42 	PROP_SIDEBAR_VISIBLE,
  43 	PROP_SWITCHER_VISIBLE,
  44 	PROP_TASKBAR_VISIBLE,
  45 	PROP_TOOLBAR_VISIBLE,
  46 	PROP_UI_MANAGER
  47 };
  48 
  49 enum {
  50 	SHELL_VIEW_CREATED,
  51 	LAST_SIGNAL
  52 };
  53 
  54 static gulong signals[LAST_SIGNAL];
  55 
  56 /* Forward Declarations */
  57 static void	e_shell_window_alert_sink_init
  58 					(EAlertSinkInterface *interface);
  59 
  60 G_DEFINE_TYPE_WITH_CODE (
  61 	EShellWindow,
  62 	e_shell_window,
  63 	GTK_TYPE_WINDOW,
  64 	G_IMPLEMENT_INTERFACE (
  65 		E_TYPE_ALERT_SINK, e_shell_window_alert_sink_init)
  66 	G_IMPLEMENT_INTERFACE (
  67 		E_TYPE_EXTENSIBLE, NULL))
  68 
  69 static void
  70 shell_window_menubar_update_new_menu (EShellWindow *shell_window)
  71 {
  72 	GtkWidget *menu;
  73 	GtkWidget *widget;
  74 	const gchar *path;
  75 
  76 	/* Update the "File -> New" submenu. */
  77 	path = "/main-menu/file-menu/new-menu";
  78 	menu = e_shell_window_create_new_menu (shell_window);
  79 	widget = e_shell_window_get_managed_widget (shell_window, path);
  80 	gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), menu);
  81 	gtk_widget_show (widget);
  82 }
  83 
  84 static void	shell_window_backend_prefer_item_changed_cb
  85 						(EShellBackend *backend,
  86 						 GParamSpec *pspec,
  87 						 EShellWindow *shell_window);
  88 
  89 static void
  90 shell_window_toolbar_update_new_menu (EShellWindow *shell_window,
  91                                       GParamSpec *pspec,
  92                                       GtkMenuToolButton *menu_tool_button)
  93 {
  94 	GtkWidget *menu;
  95 
  96 	/* Update the "New" menu tool button submenu. */
  97 	menu = e_shell_window_create_new_menu (shell_window);
  98 	gtk_menu_tool_button_set_menu (menu_tool_button, menu);
  99 
 100 	if (pspec && g_strcmp0 (pspec->name, "active-view") == 0) {
 101 		EShellView *shell_view;
 102 		EShellBackend *shell_backend;
 103 
 104 		shell_view = e_shell_window_peek_shell_view (
 105 			shell_window,
 106 			e_shell_window_get_active_view (shell_window));
 107 		g_return_if_fail (shell_view != NULL);
 108 
 109 		shell_backend = e_shell_view_get_shell_backend (shell_view);
 110 
 111 		g_signal_handlers_disconnect_by_func (
 112 			shell_backend,
 113 			shell_window_backend_prefer_item_changed_cb,
 114 			shell_window);
 115 
 116 		g_signal_connect (
 117 			shell_backend, "notify::prefer-new-item",
 118 			G_CALLBACK (shell_window_backend_prefer_item_changed_cb),
 119 			shell_window);
 120 
 121 		shell_window_backend_prefer_item_changed_cb (
 122 			shell_backend, NULL, shell_window);
 123 	}
 124 }
 125 
 126 static void
 127 shell_window_backend_prefer_item_changed_cb (EShellBackend *backend,
 128                                              GParamSpec *pspec,
 129                                              EShellWindow *shell_window)
 130 {
 131 	EShellView *shell_view;
 132 	EShellBackend *shell_backend;
 133 
 134 	shell_view = e_shell_window_peek_shell_view (
 135 		shell_window,
 136 		e_shell_window_get_active_view (shell_window));
 137 	g_return_if_fail (shell_view != NULL);
 138 
 139 	shell_backend = e_shell_view_get_shell_backend (shell_view);
 140 	if (shell_backend != backend)
 141 		return;
 142 
 143 	e_shell_window_set_toolbar_new_prefer_item (
 144 		shell_window,
 145 		e_shell_backend_get_prefer_new_item (shell_backend));
 146 }
 147 
 148 static void
 149 shell_window_set_notebook_page (EShellWindow *shell_window,
 150                                 GParamSpec *pspec,
 151                                 GtkNotebook *notebook)
 152 {
 153 	EShellView *shell_view;
 154 	const gchar *view_name;
 155 	gint page_num;
 156 
 157 	view_name = e_shell_window_get_active_view (shell_window);
 158 	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
 159 
 160 	page_num = e_shell_view_get_page_num (shell_view);
 161 	g_return_if_fail (page_num >= 0);
 162 
 163 	gtk_notebook_set_current_page (notebook, page_num);
 164 }
 165 
 166 static void
 167 shell_window_online_button_clicked_cb (EOnlineButton *button,
 168                                        EShellWindow *shell_window)
 169 {
 170 	if (e_online_button_get_online (button))
 171 		gtk_action_activate (ACTION (WORK_OFFLINE));
 172 	else
 173 		gtk_action_activate (ACTION (WORK_ONLINE));
 174 }
 175 
 176 static void
 177 shell_window_update_close_action_cb (EShellWindow *shell_window)
 178 {
 179 	EShell *shell;
 180 	GtkApplication *application;
 181 	GList *list;
 182 	gint n_shell_windows = 0;
 183 
 184 	shell = e_shell_window_get_shell (shell_window);
 185 
 186 	application = GTK_APPLICATION (shell);
 187 	list = gtk_application_get_windows (application);
 188 
 189 	/* Count the shell windows. */
 190 	while (list != NULL) {
 191 		if (E_IS_SHELL_WINDOW (list->data))
 192 			n_shell_windows++;
 193 		list = g_list_next (list);
 194 	}
 195 
 196 	/* Disable Close Window if there's only one shell window.
 197 	 * Helps prevent users from accidentally quitting. */
 198 	gtk_action_set_sensitive (ACTION (CLOSE), n_shell_windows > 1);
 199 }
 200 
 201 static void
 202 shell_window_set_geometry (EShellWindow *shell_window,
 203                            const gchar *geometry)
 204 {
 205 	g_return_if_fail (shell_window->priv->geometry == NULL);
 206 
 207 	shell_window->priv->geometry = g_strdup (geometry);
 208 }
 209 
 210 static void
 211 shell_window_set_shell (EShellWindow *shell_window,
 212                         EShell *shell)
 213 {
 214 	GArray *array;
 215 	gulong handler_id;
 216 
 217 	g_return_if_fail (shell_window->priv->shell == NULL);
 218 
 219 	shell_window->priv->shell = shell;
 220 
 221 	g_object_add_weak_pointer (
 222 		G_OBJECT (shell), &shell_window->priv->shell);
 223 
 224 	/* Need to disconnect these when the window is closing. */
 225 
 226 	array = shell_window->priv->signal_handler_ids;
 227 
 228 	handler_id = g_signal_connect_swapped (
 229 		shell, "window-added",
 230 		G_CALLBACK (shell_window_update_close_action_cb),
 231 		shell_window);
 232 
 233 	g_array_append_val (array, handler_id);
 234 
 235 	handler_id = g_signal_connect_swapped (
 236 		shell, "window-removed",
 237 		G_CALLBACK (shell_window_update_close_action_cb),
 238 		shell_window);
 239 
 240 	g_array_append_val (array, handler_id);
 241 
 242 	g_object_notify (G_OBJECT (shell), "online");
 243 }
 244 
 245 static void
 246 shell_window_set_property (GObject *object,
 247                            guint property_id,
 248                            const GValue *value,
 249                            GParamSpec *pspec)
 250 {
 251 	switch (property_id) {
 252 		case PROP_ACTIVE_VIEW:
 253 			e_shell_window_set_active_view (
 254 				E_SHELL_WINDOW (object),
 255 				g_value_get_string (value));
 256 			return;
 257 
 258 		case PROP_GEOMETRY:
 259 			shell_window_set_geometry (
 260 				E_SHELL_WINDOW (object),
 261 				g_value_get_string (value));
 262 			return;
 263 
 264 		case PROP_SAFE_MODE:
 265 			e_shell_window_set_safe_mode (
 266 				E_SHELL_WINDOW (object),
 267 				g_value_get_boolean (value));
 268 			return;
 269 
 270 		case PROP_SHELL:
 271 			shell_window_set_shell (
 272 				E_SHELL_WINDOW (object),
 273 				g_value_get_object (value));
 274 			return;
 275 
 276 		case PROP_SIDEBAR_VISIBLE:
 277 			e_shell_window_set_sidebar_visible (
 278 				E_SHELL_WINDOW (object),
 279 				g_value_get_boolean (value));
 280 			return;
 281 
 282 		case PROP_SWITCHER_VISIBLE:
 283 			e_shell_window_set_switcher_visible (
 284 				E_SHELL_WINDOW (object),
 285 				g_value_get_boolean (value));
 286 			return;
 287 
 288 		case PROP_TASKBAR_VISIBLE:
 289 			e_shell_window_set_taskbar_visible (
 290 				E_SHELL_WINDOW (object),
 291 				g_value_get_boolean (value));
 292 			return;
 293 
 294 		case PROP_TOOLBAR_VISIBLE:
 295 			e_shell_window_set_toolbar_visible (
 296 				E_SHELL_WINDOW (object),
 297 				g_value_get_boolean (value));
 298 			return;
 299 	}
 300 
 301 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 302 }
 303 
 304 static void
 305 shell_window_get_property (GObject *object,
 306                            guint property_id,
 307                            GValue *value,
 308                            GParamSpec *pspec)
 309 {
 310 	switch (property_id) {
 311 		case PROP_ACTIVE_VIEW:
 312 			g_value_set_string (
 313 				value, e_shell_window_get_active_view (
 314 				E_SHELL_WINDOW (object)));
 315 			return;
 316 
 317 		case PROP_ALERT_BAR:
 318 			g_value_set_object (
 319 				value, e_shell_window_get_alert_bar (
 320 				E_SHELL_WINDOW (object)));
 321 			return;
 322 
 323 		case PROP_FOCUS_TRACKER:
 324 			g_value_set_object (
 325 				value, e_shell_window_get_focus_tracker (
 326 				E_SHELL_WINDOW (object)));
 327 			return;
 328 
 329 		case PROP_SAFE_MODE:
 330 			g_value_set_boolean (
 331 				value, e_shell_window_get_safe_mode (
 332 				E_SHELL_WINDOW (object)));
 333 			return;
 334 
 335 		case PROP_SHELL:
 336 			g_value_set_object (
 337 				value, e_shell_window_get_shell (
 338 				E_SHELL_WINDOW (object)));
 339 			return;
 340 
 341 		case PROP_SIDEBAR_VISIBLE:
 342 			g_value_set_boolean (
 343 				value, e_shell_window_get_sidebar_visible (
 344 				E_SHELL_WINDOW (object)));
 345 			return;
 346 
 347 		case PROP_SWITCHER_VISIBLE:
 348 			g_value_set_boolean (
 349 				value, e_shell_window_get_switcher_visible (
 350 				E_SHELL_WINDOW (object)));
 351 			return;
 352 
 353 		case PROP_TASKBAR_VISIBLE:
 354 			g_value_set_boolean (
 355 				value, e_shell_window_get_taskbar_visible (
 356 				E_SHELL_WINDOW (object)));
 357 			return;
 358 
 359 		case PROP_TOOLBAR_VISIBLE:
 360 			g_value_set_boolean (
 361 				value, e_shell_window_get_toolbar_visible (
 362 				E_SHELL_WINDOW (object)));
 363 			return;
 364 
 365 		case PROP_UI_MANAGER:
 366 			g_value_set_object (
 367 				value, e_shell_window_get_ui_manager (
 368 				E_SHELL_WINDOW (object)));
 369 			return;
 370 	}
 371 
 372 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 373 }
 374 
 375 static void
 376 shell_window_dispose (GObject *object)
 377 {
 378 	e_shell_window_private_dispose (E_SHELL_WINDOW (object));
 379 
 380 	/* Chain up to parent's dispose() method. */
 381 	G_OBJECT_CLASS (e_shell_window_parent_class)->dispose (object);
 382 }
 383 
 384 static void
 385 shell_window_finalize (GObject *object)
 386 {
 387 	e_shell_window_private_finalize (E_SHELL_WINDOW (object));
 388 
 389 	/* Chain up to parent's finalize() method. */
 390 	G_OBJECT_CLASS (e_shell_window_parent_class)->finalize (object);
 391 }
 392 
 393 static void
 394 shell_window_constructed (GObject *object)
 395 {
 396 	EShellWindow *shell_window = E_SHELL_WINDOW (object);
 397 
 398 	e_shell_window_private_constructed (shell_window);
 399 
 400 	e_extensible_load_extensions (E_EXTENSIBLE (object));
 401 
 402 	if (e_shell_get_meego_mode (shell_window->priv->shell) &&
 403 	    e_shell_get_small_screen_mode (shell_window->priv->shell))
 404 		gtk_window_set_decorated (GTK_WINDOW (object), FALSE);
 405 
 406 	/* Chain up to parent's constructed() method. */
 407 	G_OBJECT_CLASS (e_shell_window_parent_class)->constructed (object);
 408 }
 409 
 410 static GtkWidget *
 411 shell_window_construct_menubar (EShellWindow *shell_window)
 412 {
 413 	GtkWidget *main_menu;
 414 
 415 	main_menu = e_shell_window_get_managed_widget (
 416 		shell_window, "/main-menu");
 417 	gtk_widget_show (main_menu);
 418 
 419 	if (e_shell_get_small_screen_mode (shell_window->priv->shell)) {
 420 		GtkWidget *parent, *child;
 421 
 422 		parent = gtk_widget_get_parent (main_menu);
 423 		g_object_ref (parent);
 424 		gtk_container_remove ((GtkContainer *) parent, main_menu);
 425 		child = gtk_hbox_new (FALSE, 0);
 426 		gtk_box_pack_start ((GtkBox *) child, main_menu, TRUE, TRUE, 0);
 427 		gtk_widget_show (child);
 428 		gtk_container_add ((GtkContainer *) parent, child);
 429 		shell_window->priv->menubar_box = child;
 430 
 431 		g_object_bind_property (
 432 			main_menu, "visible",
 433 			child, "visible",
 434 			G_BINDING_BIDIRECTIONAL |
 435 			G_BINDING_SYNC_CREATE);
 436 
 437 		main_menu = child;
 438 	}
 439 
 440 	g_signal_connect (
 441 		shell_window, "notify::active-view",
 442 		G_CALLBACK (shell_window_menubar_update_new_menu), NULL);
 443 
 444 	return main_menu;
 445 }
 446 
 447 GtkWidget *
 448 e_shell_window_get_menu_bar_box (EShellWindow *shell_window)
 449 {
 450 	return shell_window->priv->menubar_box;
 451 }
 452 
 453 static GtkWidget *
 454 shell_window_construct_toolbar (EShellWindow *shell_window)
 455 {
 456 	EShell *shell;
 457 	GtkUIManager *ui_manager;
 458 	GtkWidget *toolbar;
 459 	GtkWidget *box;
 460 	GtkToolItem *item;
 461 
 462 	shell = e_shell_window_get_shell (shell_window);
 463 	ui_manager = e_shell_window_get_ui_manager (shell_window);
 464 
 465 	box = gtk_hbox_new (FALSE, 0);
 466 	gtk_widget_show (box);
 467 
 468 	g_object_bind_property (
 469 		shell_window, "toolbar-visible",
 470 		box, "visible",
 471 		G_BINDING_SYNC_CREATE);
 472 
 473 	toolbar = e_shell_window_get_managed_widget (
 474 		shell_window, "/main-toolbar");
 475 
 476 	gtk_style_context_add_class (
 477 		gtk_widget_get_style_context (toolbar),
 478 		GTK_STYLE_CLASS_PRIMARY_TOOLBAR);
 479 
 480 	if (e_shell_get_meego_mode (shell))
 481 		 gtk_widget_set_name (GTK_WIDGET (toolbar), "MeeGoToolbar");
 482 
 483 	/* XXX Having this separator in the UI definition doesn't work
 484 	 *     because GtkUIManager is unaware of the "New" button, so
 485 	 *     it makes the separator invisible.  One possibility is to
 486 	 *     define a GtkAction subclass for which create_tool_item()
 487 	 *     return an EMenuToolButton.  Then both this separator
 488 	 *     and the "New" button could be added to the UI definition.
 489 	 *     Tempting, but the "New" button and its dynamically
 490 	 *     generated menu is already a complex beast, and I'm not
 491 	 *     convinced having it proxy some new type of GtkAction
 492 	 *     is worth the extra effort. */
 493 	item = gtk_separator_tool_item_new ();
 494 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 0);
 495 	gtk_widget_show (GTK_WIDGET (item));
 496 
 497 	item = e_menu_tool_button_new (_("New"));
 498 	gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), TRUE);
 499 	gtk_widget_add_accelerator (
 500 		GTK_WIDGET (item), "clicked",
 501 		gtk_ui_manager_get_accel_group (ui_manager),
 502 		GDK_KEY_N, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
 503 	gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 0);
 504 	gtk_widget_show (GTK_WIDGET (item));
 505 
 506 	g_signal_connect (
 507 		shell_window, "notify::active-view",
 508 		G_CALLBACK (shell_window_toolbar_update_new_menu),
 509 		GTK_MENU_TOOL_BUTTON (item));
 510 
 511 	g_signal_connect_swapped (
 512 		item, "notify::prefer-item",
 513 		G_CALLBACK (shell_window_toolbar_update_new_menu),
 514 		shell_window);
 515 
 516 	gtk_box_pack_start (GTK_BOX (box), toolbar, TRUE, TRUE, 0);
 517 
 518 	toolbar = e_shell_window_get_managed_widget (
 519 		shell_window, "/search-toolbar");
 520 	gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
 521 	if (e_shell_get_express_mode (shell))
 522 		gtk_box_pack_start (GTK_BOX (box), toolbar, FALSE, FALSE, 0);
 523 	if (e_shell_get_meego_mode (shell))
 524 		gtk_widget_set_name (GTK_WIDGET (toolbar), "MeeGoToolbar");
 525 
 526 	toolbar = e_shell_window_get_managed_widget (
 527 		shell_window, "/close-toolbar");
 528 	gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
 529 	if (e_shell_get_meego_mode (shell))
 530 		gtk_box_pack_start (GTK_BOX (box), toolbar, FALSE, FALSE, 0);
 531 	if (e_shell_get_meego_mode (shell))
 532 		gtk_widget_set_name (GTK_WIDGET (toolbar), "MeeGoToolbar");
 533 
 534 	return box;
 535 }
 536 
 537 static GtkWidget *
 538 shell_window_construct_sidebar (EShellWindow *shell_window)
 539 {
 540 	GtkWidget *notebook;
 541 	GtkWidget *switcher;
 542 
 543 	switcher = e_shell_switcher_new ();
 544 	shell_window->priv->switcher = g_object_ref_sink (switcher);
 545 
 546 	g_object_bind_property (
 547 		shell_window, "sidebar-visible",
 548 		switcher, "visible",
 549 		G_BINDING_SYNC_CREATE);
 550 
 551 	g_object_bind_property (
 552 		shell_window, "switcher-visible",
 553 		switcher, "toolbar-visible",
 554 		G_BINDING_SYNC_CREATE);
 555 
 556 	notebook = gtk_notebook_new ();
 557 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
 558 	gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
 559 	gtk_container_add (GTK_CONTAINER (switcher), notebook);
 560 	shell_window->priv->sidebar_notebook = g_object_ref (notebook);
 561 	gtk_widget_show (notebook);
 562 
 563 	g_signal_connect (
 564 		shell_window, "notify::active-view",
 565 		G_CALLBACK (shell_window_set_notebook_page), notebook);
 566 
 567 	return switcher;
 568 }
 569 
 570 static GtkWidget *
 571 shell_window_construct_content (EShellWindow *shell_window)
 572 {
 573 	GtkWidget *box;
 574 	GtkWidget *widget;
 575 
 576 	box = gtk_vbox_new (FALSE, 0);
 577 	gtk_widget_show (box);
 578 
 579 	widget = e_alert_bar_new ();
 580 	gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0);
 581 	shell_window->priv->alert_bar = g_object_ref (widget);
 582 	/* EAlertBar controls its own visibility. */
 583 
 584 	widget = gtk_notebook_new ();
 585 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE);
 586 	gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE);
 587 	gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0);
 588 	shell_window->priv->content_notebook = g_object_ref (widget);
 589 	gtk_widget_show (widget);
 590 
 591 	g_signal_connect (
 592 		shell_window, "notify::active-view",
 593 		G_CALLBACK (shell_window_set_notebook_page), widget);
 594 
 595 	return box;
 596 }
 597 
 598 static GtkWidget *
 599 shell_window_construct_taskbar (EShellWindow *shell_window)
 600 {
 601 	EShell *shell;
 602 	GtkWidget *notebook;
 603 	GtkWidget *status_area;
 604 	GtkWidget *online_button;
 605 	GtkWidget *tooltip_label;
 606 	gint height;
 607 
 608 	shell = e_shell_window_get_shell (shell_window);
 609 
 610 	status_area = gtk_hbox_new (FALSE, 3);
 611 	gtk_container_set_border_width (GTK_CONTAINER (status_area), 3);
 612 
 613 	g_object_bind_property (
 614 		shell_window, "taskbar-visible",
 615 		status_area, "visible",
 616 		G_BINDING_SYNC_CREATE);
 617 
 618 	/* Make the status area as large as the task bar. */
 619 	gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &height);
 620 	gtk_widget_set_size_request (status_area, -1, (height * 2) + 6);
 621 
 622 	online_button = e_online_button_new ();
 623 	gtk_box_pack_start (
 624 		GTK_BOX (status_area), online_button, FALSE, TRUE, 0);
 625 	gtk_widget_show (online_button);
 626 
 627 	g_object_bind_property (
 628 		shell, "online",
 629 		online_button, "online",
 630 		G_BINDING_SYNC_CREATE);
 631 
 632 	g_object_bind_property (
 633 		shell, "network-available",
 634 		online_button, "sensitive",
 635 		G_BINDING_SYNC_CREATE);
 636 
 637 	g_signal_connect (
 638 		online_button, "clicked",
 639 		G_CALLBACK (shell_window_online_button_clicked_cb),
 640 		shell_window);
 641 
 642 	tooltip_label = gtk_label_new ("");
 643 	gtk_misc_set_alignment (GTK_MISC (tooltip_label), 0.0, 0.5);
 644 	gtk_box_pack_start (
 645 		GTK_BOX (status_area), tooltip_label, TRUE, TRUE, 0);
 646 	shell_window->priv->tooltip_label = g_object_ref (tooltip_label);
 647 	gtk_widget_hide (tooltip_label);
 648 
 649 	notebook = gtk_notebook_new ();
 650 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
 651 	gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
 652 	gtk_box_pack_start (GTK_BOX (status_area), notebook, TRUE, TRUE, 0);
 653 	shell_window->priv->status_notebook = g_object_ref (notebook);
 654 	gtk_widget_show (notebook);
 655 
 656 	g_signal_connect (
 657 		shell_window, "notify::active-view",
 658 		G_CALLBACK (shell_window_set_notebook_page), notebook);
 659 
 660 	return status_area;
 661 }
 662 
 663 static EShellView *
 664 shell_window_create_shell_view (EShellWindow *shell_window,
 665                                 const gchar *view_name)
 666 {
 667 	EShell *shell;
 668 	EShellView *shell_view;
 669 	EShellBackend *shell_backend;
 670 	GHashTable *loaded_views;
 671 	GtkUIManager *ui_manager;
 672 	GtkNotebook *notebook;
 673 	GtkAction *action;
 674 	GtkWidget *widget;
 675 	const gchar *name;
 676 	const gchar *id;
 677 	gint page_num;
 678 	GType type;
 679 
 680 	shell = e_shell_window_get_shell (shell_window);
 681 	shell_backend = e_shell_get_backend_by_name (shell, view_name);
 682 
 683 	if (shell_backend == NULL) {
 684 		g_critical ("Unknown shell view name: %s", view_name);
 685 		return NULL;
 686 	}
 687 
 688 	name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name;
 689 	type = E_SHELL_BACKEND_GET_CLASS (shell_backend)->shell_view_type;
 690 
 691 	/* First off, start the shell backend. */
 692 	e_shell_backend_start (shell_backend);
 693 
 694 	/* Determine the page number for the new shell view. */
 695 	notebook = GTK_NOTEBOOK (shell_window->priv->content_notebook);
 696 	page_num = gtk_notebook_get_n_pages (notebook);
 697 
 698 	/* Get the switcher action for this view. */
 699 	action = e_shell_window_get_shell_view_action (shell_window, name);
 700 
 701 	/* Create the shell view. */
 702 	shell_view = g_object_new (
 703 		type, "action", action, "page-num", page_num,
 704 		"shell-window", shell_window, NULL);
 705 
 706 	/* Register the shell view. */
 707 	loaded_views = shell_window->priv->loaded_views;
 708 	g_hash_table_insert (loaded_views, g_strdup (name), shell_view);
 709 
 710 	/* Register the GtkUIManager ID for the shell view. */
 711 	id = E_SHELL_VIEW_GET_CLASS (shell_view)->ui_manager_id;
 712 	ui_manager = e_shell_window_get_ui_manager (shell_window);
 713 	e_plugin_ui_register_manager (ui_manager, id, shell_view);
 714 
 715 	/* Add pages to the various shell window notebooks. */
 716 
 717 	/* We can't determine the shell view's page number until after the
 718 	 * shell view is fully initialized because the shell view may load
 719 	 * other shell views during initialization, and those other shell
 720 	 * views will append their widgets to the notebooks before us. */
 721 	page_num = gtk_notebook_get_n_pages (notebook);
 722 	e_shell_view_set_page_num (shell_view, page_num);
 723 
 724 	notebook = GTK_NOTEBOOK (shell_window->priv->content_notebook);
 725 	widget = GTK_WIDGET (e_shell_view_get_shell_content (shell_view));
 726 	gtk_notebook_append_page (notebook, widget, NULL);
 727 
 728 	notebook = GTK_NOTEBOOK (shell_window->priv->sidebar_notebook);
 729 	widget = GTK_WIDGET (e_shell_view_get_shell_sidebar (shell_view));
 730 	gtk_notebook_append_page (notebook, widget, NULL);
 731 
 732 	notebook = GTK_NOTEBOOK (shell_window->priv->status_notebook);
 733 	widget = GTK_WIDGET (e_shell_view_get_shell_taskbar (shell_view));
 734 	gtk_notebook_append_page (notebook, widget, NULL);
 735 
 736 	/* Listen for changes that affect the shell window. */
 737 
 738 	g_signal_connect_swapped (
 739 		action, "notify::icon-name",
 740 		G_CALLBACK (e_shell_window_update_icon), shell_window);
 741 
 742 	g_signal_connect_swapped (
 743 		shell_view, "notify::title",
 744 		G_CALLBACK (e_shell_window_update_title), shell_window);
 745 
 746 	g_signal_connect_swapped (
 747 		shell_view, "notify::view-id",
 748 		G_CALLBACK (e_shell_window_update_view_menu), shell_window);
 749 
 750 	return shell_view;
 751 }
 752 
 753 static void
 754 shell_window_realize (GtkWidget *widget)
 755 {
 756 	EShellWindow *shell_window;
 757 
 758 	shell_window = E_SHELL_WINDOW (widget);
 759 	e_shell_adapt_window_size (
 760 		shell_window->priv->shell,
 761 		GTK_WINDOW (widget));
 762 
 763 	/* Chain up to parent's dispose() method. */
 764 	GTK_WIDGET_CLASS (e_shell_window_parent_class)->realize (widget);
 765 }
 766 
 767 static void
 768 shell_window_submit_alert (EAlertSink *alert_sink,
 769                            EAlert *alert)
 770 {
 771 	EShellWindow *shell_window;
 772 	GtkWidget *alert_bar;
 773 	GtkWidget *dialog;
 774 
 775 	shell_window = E_SHELL_WINDOW (alert_sink);
 776 	alert_bar = e_shell_window_get_alert_bar (shell_window);
 777 
 778 	switch (e_alert_get_message_type (alert)) {
 779 		case GTK_MESSAGE_INFO:
 780 		case GTK_MESSAGE_WARNING:
 781 		case GTK_MESSAGE_ERROR:
 782 			e_alert_bar_add_alert (
 783 				E_ALERT_BAR (alert_bar), alert);
 784 			break;
 785 
 786 		default:
 787 			dialog = e_alert_dialog_new (
 788 				GTK_WINDOW (shell_window), alert);
 789 			gtk_dialog_run (GTK_DIALOG (dialog));
 790 			gtk_widget_destroy (dialog);
 791 			break;
 792 	}
 793 }
 794 
 795 static void
 796 e_shell_window_class_init (EShellWindowClass *class)
 797 {
 798 	GObjectClass *object_class;
 799 	GtkWidgetClass *widget_class;
 800 
 801 	g_type_class_add_private (class, sizeof (EShellWindowPrivate));
 802 
 803 	object_class = G_OBJECT_CLASS (class);
 804 	object_class->set_property = shell_window_set_property;
 805 	object_class->get_property = shell_window_get_property;
 806 	object_class->dispose = shell_window_dispose;
 807 	object_class->finalize = shell_window_finalize;
 808 	object_class->constructed = shell_window_constructed;
 809 
 810 	widget_class = GTK_WIDGET_CLASS (class);
 811 	widget_class->realize = shell_window_realize;
 812 
 813 	class->construct_menubar = shell_window_construct_menubar;
 814 	class->construct_toolbar = shell_window_construct_toolbar;
 815 	class->construct_sidebar = shell_window_construct_sidebar;
 816 	class->construct_content = shell_window_construct_content;
 817 	class->construct_taskbar = shell_window_construct_taskbar;
 818 	class->create_shell_view = shell_window_create_shell_view;
 819 
 820 	/**
 821 	 * EShellWindow:active-view
 822 	 *
 823 	 * Name of the active #EShellView.
 824 	 **/
 825 	g_object_class_install_property (
 826 		object_class,
 827 		PROP_ACTIVE_VIEW,
 828 		g_param_spec_string (
 829 			"active-view",
 830 			"Active Shell View",
 831 			"Name of the active shell view",
 832 			NULL,
 833 			G_PARAM_READWRITE));
 834 
 835 	/**
 836 	 * EShellWindow:alert-bar
 837 	 *
 838 	 * Displays informational and error messages.
 839 	 **/
 840 	g_object_class_install_property (
 841 		object_class,
 842 		PROP_ALERT_BAR,
 843 		g_param_spec_object (
 844 			"alert-bar",
 845 			"Alert Bar",
 846 			"Displays informational and error messages",
 847 			E_TYPE_ALERT_BAR,
 848 			G_PARAM_READABLE));
 849 
 850 	/**
 851 	 * EShellWindow:focus-tracker
 852 	 *
 853 	 * The shell window's #EFocusTracker.
 854 	 **/
 855 	g_object_class_install_property (
 856 		object_class,
 857 		PROP_FOCUS_TRACKER,
 858 		g_param_spec_object (
 859 			"focus-tracker",
 860 			"Focus Tracker",
 861 			"The shell window's EFocusTracker",
 862 			E_TYPE_FOCUS_TRACKER,
 863 			G_PARAM_READABLE));
 864 
 865 	/**
 866 	 * EShellWindow:geometry
 867 	 *
 868 	 * User-specified initial window geometry string.
 869 	 **/
 870 	g_object_class_install_property (
 871 		object_class,
 872 		PROP_GEOMETRY,
 873 		g_param_spec_string (
 874 			"geometry",
 875 			"Geometry",
 876 			"Initial window geometry string",
 877 			NULL,
 878 			G_PARAM_WRITABLE |
 879 			G_PARAM_CONSTRUCT_ONLY));
 880 
 881 	/**
 882 	 * EShellWindow:safe-mode
 883 	 *
 884 	 * Whether the shell window is in safe mode.
 885 	 **/
 886 	g_object_class_install_property (
 887 		object_class,
 888 		PROP_SAFE_MODE,
 889 		g_param_spec_boolean (
 890 			"safe-mode",
 891 			"Safe Mode",
 892 			"Whether the shell window is in safe mode",
 893 			FALSE,
 894 			G_PARAM_READWRITE |
 895 			G_PARAM_CONSTRUCT));
 896 
 897 	/**
 898 	 * EShellWindow:shell
 899 	 *
 900 	 * The #EShell singleton.
 901 	 **/
 902 	g_object_class_install_property (
 903 		object_class,
 904 		PROP_SHELL,
 905 		g_param_spec_object (
 906 			"shell",
 907 			"Shell",
 908 			"The EShell singleton",
 909 			E_TYPE_SHELL,
 910 			G_PARAM_READWRITE |
 911 			G_PARAM_CONSTRUCT_ONLY));
 912 
 913 	/**
 914 	 * EShellWindow:sidebar-visible
 915 	 *
 916 	 * Whether the shell window's side bar is visible.
 917 	 **/
 918 	g_object_class_install_property (
 919 		object_class,
 920 		PROP_SIDEBAR_VISIBLE,
 921 		g_param_spec_boolean (
 922 			"sidebar-visible",
 923 			"Sidebar Visible",
 924 			"Whether the shell window's side bar is visible",
 925 			TRUE,
 926 			G_PARAM_READWRITE));
 927 
 928 	/**
 929 	 * EShellWindow:switcher-visible
 930 	 *
 931 	 * Whether the shell window's switcher buttons are visible.
 932 	 **/
 933 	g_object_class_install_property (
 934 		object_class,
 935 		PROP_SWITCHER_VISIBLE,
 936 		g_param_spec_boolean (
 937 			"switcher-visible",
 938 			"Switcher Visible",
 939 			"Whether the shell window's "
 940 			"switcher buttons are visible",
 941 			TRUE,
 942 			G_PARAM_READWRITE));
 943 
 944 	/**
 945 	 * EShellWindow:taskbar-visible
 946 	 *
 947 	 * Whether the shell window's task bar is visible.
 948 	 **/
 949 	g_object_class_install_property (
 950 		object_class,
 951 		PROP_TASKBAR_VISIBLE,
 952 		g_param_spec_boolean (
 953 			"taskbar-visible",
 954 			"Taskbar Visible",
 955 			"Whether the shell window's task bar is visible",
 956 			TRUE,
 957 			G_PARAM_READWRITE));
 958 
 959 	/**
 960 	 * EShellWindow:toolbar-visible
 961 	 *
 962 	 * Whether the shell window's tool bar is visible.
 963 	 **/
 964 	g_object_class_install_property (
 965 		object_class,
 966 		PROP_TOOLBAR_VISIBLE,
 967 		g_param_spec_boolean (
 968 			"toolbar-visible",
 969 			"Toolbar Visible",
 970 			"Whether the shell window's tool bar is visible",
 971 			TRUE,
 972 			G_PARAM_READWRITE));
 973 
 974 	/**
 975 	 * EShellWindow:ui-manager
 976 	 *
 977 	 * The shell window's #GtkUIManager.
 978 	 **/
 979 	g_object_class_install_property (
 980 		object_class,
 981 		PROP_UI_MANAGER,
 982 		g_param_spec_object (
 983 			"ui-manager",
 984 			"UI Manager",
 985 			"The shell window's GtkUIManager",
 986 			GTK_TYPE_UI_MANAGER,
 987 			G_PARAM_READABLE));
 988 
 989 	/**
 990 	 * EShellWindow::shell-view-created
 991 	 * @shell_window: the #EShellWindow which emitted the signal
 992 	 * @shell_view: the new #EShellView
 993 	 *
 994 	 * Emitted when a new #EShellView is instantiated by way of
 995 	 * e_shell_window_get_shell_view().  The signal detail denotes
 996 	 * the new view name, which can be used to obtain notification
 997 	 * of when a particular #EShellView is created.
 998 	 **/
 999 	signals[SHELL_VIEW_CREATED] = g_signal_new (
1000 		"shell-view-created",
1001 		G_OBJECT_CLASS_TYPE (object_class),
1002 		G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
1003 		G_STRUCT_OFFSET (EShellWindowClass, shell_view_created),
1004 		NULL, NULL,
1005 		g_cclosure_marshal_VOID__OBJECT,
1006 		G_TYPE_NONE, 1,
1007 		E_TYPE_SHELL_VIEW);
1008 }
1009 
1010 static void
1011 e_shell_window_alert_sink_init (EAlertSinkInterface *interface)
1012 {
1013 	interface->submit_alert = shell_window_submit_alert;
1014 }
1015 
1016 static void
1017 e_shell_window_init (EShellWindow *shell_window)
1018 {
1019 	shell_window->priv = E_SHELL_WINDOW_GET_PRIVATE (shell_window);
1020 
1021 	e_shell_window_private_init (shell_window);
1022 }
1023 
1024 /**
1025  * e_shell_window_new:
1026  * @shell: an #EShell
1027  * @safe_mode: whether to initialize the window to "safe mode"
1028  * @geometry: initial window geometry string, or %NULL
1029  *
1030  * Returns a new #EShellWindow.
1031  *
1032  * It's up to the various #EShellView<!-- -->'s to define exactly
1033  * what "safe mode" means, but the #EShell usually puts the initial
1034  * #EShellWindow into "safe mode" if detects the previous Evolution
1035  * session crashed.
1036  *
1037  * The initial view for the window is determined by GSettings key
1038  * <filename>/org/gnome/evolution/shell/default-component-id</filename>.
1039  * Or, if the GSettings key is not set or can't be read, the first view
1040  * in the switcher is used.
1041  *
1042  * Returns: a new #EShellWindow
1043  **/
1044 GtkWidget *
1045 e_shell_window_new (EShell *shell,
1046                     gboolean safe_mode,
1047                     const gchar *geometry)
1048 {
1049 	return g_object_new (
1050 		E_TYPE_SHELL_WINDOW,
1051 		"shell", shell, "geometry", geometry,
1052 		"safe-mode", safe_mode, NULL);
1053 }
1054 
1055 /**
1056  * e_shell_window_get_shell:
1057  * @shell_window: an #EShellWindow
1058  *
1059  * Returns the #EShell that was passed to e_shell_window_new().
1060  *
1061  * Returns: the #EShell
1062  **/
1063 EShell *
1064 e_shell_window_get_shell (EShellWindow *shell_window)
1065 {
1066 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1067 
1068 	return E_SHELL (shell_window->priv->shell);
1069 }
1070 
1071 /**
1072  * e_shell_window_get_shell_view:
1073  * @shell_window: an #EShellWindow
1074  * @view_name: name of a shell view
1075  *
1076  * Returns the #EShellView named @view_name (see the
1077  * <structfield>name</structfield> field in #EShellBackendInfo).  This
1078  * will also instantiate the #EShellView the first time it's requested.
1079  * To reduce resource consumption, Evolution tries to delay instantiating
1080  * shell views until the user switches to them.  So in general, only the
1081  * active view name, as returned by e_shell_window_get_active_view(),
1082  * should be requested.
1083  *
1084  * The function emits a #EShellWindow::shell-view-created signal with
1085  * @view_name as the signal detail when it instantiates an #EShellView.
1086  *
1087  * Returns: the requested #EShellView, or %NULL if no such view is
1088  *          registered
1089  **/
1090 EShellView *
1091 e_shell_window_get_shell_view (EShellWindow *shell_window,
1092                                const gchar *view_name)
1093 {
1094 	EShellView *shell_view;
1095 	EShellWindowClass *class;
1096 
1097 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1098 	g_return_val_if_fail (view_name != NULL, NULL);
1099 
1100 	shell_view = e_shell_window_peek_shell_view (shell_window, view_name);
1101 	if (shell_view != NULL)
1102 		return shell_view;
1103 
1104 	class = E_SHELL_WINDOW_GET_CLASS (shell_window);
1105 	g_return_val_if_fail (class->create_shell_view != NULL, NULL);
1106 
1107 	shell_view = class->create_shell_view (shell_window, view_name);
1108 
1109 	g_signal_emit (
1110 		shell_window, signals[SHELL_VIEW_CREATED],
1111 		g_quark_from_string (view_name), shell_view);
1112 
1113 	return shell_view;
1114 }
1115 
1116 /**
1117  * e_shell_window_peek_shell_view:
1118  * @shell_window: an #EShellWindow
1119  * @view_name: name of a shell view
1120  *
1121  * Returns the #EShellView named @view_name (see the
1122  * <structfield>name</structfield> field in #EShellBackendInfo), or
1123  * %NULL if the requested view has not yet been instantiated.  Unlike
1124  * e_shell_window_get_shell_view(), this function will not instantiate
1125  * the view itself.
1126  *
1127  * Returns: the requested #EShellView, or %NULL if no such view is
1128  *          instantiated
1129  **/
1130 EShellView *
1131 e_shell_window_peek_shell_view (EShellWindow *shell_window,
1132                                 const gchar *view_name)
1133 {
1134 	GHashTable *loaded_views;
1135 
1136 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1137 	g_return_val_if_fail (view_name != NULL, NULL);
1138 
1139 	loaded_views = shell_window->priv->loaded_views;
1140 
1141 	return g_hash_table_lookup (loaded_views, view_name);
1142 }
1143 
1144 /**
1145  * e_shell_window_get_shell_view_action:
1146  * @shell_window: an #EShellWindow
1147  * @view_name: name of a shell view
1148  *
1149  * Returns the switcher action for @view_name.
1150  *
1151  * An #EShellWindow creates a #GtkRadioAction for each registered subclass
1152  * of #EShellView.  This action gets passed to the #EShellSwitcher, which
1153  * displays a button that proxies the action.  When the #EShellView named
1154  * @view_name is active, the action's icon becomes the @shell_window icon.
1155  *
1156  * Returns: the switcher action for the #EShellView named @view_name,
1157  *          or %NULL if no such shell view exists
1158  **/
1159 GtkAction *
1160 e_shell_window_get_shell_view_action (EShellWindow *shell_window,
1161                                       const gchar *view_name)
1162 {
1163 	GtkAction *action;
1164 	gchar *action_name;
1165 
1166 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1167 	g_return_val_if_fail (view_name != NULL, NULL);
1168 
1169 	action_name = g_strdup_printf (E_SHELL_SWITCHER_FORMAT, view_name);
1170 	action = e_shell_window_get_action (shell_window, action_name);
1171 	g_free (action_name);
1172 
1173 	return action;
1174 }
1175 
1176 /**
1177  * e_shell_window_get_alert_bar:
1178  * @shell_window: an #EShellWindow
1179  *
1180  * Returns the #EAlertBar used to display informational and error messages.
1181  *
1182  * Returns: the #EAlertBar for @shell_window
1183  **/
1184 GtkWidget *
1185 e_shell_window_get_alert_bar (EShellWindow *shell_window)
1186 {
1187 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1188 
1189 	return shell_window->priv->alert_bar;
1190 }
1191 
1192 /**
1193  * e_shell_window_get_focus_tracker:
1194  * @shell_window: an #EShellWindow
1195  *
1196  * Returns @shell_window<!-- -->'s focus tracker, which directs
1197  * Cut, Copy, Paste and Select All main menu activations to the
1198  * appropriate editable or selectable widget.
1199  *
1200  * Returns: the #EFocusTracker for @shell_window
1201  **/
1202 EFocusTracker *
1203 e_shell_window_get_focus_tracker (EShellWindow *shell_window)
1204 {
1205 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1206 
1207 	return shell_window->priv->focus_tracker;
1208 }
1209 
1210 /**
1211  * e_shell_window_get_ui_manager:
1212  * @shell_window: an #EShellWindow
1213  *
1214  * Returns @shell_window<!-- -->'s user interface manager, which
1215  * manages the window's menus and toolbars via #GtkAction<!-- -->s.
1216  * This is the mechanism by which shell views and plugins can extend
1217  * Evolution's menus and toolbars.
1218  *
1219  * Returns: the #GtkUIManager for @shell_window
1220  **/
1221 GtkUIManager *
1222 e_shell_window_get_ui_manager (EShellWindow *shell_window)
1223 {
1224 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1225 
1226 	return shell_window->priv->ui_manager;
1227 }
1228 
1229 /**
1230  * e_shell_window_get_action:
1231  * @shell_window: an #EShellWindow
1232  * @action_name: the name of an action
1233  *
1234  * Returns the #GtkAction named @action_name in @shell_window<!-- -->'s
1235  * user interface manager, or %NULL if no such action exists.
1236  *
1237  * Returns: the #GtkAction named @action_name
1238  **/
1239 GtkAction *
1240 e_shell_window_get_action (EShellWindow *shell_window,
1241                            const gchar *action_name)
1242 {
1243 	GtkUIManager *ui_manager;
1244 
1245 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1246 	g_return_val_if_fail (action_name != NULL, NULL);
1247 
1248 	ui_manager = e_shell_window_get_ui_manager (shell_window);
1249 
1250 	return e_lookup_action (ui_manager, action_name);
1251 }
1252 
1253 /**
1254  * e_shell_window_get_action_group:
1255  * @shell_window: an #EShellWindow
1256  * @group_name: the name of an action group
1257  *
1258  * Returns the #GtkActionGroup named @group_name in
1259  * @shell_window<!-- -->'s user interface manager, or %NULL if no
1260  * such action group exists.
1261  *
1262  * Returns: the #GtkActionGroup named @group_name
1263  **/
1264 GtkActionGroup *
1265 e_shell_window_get_action_group (EShellWindow *shell_window,
1266                                  const gchar *group_name)
1267 {
1268 	GtkUIManager *ui_manager;
1269 
1270 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1271 	g_return_val_if_fail (group_name != NULL, NULL);
1272 
1273 	ui_manager = e_shell_window_get_ui_manager (shell_window);
1274 
1275 	return e_lookup_action_group (ui_manager, group_name);
1276 }
1277 
1278 /**
1279  * e_shell_window_get_managed_widget:
1280  * @shell_window: an #EShellWindow
1281  * @widget_path: path in the UI definintion
1282  *
1283  * Looks up a widget in @shell_window<!-- -->'s user interface manager by
1284  * following a path.  See gtk_ui_manager_get_widget() for more information
1285  * about paths.
1286  *
1287  * Returns: the widget found by following the path, or %NULL if no widget
1288  *          was found
1289  **/
1290 GtkWidget *
1291 e_shell_window_get_managed_widget (EShellWindow *shell_window,
1292                                    const gchar *widget_path)
1293 {
1294 	GtkUIManager *ui_manager;
1295 	GtkWidget *widget;
1296 
1297 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1298 	g_return_val_if_fail (widget_path != NULL, NULL);
1299 
1300 	ui_manager = e_shell_window_get_ui_manager (shell_window);
1301 	widget = gtk_ui_manager_get_widget (ui_manager, widget_path);
1302 
1303 	g_return_val_if_fail (widget != NULL, NULL);
1304 
1305 	return widget;
1306 }
1307 
1308 /**
1309  * e_shell_window_get_active_view:
1310  * @shell_window: an #EShellWindow
1311  *
1312  * Returns the name of the active #EShellView.
1313  *
1314  * Returns: the name of the active view
1315  **/
1316 const gchar *
1317 e_shell_window_get_active_view (EShellWindow *shell_window)
1318 {
1319 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1320 
1321 	return shell_window->priv->active_view;
1322 }
1323 
1324 /**
1325  * e_shell_window_set_active_view:
1326  * @shell_window: an #EShellWindow
1327  * @view_name: the name of the shell view to switch to
1328  *
1329  * Switches @shell_window to the #EShellView named @view_name, causing
1330  * the entire content of @shell_window to change.  This is typically
1331  * called as a result of the user clicking one of the switcher buttons.
1332  *
1333  * The name of the newly activated shell view is also written to GSettings key
1334  * <filename>/org/gnome/evolution/shell/default-component-id</filename>.
1335  * This makes the active shell view persistent across Evolution sessions.
1336  * It also causes new shell windows created within the current Evolution
1337  * session to open to the most recently selected shell view.
1338  **/
1339 void
1340 e_shell_window_set_active_view (EShellWindow *shell_window,
1341                                 const gchar *view_name)
1342 {
1343 	GtkAction *action;
1344 	EShellView *shell_view;
1345 
1346 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1347 	g_return_if_fail (view_name != NULL);
1348 
1349 	shell_view = e_shell_window_get_shell_view (shell_window, view_name);
1350 	g_return_if_fail (shell_view != NULL);
1351 
1352 	action = e_shell_view_get_action (shell_view);
1353 	gtk_action_activate (action);
1354 }
1355 
1356 /**
1357  * e_shell_window_get_safe_mode:
1358  * @shell_window: an #EShellWindow
1359  *
1360  * Returns %TRUE if @shell_window is in "safe mode".
1361  *
1362  * It's up to the various #EShellView<!-- -->'s to define exactly
1363  * what "safe mode" means.  The @shell_window simply manages the
1364  * "safe mode" state.
1365  *
1366  * Returns: %TRUE if @shell_window is in "safe mode"
1367  **/
1368 gboolean
1369 e_shell_window_get_safe_mode (EShellWindow *shell_window)
1370 {
1371 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
1372 
1373 	return shell_window->priv->safe_mode;
1374 }
1375 
1376 /**
1377  * e_shell_window_set_safe_mode:
1378  * @shell_window: an #EShellWindow
1379  * @safe_mode: whether to put @shell_window into "safe mode"
1380  *
1381  * If %TRUE, puts @shell_window into "safe mode".
1382  *
1383  * It's up to the various #EShellView<!-- -->'s to define exactly
1384  * what "safe mode" means.  The @shell_window simply manages the
1385  * "safe mode" state.
1386  **/
1387 void
1388 e_shell_window_set_safe_mode (EShellWindow *shell_window,
1389                               gboolean safe_mode)
1390 {
1391 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1392 
1393 	if (shell_window->priv->safe_mode == safe_mode)
1394 		return;
1395 
1396 	shell_window->priv->safe_mode = safe_mode;
1397 
1398 	g_object_notify (G_OBJECT (shell_window), "safe-mode");
1399 }
1400 
1401 /**
1402  * e_shell_window_add_action_group:
1403  * @shell_window: an #EShellWindow
1404  * @group_name: the name of the new action group
1405  *
1406  * Creates a new #GtkActionGroup and adds it to @shell_window<!-- -->'s
1407  * user interface manager.  This also takes care of details like setting
1408  * the translation domain.
1409  **/
1410 void
1411 e_shell_window_add_action_group (EShellWindow *shell_window,
1412                                  const gchar *group_name)
1413 {
1414 	GtkActionGroup *action_group;
1415 	GtkUIManager *ui_manager;
1416 	const gchar *domain;
1417 
1418 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1419 	g_return_if_fail (group_name != NULL);
1420 
1421 	ui_manager = e_shell_window_get_ui_manager (shell_window);
1422 	domain = GETTEXT_PACKAGE;
1423 
1424 	action_group = gtk_action_group_new (group_name);
1425 	gtk_action_group_set_translation_domain (action_group, domain);
1426 	gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
1427 	g_object_unref (action_group);
1428 }
1429 
1430 /**
1431  * e_shell_window_get_sidebar_visible:
1432  * @shell_window: an #EShellWindow
1433  *
1434  * Returns %TRUE if @shell_window<!-- -->'s side bar is visible.
1435  *
1436  * Returns: %TRUE is the side bar is visible
1437  **/
1438 gboolean
1439 e_shell_window_get_sidebar_visible (EShellWindow *shell_window)
1440 {
1441 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
1442 
1443 	return shell_window->priv->sidebar_visible;
1444 }
1445 
1446 /**
1447  * e_shell_window_set_sidebar_visible:
1448  * @shell_window: an #EShellWindow
1449  * @sidebar_visible: whether the side bar should be visible
1450  *
1451  * Makes @shell_window<!-- -->'s side bar visible or invisible.
1452  **/
1453 void
1454 e_shell_window_set_sidebar_visible (EShellWindow *shell_window,
1455                                     gboolean sidebar_visible)
1456 {
1457 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1458 
1459 	if (shell_window->priv->sidebar_visible == sidebar_visible)
1460 		return;
1461 
1462 	shell_window->priv->sidebar_visible = sidebar_visible;
1463 
1464 	g_object_notify (G_OBJECT (shell_window), "sidebar-visible");
1465 }
1466 
1467 /**
1468  * e_shell_window_get_switcher_visible:
1469  * @shell_window: an #EShellWindow
1470  *
1471  * Returns %TRUE if @shell_window<!-- -->'s switcher buttons are visible.
1472  *
1473  * Returns: %TRUE is the switcher buttons are visible
1474  **/
1475 gboolean
1476 e_shell_window_get_switcher_visible (EShellWindow *shell_window)
1477 {
1478 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
1479 
1480 	return shell_window->priv->switcher_visible;
1481 }
1482 
1483 /**
1484  * e_shell_window_set_switcher_visible:
1485  * @shell_window: an #EShellWindow
1486  * @switcher_visible: whether the switcher buttons should be visible
1487  *
1488  * Makes @shell_window<!-- -->'s switcher buttons visible or invisible.
1489  **/
1490 void
1491 e_shell_window_set_switcher_visible (EShellWindow *shell_window,
1492                                      gboolean switcher_visible)
1493 {
1494 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1495 
1496 	if (shell_window->priv->switcher_visible == switcher_visible)
1497 		return;
1498 
1499 	shell_window->priv->switcher_visible = switcher_visible;
1500 
1501 	g_object_notify (G_OBJECT (shell_window), "switcher-visible");
1502 }
1503 
1504 /**
1505  * e_shell_window_get_taskbar_visible:
1506  * @shell_window: an #EShellWindow
1507  *
1508  * Returns %TRUE if @shell_window<!-- -->'s task bar is visible.
1509  *
1510  * Returns: %TRUE is the task bar is visible
1511  **/
1512 gboolean
1513 e_shell_window_get_taskbar_visible (EShellWindow *shell_window)
1514 {
1515 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
1516 
1517 	return shell_window->priv->taskbar_visible;
1518 }
1519 
1520 /**
1521  * e_shell_window_set_taskbar_visible:
1522  * @shell_window: an #EShellWindow
1523  * @taskbar_visible: whether the task bar should be visible
1524  *
1525  * Makes @shell_window<!-- -->'s task bar visible or invisible.
1526  **/
1527 void
1528 e_shell_window_set_taskbar_visible (EShellWindow *shell_window,
1529                                     gboolean taskbar_visible)
1530 {
1531 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1532 
1533 	if (shell_window->priv->taskbar_visible == taskbar_visible)
1534 		return;
1535 
1536 	shell_window->priv->taskbar_visible = taskbar_visible;
1537 
1538 	g_object_notify (G_OBJECT (shell_window), "taskbar-visible");
1539 }
1540 
1541 /**
1542  * e_shell_window_get_toolbar_visible:
1543  * @shell_window: an #EShellWindow
1544  *
1545  * Returns %TRUE if @shell_window<!-- -->'s tool bar is visible.
1546  *
1547  * Returns: %TRUE if the tool bar is visible
1548  **/
1549 gboolean
1550 e_shell_window_get_toolbar_visible (EShellWindow *shell_window)
1551 {
1552 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE);
1553 
1554 	return shell_window->priv->toolbar_visible;
1555 }
1556 
1557 /**
1558  * e_shell_window_set_toolbar_visible:
1559  * @shell_window: an #EShellWindow
1560  * @toolbar_visible: whether the tool bar should be visible
1561  *
1562  * Makes @shell_window<!-- -->'s tool bar visible or invisible.
1563  **/
1564 void
1565 e_shell_window_set_toolbar_visible (EShellWindow *shell_window,
1566                                     gboolean toolbar_visible)
1567 {
1568 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1569 
1570 	if (shell_window->priv->toolbar_visible == toolbar_visible)
1571 		return;
1572 
1573 	shell_window->priv->toolbar_visible = toolbar_visible;
1574 
1575 	g_object_notify (G_OBJECT (shell_window), "toolbar-visible");
1576 }
1577 
1578 /**
1579  * e_shell_window_set_toolbar_new_prefer_item:
1580  * @shell_window: an #EShellWindow
1581  * @prefer_item: prefer-item name to be set
1582  *
1583  * Sets prefer item on the New button for current view.
1584  *
1585  * Since: 3.4
1586  **/
1587 void
1588 e_shell_window_set_toolbar_new_prefer_item (EShellWindow *shell_window,
1589                                             const gchar *prefer_item)
1590 {
1591 	GtkWidget *toolbar;
1592 	GtkToolItem *item;
1593 
1594 	g_return_if_fail (shell_window != NULL);
1595 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1596 
1597 	toolbar = e_shell_window_get_managed_widget (shell_window, "/main-toolbar");
1598 	g_return_if_fail (toolbar != NULL);
1599 
1600 	item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), 0);
1601 	g_return_if_fail (item != NULL);
1602 	g_return_if_fail (E_IS_MENU_TOOL_BUTTON (item));
1603 
1604 	e_menu_tool_button_set_prefer_item (E_MENU_TOOL_BUTTON (item), prefer_item);
1605 }
1606 
1607 /**
1608  * e_shell_window_get_toolbar_new_prefer_item:
1609  * @shell_window: an #EShellWindow
1610  *
1611  * Returns: name of preferred item on the New button for current view.
1612  *
1613  * Since: 3.4
1614  **/
1615 const gchar *
1616 e_shell_window_get_toolbar_new_prefer_item (EShellWindow *shell_window)
1617 {
1618 	GtkWidget *toolbar;
1619 	GtkToolItem *item;
1620 
1621 	g_return_val_if_fail (shell_window != NULL, NULL);
1622 	g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL);
1623 
1624 	toolbar = e_shell_window_get_managed_widget (shell_window, "/main-toolbar");
1625 	g_return_val_if_fail (toolbar != NULL, NULL);
1626 
1627 	item = gtk_toolbar_get_nth_item (GTK_TOOLBAR (toolbar), 0);
1628 	g_return_val_if_fail (item != NULL, NULL);
1629 	g_return_val_if_fail (E_IS_MENU_TOOL_BUTTON (item), NULL);
1630 
1631 	return e_menu_tool_button_get_prefer_item (E_MENU_TOOL_BUTTON (item));
1632 }
1633 
1634 /**
1635  * e_shell_window_register_new_item_actions:
1636  * @shell_window: an #EShellWindow
1637  * @backend_name: name of an #EShellBackend
1638  * @entries: an array of #GtkActionEntry<!-- -->s
1639  * @n_entries: number of elements in the array
1640  *
1641  * Registers a list of #GtkAction<!-- -->s to appear in
1642  * @shell_window<!-- -->'s "New" menu and toolbar button.  This
1643  * function should be called from an #EShell<!-- -->'s
1644  * #GtkApplication::window-added signal handler.  The #EShellBackend
1645  * calling this function should pass its own name for the @backend_name
1646  * argument (i.e. the <structfield>name</structfield> field from its own
1647  * #EShellBackendInfo).
1648  *
1649  * The registered #GtkAction<!-- -->s should be for creating individual
1650  * items such as an email message or a calendar appointment.  The action
1651  * labels should be marked for translation with the "New" context using
1652  * the NC_() macro.
1653  **/
1654 void
1655 e_shell_window_register_new_item_actions (EShellWindow *shell_window,
1656                                           const gchar *backend_name,
1657                                           GtkActionEntry *entries,
1658                                           guint n_entries)
1659 {
1660 	GtkActionGroup *action_group;
1661 	GtkAccelGroup *accel_group;
1662 	GtkUIManager *ui_manager;
1663 	guint ii;
1664 
1665 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1666 	g_return_if_fail (backend_name != NULL);
1667 	g_return_if_fail (entries != NULL);
1668 
1669 	action_group = ACTION_GROUP (NEW_ITEM);
1670 	ui_manager = e_shell_window_get_ui_manager (shell_window);
1671 	accel_group = gtk_ui_manager_get_accel_group (ui_manager);
1672 	backend_name = g_intern_string (backend_name);
1673 
1674 	/* XXX The action label translations are retrieved from the
1675 	 *     message context "New", but gtk_action_group_add_actions()
1676 	 *     does not support message contexts.  So we have to fetch
1677 	 *     the label translations ourselves before adding them to
1678 	 *     the action group.
1679 	 *
1680 	 *     gtk_action_group_set_translate_func() does not help here
1681 	 *     because the action tooltips do not use a message context
1682 	 *     (though I suppose they could). */
1683 	for (ii = 0; ii < n_entries; ii++)
1684 		entries[ii].label = g_dpgettext2 (
1685 			GETTEXT_PACKAGE, "New", entries[ii].label);
1686 
1687 	gtk_action_group_add_actions (
1688 		action_group, entries, n_entries, shell_window);
1689 
1690 	/* Tag each action with the name of the shell backend that
1691 	 * registered it.  This is used to help sort actions in the
1692 	 * "New" menu. */
1693 
1694 	for (ii = 0; ii < n_entries; ii++) {
1695 		const gchar *action_name;
1696 		GtkAction *action;
1697 
1698 		action_name = entries[ii].name;
1699 
1700 		action = gtk_action_group_get_action (
1701 			action_group, action_name);
1702 
1703 		gtk_action_set_accel_group (action, accel_group);
1704 
1705 		g_object_set_data (
1706 			G_OBJECT (action),
1707 			"backend-name", (gpointer) backend_name);
1708 
1709 		/* The first action becomes the first item in the "New"
1710 		 * menu, and consequently its icon is shown in the "New"
1711 		 * button when the shell backend's view is active.  This
1712 		 * is all sorted out in shell_window_extract_actions().
1713 		 * Note, the data value just needs to be non-zero. */
1714 		if (ii == 0)
1715 			g_object_set_data (
1716 				G_OBJECT (action),
1717 				"primary", GINT_TO_POINTER (TRUE));
1718 	}
1719 }
1720 
1721 /**
1722  * e_shell_window_register_new_source_actions:
1723  * @shell_window: an #EShellWindow
1724  * @backend_name: name of an #EShellBackend
1725  * @entries: an array of #GtkActionEntry<!-- -->s
1726  * @n_entries: number of elements in the array
1727  *
1728  * Registers a list of #GtkAction<!-- -->s to appear in
1729  * @shell_window<!-- -->'s "New" menu and toolbar button.  This
1730  * function should be called from an #EShell<!-- -->'s
1731  * #GtkApplication::window-added signal handler.  The #EShellBackend
1732  * calling this function should pass its own name for the @backend_name
1733  * argument (i.e. the <structfield>name</structfield> field from its own
1734  * #EShellBackendInfo).
1735  *
1736  * The registered #GtkAction<!-- -->s should be for creating item
1737  * containers such as an email folder or a calendar.  The action labels
1738  * should be marked for translation with the "New" context using the
1739  * NC_() macro.
1740  **/
1741 void
1742 e_shell_window_register_new_source_actions (EShellWindow *shell_window,
1743                                             const gchar *backend_name,
1744                                             GtkActionEntry *entries,
1745                                             guint n_entries)
1746 {
1747 	GtkActionGroup *action_group;
1748 	GtkAccelGroup *accel_group;
1749 	GtkUIManager *ui_manager;
1750 	guint ii;
1751 
1752 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
1753 	g_return_if_fail (backend_name != NULL);
1754 	g_return_if_fail (entries != NULL);
1755 
1756 	action_group = ACTION_GROUP (NEW_SOURCE);
1757 	ui_manager = e_shell_window_get_ui_manager (shell_window);
1758 	accel_group = gtk_ui_manager_get_accel_group (ui_manager);
1759 	backend_name = g_intern_string (backend_name);
1760 
1761 	/* XXX The action label translations are retrieved from the
1762 	 *     message context "New", but gtk_action_group_add_actions()
1763 	 *     does not support message contexts.  So we have to fetch
1764 	 *     the label translations ourselves before adding them to
1765 	 *     the action group.
1766 	 *
1767 	 *     gtk_action_group_set_translate_func() does not help here
1768 	 *     because the action tooltips do not use a message context
1769 	 *     (though I suppose they could). */
1770 	for (ii = 0; ii < n_entries; ii++)
1771 		entries[ii].label = g_dpgettext2 (
1772 			GETTEXT_PACKAGE, "New", entries[ii].label);
1773 
1774 	gtk_action_group_add_actions (
1775 		action_group, entries, n_entries, shell_window);
1776 
1777 	/* Tag each action with the name of the shell backend that
1778 	 * registered it.  This is used to help sort actions in the
1779 	 * "New" menu. */
1780 
1781 	for (ii = 0; ii < n_entries; ii++) {
1782 		const gchar *action_name;
1783 		GtkAction *action;
1784 
1785 		action_name = entries[ii].name;
1786 
1787 		action = gtk_action_group_get_action (
1788 			action_group, action_name);
1789 
1790 		gtk_action_set_accel_group (action, accel_group);
1791 
1792 		g_object_set_data (
1793 			G_OBJECT (action),
1794 			"backend-name", (gpointer) backend_name);
1795 	}
1796 }