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

No issues found

   1 /*
   2  * e-shell-view.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-view
  24  * @short_description: views within the main window
  25  * @include: shell/e-shell-view.h
  26  **/
  27 
  28 #ifdef HAVE_CONFIG_H
  29 #include <config.h>
  30 #endif
  31 
  32 #include "e-shell-view.h"
  33 
  34 #include <string.h>
  35 #include <glib/gi18n.h>
  36 #include <libebackend/libebackend.h>
  37 
  38 #include "e-util/e-file-utils.h"
  39 #include "e-util/e-plugin-ui.h"
  40 #include "e-util/e-source-util.h"
  41 #include "e-util/e-ui-manager.h"
  42 #include "e-util/e-util-private.h"
  43 #include "e-util/e-util.h"
  44 #include "filter/e-rule-context.h"
  45 
  46 #include "e-shell-searchbar.h"
  47 #include "e-shell-window-actions.h"
  48 
  49 #define E_SHELL_VIEW_GET_PRIVATE(obj) \
  50 	(G_TYPE_INSTANCE_GET_PRIVATE \
  51 	((obj), E_TYPE_SHELL_VIEW, EShellViewPrivate))
  52 
  53 #define SIMPLE_SEARCHBAR_WIDTH 300
  54 #define STATE_SAVE_TIMEOUT_SECONDS 3
  55 
  56 struct _EShellViewPrivate {
  57 
  58 	gpointer shell_window;  /* weak pointer */
  59 
  60 	GKeyFile *state_key_file;
  61 	gpointer state_save_activity;  /* weak pointer */
  62 	guint state_save_timeout_id;
  63 
  64 	gchar *title;
  65 	gchar *view_id;
  66 	gint page_num;
  67 	guint merge_id;
  68 
  69 	GtkAction *action;
  70 	GtkSizeGroup *size_group;
  71 	GtkWidget *shell_content;
  72 	GtkWidget *shell_sidebar;
  73 	GtkWidget *shell_taskbar;
  74 	GtkWidget *searchbar;
  75 
  76 	EFilterRule *search_rule;
  77 	guint execute_search_blocked;
  78 
  79 	guint update_actions_blocked;
  80 	gboolean update_actions_called;
  81 
  82 	GtkWidget *preferences_window;
  83 	gulong preferences_hide_id;
  84 };
  85 
  86 enum {
  87 	PROP_0,
  88 	PROP_ACTION,
  89 	PROP_PAGE_NUM,
  90 	PROP_SEARCHBAR,
  91 	PROP_SEARCH_RULE,
  92 	PROP_SHELL_BACKEND,
  93 	PROP_SHELL_CONTENT,
  94 	PROP_SHELL_SIDEBAR,
  95 	PROP_SHELL_TASKBAR,
  96 	PROP_SHELL_WINDOW,
  97 	PROP_STATE_KEY_FILE,
  98 	PROP_TITLE,
  99 	PROP_VIEW_ID
 100 };
 101 
 102 enum {
 103 	TOGGLED,
 104 	CLEAR_SEARCH,
 105 	CUSTOM_SEARCH,
 106 	EXECUTE_SEARCH,
 107 	UPDATE_ACTIONS,
 108 	LAST_SIGNAL
 109 };
 110 
 111 static gpointer parent_class;
 112 static gulong signals[LAST_SIGNAL];
 113 
 114 static void
 115 shell_view_init_search_context (EShellViewClass *class)
 116 {
 117 	EShellBackend *shell_backend;
 118 	ERuleContext *search_context;
 119 	const gchar *config_dir;
 120 	gchar *system_filename;
 121 	gchar *user_filename;
 122 
 123 	shell_backend = class->shell_backend;
 124 
 125 	/* Sanity check the class fields we need. */
 126 	g_return_if_fail (class->search_rules != NULL);
 127 	g_return_if_fail (E_IS_SHELL_BACKEND (shell_backend));
 128 
 129 	/* The basename for built-in searches is specified in the
 130 	 * shell view class.  All built-in search rules live in the
 131 	 * same directory. */
 132 	system_filename = g_build_filename (
 133 		EVOLUTION_RULEDIR, class->search_rules, NULL);
 134 
 135 	/* The filename for custom saved searches is always of
 136 	 * the form "$(shell_backend_config_dir)/searches.xml". */
 137 	config_dir = e_shell_backend_get_config_dir (shell_backend);
 138 	user_filename = g_build_filename (config_dir, "searches.xml", NULL);
 139 
 140 	/* Create the search context instance.  Subclasses may override
 141 	 * the GType so check that it's really an ERuleContext instance. */
 142 	search_context = g_object_new (class->search_context_type, NULL);
 143 	g_return_if_fail (E_IS_RULE_CONTEXT (search_context));
 144 	class->search_context = search_context;
 145 
 146 	e_rule_context_add_part_set (
 147 		search_context, "partset", E_TYPE_FILTER_PART,
 148 		e_rule_context_add_part, e_rule_context_next_part);
 149 	e_rule_context_add_rule_set (
 150 		search_context, "ruleset", E_TYPE_FILTER_RULE,
 151 		e_rule_context_add_rule, e_rule_context_next_rule);
 152 	e_rule_context_load (search_context, system_filename, user_filename);
 153 
 154 	g_free (system_filename);
 155 	g_free (user_filename);
 156 }
 157 
 158 static void
 159 shell_view_init_view_collection (EShellViewClass *class)
 160 {
 161 	EShellBackend *shell_backend;
 162 	const gchar *base_dir;
 163 	const gchar *backend_name;
 164 	gchar *system_dir;
 165 	gchar *local_dir;
 166 
 167 	shell_backend = class->shell_backend;
 168 	g_return_if_fail (E_IS_SHELL_BACKEND (shell_backend));
 169 	backend_name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name;
 170 
 171 	base_dir = EVOLUTION_GALVIEWSDIR;
 172 	system_dir = g_build_filename (base_dir, backend_name, NULL);
 173 
 174 	base_dir = e_shell_backend_get_config_dir (shell_backend);
 175 	local_dir = g_build_filename (base_dir, "views", NULL);
 176 
 177 	/* The view collection is never destroyed. */
 178 	class->view_collection = gal_view_collection_new ();
 179 
 180 	gal_view_collection_set_title (
 181 		class->view_collection, class->label);
 182 
 183 	gal_view_collection_set_storage_directories (
 184 		class->view_collection, system_dir, local_dir);
 185 
 186 	g_free (system_dir);
 187 	g_free (local_dir);
 188 
 189 	/* This is all we can do.  It's up to the subclasses to
 190 	 * add the appropriate factories to the view collection. */
 191 }
 192 
 193 static void
 194 shell_view_update_view_id (EShellView *shell_view,
 195                            GalViewInstance *view_instance)
 196 {
 197 	gchar *view_id;
 198 
 199 	view_id = gal_view_instance_get_current_view_id (view_instance);
 200 	e_shell_view_set_view_id (shell_view, view_id);
 201 	g_free (view_id);
 202 }
 203 
 204 static void
 205 shell_view_load_state (EShellView *shell_view)
 206 {
 207 	EShellBackend *shell_backend;
 208 	GKeyFile *key_file;
 209 	const gchar *config_dir;
 210 	gchar *filename;
 211 	GError *error = NULL;
 212 
 213 	shell_backend = e_shell_view_get_shell_backend (shell_view);
 214 	config_dir = e_shell_backend_get_config_dir (shell_backend);
 215 	filename = g_build_filename (config_dir, "state.ini", NULL);
 216 
 217 	/* XXX Should do this asynchronously. */
 218 	key_file = shell_view->priv->state_key_file;
 219 	g_key_file_load_from_file (key_file, filename, 0, &error);
 220 
 221 	if (error == NULL)
 222 		goto exit;
 223 
 224 	if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
 225 		g_warning ("%s", error->message);
 226 
 227 	g_error_free (error);
 228 
 229 exit:
 230 	g_free (filename);
 231 }
 232 
 233 typedef struct {
 234 	EShellView *shell_view;
 235 	gchar *contents;
 236 } SaveStateData;
 237 
 238 static void
 239 shell_view_save_state_done_cb (GFile *file,
 240                                GAsyncResult *result,
 241                                SaveStateData *data)
 242 {
 243 	GError *error = NULL;
 244 
 245 	e_file_replace_contents_finish (file, result, NULL, &error);
 246 
 247 	if (error != NULL) {
 248 		g_warning ("%s", error->message);
 249 		g_error_free (error);
 250 	}
 251 
 252 	g_object_unref (data->shell_view);
 253 	g_free (data->contents);
 254 	g_slice_free (SaveStateData, data);
 255 }
 256 
 257 static EActivity *
 258 shell_view_save_state (EShellView *shell_view,
 259                        gboolean immediately)
 260 {
 261 	EShellBackend *shell_backend;
 262 	SaveStateData *data;
 263 	EActivity *activity;
 264 	GKeyFile *key_file;
 265 	GFile *file;
 266 	const gchar *config_dir;
 267 	gchar *contents;
 268 	gchar *path;
 269 
 270 	shell_backend = e_shell_view_get_shell_backend (shell_view);
 271 	config_dir = e_shell_backend_get_config_dir (shell_backend);
 272 	key_file = shell_view->priv->state_key_file;
 273 
 274 	contents = g_key_file_to_data (key_file, NULL, NULL);
 275 	g_return_val_if_fail (contents != NULL, NULL);
 276 
 277 	path = g_build_filename (config_dir, "state.ini", NULL);
 278 	if (immediately) {
 279 		g_file_set_contents (path, contents, -1, NULL);
 280 
 281 		g_free (path);
 282 		g_free (contents);
 283 
 284 		return NULL;
 285 	}
 286 
 287 	file = g_file_new_for_path (path);
 288 	g_free (path);
 289 
 290 	/* GIO does not copy the contents string, so we need to keep
 291 	 * it in memory until saving is complete.  We reference the
 292 	 * shell view to keep it from being finalized while saving. */
 293 	data = g_slice_new (SaveStateData);
 294 	data->shell_view = g_object_ref (shell_view);
 295 	data->contents = contents;
 296 
 297 	/* The returned activity is a borrowed reference. */
 298 	activity = e_file_replace_contents_async (
 299 		file, contents, strlen (contents), NULL,
 300 		FALSE, G_FILE_CREATE_PRIVATE, (GAsyncReadyCallback)
 301 		shell_view_save_state_done_cb, data);
 302 
 303 	e_activity_set_text (
 304 		activity, (_("Saving user interface state")));
 305 
 306 	e_shell_backend_add_activity (shell_backend, activity);
 307 
 308 	g_object_unref (file);
 309 
 310 	return activity;
 311 }
 312 
 313 static gboolean
 314 shell_view_state_timeout_cb (EShellView *shell_view)
 315 {
 316 	EActivity *activity;
 317 
 318 	/* If a save is still in progress, check back later. */
 319 	if (shell_view->priv->state_save_activity != NULL)
 320 		return TRUE;
 321 
 322 	activity = shell_view_save_state (shell_view, FALSE);
 323 
 324 	/* Set up a weak pointer that gets set to NULL when the
 325 	 * activity finishes.  This will tell us if we're still
 326 	 * busy saving state data to disk on the next timeout. */
 327 	shell_view->priv->state_save_activity = activity;
 328 	g_object_add_weak_pointer (
 329 		G_OBJECT (shell_view->priv->state_save_activity),
 330 		&shell_view->priv->state_save_activity);
 331 
 332 	shell_view->priv->state_save_timeout_id = 0;
 333 
 334 	return FALSE;
 335 }
 336 
 337 static void
 338 shell_view_emit_toggled (EShellView *shell_view)
 339 {
 340 	g_signal_emit (shell_view, signals[TOGGLED], 0);
 341 }
 342 
 343 static void
 344 shell_view_set_action (EShellView *shell_view,
 345                        GtkAction *action)
 346 {
 347 	gchar *label;
 348 
 349 	g_return_if_fail (shell_view->priv->action == NULL);
 350 
 351 	shell_view->priv->action = g_object_ref (action);
 352 
 353 	g_object_get (action, "label", &label, NULL);
 354 	e_shell_view_set_title (shell_view, label);
 355 	g_free (label);
 356 
 357 	g_signal_connect_swapped (
 358 		action, "toggled",
 359 		G_CALLBACK (shell_view_emit_toggled), shell_view);
 360 }
 361 
 362 static void
 363 shell_view_set_shell_window (EShellView *shell_view,
 364                              EShellWindow *shell_window)
 365 {
 366 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
 367 	g_return_if_fail (shell_view->priv->shell_window == NULL);
 368 
 369 	shell_view->priv->shell_window = shell_window;
 370 
 371 	g_object_add_weak_pointer (
 372 		G_OBJECT (shell_window),
 373 		&shell_view->priv->shell_window);
 374 }
 375 
 376 static void
 377 shell_view_set_property (GObject *object,
 378                          guint property_id,
 379                          const GValue *value,
 380                          GParamSpec *pspec)
 381 {
 382 	switch (property_id) {
 383 		case PROP_ACTION:
 384 			shell_view_set_action (
 385 				E_SHELL_VIEW (object),
 386 				g_value_get_object (value));
 387 			return;
 388 
 389 		case PROP_PAGE_NUM:
 390 			e_shell_view_set_page_num (
 391 				E_SHELL_VIEW (object),
 392 				g_value_get_int (value));
 393 			return;
 394 
 395 		case PROP_SEARCH_RULE:
 396 			e_shell_view_set_search_rule (
 397 				E_SHELL_VIEW (object),
 398 				g_value_get_object (value));
 399 			return;
 400 
 401 		case PROP_SHELL_WINDOW:
 402 			shell_view_set_shell_window (
 403 				E_SHELL_VIEW (object),
 404 				g_value_get_object (value));
 405 			return;
 406 
 407 		case PROP_TITLE:
 408 			e_shell_view_set_title (
 409 				E_SHELL_VIEW (object),
 410 				g_value_get_string (value));
 411 			return;
 412 
 413 		case PROP_VIEW_ID:
 414 			e_shell_view_set_view_id (
 415 				E_SHELL_VIEW (object),
 416 				g_value_get_string (value));
 417 			return;
 418 	}
 419 
 420 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 421 }
 422 
 423 static void
 424 shell_view_get_property (GObject *object,
 425                          guint property_id,
 426                          GValue *value,
 427                          GParamSpec *pspec)
 428 {
 429 	switch (property_id) {
 430 		case PROP_ACTION:
 431 			g_value_set_object (
 432 				value, e_shell_view_get_action (
 433 				E_SHELL_VIEW (object)));
 434 			return;
 435 
 436 		case PROP_PAGE_NUM:
 437 			g_value_set_int (
 438 				value, e_shell_view_get_page_num (
 439 				E_SHELL_VIEW (object)));
 440 			return;
 441 
 442 		case PROP_SEARCHBAR:
 443 			g_value_set_object (
 444 				value, e_shell_view_get_searchbar (
 445 				E_SHELL_VIEW (object)));
 446 			return;
 447 
 448 		case PROP_SEARCH_RULE:
 449 			g_value_set_object (
 450 				value, e_shell_view_get_search_rule (
 451 				E_SHELL_VIEW (object)));
 452 			return;
 453 
 454 		case PROP_SHELL_BACKEND:
 455 			g_value_set_object (
 456 				value, e_shell_view_get_shell_backend (
 457 				E_SHELL_VIEW (object)));
 458 
 459 		case PROP_SHELL_CONTENT:
 460 			g_value_set_object (
 461 				value, e_shell_view_get_shell_content (
 462 				E_SHELL_VIEW (object)));
 463 			return;
 464 
 465 		case PROP_SHELL_SIDEBAR:
 466 			g_value_set_object (
 467 				value, e_shell_view_get_shell_sidebar (
 468 				E_SHELL_VIEW (object)));
 469 			return;
 470 
 471 		case PROP_SHELL_TASKBAR:
 472 			g_value_set_object (
 473 				value, e_shell_view_get_shell_taskbar (
 474 				E_SHELL_VIEW (object)));
 475 			return;
 476 
 477 		case PROP_SHELL_WINDOW:
 478 			g_value_set_object (
 479 				value, e_shell_view_get_shell_window (
 480 				E_SHELL_VIEW (object)));
 481 			return;
 482 
 483 		case PROP_STATE_KEY_FILE:
 484 			g_value_set_pointer (
 485 				value, e_shell_view_get_state_key_file (
 486 				E_SHELL_VIEW (object)));
 487 			return;
 488 
 489 		case PROP_TITLE:
 490 			g_value_set_string (
 491 				value, e_shell_view_get_title (
 492 				E_SHELL_VIEW (object)));
 493 			return;
 494 
 495 		case PROP_VIEW_ID:
 496 			g_value_set_string (
 497 				value, e_shell_view_get_view_id (
 498 				E_SHELL_VIEW (object)));
 499 			return;
 500 	}
 501 
 502 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 503 }
 504 
 505 static void
 506 shell_view_dispose (GObject *object)
 507 {
 508 	EShellViewPrivate *priv;
 509 
 510 	priv = E_SHELL_VIEW_GET_PRIVATE (object);
 511 
 512 	/* Expedite any pending state saves. */
 513 	if (priv->state_save_timeout_id > 0) {
 514 		g_source_remove (priv->state_save_timeout_id);
 515 		priv->state_save_timeout_id = 0;
 516 		if (priv->state_save_activity == NULL)
 517 			shell_view_save_state (E_SHELL_VIEW (object), TRUE);
 518 	}
 519 
 520 	if (priv->state_save_activity != NULL) {
 521 		g_object_remove_weak_pointer (
 522 			G_OBJECT (priv->state_save_activity),
 523 			&priv->state_save_activity);
 524 		priv->state_save_activity = NULL;
 525 	}
 526 
 527 	if (priv->shell_window != NULL) {
 528 		g_object_remove_weak_pointer (
 529 			G_OBJECT (priv->shell_window), &priv->shell_window);
 530 		priv->shell_window = NULL;
 531 	}
 532 
 533 	if (priv->shell_content != NULL) {
 534 		g_object_unref (priv->shell_content);
 535 		priv->shell_content = NULL;
 536 	}
 537 
 538 	if (priv->shell_sidebar != NULL) {
 539 		g_object_unref (priv->shell_sidebar);
 540 		priv->shell_sidebar = NULL;
 541 	}
 542 
 543 	if (priv->shell_taskbar != NULL) {
 544 		g_object_unref (priv->shell_taskbar);
 545 		priv->shell_taskbar = NULL;
 546 	}
 547 
 548 	if (priv->searchbar != NULL) {
 549 		g_object_unref (priv->searchbar);
 550 		priv->searchbar = NULL;
 551 	}
 552 
 553 	if (priv->search_rule != NULL) {
 554 		g_object_unref (priv->search_rule);
 555 		priv->search_rule = NULL;
 556 	}
 557 
 558 	if (priv->preferences_window != NULL) {
 559 		g_signal_handler_disconnect (
 560 			priv->preferences_window,
 561 			priv->preferences_hide_id);
 562 		g_object_unref (priv->preferences_window);
 563 		priv->preferences_window = NULL;
 564 		priv->preferences_hide_id = 0;
 565 	}
 566 
 567 	/* Chain up to parent's dispose() method. */
 568 	G_OBJECT_CLASS (parent_class)->dispose (object);
 569 }
 570 
 571 static void
 572 shell_view_finalize (GObject *object)
 573 {
 574 	EShellViewPrivate *priv;
 575 
 576 	priv = E_SHELL_VIEW_GET_PRIVATE (object);
 577 
 578 	g_key_file_free (priv->state_key_file);
 579 
 580 	g_free (priv->title);
 581 	g_free (priv->view_id);
 582 
 583 	/* Chain up to parent's finalize() method. */
 584 	G_OBJECT_CLASS (parent_class)->finalize (object);
 585 }
 586 
 587 static void
 588 shell_view_constructed (GObject *object)
 589 {
 590 	EShell *shell;
 591 	EShellView *shell_view;
 592 	EShellBackend *shell_backend;
 593 	EShellViewClass *shell_view_class;
 594 	GtkWidget *widget;
 595 
 596 	shell_view = E_SHELL_VIEW (object);
 597 	shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
 598 
 599 	shell_backend = e_shell_view_get_shell_backend (shell_view);
 600 	shell = e_shell_backend_get_shell (shell_backend);
 601 
 602 	shell_view_load_state (shell_view);
 603 
 604 	/* Invoke factory methods. */
 605 
 606 	/* Create the taskbar widget first so the content and
 607 	 * sidebar widgets can access it during construction. */
 608 	widget = shell_view_class->new_shell_taskbar (shell_view);
 609 	shell_view->priv->shell_taskbar = g_object_ref_sink (widget);
 610 	gtk_widget_show (widget);
 611 
 612 	widget = shell_view_class->new_shell_content (shell_view);
 613 	shell_view->priv->shell_content = g_object_ref_sink (widget);
 614 	gtk_widget_show (widget);
 615 
 616 	widget = shell_view_class->new_shell_sidebar (shell_view);
 617 	shell_view->priv->shell_sidebar = g_object_ref_sink (widget);
 618 	gtk_widget_show (widget);
 619 
 620 	if (shell_view_class->construct_searchbar != NULL) {
 621 		widget = shell_view_class->construct_searchbar (shell_view);
 622 		shell_view->priv->searchbar = g_object_ref_sink (widget);
 623 	}
 624 
 625 	/* Size group should be safe to unreference now. */
 626 	g_object_unref (shell_view->priv->size_group);
 627 	shell_view->priv->size_group = NULL;
 628 
 629 	/* Update actions whenever the Preferences window is closed. */
 630 	widget = e_shell_get_preferences_window (shell);
 631 	shell_view->priv->preferences_window = g_object_ref (widget);
 632 	shell_view->priv->preferences_hide_id = g_signal_connect_swapped (
 633 		shell_view->priv->preferences_window, "hide",
 634 		G_CALLBACK (e_shell_view_update_actions), shell_view);
 635 
 636 	e_extensible_load_extensions (E_EXTENSIBLE (object));
 637 
 638 	/* Chain up to parent's constructed() method. */
 639 	G_OBJECT_CLASS (parent_class)->constructed (object);
 640 }
 641 
 642 static GtkWidget *
 643 shell_view_construct_searchbar (EShellView *shell_view)
 644 {
 645 	EShell *shell;
 646 	EShellWindow *shell_window;
 647 	EShellContent *shell_content;
 648 	EShellSearchbar *shell_searchbar;
 649 	EShellViewClass *shell_view_class;
 650 	GtkToolItem *item;
 651 	GtkAction *action;
 652 	GtkWidget *main_toolbar;
 653 	GtkWidget *widget;
 654 
 655 	shell_content = e_shell_view_get_shell_content (shell_view);
 656 	shell_window = e_shell_view_get_shell_window (shell_view);
 657 	shell = e_shell_window_get_shell (shell_window);
 658 
 659 	shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
 660 	widget = shell_view_class->new_shell_searchbar (shell_view);
 661 
 662 	/* In normal mode, we hand the searchbar off to EShellContent. */
 663 	if (!e_shell_get_express_mode (shell)) {
 664 		e_shell_content_set_searchbar (shell_content, widget);
 665 		gtk_widget_show (widget);
 666 		return widget;
 667 	}
 668 
 669 	/* Express mode is more complicated.  We append a heavily simplified
 670 	 * version of it to the main toolbar, but only show it when this shell
 671 	 * view is active.  So each view still gets its own searchbar. */
 672 
 673 	shell_searchbar = E_SHELL_SEARCHBAR (widget);
 674 	e_shell_searchbar_set_express_mode (shell_searchbar, TRUE);
 675 
 676 	/* XXX Hardcoded sizes are evil, but what should the width be
 677 	 *     relative to.  Window width?  The other toolbar width? */
 678 	gtk_widget_set_size_request (widget, SIMPLE_SEARCHBAR_WIDTH, -1);
 679 
 680 	main_toolbar = e_shell_window_get_managed_widget (
 681 		shell_window, "/search-toolbar");
 682 
 683 	item = gtk_tool_item_new ();
 684 	gtk_container_add (GTK_CONTAINER (item), widget);
 685 	gtk_widget_show (GTK_WIDGET (item));
 686 
 687 	action = e_shell_view_get_action (shell_view);
 688 	g_object_bind_property (
 689 		action, "active",
 690 		widget, "visible",
 691 		G_BINDING_SYNC_CREATE);
 692 
 693 	gtk_toolbar_insert (GTK_TOOLBAR (main_toolbar), item, -1);
 694 
 695 	if (e_shell_get_small_screen_mode (shell)) {
 696 		GtkWidget *image;
 697 		GtkWidget *container;
 698 		GtkAction *action;
 699 		GtkToolItem *item;
 700 
 701 		action = e_shell_window_get_action (
 702 			shell_window, "close-window");
 703 		image = gtk_image_new_from_icon_name (
 704 			"window-close-hover", GTK_ICON_SIZE_DIALOG);
 705 		item = gtk_tool_button_new (
 706 			image, gtk_action_get_label (action));
 707 		gtk_widget_set_name (GTK_WIDGET (item), "MeeGoCloseButton");
 708 		gtk_activatable_set_related_action (
 709 			GTK_ACTIVATABLE (item), action);
 710 		container = e_shell_window_get_menu_bar_box (shell_window);
 711 		gtk_box_pack_start (
 712 			GTK_BOX (container),
 713 			GTK_WIDGET (item), FALSE, FALSE, 0);
 714 		gtk_widget_show_all (GTK_WIDGET (item));
 715 	}
 716 
 717 	return widget;
 718 }
 719 
 720 static gchar *
 721 shell_view_get_search_name (EShellView *shell_view)
 722 {
 723 	EShellSearchbar *searchbar;
 724 	EFilterRule *rule;
 725 	const gchar *search_text;
 726 
 727 	rule = e_shell_view_get_search_rule (shell_view);
 728 	g_return_val_if_fail (E_IS_FILTER_RULE (rule), NULL);
 729 
 730 	searchbar = E_SHELL_SEARCHBAR (shell_view->priv->searchbar);
 731 	search_text = e_shell_searchbar_get_search_text (searchbar);
 732 
 733 	if (search_text == NULL || *search_text == '\0')
 734 		search_text = "''";
 735 
 736 	return g_strdup_printf ("%s %s", rule->name, search_text);
 737 }
 738 
 739 static void
 740 shell_view_toggled (EShellView *shell_view)
 741 {
 742 	EShellViewPrivate *priv = shell_view->priv;
 743 	EShellViewClass *shell_view_class;
 744 	EShellWindow *shell_window;
 745 	GtkUIManager *ui_manager;
 746 	const gchar *basename, *id;
 747 	gboolean view_is_active;
 748 
 749 	shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
 750 	shell_window = e_shell_view_get_shell_window (shell_view);
 751 	ui_manager = e_shell_window_get_ui_manager (shell_window);
 752 	view_is_active = e_shell_view_is_active (shell_view);
 753 	basename = shell_view_class->ui_definition;
 754 	id = shell_view_class->ui_manager_id;
 755 
 756 	if (view_is_active && priv->merge_id == 0) {
 757 		priv->merge_id = e_ui_manager_add_ui_from_file (
 758 			E_UI_MANAGER (ui_manager), basename);
 759 		e_plugin_ui_enable_manager (ui_manager, id);
 760 	} else if (!view_is_active && priv->merge_id != 0) {
 761 		e_plugin_ui_disable_manager (ui_manager, id);
 762 		gtk_ui_manager_remove_ui (ui_manager, priv->merge_id);
 763 		gtk_ui_manager_ensure_update (ui_manager);
 764 		priv->merge_id = 0;
 765 	}
 766 
 767 	gtk_ui_manager_ensure_update (ui_manager);
 768 }
 769 
 770 static void
 771 shell_view_clear_search (EShellView *shell_view)
 772 {
 773 	e_shell_view_set_search_rule (shell_view, NULL);
 774 	e_shell_view_execute_search (shell_view);
 775 }
 776 
 777 static void
 778 shell_view_custom_search (EShellView *shell_view,
 779                           EFilterRule *custom_rule)
 780 {
 781 	e_shell_view_set_search_rule (shell_view, custom_rule);
 782 	e_shell_view_execute_search (shell_view);
 783 }
 784 
 785 static void
 786 shell_view_update_actions (EShellView *shell_view)
 787 {
 788 	EShellWindow *shell_window;
 789 	EFocusTracker *focus_tracker;
 790 
 791 	g_return_if_fail (!shell_view->priv->update_actions_blocked);
 792 	g_return_if_fail (e_shell_view_is_active (shell_view));
 793 
 794 	shell_window = e_shell_view_get_shell_window (shell_view);
 795 	focus_tracker = e_shell_window_get_focus_tracker (shell_window);
 796 
 797 	e_focus_tracker_update_actions (focus_tracker);
 798 }
 799 
 800 static void
 801 e_shell_view_class_init (EShellViewClass *class)
 802 {
 803 	GObjectClass *object_class;
 804 
 805 	parent_class = g_type_class_peek_parent (class);
 806 	g_type_class_add_private (class, sizeof (EShellViewPrivate));
 807 
 808 	object_class = G_OBJECT_CLASS (class);
 809 	object_class->set_property = shell_view_set_property;
 810 	object_class->get_property = shell_view_get_property;
 811 	object_class->dispose = shell_view_dispose;
 812 	object_class->finalize = shell_view_finalize;
 813 	object_class->constructed = shell_view_constructed;
 814 
 815 	class->search_context_type = E_TYPE_RULE_CONTEXT;
 816 
 817 	/* Default Factories */
 818 	class->new_shell_content = e_shell_content_new;
 819 	class->new_shell_sidebar = e_shell_sidebar_new;
 820 	class->new_shell_taskbar = e_shell_taskbar_new;
 821 	class->new_shell_searchbar = e_shell_searchbar_new;
 822 
 823 	class->construct_searchbar = shell_view_construct_searchbar;
 824 	class->get_search_name = shell_view_get_search_name;
 825 
 826 	class->toggled = shell_view_toggled;
 827 	class->clear_search = shell_view_clear_search;
 828 	class->custom_search = shell_view_custom_search;
 829 	class->update_actions = shell_view_update_actions;
 830 
 831 	/**
 832 	 * EShellView:action:
 833 	 *
 834 	 * The #GtkRadioAction registered with #EShellSwitcher.
 835 	 **/
 836 	g_object_class_install_property (
 837 		object_class,
 838 		PROP_ACTION,
 839 		g_param_spec_object (
 840 			"action",
 841 			"Switcher Action",
 842 			"The switcher action for this shell view",
 843 			GTK_TYPE_RADIO_ACTION,
 844 			G_PARAM_READWRITE |
 845 			G_PARAM_CONSTRUCT_ONLY));
 846 
 847 	/**
 848 	 * EShellView:page-num
 849 	 *
 850 	 * The #GtkNotebook page number of the shell view.
 851 	 **/
 852 	g_object_class_install_property (
 853 		object_class,
 854 		PROP_PAGE_NUM,
 855 		g_param_spec_int (
 856 			"page-num",
 857 			"Page Number",
 858 			"The notebook page number of the shell view",
 859 			-1,
 860 			G_MAXINT,
 861 			-1,
 862 			G_PARAM_READWRITE));
 863 
 864 	/**
 865 	 * EShellView:search-rule
 866 	 *
 867 	 * Criteria for the current search results.
 868 	 **/
 869 	g_object_class_install_property (
 870 		object_class,
 871 		PROP_SEARCH_RULE,
 872 		g_param_spec_object (
 873 			"search-rule",
 874 			"Search Rule",
 875 			"Criteria for the current search results",
 876 			E_TYPE_FILTER_RULE,
 877 			G_PARAM_READWRITE));
 878 
 879 	/**
 880 	 * EShellView:shell-backend
 881 	 *
 882 	 * The #EShellBackend for this shell view.
 883 	 **/
 884 	g_object_class_install_property (
 885 		object_class,
 886 		PROP_SHELL_BACKEND,
 887 		g_param_spec_object (
 888 			"shell-backend",
 889 			"Shell Backend",
 890 			"The EShellBackend for this shell view",
 891 			E_TYPE_SHELL_BACKEND,
 892 			G_PARAM_READABLE));
 893 
 894 	/**
 895 	 * EShellView:shell-content
 896 	 *
 897 	 * The content widget appears in an #EShellWindow<!-- -->'s
 898 	 * right pane.
 899 	 **/
 900 	g_object_class_install_property (
 901 		object_class,
 902 		PROP_SHELL_CONTENT,
 903 		g_param_spec_object (
 904 			"shell-content",
 905 			"Shell Content Widget",
 906 			"The content widget appears in "
 907 			"a shell window's right pane",
 908 			E_TYPE_SHELL_CONTENT,
 909 			G_PARAM_READABLE));
 910 
 911 	/**
 912 	 * EShellView:shell-sidebar
 913 	 *
 914 	 * The sidebar widget appears in an #EShellWindow<!-- -->'s
 915 	 * left pane.
 916 	 **/
 917 	g_object_class_install_property (
 918 		object_class,
 919 		PROP_SHELL_SIDEBAR,
 920 		g_param_spec_object (
 921 			"shell-sidebar",
 922 			"Shell Sidebar Widget",
 923 			"The sidebar widget appears in "
 924 			"a shell window's left pane",
 925 			E_TYPE_SHELL_SIDEBAR,
 926 			G_PARAM_READABLE));
 927 
 928 	/**
 929 	 * EShellView:shell-taskbar
 930 	 *
 931 	 * The taskbar widget appears at the bottom of an #EShellWindow.
 932 	 **/
 933 	g_object_class_install_property (
 934 		object_class,
 935 		PROP_SHELL_TASKBAR,
 936 		g_param_spec_object (
 937 			"shell-taskbar",
 938 			"Shell Taskbar Widget",
 939 			"The taskbar widget appears at "
 940 			"the bottom of a shell window",
 941 			E_TYPE_SHELL_TASKBAR,
 942 			G_PARAM_READABLE));
 943 
 944 	/**
 945 	 * EShellView:shell-window
 946 	 *
 947 	 * The #EShellWindow to which the shell view belongs.
 948 	 **/
 949 	g_object_class_install_property (
 950 		object_class,
 951 		PROP_SHELL_WINDOW,
 952 		g_param_spec_object (
 953 			"shell-window",
 954 			"Shell Window",
 955 			"The window to which the shell view belongs",
 956 			E_TYPE_SHELL_WINDOW,
 957 			G_PARAM_READWRITE |
 958 			G_PARAM_CONSTRUCT_ONLY));
 959 
 960 	/**
 961 	 * EShellView:state-key-file
 962 	 *
 963 	 * The #GKeyFile holding widget state data.
 964 	 **/
 965 	g_object_class_install_property (
 966 		object_class,
 967 		PROP_STATE_KEY_FILE,
 968 		g_param_spec_pointer (
 969 			"state-key-file",
 970 			"State Key File",
 971 			"The key file holding widget state data",
 972 			G_PARAM_READABLE));
 973 
 974 	/**
 975 	 * EShellView:title
 976 	 *
 977 	 * The title of the shell view.  Also serves as the #EShellWindow
 978 	 * title when the shell view is active.
 979 	 **/
 980 	g_object_class_install_property (
 981 		object_class,
 982 		PROP_TITLE,
 983 		g_param_spec_string (
 984 			"title",
 985 			"Title",
 986 			"The title of the shell view",
 987 			NULL,
 988 			G_PARAM_READWRITE));
 989 
 990 	/**
 991 	 * EShellView:view-id
 992 	 *
 993 	 * The current #GalView ID.
 994 	 **/
 995 	g_object_class_install_property (
 996 		object_class,
 997 		PROP_VIEW_ID,
 998 		g_param_spec_string (
 999 			"view-id",
1000 			"Current View ID",
1001 			"The current GAL view ID",
1002 			NULL,
1003 			G_PARAM_READWRITE));
1004 
1005 	/**
1006 	 * EShellView::toggled
1007 	 * @shell_view: the #EShellView which emitted the signal
1008 	 *
1009 	 * Emitted when @shell_view is activated or deactivated.
1010 	 * Use e_shell_view_is_active() to find out which event has
1011 	 * occurred.  The shell view being deactivated is always
1012 	 * notified before the shell view being activated.
1013 	 *
1014 	 * By default, #EShellView adds the UI definition file
1015 	 * given in the <structfield>ui_definition</structfield>
1016 	 * field of #EShellViewClass on activation, and removes the
1017 	 * UI definition on deactivation.
1018 	 **/
1019 	signals[TOGGLED] = g_signal_new (
1020 		"toggled",
1021 		G_OBJECT_CLASS_TYPE (object_class),
1022 		G_SIGNAL_RUN_FIRST,
1023 		G_STRUCT_OFFSET (EShellViewClass, toggled),
1024 		NULL, NULL,
1025 		g_cclosure_marshal_VOID__VOID,
1026 		G_TYPE_NONE, 0);
1027 
1028 	/**
1029 	 * EShellView::clear-search
1030 	 * @shell_view: the #EShellView which emitted the signal
1031 	 *
1032 	 * Clears the current search.  See e_shell_view_clear_search() for
1033 	 * details.
1034 	 **/
1035 	signals[CLEAR_SEARCH] = g_signal_new (
1036 		"clear-search",
1037 		G_OBJECT_CLASS_TYPE (object_class),
1038 		G_SIGNAL_RUN_LAST,
1039 		G_STRUCT_OFFSET (EShellViewClass, clear_search),
1040 		NULL, NULL,
1041 		g_cclosure_marshal_VOID__VOID,
1042 		G_TYPE_NONE, 0);
1043 
1044 	/**
1045 	 * EShellView::custom-search
1046 	 * @shell_view: the #EShellView which emitted the signal
1047 	 * @custom_rule: criteria for the custom search
1048 	 *
1049 	 * Emitted when an advanced or saved search is about to be executed.
1050 	 * See e_shell_view_custom_search() for details.
1051 	 **/
1052 	signals[CUSTOM_SEARCH] = g_signal_new (
1053 		"custom-search",
1054 		G_OBJECT_CLASS_TYPE (object_class),
1055 		G_SIGNAL_RUN_LAST,
1056 		G_STRUCT_OFFSET (EShellViewClass, custom_search),
1057 		NULL, NULL,
1058 		g_cclosure_marshal_VOID__OBJECT,
1059 		G_TYPE_NONE, 1,
1060 		E_TYPE_FILTER_RULE);
1061 
1062 	/**
1063 	 * EShellView::execute-search
1064 	 * @shell_view: the #EShellView which emitted the signal
1065 	 *
1066 	 * #EShellView subclasses should override the
1067 	 * <structfield>execute_search</structfield> method in
1068 	 * #EShellViewClass to execute the current search conditions.
1069 	 **/
1070 	signals[EXECUTE_SEARCH] = g_signal_new (
1071 		"execute-search",
1072 		G_OBJECT_CLASS_TYPE (object_class),
1073 		G_SIGNAL_RUN_FIRST,
1074 		G_STRUCT_OFFSET (EShellViewClass, execute_search),
1075 		NULL, NULL,
1076 		g_cclosure_marshal_VOID__VOID,
1077 		G_TYPE_NONE, 0);
1078 
1079 	/**
1080 	 * EShellView::update-actions
1081 	 * @shell_view: the #EShellView which emitted the signal
1082 	 *
1083 	 * #EShellView subclasses should override the
1084 	 * <structfield>update_actions</structfield> method in
1085 	 * #EShellViewClass to update sensitivities, labels, or any
1086 	 * other aspect of the #GtkAction<!-- -->s they have registered.
1087 	 *
1088 	 * Plugins can also connect to this signal to be notified
1089 	 * when to update their own #GtkAction<!-- -->s.
1090 	 **/
1091 	signals[UPDATE_ACTIONS] = g_signal_new (
1092 		"update-actions",
1093 		G_OBJECT_CLASS_TYPE (object_class),
1094 		G_SIGNAL_RUN_FIRST,
1095 		G_STRUCT_OFFSET (EShellViewClass, update_actions),
1096 		NULL, NULL,
1097 		g_cclosure_marshal_VOID__VOID,
1098 		G_TYPE_NONE, 0);
1099 }
1100 
1101 static void
1102 e_shell_view_init (EShellView *shell_view,
1103                    EShellViewClass *class)
1104 {
1105 	GtkSizeGroup *size_group;
1106 
1107 	/* XXX Our use of GInstanceInitFunc's 'class' parameter
1108 	 *     prevents us from using G_DEFINE_ABSTRACT_TYPE. */
1109 
1110 	if (class->search_context == NULL)
1111 		shell_view_init_search_context (class);
1112 
1113 	if (class->view_collection == NULL)
1114 		shell_view_init_view_collection (class);
1115 
1116 	size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
1117 
1118 	shell_view->priv = E_SHELL_VIEW_GET_PRIVATE (shell_view);
1119 	shell_view->priv->state_key_file = g_key_file_new ();
1120 	shell_view->priv->size_group = size_group;
1121 }
1122 
1123 GType
1124 e_shell_view_get_type (void)
1125 {
1126 	static GType type = 0;
1127 
1128 	if (G_UNLIKELY (type == 0)) {
1129 		const GTypeInfo type_info = {
1130 			sizeof (EShellViewClass),
1131 			(GBaseInitFunc) NULL,
1132 			(GBaseFinalizeFunc) NULL,
1133 			(GClassInitFunc) e_shell_view_class_init,
1134 			(GClassFinalizeFunc) NULL,
1135 			NULL,  /* class_data */
1136 			sizeof (EShellView),
1137 			0,     /* n_preallocs */
1138 			(GInstanceInitFunc) e_shell_view_init,
1139 			NULL   /* value_table */
1140 		};
1141 
1142 		const GInterfaceInfo extensible_info = {
1143 			(GInterfaceInitFunc) NULL,
1144 			(GInterfaceFinalizeFunc) NULL,
1145 			NULL   /* interface_data */
1146 		};
1147 
1148 		type = g_type_register_static (
1149 			G_TYPE_OBJECT, "EShellView",
1150 			&type_info, G_TYPE_FLAG_ABSTRACT);
1151 
1152 		g_type_add_interface_static (
1153 			type, E_TYPE_EXTENSIBLE, &extensible_info);
1154 	}
1155 
1156 	return type;
1157 }
1158 
1159 /**
1160  * e_shell_view_get_name:
1161  * @shell_view: an #EShellView
1162  *
1163  * Returns the view name for @shell_view, which is also the name of
1164  * the corresponding #EShellBackend (see the <structfield>name</structfield>
1165  * field in #EShellBackendInfo).
1166  *
1167  * Returns: the view name for @shell_view
1168  **/
1169 const gchar *
1170 e_shell_view_get_name (EShellView *shell_view)
1171 {
1172 	GtkAction *action;
1173 
1174 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1175 
1176 	action = e_shell_view_get_action (shell_view);
1177 
1178 	/* Switcher actions have a secret "view-name" data value.
1179 	 * This gets set in e_shell_window_create_switcher_actions(). */
1180 	return g_object_get_data (G_OBJECT (action), "view-name");
1181 }
1182 
1183 /**
1184  * e_shell_view_get_action:
1185  * @shell_view: an #EShellView
1186  *
1187  * Returns the switcher action for @shell_view.
1188  *
1189  * An #EShellWindow creates a #GtkRadioAction for each registered subclass
1190  * of #EShellView.  This action gets passed to the #EShellSwitcher, which
1191  * displays a button that proxies the action.  The icon at the top of the
1192  * sidebar also proxies the action.  When @shell_view is active, the
1193  * action's icon becomes the #EShellWindow icon.
1194  *
1195  * Returns: the switcher action for @shell_view
1196  **/
1197 GtkAction *
1198 e_shell_view_get_action (EShellView *shell_view)
1199 {
1200 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1201 
1202 	return shell_view->priv->action;
1203 }
1204 
1205 /**
1206  * e_shell_view_get_title:
1207  * @shell_view: an #EShellView
1208  *
1209  * Returns the title for @shell_view.  When @shell_view is active, the
1210  * shell view's title becomes the #EShellWindow title.
1211  *
1212  * Returns: the title for @shell_view
1213  **/
1214 const gchar *
1215 e_shell_view_get_title (EShellView *shell_view)
1216 {
1217 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1218 
1219 	return shell_view->priv->title;
1220 }
1221 
1222 /**
1223  * e_shell_view_set_title:
1224  * @shell_view: an #EShellView
1225  * @title: a title for @shell_view
1226  *
1227  * Sets the title for @shell_view.  When @shell_view is active, the
1228  * shell view's title becomes the #EShellWindow title.
1229  **/
1230 void
1231 e_shell_view_set_title (EShellView *shell_view,
1232                         const gchar *title)
1233 {
1234 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1235 
1236 	if (title == NULL)
1237 		title = E_SHELL_VIEW_GET_CLASS (shell_view)->label;
1238 
1239 	if (g_strcmp0 (shell_view->priv->title, title) == 0)
1240 		return;
1241 
1242 	g_free (shell_view->priv->title);
1243 	shell_view->priv->title = g_strdup (title);
1244 
1245 	g_object_notify (G_OBJECT (shell_view), "title");
1246 }
1247 
1248 /**
1249  * e_shell_view_get_view_id:
1250  * @shell_view: an #EShellView
1251  *
1252  * Returns the ID of the currently selected #GalView.
1253  *
1254  * #EShellView subclasses are responsible for keeping this property in
1255  * sync with their #GalViewInstance.  #EShellView itself just provides
1256  * a place to store the view ID, and emits a #GObject::notify signal
1257  * when the property changes.
1258  *
1259  * Returns: the ID of the current #GalView
1260  **/
1261 const gchar *
1262 e_shell_view_get_view_id (EShellView *shell_view)
1263 {
1264 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1265 
1266 	return shell_view->priv->view_id;
1267 }
1268 
1269 /**
1270  * e_shell_view_set_view_id:
1271  * @shell_view: an #EShellView
1272  * @view_id: a #GalView ID
1273  *
1274  * Selects the #GalView whose ID is equal to @view_id.
1275  *
1276  * #EShellView subclasses are responsible for keeping this property in
1277  * sync with their #GalViewInstance.  #EShellView itself just provides
1278  * a place to store the view ID, and emits a #GObject::notify signal
1279  * when the property changes.
1280  **/
1281 void
1282 e_shell_view_set_view_id (EShellView *shell_view,
1283                           const gchar *view_id)
1284 {
1285 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1286 
1287 	if (g_strcmp0 (shell_view->priv->view_id, view_id) == 0)
1288 		return;
1289 
1290 	g_free (shell_view->priv->view_id);
1291 	shell_view->priv->view_id = g_strdup (view_id);
1292 
1293 	g_object_notify (G_OBJECT (shell_view), "view-id");
1294 }
1295 
1296 /**
1297  * e_shell_view_get_shell_window:
1298  * @shell_view: an #EShellView
1299  *
1300  * Returns the #EShellWindow to which @shell_view belongs.
1301  *
1302  * Returns: the #EShellWindow to which @shell_view belongs
1303  **/
1304 EShellWindow *
1305 e_shell_view_get_shell_window (EShellView *shell_view)
1306 {
1307 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1308 
1309 	return E_SHELL_WINDOW (shell_view->priv->shell_window);
1310 }
1311 
1312 /**
1313  * e_shell_view_is_active:
1314  * @shell_view: an #EShellView
1315  *
1316  * Returns %TRUE if @shell_view is active.  That is, if it's currently
1317  * visible in its #EShellWindow.  An #EShellWindow can only display one
1318  * shell view at a time.
1319  *
1320  * Technically this just checks the #GtkToggleAction:active property of
1321  * the shell view's switcher action.  See e_shell_view_get_action().
1322  *
1323  * Returns: %TRUE if @shell_view is active
1324  **/
1325 gboolean
1326 e_shell_view_is_active (EShellView *shell_view)
1327 {
1328 	GtkAction *action;
1329 
1330 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE);
1331 
1332 	action = e_shell_view_get_action (shell_view);
1333 
1334 	return gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
1335 }
1336 
1337 /**
1338  * e_shell_view_get_page_num:
1339  * @shell_view: an #EShellView
1340  *
1341  * This function is only interesting to #EShellWindow.  It returns the
1342  * #GtkNotebook page number for @shell_view.  The rest of the application
1343  * should have no need for this.
1344  *
1345  * Returns: the notebook page number for @shell_view
1346  **/
1347 gint
1348 e_shell_view_get_page_num (EShellView *shell_view)
1349 {
1350 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), -1);
1351 
1352 	return shell_view->priv->page_num;
1353 }
1354 
1355 /**
1356  * e_shell_view_set_page_num:
1357  * @shell_view: an #EShellView
1358  * @page_num: a notebook page number
1359  *
1360  * This function is only interesting to #EShellWindow.  It sets the
1361  * #GtkNotebook page number for @shell_view.  The rest of the application
1362  * must never call this because it could mess up shell view switching.
1363  **/
1364 void
1365 e_shell_view_set_page_num (EShellView *shell_view,
1366                            gint page_num)
1367 {
1368 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1369 
1370 	if (shell_view->priv->page_num == page_num)
1371 		return;
1372 
1373 	shell_view->priv->page_num = page_num;
1374 
1375 	g_object_notify (G_OBJECT (shell_view), "page-num");
1376 }
1377 
1378 /**
1379  * e_shell_view_get_search_name:
1380  * @shell_view: an #EShellView
1381  *
1382  * Returns a newly-allocated string containing a suitable name for the
1383  * current search criteria.  This is used as the suggested name in the
1384  * Save Search dialog.  Free the returned string with g_free().
1385  *
1386  * Returns: a name for the current search criteria
1387  **/
1388 gchar *
1389 e_shell_view_get_search_name (EShellView *shell_view)
1390 {
1391 	EShellViewClass *class;
1392 
1393 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1394 
1395 	class = E_SHELL_VIEW_GET_CLASS (shell_view);
1396 	g_return_val_if_fail (class->get_search_name != NULL, NULL);
1397 
1398 	return class->get_search_name (shell_view);
1399 }
1400 
1401 /**
1402  * e_shell_view_get_search_rule:
1403  * @shell_view: an #EShellView
1404  *
1405  * Returns the search criteria used to generate the current search results.
1406  *
1407  * Returns: the current search criteria
1408  **/
1409 EFilterRule *
1410 e_shell_view_get_search_rule (EShellView *shell_view)
1411 {
1412 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1413 
1414 	return shell_view->priv->search_rule;
1415 }
1416 
1417 /**
1418  * e_shell_view_get_searchbar:
1419  * @shell_view: an #EShellView
1420  *
1421  * Returns the searchbar widget for @shell_view.
1422  **/
1423 GtkWidget *
1424 e_shell_view_get_searchbar (EShellView *shell_view)
1425 {
1426 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1427 
1428 	return shell_view->priv->searchbar;
1429 }
1430 
1431 /**
1432  * e_shell_view_set_search_rule:
1433  * @shell_view: an #EShellView
1434  * @search_rule: an #EFilterRule
1435  *
1436  * Sets the search criteria used to generate the current search results.
1437  * Note that this will not trigger a search.  e_shell_view_execute_search()
1438  * must be called explicitly.
1439  **/
1440 void
1441 e_shell_view_set_search_rule (EShellView *shell_view,
1442                               EFilterRule *search_rule)
1443 {
1444 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1445 
1446 	if (shell_view->priv->search_rule == search_rule)
1447 		return;
1448 
1449 	if (search_rule != NULL) {
1450 		g_return_if_fail (E_IS_FILTER_RULE (search_rule));
1451 		g_object_ref (search_rule);
1452 	}
1453 
1454 	if (shell_view->priv->search_rule != NULL)
1455 		g_object_unref (shell_view->priv->search_rule);
1456 
1457 	shell_view->priv->search_rule = search_rule;
1458 
1459 	g_object_notify (G_OBJECT (shell_view), "search-rule");
1460 }
1461 
1462 /**
1463  * e_shell_view_get_search_query:
1464  * @shell_view: an #EShellView
1465  *
1466  * Converts the #EShellView:search-rule property to a newly-allocated
1467  * S-expression string.  If the #EShellView:search-rule property is %NULL
1468  * the function returns %NULL.
1469  *
1470  * Returns: an S-expression string, or %NULL
1471  **/
1472 gchar *
1473 e_shell_view_get_search_query (EShellView *shell_view)
1474 {
1475 	EFilterRule *rule;
1476 	GString *string;
1477 
1478 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1479 
1480 	rule = e_shell_view_get_search_rule (shell_view);
1481 	if (rule == NULL)
1482 		return NULL;
1483 
1484 	string = g_string_sized_new (1024);
1485 	e_filter_rule_build_code (rule, string);
1486 
1487 	return g_string_free (string, FALSE);
1488 }
1489 
1490 /**
1491  * e_shell_view_get_size_group:
1492  * @shell_view: an #EShellView
1493  *
1494  * Returns a #GtkSizeGroup that #EShellContent and #EShellSidebar use
1495  * to keep the search bar and sidebar banner vertically aligned.  The
1496  * rest of the application should have no need for this.
1497  *
1498  * Note, this is only available during #EShellView construction.
1499  *
1500  * Returns: a #GtkSizeGroup for internal use
1501  **/
1502 GtkSizeGroup *
1503 e_shell_view_get_size_group (EShellView *shell_view)
1504 {
1505 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1506 
1507 	return shell_view->priv->size_group;
1508 }
1509 
1510 /**
1511  * e_shell_view_get_shell_backend:
1512  * @shell_view: an #EShellView
1513  *
1514  * Returns the corresponding #EShellBackend for @shell_view.
1515  *
1516  * Returns: the corresponding #EShellBackend for @shell_view
1517  **/
1518 EShellBackend *
1519 e_shell_view_get_shell_backend (EShellView *shell_view)
1520 {
1521 	EShellViewClass *class;
1522 
1523 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1524 
1525 	class = E_SHELL_VIEW_GET_CLASS (shell_view);
1526 	g_return_val_if_fail (class->shell_backend != NULL, NULL);
1527 
1528 	return class->shell_backend;
1529 }
1530 
1531 /**
1532  * e_shell_view_get_shell_content:
1533  * @shell_view: an #EShellView
1534  *
1535  * Returns the #EShellContent instance for @shell_view.
1536  *
1537  * By default, #EShellView creates a plain #EShellContent during
1538  * initialization.  But #EShellView subclasses can override the
1539  * <structfield>new_shell_content</structfield> factory method
1540  * in #EShellViewClass to create a custom #EShellContent.
1541  *
1542  * Returns: the #EShellContent instance for @shell_view
1543  **/
1544 EShellContent *
1545 e_shell_view_get_shell_content (EShellView *shell_view)
1546 {
1547 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1548 
1549 	return E_SHELL_CONTENT (shell_view->priv->shell_content);
1550 }
1551 
1552 /**
1553  * e_shell_view_get_shell_sidebar:
1554  * @shell_view: an #EShellView
1555  *
1556  * Returns the #EShellSidebar instance for @shell_view.
1557  *
1558  * By default, #EShellView creates a plain #EShellSidebar during
1559  * initialization.  But #EShellView subclasses can override the
1560  * <structfield>new_shell_sidebar</structfield> factory method
1561  * in #EShellViewClass to create a custom #EShellSidebar.
1562  *
1563  * Returns: the #EShellSidebar instance for @shell_view
1564  **/
1565 EShellSidebar *
1566 e_shell_view_get_shell_sidebar (EShellView *shell_view)
1567 {
1568 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1569 
1570 	return E_SHELL_SIDEBAR (shell_view->priv->shell_sidebar);
1571 }
1572 
1573 /**
1574  * e_shell_view_get_shell_taskbar:
1575  * @shell_view: an #EShellView
1576  *
1577  * Returns the #EShellTaskbar instance for @shell_view.
1578  *
1579  * By default, #EShellView creates a plain #EShellTaskbar during
1580  * initialization.  But #EShellView subclasses can override the
1581  * <structfield>new_shell_taskbar</structfield> factory method
1582  * in #EShellViewClass to create a custom #EShellTaskbar.
1583  *
1584  * Returns: the #EShellTaskbar instance for @shell_view
1585  **/
1586 EShellTaskbar *
1587 e_shell_view_get_shell_taskbar (EShellView *shell_view)
1588 {
1589 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1590 
1591 	return E_SHELL_TASKBAR (shell_view->priv->shell_taskbar);
1592 }
1593 
1594 /**
1595  * e_shell_view_get_state_key_file:
1596  * @shell_view: an #EShellView
1597  *
1598  * Returns the #GKeyFile holding widget state data for @shell_view.
1599  *
1600  * Returns: the #GKeyFile for @shell_view
1601  **/
1602 GKeyFile *
1603 e_shell_view_get_state_key_file (EShellView *shell_view)
1604 {
1605 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1606 
1607 	return shell_view->priv->state_key_file;
1608 }
1609 
1610 /**
1611  * e_shell_view_set_state_dirty:
1612  * @shell_view: an #EShellView
1613  *
1614  * Marks the widget state data as modified (or "dirty") and schedules it
1615  * to be saved to disk after a short delay.  The delay caps the frequency
1616  * of saving to disk.
1617  **/
1618 void
1619 e_shell_view_set_state_dirty (EShellView *shell_view)
1620 {
1621 	guint source_id;
1622 
1623 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1624 
1625 	/* If a timeout is already scheduled, do nothing. */
1626 	if (shell_view->priv->state_save_timeout_id > 0)
1627 		return;
1628 
1629 	source_id = g_timeout_add_seconds (
1630 		STATE_SAVE_TIMEOUT_SECONDS, (GSourceFunc)
1631 		shell_view_state_timeout_cb, shell_view);
1632 
1633 	shell_view->priv->state_save_timeout_id = source_id;
1634 }
1635 
1636 /**
1637  * e_shell_view_clear_search:
1638  * @shell_view: an #EShellView
1639  *
1640  * Emits the #EShellView::clear-search signal.
1641  *
1642  * The default method sets the #EShellView:search-rule property to
1643  * %NULL and then emits the #EShellView::execute-search signal.
1644  **/
1645 void
1646 e_shell_view_clear_search (EShellView *shell_view)
1647 {
1648 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1649 
1650 	g_signal_emit (shell_view, signals[CLEAR_SEARCH], 0);
1651 }
1652 
1653 /**
1654  * e_shell_view_custom_search:
1655  * @shell_view: an #EShellView
1656  * @custom_rule: an #EFilterRule
1657  *
1658  * Emits the #EShellView::custom-search signal to indicate an advanced
1659  * or saved search is about to be executed.
1660  *
1661  * The default method sets the #EShellView:search-rule property to
1662  * @custom_rule and then emits the #EShellView::execute-search signal.
1663  **/
1664 void
1665 e_shell_view_custom_search (EShellView *shell_view,
1666                             EFilterRule *custom_rule)
1667 {
1668 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1669 	g_return_if_fail (E_IS_FILTER_RULE (custom_rule));
1670 
1671 	g_signal_emit (shell_view, signals[CUSTOM_SEARCH], 0, custom_rule);
1672 }
1673 
1674 /**
1675  * e_shell_view_execute_search:
1676  * @shell_view: an #EShellView
1677  *
1678  * Emits the #EShellView::execute-search signal.
1679  *
1680  * #EShellView subclasses should implement the
1681  * <structfield>execute_search</structfield> method in #EShellViewClass
1682  * to execute a search based on the current search conditions.
1683  **/
1684 void
1685 e_shell_view_execute_search (EShellView *shell_view)
1686 {
1687 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1688 
1689 	if (!e_shell_view_is_execute_search_blocked (shell_view))
1690 		g_signal_emit (shell_view, signals[EXECUTE_SEARCH], 0);
1691 }
1692 
1693 /**
1694  * e_shell_view_block_execute_search:
1695  * @shell_view: an #EShellView
1696  *
1697  * Blocks e_shell_view_execute_search() in a way it does nothing.
1698  * Pair function for this is e_shell_view_unblock_execute_search().
1699  **/
1700 void
1701 e_shell_view_block_execute_search (EShellView *shell_view)
1702 {
1703 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1704 	g_return_if_fail (shell_view->priv->execute_search_blocked + 1 != 0);
1705 
1706 	shell_view->priv->execute_search_blocked++;
1707 }
1708 
1709 /**
1710  * e_shell_view_unblock_execute_search:
1711  * @shell_view: an #EShellView
1712  *
1713  * Unblocks previously blocked e_shell_view_execute_search() with
1714  * function e_shell_view_block_execute_search().
1715  **/
1716 void
1717 e_shell_view_unblock_execute_search (EShellView *shell_view)
1718 {
1719 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1720 	g_return_if_fail (shell_view->priv->execute_search_blocked > 0);
1721 
1722 	shell_view->priv->execute_search_blocked--;
1723 }
1724 
1725 /**
1726  * e_shell_view_is_execute_search_blocked:
1727  * @shell_view: an #EShellView
1728  *
1729  * Returns whether e_shell_view_execute_search() is blocked.
1730  **/
1731 gboolean
1732 e_shell_view_is_execute_search_blocked (EShellView *shell_view)
1733 {
1734 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE);
1735 
1736 	return shell_view->priv->execute_search_blocked > 0;
1737 }
1738 
1739 /**
1740  * e_shell_view_update_actions:
1741  * @shell_view: an #EShellView
1742  *
1743  * Emits the #EShellView::update-actions signal.
1744  *
1745  * #EShellView subclasses should implement the
1746  * <structfield>update_actions</structfield> method in #EShellViewClass
1747  * to update the various #GtkAction<!-- -->s based on the current
1748  * #EShellSidebar and #EShellContent selections.  The
1749  * #EShellView::update-actions signal is typically emitted just before
1750  * showing a popup menu or just after the user selects an item in the
1751  * shell view.
1752  *
1753  * Emission can be blocked by e_shell_view_block_update_actions().
1754  **/
1755 void
1756 e_shell_view_update_actions (EShellView *shell_view)
1757 {
1758 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1759 
1760 	if (!e_shell_view_is_active (shell_view))
1761 		return;
1762 
1763 	if (shell_view->priv->update_actions_blocked > 0) {
1764 		shell_view->priv->update_actions_called = TRUE;
1765 	} else {
1766 		shell_view->priv->update_actions_called = FALSE;
1767 		g_signal_emit (shell_view, signals[UPDATE_ACTIONS], 0);
1768 	}
1769 }
1770 
1771 /**
1772  * e_shell_view_block_update_actions:
1773  * @shell_view: an #EShellView
1774  *
1775  * Block emission of #EShellView::update-actions signal through
1776  * e_shell_view_update_actions(). The emission si blocked until
1777  * e_shell_view_unblock_update_actions() is called same times as
1778  * this function.
1779  **/
1780 void
1781 e_shell_view_block_update_actions (EShellView *shell_view)
1782 {
1783 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1784 	g_return_if_fail (shell_view->priv->update_actions_blocked + 1 != 0);
1785 
1786 	shell_view->priv->update_actions_blocked++;
1787 	if (shell_view->priv->update_actions_blocked == 1)
1788 		shell_view->priv->update_actions_called = FALSE;
1789 }
1790 
1791 /**
1792  * e_shell_view_unblock_update_actions:
1793  * @shell_view: an #EShellView
1794  *
1795  * Unblock emission of #EShellView::update-actions signal through
1796  * e_shell_view_update_actions(), previously blocked by function
1797  * e_shell_view_block_update_actions().
1798  **/
1799 void
1800 e_shell_view_unblock_update_actions (EShellView *shell_view)
1801 {
1802 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1803 	g_return_if_fail (shell_view->priv->update_actions_blocked > 0);
1804 
1805 	shell_view->priv->update_actions_blocked--;
1806 
1807 	if (!shell_view->priv->update_actions_blocked &&
1808 		shell_view->priv->update_actions_called) {
1809 
1810 		shell_view->priv->update_actions_called = FALSE;
1811 		e_shell_view_update_actions (shell_view);
1812 	}
1813 }
1814 
1815 /**
1816  * e_shell_view_show_popup_menu:
1817  * @shell_view: an #EShellView
1818  * @widget_path: path in the UI definition
1819  * @event: a #GdkEventButton
1820  *
1821  * Displays a context-sensitive (or "popup") menu that is described in
1822  * the UI definition loaded into @shell_view<!-- -->'s user interface
1823  * manager.  The menu will be shown at the current mouse cursor position.
1824  *
1825  * The #EShellView::update-actions signal is emitted just prior to
1826  * showing the menu to give @shell_view and any plugins that extend
1827  * @shell_view a chance to update the menu's actions.
1828  *
1829  * Returns: the popup menu being displayed
1830  **/
1831 GtkWidget *
1832 e_shell_view_show_popup_menu (EShellView *shell_view,
1833                               const gchar *widget_path,
1834                               GdkEventButton *event)
1835 {
1836 	EShellWindow *shell_window;
1837 	GtkWidget *menu;
1838 
1839 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1840 
1841 	e_shell_view_update_actions (shell_view);
1842 
1843 	shell_window = e_shell_view_get_shell_window (shell_view);
1844 	menu = e_shell_window_get_managed_widget (shell_window, widget_path);
1845 	g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
1846 
1847 	if (event != NULL)
1848 		gtk_menu_popup (
1849 			GTK_MENU (menu), NULL, NULL, NULL, NULL,
1850 			event->button, event->time);
1851 	else
1852 		gtk_menu_popup (
1853 			GTK_MENU (menu), NULL, NULL, NULL, NULL,
1854 			0, gtk_get_current_event_time ());
1855 
1856 	return menu;
1857 }
1858 
1859 /**
1860  * e_shell_view_new_view_instance:
1861  * @shell_view: an #EShellView
1862  * @instance_id: a name for the #GalViewInstance
1863  *
1864  * Creates a new #GalViewInstance and configures it to keep
1865  * @shell_view<!-- -->'s #EShellView:view-id property up-to-date.
1866  *
1867  * Returns: a new #GalViewInstance
1868  **/
1869 GalViewInstance *
1870 e_shell_view_new_view_instance (EShellView *shell_view,
1871                                 const gchar *instance_id)
1872 {
1873 	EShellViewClass *class;
1874 	GalViewCollection *view_collection;
1875 	GalViewInstance *view_instance;
1876 
1877 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1878 
1879 	class = E_SHELL_VIEW_GET_CLASS (shell_view);
1880 
1881 	view_collection = class->view_collection;
1882 	view_instance = gal_view_instance_new (view_collection, instance_id);
1883 
1884 	g_signal_connect_swapped (
1885 		view_instance, "changed",
1886 		G_CALLBACK (shell_view_update_view_id), shell_view);
1887 
1888 	g_signal_connect_swapped (
1889 		view_instance, "loaded",
1890 		G_CALLBACK (shell_view_update_view_id), shell_view);
1891 
1892 	return view_instance;
1893 }
1894 
1895 /**
1896  * e_shell_view_write_source:
1897  * @shell_view: an #EShellView
1898  * @source: an #ESource
1899  *
1900  * Submits the current contents of @source to the D-Bus service to be
1901  * written to disk and broadcast to other clients.
1902  *
1903  * This function does not block: @shell_view will dispatch the operation
1904  * asynchronously and handle any errors.
1905  **/
1906 void
1907 e_shell_view_write_source (EShellView *shell_view,
1908                            ESource *source)
1909 {
1910 	EActivity *activity;
1911 	EAlertSink *alert_sink;
1912 	EShellBackend *shell_backend;
1913 	EShellContent *shell_content;
1914 
1915 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1916 	g_return_if_fail (E_IS_SOURCE (source));
1917 
1918 	shell_backend = e_shell_view_get_shell_backend (shell_view);
1919 	shell_content = e_shell_view_get_shell_content (shell_view);
1920 
1921 	alert_sink = E_ALERT_SINK (shell_content);
1922 	activity = e_source_util_write (source, alert_sink);
1923 	e_shell_backend_add_activity (shell_backend, activity);
1924 }
1925 
1926 /**
1927  * e_shell_view_remove_source:
1928  * @shell_view: an #EShellView
1929  * @source: the #ESource to be removed
1930  *
1931  * Requests the D-Bus service to delete the key files for @source and all of
1932  * its descendants and broadcast their removal to all clients.
1933  *
1934  * This function does not block: @shell_view will dispatch the operation
1935  * asynchronously and handle any errors.
1936  **/
1937 void
1938 e_shell_view_remove_source (EShellView *shell_view,
1939                             ESource *source)
1940 {
1941 	EActivity *activity;
1942 	EAlertSink *alert_sink;
1943 	EShellBackend *shell_backend;
1944 	EShellContent *shell_content;
1945 
1946 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1947 	g_return_if_fail (E_IS_SOURCE (source));
1948 
1949 	shell_backend = e_shell_view_get_shell_backend (shell_view);
1950 	shell_content = e_shell_view_get_shell_content (shell_view);
1951 
1952 	alert_sink = E_ALERT_SINK (shell_content);
1953 	activity = e_source_util_remove (source, alert_sink);
1954 	e_shell_backend_add_activity (shell_backend, activity);
1955 }
1956 
1957 /**
1958  * e_shell_view_remote_delete_source:
1959  * @shell_view: an #EShellView
1960  * @source: an #ESource
1961  *
1962  * Deletes the resource represented by @source from a remote server.
1963  * The @source must be #ESource:remote-deletable.  This will also delete
1964  * the key file for @source and broadcast its removal to all clients,
1965  * similar to e_shell_view_remove_source().
1966  *
1967  * This function does not block; @shell_view will dispatch the operation
1968  * asynchronously and handle any errors.
1969  **/
1970 void
1971 e_shell_view_remote_delete_source (EShellView *shell_view,
1972                                    ESource *source)
1973 {
1974 	EActivity *activity;
1975 	EAlertSink *alert_sink;
1976 	EShellBackend *shell_backend;
1977 	EShellContent *shell_content;
1978 
1979 	g_return_if_fail (E_IS_SHELL_VIEW (shell_view));
1980 	g_return_if_fail (E_IS_SOURCE (source));
1981 
1982 	shell_backend = e_shell_view_get_shell_backend (shell_view);
1983 	shell_content = e_shell_view_get_shell_content (shell_view);
1984 
1985 	alert_sink = E_ALERT_SINK (shell_content);
1986 	activity = e_source_util_remote_delete (source, alert_sink);
1987 	e_shell_backend_add_activity (shell_backend, activity);
1988 }