evolution-3.6.4/addressbook/gui/widgets/e-addressbook-view.c

Location Tool Test ID Function Issue
e-addressbook-view.c:1441:38 clang-analyzer Access to field 'sorter' results in a dereference of a null pointer (loaded from variable 'selection_model')
e-addressbook-view.c:1441:38 clang-analyzer Access to field 'sorter' results in a dereference of a null pointer (loaded from variable 'selection_model')
   1 /*
   2  * This program is free software; you can redistribute it and/or
   3  * modify it under the terms of the GNU Lesser General Public
   4  * License as published by the Free Software Foundation; either
   5  * version 2 of the License, or (at your option) version 3.
   6  *
   7  * This program is distributed in the hope that it will be useful,
   8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10  * Lesser General Public License for more details.
  11  *
  12  * You should have received a copy of the GNU Lesser General Public
  13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  14  *
  15  *
  16  * Authors:
  17  *		Chris Lahey <clahey@ximian.com>
  18  *      Chris Toshok <toshok@ximian.com>
  19  *
  20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  21  *
  22  */
  23 
  24 #ifdef HAVE_CONFIG_H
  25 #include <config.h>
  26 #endif
  27 
  28 #include <glib/gi18n.h>
  29 #include <table/e-table.h>
  30 #include <table/e-table-model.h>
  31 #include <table/e-cell-date.h>
  32 #include <misc/e-selectable.h>
  33 #include <widgets/menus/gal-view-factory-etable.h>
  34 #include <filter/e-rule-editor.h>
  35 #include <widgets/menus/gal-view-etable.h>
  36 #include <shell/e-shell-sidebar.h>
  37 
  38 #include "addressbook/printing/e-contact-print.h"
  39 #include "ea-addressbook.h"
  40 
  41 #include "e-util/e-print.h"
  42 #include "e-util/e-selection.h"
  43 #include "e-util/e-util.h"
  44 
  45 #include "gal-view-minicard.h"
  46 #include "gal-view-factory-minicard.h"
  47 
  48 #include "e-addressbook-view.h"
  49 #include "e-addressbook-model.h"
  50 #include "eab-gui-util.h"
  51 #include "util/eab-book-util.h"
  52 #include "e-addressbook-table-adapter.h"
  53 #include "eab-contact-merging.h"
  54 
  55 #include "libevolution-utils/e-alert-dialog.h"
  56 #include "e-util/e-util-private.h"
  57 
  58 #include <gdk/gdkkeysyms.h>
  59 #include <ctype.h>
  60 #include <string.h>
  61 
  62 #define E_ADDRESSBOOK_VIEW_GET_PRIVATE(obj) \
  63 	(G_TYPE_INSTANCE_GET_PRIVATE \
  64 	((obj), E_TYPE_ADDRESSBOOK_VIEW, EAddressbookViewPrivate))
  65 
  66 #define d(x)
  67 
  68 static void	status_message			(EAddressbookView *view,
  69 						 const gchar *status, gint percent);
  70 static void	search_result			(EAddressbookView *view,
  71 						 const GError *error);
  72 static void	folder_bar_message		(EAddressbookView *view,
  73 						 const gchar *status);
  74 static void	stop_state_changed		(GObject *object,
  75 						 EAddressbookView *view);
  76 static void	backend_died			(EAddressbookView *view);
  77 static void	command_state_change		(EAddressbookView *view);
  78 
  79 struct _EAddressbookViewPrivate {
  80 	gpointer shell_view;  /* weak pointer */
  81 
  82 	EAddressbookModel *model;
  83 	EActivity *activity;
  84 
  85 	ESource *source;
  86 
  87 	GObject *object;
  88 
  89 	GalViewInstance *view_instance;
  90 
  91 	/* stored search setup for this view */
  92 	gint filter_id;
  93 	gchar *search_text;
  94 	gint search_id;
  95 	EFilterRule *advanced_search;
  96 
  97 	GtkTargetList *copy_target_list;
  98 	GtkTargetList *paste_target_list;
  99 };
 100 
 101 enum {
 102 	PROP_0,
 103 	PROP_COPY_TARGET_LIST,
 104 	PROP_MODEL,
 105 	PROP_PASTE_TARGET_LIST,
 106 	PROP_SHELL_VIEW,
 107 	PROP_SOURCE
 108 };
 109 
 110 enum {
 111 	OPEN_CONTACT,
 112 	POPUP_EVENT,
 113 	COMMAND_STATE_CHANGE,
 114 	SELECTION_CHANGE,
 115 	LAST_SIGNAL
 116 };
 117 
 118 enum {
 119 	DND_TARGET_TYPE_SOURCE_VCARD,
 120 	DND_TARGET_TYPE_VCARD
 121 };
 122 
 123 static GtkTargetEntry drag_types[] = {
 124 	{ (gchar *) "text/x-source-vcard", 0, DND_TARGET_TYPE_SOURCE_VCARD },
 125 	{ (gchar *) "text/x-vcard", 0, DND_TARGET_TYPE_VCARD }
 126 };
 127 
 128 static guint signals[LAST_SIGNAL];
 129 
 130 /* Forward Declarations */
 131 static void	e_addressbook_view_selectable_init
 132 					(ESelectableInterface *interface);
 133 
 134 G_DEFINE_TYPE_WITH_CODE (
 135 	EAddressbookView,
 136 	e_addressbook_view,
 137 	GTK_TYPE_SCROLLED_WINDOW,
 138 	G_IMPLEMENT_INTERFACE (
 139 		E_TYPE_SELECTABLE,
 140 		e_addressbook_view_selectable_init))
 141 
 142 static void
 143 addressbook_view_emit_open_contact (EAddressbookView *view,
 144                                     EContact *contact,
 145                                     gboolean is_new_contact)
 146 {
 147 	g_signal_emit (view, signals[OPEN_CONTACT], 0, contact, is_new_contact);
 148 }
 149 
 150 static void
 151 addressbook_view_emit_popup_event (EAddressbookView *view,
 152                                    GdkEvent *event)
 153 {
 154 	/* Grab focus so that EFocusTracker asks us to update the
 155 	 * selection-related actions before showing the popup menu.
 156 	 * Apparently ETable doesn't automatically grab focus on
 157 	 * right-clicks (is that a bug?). */
 158 	gtk_widget_grab_focus (GTK_WIDGET (view));
 159 
 160 	g_signal_emit (view, signals[POPUP_EVENT], 0, event);
 161 }
 162 
 163 static void
 164 addressbook_view_emit_selection_change (EAddressbookView *view)
 165 {
 166 	g_signal_emit (view, signals[SELECTION_CHANGE], 0);
 167 }
 168 
 169 static void
 170 addressbook_view_open_contact (EAddressbookView *view,
 171                                EContact *contact)
 172 {
 173 	addressbook_view_emit_open_contact (view, contact, FALSE);
 174 }
 175 
 176 static void
 177 addressbook_view_create_contact (EAddressbookView *view)
 178 {
 179 	EContact *contact;
 180 
 181 	contact = e_contact_new ();
 182 	addressbook_view_emit_open_contact (view, contact, TRUE);
 183 	g_object_unref (contact);
 184 }
 185 
 186 static void
 187 addressbook_view_create_contact_list (EAddressbookView *view)
 188 {
 189 	EContact *contact;
 190 
 191 	contact = e_contact_new ();
 192 	e_contact_set (contact, E_CONTACT_IS_LIST, GINT_TO_POINTER (TRUE));
 193 	addressbook_view_emit_open_contact (view, contact, TRUE);
 194 	g_object_unref (contact);
 195 }
 196 
 197 static void
 198 table_double_click (ETable *table,
 199                     gint row,
 200                     gint col,
 201                     GdkEvent *event,
 202                     EAddressbookView *view)
 203 {
 204 	EAddressbookModel *model;
 205 	EContact *contact;
 206 
 207 	if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object))
 208 		return;
 209 
 210 	model = e_addressbook_view_get_model (view);
 211 	contact = e_addressbook_model_get_contact (model, row);
 212 	addressbook_view_emit_open_contact (view, contact, FALSE);
 213 	g_object_unref (contact);
 214 }
 215 
 216 static gint
 217 table_right_click (ETable *table,
 218                    gint row,
 219                    gint col,
 220                    GdkEvent *event,
 221                    EAddressbookView *view)
 222 {
 223 	addressbook_view_emit_popup_event (view, event);
 224 
 225 	return TRUE;
 226 }
 227 
 228 static gint
 229 table_white_space_event (ETable *table,
 230                          GdkEvent *event,
 231                          EAddressbookView *view)
 232 {
 233 	gint button = ((GdkEventButton *) event)->button;
 234 
 235 	if (event->type == GDK_BUTTON_PRESS && button == 3) {
 236 		addressbook_view_emit_popup_event (view, event);
 237 		return TRUE;
 238 	}
 239 
 240 	return FALSE;
 241 }
 242 
 243 static void
 244 table_drag_data_get (ETable *table,
 245                      gint row,
 246                      gint col,
 247                      GdkDragContext *context,
 248                      GtkSelectionData *selection_data,
 249                      guint info,
 250                      guint time,
 251                      gpointer user_data)
 252 {
 253 	EAddressbookView *view = user_data;
 254 	EAddressbookModel *model;
 255 	EBookClient *book_client;
 256 	GSList *contact_list;
 257 	GdkAtom target;
 258 	gchar *value;
 259 
 260 	if (!E_IS_ADDRESSBOOK_TABLE_ADAPTER (view->priv->object))
 261 		return;
 262 
 263 	model = e_addressbook_view_get_model (view);
 264 	book_client = e_addressbook_model_get_client (model);
 265 
 266 	contact_list = e_addressbook_view_get_selected (view);
 267 	target = gtk_selection_data_get_target (selection_data);
 268 
 269 	switch (info) {
 270 		case DND_TARGET_TYPE_VCARD:
 271 			value = eab_contact_list_to_string (contact_list);
 272 
 273 			gtk_selection_data_set (
 274 				selection_data, target, 8,
 275 				(guchar *) value, strlen (value));
 276 
 277 			g_free (value);
 278 			break;
 279 
 280 		case DND_TARGET_TYPE_SOURCE_VCARD:
 281 			value = eab_book_and_contact_list_to_string (
 282 				book_client, contact_list);
 283 
 284 			gtk_selection_data_set (
 285 				selection_data, target, 8,
 286 				(guchar *) value, strlen (value));
 287 
 288 			g_free (value);
 289 			break;
 290 	}
 291 
 292 	e_client_util_free_object_slist (contact_list);
 293 }
 294 
 295 static void
 296 addressbook_view_create_table_view (EAddressbookView *view,
 297                                     GalViewEtable *gal_view)
 298 {
 299 	ETableModel *adapter;
 300 	ETableExtras *extras;
 301 	ECell *cell;
 302 	GtkWidget *widget;
 303 	gchar *etspecfile;
 304 
 305 	adapter = e_addressbook_table_adapter_new (view->priv->model);
 306 
 307 	extras = e_table_extras_new ();
 308 
 309 	/* Set proper format component for a default 'date' cell renderer. */
 310 	cell = e_table_extras_get_cell (extras, "date");
 311 	e_cell_date_set_format_component (E_CELL_DATE (cell), "addressbook");
 312 
 313 	/* Here we create the table.  We give it the three pieces of
 314 	 * the table we've created, the header, the model, and the
 315 	 * initial layout.  It does the rest.  */
 316 	etspecfile = g_build_filename (
 317 		EVOLUTION_ETSPECDIR, "e-addressbook-view.etspec", NULL);
 318 	widget = e_table_new_from_spec_file (
 319 		adapter, extras, etspecfile, NULL);
 320 	gtk_container_add (GTK_CONTAINER (view), widget);
 321 	g_free (etspecfile);
 322 
 323 	view->priv->object = G_OBJECT (adapter);
 324 
 325 	g_signal_connect (
 326 		widget, "double_click",
 327 		G_CALLBACK (table_double_click), view);
 328 	g_signal_connect (
 329 		widget, "right_click",
 330 		G_CALLBACK (table_right_click), view);
 331 	g_signal_connect (
 332 		widget, "white_space_event",
 333 		G_CALLBACK (table_white_space_event), view);
 334 	g_signal_connect_swapped (
 335 		widget, "selection_change",
 336 		G_CALLBACK (addressbook_view_emit_selection_change), view);
 337 
 338 	e_table_drag_source_set (
 339 		E_TABLE (widget), GDK_BUTTON1_MASK,
 340 		drag_types, G_N_ELEMENTS (drag_types),
 341 		GDK_ACTION_MOVE | GDK_ACTION_COPY);
 342 
 343 	g_signal_connect (
 344 		E_TABLE (widget), "table_drag_data_get",
 345 		G_CALLBACK (table_drag_data_get), view);
 346 
 347 	gtk_widget_show (widget);
 348 
 349 	gal_view_etable_attach_table (gal_view, E_TABLE (widget));
 350 }
 351 
 352 static void
 353 addressbook_view_create_minicard_view (EAddressbookView *view,
 354                                        GalViewMinicard *gal_view)
 355 {
 356 	GtkWidget *minicard_view;
 357 	EAddressbookReflowAdapter *adapter;
 358 
 359 	adapter = E_ADDRESSBOOK_REFLOW_ADAPTER (
 360 		e_addressbook_reflow_adapter_new (view->priv->model));
 361 	minicard_view = e_minicard_view_widget_new (adapter);
 362 
 363 	g_signal_connect_swapped (
 364 		adapter, "open-contact",
 365 		G_CALLBACK (addressbook_view_open_contact), view);
 366 
 367 	g_signal_connect_swapped (
 368 		minicard_view, "create-contact",
 369 		G_CALLBACK (addressbook_view_create_contact), view);
 370 
 371 	g_signal_connect_swapped (
 372 		minicard_view, "create-contact-list",
 373 		G_CALLBACK (addressbook_view_create_contact_list), view);
 374 
 375 	g_signal_connect_swapped (
 376 		minicard_view, "selection_change",
 377 		G_CALLBACK (addressbook_view_emit_selection_change), view);
 378 
 379 	g_signal_connect_swapped (
 380 		minicard_view, "right_click",
 381 		G_CALLBACK (addressbook_view_emit_popup_event), view);
 382 
 383 	view->priv->object = G_OBJECT (minicard_view);
 384 
 385 	gtk_container_add (GTK_CONTAINER (view), minicard_view);
 386 	gtk_widget_show (minicard_view);
 387 
 388 	e_reflow_model_changed (E_REFLOW_MODEL (adapter));
 389 
 390 	gal_view_minicard_attach (gal_view, view);
 391 }
 392 
 393 static void
 394 addressbook_view_display_view_cb (EAddressbookView *view,
 395                                   GalView *gal_view)
 396 {
 397 	GtkWidget *child;
 398 
 399 	child = gtk_bin_get_child (GTK_BIN (view));
 400 	if (child != NULL)
 401 		gtk_container_remove (GTK_CONTAINER (view), child);
 402 	view->priv->object = NULL;
 403 
 404 	if (GAL_IS_VIEW_ETABLE (gal_view))
 405 		addressbook_view_create_table_view (
 406 			view, GAL_VIEW_ETABLE (gal_view));
 407 	else if (GAL_IS_VIEW_MINICARD (gal_view))
 408 		addressbook_view_create_minicard_view (
 409 			view, GAL_VIEW_MINICARD (gal_view));
 410 
 411 	command_state_change (view);
 412 }
 413 
 414 static void
 415 addressbook_view_set_shell_view (EAddressbookView *view,
 416                                  EShellView *shell_view)
 417 {
 418 	g_return_if_fail (view->priv->shell_view == NULL);
 419 
 420 	view->priv->shell_view = shell_view;
 421 
 422 	g_object_add_weak_pointer (
 423 		G_OBJECT (shell_view),
 424 		&view->priv->shell_view);
 425 }
 426 
 427 static void
 428 addressbook_view_set_source (EAddressbookView *view,
 429                              ESource *source)
 430 {
 431 	g_return_if_fail (view->priv->source == NULL);
 432 
 433 	view->priv->source = g_object_ref (source);
 434 }
 435 
 436 static void
 437 addressbook_view_set_property (GObject *object,
 438                                guint property_id,
 439                                const GValue *value,
 440                                GParamSpec *pspec)
 441 {
 442 	switch (property_id) {
 443 		case PROP_SHELL_VIEW:
 444 			addressbook_view_set_shell_view (
 445 				E_ADDRESSBOOK_VIEW (object),
 446 				g_value_get_object (value));
 447 			return;
 448 
 449 		case PROP_SOURCE:
 450 			addressbook_view_set_source (
 451 				E_ADDRESSBOOK_VIEW (object),
 452 				g_value_get_object (value));
 453 			return;
 454 	}
 455 
 456 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 457 }
 458 
 459 static void
 460 addressbook_view_get_property (GObject *object,
 461                                guint property_id,
 462                                GValue *value,
 463                                GParamSpec *pspec)
 464 {
 465 	switch (property_id) {
 466 		case PROP_COPY_TARGET_LIST:
 467 			g_value_set_boxed (
 468 				value,
 469 				e_addressbook_view_get_copy_target_list (
 470 				E_ADDRESSBOOK_VIEW (object)));
 471 			return;
 472 
 473 		case PROP_MODEL:
 474 			g_value_set_object (
 475 				value,
 476 				e_addressbook_view_get_model (
 477 				E_ADDRESSBOOK_VIEW (object)));
 478 			return;
 479 
 480 		case PROP_PASTE_TARGET_LIST:
 481 			g_value_set_boxed (
 482 				value,
 483 				e_addressbook_view_get_paste_target_list (
 484 				E_ADDRESSBOOK_VIEW (object)));
 485 			return;
 486 
 487 		case PROP_SHELL_VIEW:
 488 			g_value_set_object (
 489 				value,
 490 				e_addressbook_view_get_shell_view (
 491 				E_ADDRESSBOOK_VIEW (object)));
 492 			return;
 493 
 494 		case PROP_SOURCE:
 495 			g_value_set_object (
 496 				value,
 497 				e_addressbook_view_get_source (
 498 				E_ADDRESSBOOK_VIEW (object)));
 499 			return;
 500 	}
 501 
 502 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 503 }
 504 
 505 static void
 506 addressbook_view_dispose (GObject *object)
 507 {
 508 	EAddressbookViewPrivate *priv;
 509 
 510 	priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (object);
 511 
 512 	if (priv->shell_view != NULL) {
 513 		g_object_remove_weak_pointer (
 514 			G_OBJECT (priv->shell_view),
 515 			&priv->shell_view);
 516 		priv->shell_view = NULL;
 517 	}
 518 
 519 	if (priv->model != NULL) {
 520 		g_signal_handlers_disconnect_matched (
 521 			priv->model, G_SIGNAL_MATCH_DATA,
 522 			0, 0, NULL, NULL, object);
 523 		g_object_unref (priv->model);
 524 		priv->model = NULL;
 525 	}
 526 
 527 	if (priv->activity != NULL) {
 528 		/* XXX Activity is not cancellable. */
 529 		e_activity_set_state (priv->activity, E_ACTIVITY_COMPLETED);
 530 		g_object_unref (priv->activity);
 531 		priv->activity = NULL;
 532 	}
 533 
 534 	if (priv->source != NULL) {
 535 		g_object_unref (priv->source);
 536 		priv->source = NULL;
 537 	}
 538 
 539 	if (priv->view_instance != NULL) {
 540 		g_object_unref (priv->view_instance);
 541 		priv->view_instance = NULL;
 542 	}
 543 
 544 	priv->filter_id = 0;
 545 	priv->search_id = 0;
 546 
 547 	if (priv->search_text) {
 548 		g_free (priv->search_text);
 549 		priv->search_text = NULL;
 550 	}
 551 
 552 	if (priv->advanced_search) {
 553 		g_object_unref (priv->advanced_search);
 554 		priv->advanced_search = NULL;
 555 	}
 556 
 557 	if (priv->copy_target_list != NULL) {
 558 		gtk_target_list_unref (priv->copy_target_list);
 559 		priv->copy_target_list = NULL;
 560 	}
 561 
 562 	if (priv->paste_target_list != NULL) {
 563 		gtk_target_list_unref (priv->paste_target_list);
 564 		priv->paste_target_list = NULL;
 565 	}
 566 
 567 	/* Chain up to parent's dispose() method. */
 568 	G_OBJECT_CLASS (e_addressbook_view_parent_class)->dispose (object);
 569 }
 570 
 571 static void
 572 addressbook_view_constructed (GObject *object)
 573 {
 574 	EAddressbookView *view = E_ADDRESSBOOK_VIEW (object);
 575 	GalViewInstance *view_instance;
 576 	EShell *shell;
 577 	EShellView *shell_view;
 578 	EShellBackend *shell_backend;
 579 	ESourceRegistry *registry;
 580 	ESource *source;
 581 	const gchar *uid;
 582 
 583 	shell_view = e_addressbook_view_get_shell_view (view);
 584 	shell_backend = e_shell_view_get_shell_backend (shell_view);
 585 	shell = e_shell_backend_get_shell (shell_backend);
 586 	registry = e_shell_get_registry (shell);
 587 
 588 	source = e_addressbook_view_get_source (view);
 589 	uid = e_source_get_uid (source);
 590 
 591 	view->priv->model = e_addressbook_model_new (registry);
 592 
 593 	view_instance = e_shell_view_new_view_instance (shell_view, uid);
 594 	g_signal_connect_swapped (
 595 		view_instance, "display-view",
 596 		G_CALLBACK (addressbook_view_display_view_cb), view);
 597 	view->priv->view_instance = view_instance;
 598 
 599 	/* Do not call gal_view_instance_load() here.  EBookShellContent
 600 	 * must first obtain a reference to this EAddressbookView so that
 601 	 * e_book_shell_content_get_current_view() returns the correct
 602 	 * view in GalViewInstance::loaded signal handlers. */
 603 
 604 	/* Chain up to parent's constructed() method. */
 605 	G_OBJECT_CLASS (e_addressbook_view_parent_class)->constructed (object);
 606 }
 607 
 608 static void
 609 addressbook_view_update_actions (ESelectable *selectable,
 610                                  EFocusTracker *focus_tracker,
 611                                  GdkAtom *clipboard_targets,
 612                                  gint n_clipboard_targets)
 613 {
 614 	EAddressbookView *view;
 615 	EAddressbookModel *model;
 616 	ESelectionModel *selection_model;
 617 	GtkAction *action;
 618 	GtkTargetList *target_list;
 619 	gboolean can_paste = FALSE;
 620 	gboolean source_is_editable;
 621 	gboolean sensitive;
 622 	const gchar *tooltip;
 623 	gint n_contacts;
 624 	gint n_selected;
 625 	gint ii;
 626 
 627 	view = E_ADDRESSBOOK_VIEW (selectable);
 628 	model = e_addressbook_view_get_model (view);
 629 	selection_model = e_addressbook_view_get_selection_model (view);
 630 
 631 	source_is_editable = e_addressbook_model_get_editable (model);
 632 	n_contacts = (selection_model != NULL) ?
 633 		e_selection_model_row_count (selection_model) : 0;
 634 	n_selected = (selection_model != NULL) ?
 635 		e_selection_model_selected_count (selection_model) : 0;
 636 
 637 	target_list = e_selectable_get_paste_target_list (selectable);
 638 	for (ii = 0; ii < n_clipboard_targets && !can_paste; ii++)
 639 		can_paste = gtk_target_list_find (
 640 			target_list, clipboard_targets[ii], NULL);
 641 
 642 	action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
 643 	sensitive = source_is_editable && (n_selected > 0);
 644 	tooltip = _("Cut selected contacts to the clipboard");
 645 	gtk_action_set_sensitive (action, sensitive);
 646 	gtk_action_set_tooltip (action, tooltip);
 647 
 648 	action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
 649 	sensitive = (n_selected > 0);
 650 	tooltip = _("Copy selected contacts to the clipboard");
 651 	gtk_action_set_sensitive (action, sensitive);
 652 	gtk_action_set_tooltip (action, tooltip);
 653 
 654 	action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
 655 	sensitive = source_is_editable && can_paste;
 656 	tooltip = _("Paste contacts from the clipboard");
 657 	gtk_action_set_sensitive (action, sensitive);
 658 	gtk_action_set_tooltip (action, tooltip);
 659 
 660 	action = e_focus_tracker_get_delete_selection_action (focus_tracker);
 661 	sensitive = source_is_editable && (n_selected > 0);
 662 	tooltip = _("Delete selected contacts");
 663 	gtk_action_set_sensitive (action, sensitive);
 664 	gtk_action_set_tooltip (action, tooltip);
 665 
 666 	action = e_focus_tracker_get_select_all_action (focus_tracker);
 667 	sensitive = (n_contacts > 0);
 668 	tooltip = _("Select all visible contacts");
 669 	gtk_action_set_sensitive (action, sensitive);
 670 	gtk_action_set_tooltip (action, tooltip);
 671 }
 672 
 673 static void
 674 addressbook_view_cut_clipboard (ESelectable *selectable)
 675 {
 676 	EAddressbookView *view;
 677 
 678 	view = E_ADDRESSBOOK_VIEW (selectable);
 679 
 680 	e_selectable_copy_clipboard (selectable);
 681 	e_addressbook_view_delete_selection (view, FALSE);
 682 }
 683 
 684 static void
 685 addressbook_view_copy_clipboard (ESelectable *selectable)
 686 {
 687 	EAddressbookView *view;
 688 	GtkClipboard *clipboard;
 689 	GSList *contact_list;
 690 	gchar *string;
 691 
 692 	view = E_ADDRESSBOOK_VIEW (selectable);
 693 	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
 694 
 695 	contact_list = e_addressbook_view_get_selected (view);
 696 
 697 	string = eab_contact_list_to_string (contact_list);
 698 	e_clipboard_set_directory (clipboard, string, -1);
 699 	g_free (string);
 700 
 701 	e_client_util_free_object_slist (contact_list);
 702 }
 703 
 704 static void
 705 addressbook_view_paste_clipboard (ESelectable *selectable)
 706 {
 707 	EBookClient *book_client;
 708 	EAddressbookView *view;
 709 	EAddressbookModel *model;
 710 	ESourceRegistry *registry;
 711 	GtkClipboard *clipboard;
 712 	GSList *contact_list, *iter;
 713 	gchar *string;
 714 
 715 	view = E_ADDRESSBOOK_VIEW (selectable);
 716 	clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
 717 
 718 	if (!e_clipboard_wait_is_directory_available (clipboard))
 719 		return;
 720 
 721 	model = e_addressbook_view_get_model (view);
 722 	registry = e_addressbook_model_get_registry (model);
 723 	book_client = e_addressbook_model_get_client (model);
 724 
 725 	string = e_clipboard_wait_for_directory (clipboard);
 726 	contact_list = eab_contact_list_from_string (string);
 727 	g_free (string);
 728 
 729 	for (iter = contact_list; iter != NULL; iter = iter->next) {
 730 		EContact *contact = iter->data;
 731 
 732 		eab_merging_book_add_contact (
 733 			registry, book_client, contact, NULL, NULL);
 734 	}
 735 
 736 	e_client_util_free_object_slist (contact_list);
 737 }
 738 
 739 static void
 740 addressbook_view_delete_selection (ESelectable *selectable)
 741 {
 742 	EAddressbookView *view;
 743 
 744 	view = E_ADDRESSBOOK_VIEW (selectable);
 745 
 746 	e_addressbook_view_delete_selection (view, TRUE);
 747 }
 748 
 749 static void
 750 addressbook_view_select_all (ESelectable *selectable)
 751 {
 752 	EAddressbookView *view;
 753 	ESelectionModel *selection_model;
 754 
 755 	view = E_ADDRESSBOOK_VIEW (selectable);
 756 	selection_model = e_addressbook_view_get_selection_model (view);
 757 
 758 	if (selection_model != NULL)
 759 		e_selection_model_select_all (selection_model);
 760 }
 761 
 762 static void
 763 e_addressbook_view_class_init (EAddressbookViewClass *class)
 764 {
 765 	GObjectClass *object_class;
 766 
 767 	g_type_class_add_private (class, sizeof (EAddressbookViewPrivate));
 768 
 769 	object_class = G_OBJECT_CLASS (class);
 770 	object_class->set_property = addressbook_view_set_property;
 771 	object_class->get_property = addressbook_view_get_property;
 772 	object_class->dispose = addressbook_view_dispose;
 773 	object_class->constructed = addressbook_view_constructed;
 774 
 775 	/* Inherited from ESelectableInterface */
 776 	g_object_class_override_property (
 777 		object_class,
 778 		PROP_COPY_TARGET_LIST,
 779 		"copy-target-list");
 780 
 781 	g_object_class_install_property (
 782 		object_class,
 783 		PROP_MODEL,
 784 		g_param_spec_object (
 785 			"model",
 786 			"Model",
 787 			NULL,
 788 			E_TYPE_ADDRESSBOOK_MODEL,
 789 			G_PARAM_READABLE));
 790 
 791 	/* Inherited from ESelectableInterface */
 792 	g_object_class_override_property (
 793 		object_class,
 794 		PROP_PASTE_TARGET_LIST,
 795 		"paste-target-list");
 796 
 797 	g_object_class_install_property (
 798 		object_class,
 799 		PROP_SHELL_VIEW,
 800 		g_param_spec_object (
 801 			"shell-view",
 802 			"Shell View",
 803 			NULL,
 804 			E_TYPE_SHELL_VIEW,
 805 			G_PARAM_READWRITE |
 806 			G_PARAM_CONSTRUCT_ONLY));
 807 
 808 	g_object_class_install_property (
 809 		object_class,
 810 		PROP_SOURCE,
 811 		g_param_spec_object (
 812 			"source",
 813 			"Source",
 814 			NULL,
 815 			E_TYPE_SOURCE,
 816 			G_PARAM_READWRITE |
 817 			G_PARAM_CONSTRUCT_ONLY));
 818 
 819 	signals[OPEN_CONTACT] = g_signal_new (
 820 		"open-contact",
 821 		G_TYPE_FROM_CLASS (class),
 822 		G_SIGNAL_RUN_LAST,
 823 		G_STRUCT_OFFSET (EAddressbookViewClass, open_contact),
 824 		NULL, NULL,
 825 		e_marshal_VOID__OBJECT_BOOLEAN,
 826 		G_TYPE_NONE, 2,
 827 		E_TYPE_CONTACT,
 828 		G_TYPE_BOOLEAN);
 829 
 830 	signals[POPUP_EVENT] = g_signal_new (
 831 		"popup-event",
 832 		G_TYPE_FROM_CLASS (class),
 833 		G_SIGNAL_RUN_LAST,
 834 		G_STRUCT_OFFSET (EAddressbookViewClass, popup_event),
 835 		NULL, NULL,
 836 		g_cclosure_marshal_VOID__BOXED,
 837 		G_TYPE_NONE, 1,
 838 		GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 839 
 840 	signals[COMMAND_STATE_CHANGE] = g_signal_new (
 841 		"command-state-change",
 842 		G_TYPE_FROM_CLASS (class),
 843 		G_SIGNAL_RUN_LAST,
 844 		G_STRUCT_OFFSET (EAddressbookViewClass, command_state_change),
 845 		NULL, NULL,
 846 		g_cclosure_marshal_VOID__VOID,
 847 		G_TYPE_NONE, 0);
 848 
 849 	signals[SELECTION_CHANGE] = g_signal_new (
 850 		"selection-change",
 851 		G_TYPE_FROM_CLASS (class),
 852 		G_SIGNAL_RUN_LAST,
 853 		G_STRUCT_OFFSET (EAddressbookViewClass, selection_change),
 854 		NULL, NULL,
 855 		g_cclosure_marshal_VOID__VOID,
 856 		G_TYPE_NONE, 0);
 857 
 858 	/* init the accessibility support for e_addressbook_view */
 859 	eab_view_a11y_init ();
 860 }
 861 
 862 static void
 863 e_addressbook_view_init (EAddressbookView *view)
 864 {
 865 	GtkTargetList *target_list;
 866 
 867 	view->priv = E_ADDRESSBOOK_VIEW_GET_PRIVATE (view);
 868 
 869 	target_list = gtk_target_list_new (NULL, 0);
 870 	e_target_list_add_directory_targets (target_list, 0);
 871 	view->priv->copy_target_list = target_list;
 872 
 873 	target_list = gtk_target_list_new (NULL, 0);
 874 	e_target_list_add_directory_targets (target_list, 0);
 875 	view->priv->paste_target_list = target_list;
 876 
 877 	gtk_scrolled_window_set_policy (
 878 		GTK_SCROLLED_WINDOW (view),
 879 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 880 	gtk_scrolled_window_set_shadow_type (
 881 		GTK_SCROLLED_WINDOW (view), GTK_SHADOW_IN);
 882 }
 883 
 884 static void
 885 e_addressbook_view_selectable_init (ESelectableInterface *interface)
 886 {
 887 	interface->update_actions = addressbook_view_update_actions;
 888 	interface->cut_clipboard = addressbook_view_cut_clipboard;
 889 	interface->copy_clipboard = addressbook_view_copy_clipboard;
 890 	interface->paste_clipboard = addressbook_view_paste_clipboard;
 891 	interface->delete_selection = addressbook_view_delete_selection;
 892 	interface->select_all = addressbook_view_select_all;
 893 }
 894 
 895 GtkWidget *
 896 e_addressbook_view_new (EShellView *shell_view,
 897                         ESource *source)
 898 {
 899 	GtkWidget *widget;
 900 	EAddressbookView *view;
 901 
 902 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
 903 
 904 	widget = g_object_new (
 905 		E_TYPE_ADDRESSBOOK_VIEW, "shell-view",
 906 		shell_view, "source", source, NULL);
 907 
 908 	view = E_ADDRESSBOOK_VIEW (widget);
 909 
 910 	g_signal_connect_swapped (
 911 		view->priv->model, "status_message",
 912 		G_CALLBACK (status_message), view);
 913 	g_signal_connect_swapped (
 914 		view->priv->model, "search_result",
 915 		G_CALLBACK (search_result), view);
 916 	g_signal_connect_swapped (
 917 		view->priv->model, "folder_bar_message",
 918 		G_CALLBACK (folder_bar_message), view);
 919 	g_signal_connect (
 920 		view->priv->model, "stop_state_changed",
 921 		G_CALLBACK (stop_state_changed), view);
 922 	g_signal_connect_swapped (
 923 		view->priv->model, "writable-status",
 924 		G_CALLBACK (command_state_change), view);
 925 	g_signal_connect_swapped (
 926 		view->priv->model, "backend_died",
 927 		G_CALLBACK (backend_died), view);
 928 
 929 	return widget;
 930 }
 931 
 932 EAddressbookModel *
 933 e_addressbook_view_get_model (EAddressbookView *view)
 934 {
 935 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
 936 
 937 	return view->priv->model;
 938 }
 939 
 940 GalViewInstance *
 941 e_addressbook_view_get_view_instance (EAddressbookView *view)
 942 {
 943 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
 944 
 945 	return view->priv->view_instance;
 946 }
 947 
 948 GObject *
 949 e_addressbook_view_get_view_object (EAddressbookView *view)
 950 {
 951 	/* XXX Find a more descriptive name for this. */
 952 
 953 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
 954 
 955 	return view->priv->object;
 956 }
 957 
 958 /* Helper for e_addressbook_view_get_selected() */
 959 static void
 960 add_to_list (gint model_row,
 961              gpointer closure)
 962 {
 963 	GSList **list = closure;
 964 	*list = g_slist_prepend (*list, GINT_TO_POINTER (model_row));
 965 }
 966 
 967 GSList *
 968 e_addressbook_view_get_selected (EAddressbookView *view)
 969 {
 970 	GSList *list, *iter;
 971 	ESelectionModel *selection;
 972 
 973 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
 974 
 975 	list = NULL;
 976 	selection = e_addressbook_view_get_selection_model (view);
 977 	e_selection_model_foreach (selection, add_to_list, &list);
 978 
 979 	for (iter = list; iter != NULL; iter = iter->next)
 980 		iter->data = e_addressbook_model_get_contact (
 981 			view->priv->model, GPOINTER_TO_INT (iter->data));
 982 	return g_slist_reverse (list);
 983 }
 984 
 985 ESelectionModel *
 986 e_addressbook_view_get_selection_model (EAddressbookView *view)
 987 {
 988 	GalView *gal_view;
 989 	GalViewInstance *view_instance;
 990 	ESelectionModel *model = NULL;
 991 
 992 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
 993 
 994 	view_instance = e_addressbook_view_get_view_instance (view);
 995 	gal_view = gal_view_instance_get_current_view (view_instance);
 996 
 997 	if (GAL_IS_VIEW_ETABLE (gal_view)) {
 998 		GtkWidget *child;
 999 
1000 		child = gtk_bin_get_child (GTK_BIN (view));
1001 		model = e_table_get_selection_model (E_TABLE (child));
1002 
1003 	} else if (GAL_IS_VIEW_MINICARD (gal_view)) {
1004 		EMinicardViewWidget *widget;
1005 
1006 		widget = E_MINICARD_VIEW_WIDGET (view->priv->object);
1007 		model = e_minicard_view_widget_get_selection_model (widget);
1008 	}
1009 
1010 	return model;
1011 }
1012 
1013 EShellView *
1014 e_addressbook_view_get_shell_view (EAddressbookView *view)
1015 {
1016 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
1017 
1018 	return view->priv->shell_view;
1019 }
1020 
1021 ESource *
1022 e_addressbook_view_get_source (EAddressbookView *view)
1023 {
1024 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
1025 
1026 	return view->priv->source;
1027 }
1028 
1029 GtkTargetList *
1030 e_addressbook_view_get_copy_target_list (EAddressbookView *view)
1031 {
1032 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
1033 
1034 	return view->priv->copy_target_list;
1035 }
1036 
1037 GtkTargetList *
1038 e_addressbook_view_get_paste_target_list (EAddressbookView *view)
1039 {
1040 	g_return_val_if_fail (E_IS_ADDRESSBOOK_VIEW (view), NULL);
1041 
1042 	return view->priv->paste_target_list;
1043 }
1044 
1045 static void
1046 status_message (EAddressbookView *view,
1047                 const gchar *status,
1048                 gint percent)
1049 {
1050 	EActivity *activity;
1051 	EShellView *shell_view;
1052 	EShellBackend *shell_backend;
1053 
1054 	activity = view->priv->activity;
1055 	shell_view = e_addressbook_view_get_shell_view (view);
1056 	shell_backend = e_shell_view_get_shell_backend (shell_view);
1057 
1058 	if (status == NULL || *status == '\0') {
1059 		if (activity != NULL) {
1060 			view->priv->activity = NULL;
1061 			e_activity_set_state (activity, E_ACTIVITY_COMPLETED);
1062 			g_object_unref (activity);
1063 		}
1064 
1065 	} else if (activity == NULL) {
1066 		activity = e_activity_new ();
1067 		view->priv->activity = activity;
1068 		e_activity_set_text (activity, status);
1069 		if (percent >= 0)
1070 			e_activity_set_percent (activity, percent);
1071 		e_shell_backend_add_activity (shell_backend, activity);
1072 	} else {
1073 		e_activity_set_text (activity, status);
1074 		if (percent >= 0)
1075 			e_activity_set_percent (activity, percent);
1076 	}
1077 }
1078 
1079 static void
1080 search_result (EAddressbookView *view,
1081                const GError *error)
1082 {
1083 	EShellView *shell_view;
1084 	EAlertSink *alert_sink;
1085 
1086 	shell_view = e_addressbook_view_get_shell_view (view);
1087 	alert_sink = E_ALERT_SINK (e_shell_view_get_shell_content (shell_view));
1088 
1089 	eab_search_result_dialog (alert_sink, error);
1090 }
1091 
1092 static void
1093 folder_bar_message (EAddressbookView *view,
1094                     const gchar *message)
1095 {
1096 	EShellView *shell_view;
1097 	EShellSidebar *shell_sidebar;
1098 	const gchar *display_name;
1099 
1100 	shell_view = e_addressbook_view_get_shell_view (view);
1101 	shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
1102 
1103 	if (view->priv->source == NULL)
1104 		return;
1105 
1106 	display_name = e_source_get_display_name (view->priv->source);
1107 	e_shell_sidebar_set_primary_text (shell_sidebar, display_name);
1108 	e_shell_sidebar_set_secondary_text (shell_sidebar, message);
1109 }
1110 
1111 static void
1112 stop_state_changed (GObject *object,
1113                     EAddressbookView *view)
1114 {
1115 	command_state_change (view);
1116 }
1117 
1118 static void
1119 command_state_change (EAddressbookView *view)
1120 {
1121 	g_signal_emit (view, signals[COMMAND_STATE_CHANGE], 0);
1122 }
1123 
1124 static void
1125 backend_died (EAddressbookView *view)
1126 {
1127 	EShellView *shell_view;
1128 	EAlertSink *alert_sink;
1129 	EAddressbookModel *model;
1130 	EBookClient *book_client;
1131 	ESource *source;
1132 
1133 	shell_view = e_addressbook_view_get_shell_view (view);
1134 	alert_sink = E_ALERT_SINK (e_shell_view_get_shell_content (shell_view));
1135 
1136 	model = e_addressbook_view_get_model (view);
1137 	book_client = e_addressbook_model_get_client (model);
1138 	source = e_client_get_source (E_CLIENT (book_client));
1139 
1140 	e_alert_submit (
1141 		alert_sink,
1142 		"addressbook:backend-died",
1143 		e_source_get_display_name (source), NULL);
1144 }
1145 
1146 static void
1147 contact_print_button_draw_page (GtkPrintOperation *operation,
1148                                 GtkPrintContext *context,
1149                                 gint page_nr,
1150                                 EPrintable *printable)
1151 {
1152 	GtkPageSetup *setup;
1153 	gdouble top_margin, page_width;
1154 	cairo_t *cr;
1155 
1156 	setup = gtk_print_context_get_page_setup (context);
1157 	top_margin = gtk_page_setup_get_top_margin (setup, GTK_UNIT_POINTS);
1158 	page_width = gtk_page_setup_get_page_width (setup, GTK_UNIT_POINTS);
1159 
1160 	cr = gtk_print_context_get_cairo_context (context);
1161 
1162 	e_printable_reset (printable);
1163 
1164 	while (e_printable_data_left (printable)) {
1165 		cairo_save (cr);
1166 		contact_page_draw_footer (operation,context,page_nr++);
1167 		e_printable_print_page (
1168 			printable, context, page_width - 16, top_margin + 10, TRUE);
1169 		cairo_restore (cr);
1170 	}
1171 }
1172 
1173 static void
1174 e_contact_print_button (EPrintable *printable,
1175                         GtkPrintOperationAction action)
1176 {
1177 	GtkPrintOperation *operation;
1178 
1179 	operation = e_print_operation_new ();
1180 	gtk_print_operation_set_n_pages (operation, 1);
1181 
1182 	g_signal_connect (
1183 		operation, "draw_page",
1184 		G_CALLBACK (contact_print_button_draw_page), printable);
1185 
1186 	gtk_print_operation_run (operation, action, NULL, NULL);
1187 
1188 	g_object_unref (operation);
1189 }
1190 
1191 void
1192 e_addressbook_view_print (EAddressbookView *view,
1193                           gboolean selection_only,
1194                           GtkPrintOperationAction action)
1195 {
1196 	GalView *gal_view;
1197 	GalViewInstance *view_instance;
1198 
1199 	g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view));
1200 
1201 	view_instance = e_addressbook_view_get_view_instance (view);
1202 	gal_view = gal_view_instance_get_current_view (view_instance);
1203 
1204 	/* Print the selected contacts. */
1205 	if (GAL_IS_VIEW_MINICARD (gal_view) && selection_only) {
1206 		GSList *contact_list;
1207 
1208 		contact_list = e_addressbook_view_get_selected (view);
1209 		e_contact_print (NULL, NULL, contact_list, action);
1210 		e_client_util_free_object_slist (contact_list);
1211 
1212 	/* Print the latest query results. */
1213 	} else if (GAL_IS_VIEW_MINICARD (gal_view)) {
1214 		EAddressbookModel *model;
1215 		EBookClient *book_client;
1216 		EBookQuery *query;
1217 		const gchar *query_string;
1218 
1219 		model = e_addressbook_view_get_model (view);
1220 		book_client = e_addressbook_model_get_client (model);
1221 		query_string = e_addressbook_model_get_query (model);
1222 
1223 		if (query_string != NULL)
1224 			query = e_book_query_from_string (query_string);
1225 		else
1226 			query = NULL;
1227 
1228 		e_contact_print (book_client, query, NULL, action);
1229 
1230 		if (query != NULL)
1231 			e_book_query_unref (query);
1232 
1233 	/* XXX Does this print the entire table or just selected? */
1234 	} else if (GAL_IS_VIEW_ETABLE (gal_view)) {
1235 		EPrintable *printable;
1236 		GtkWidget *widget;
1237 
1238 		widget = gtk_bin_get_child (GTK_BIN (view));
1239 		printable = e_table_get_printable (E_TABLE (widget));
1240 		g_object_ref_sink (printable);
1241 
1242 		e_contact_print_button (printable, action);
1243 
1244 		g_object_unref (printable);
1245 	}
1246 }
1247 
1248 static void
1249 report_and_free_error_if_any (GError *error)
1250 {
1251 	if (!error)
1252 		return;
1253 
1254 	if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_CANCELLED) ||
1255 	    g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
1256 		g_error_free (error);
1257 		return;
1258 	}
1259 
1260 	if (g_error_matches (error, E_CLIENT_ERROR, E_CLIENT_ERROR_PERMISSION_DENIED)) {
1261 		e_alert_run_dialog_for_args (
1262 			e_shell_get_active_window (NULL),
1263 			"addressbook:contact-delete-error-perm", NULL);
1264 	} else {
1265 		eab_error_dialog (NULL, _("Failed to delete contact"), error);
1266 	}
1267 
1268 	g_error_free (error);
1269 }
1270 
1271 /* callback function to handle removal of contacts for
1272  * which a user doesnt have write permission
1273  */
1274 static void
1275 remove_contacts_cb (GObject *source_object,
1276                     GAsyncResult *result,
1277                     gpointer user_data)
1278 {
1279 	EBookClient *book_client = E_BOOK_CLIENT (source_object);
1280 	GError *error = NULL;
1281 
1282 	e_book_client_remove_contacts_finish (book_client, result, &error);
1283 
1284 	report_and_free_error_if_any (error);
1285 }
1286 
1287 static void
1288 remove_contact_cb (GObject *source_object,
1289                    GAsyncResult *result,
1290                    gpointer user_data)
1291 {
1292 	EBookClient *book_client = E_BOOK_CLIENT (source_object);
1293 	GError *error = NULL;
1294 
1295 	e_book_client_remove_contact_finish (book_client, result, &error);
1296 
1297 	report_and_free_error_if_any (error);
1298 }
1299 
1300 static gboolean
1301 addressbook_view_confirm_delete (GtkWindow *parent,
1302                                  gboolean plural,
1303                                  gboolean is_list,
1304                                  const gchar *name)
1305 {
1306 	GtkWidget *dialog;
1307 	gchar *message;
1308 	gint response;
1309 
1310 	if (is_list) {
1311 		if (plural) {
1312 			message = g_strdup (
1313 				_("Are you sure you want to "
1314 				"delete these contact lists?"));
1315 		} else if (name == NULL) {
1316 			message = g_strdup (
1317 				_("Are you sure you want to "
1318 				"delete this contact list?"));
1319 		} else {
1320 			message = g_strdup_printf (
1321 				_("Are you sure you want to delete "
1322 				"this contact list (%s)?"), name);
1323 		}
1324 	} else {
1325 		if (plural) {
1326 			message = g_strdup (
1327 				_("Are you sure you want to "
1328 				"delete these contacts?"));
1329 		} else if (name == NULL) {
1330 			message = g_strdup (
1331 				_("Are you sure you want to "
1332 				"delete this contact?"));
1333 		} else {
1334 			message = g_strdup_printf (
1335 				_("Are you sure you want to delete "
1336 				"this contact (%s)?"), name);
1337 		}
1338 	}
1339 
1340 	dialog = gtk_message_dialog_new (
1341 		parent, 0, GTK_MESSAGE_QUESTION,
1342 		GTK_BUTTONS_NONE, "%s", message);
1343 	gtk_dialog_add_buttons (
1344 		GTK_DIALOG (dialog),
1345 		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1346 		GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT,
1347 		NULL);
1348 	response = gtk_dialog_run (GTK_DIALOG (dialog));
1349 	gtk_widget_destroy (dialog);
1350 
1351 	g_free (message);
1352 
1353 	return (response == GTK_RESPONSE_ACCEPT);
1354 }
1355 
1356 void
1357 e_addressbook_view_delete_selection (EAddressbookView *view,
1358                                      gboolean is_delete)
1359 {
1360 	GSList *list, *l;
1361 	gboolean plural = FALSE, is_list = FALSE;
1362 	EContact *contact;
1363 	ETable *etable = NULL;
1364 	EAddressbookModel *model;
1365 	EBookClient *book_client;
1366 	ESelectionModel *selection_model = NULL;
1367 	GalViewInstance *view_instance;
1368 	GalView *gal_view;
1369 	GtkWidget *widget;
1370 	gchar *name = NULL;
1371 	gint row = 0, select;
1372 
1373 	model = e_addressbook_view_get_model (view);
1374 	book_client = e_addressbook_model_get_client (model);
1375 
1376 	view_instance = e_addressbook_view_get_view_instance (view);
1377 	gal_view = gal_view_instance_get_current_view (view_instance);
1378 
1379 	list = e_addressbook_view_get_selected (view);
1380 	contact = list->data;
1381 
1382 	if (g_slist_next (list))
1383 		plural = TRUE;
1384 	else
1385 		name = e_contact_get (contact, E_CONTACT_FILE_AS);
1386 
1387 	if (e_contact_get (contact, E_CONTACT_IS_LIST))
1388 		is_list = TRUE;
1389 
1390 	widget = gtk_bin_get_child (GTK_BIN (view));
1391 
1392 	if (GAL_IS_VIEW_MINICARD (gal_view)) {
1393 		selection_model = e_addressbook_view_get_selection_model (view);
1394 		row = e_selection_model_cursor_row (selection_model);
1395 	}
1396 
1397 	else if (GAL_IS_VIEW_ETABLE (gal_view)) {
1398 		etable = E_TABLE (widget);
1399 		row = e_table_get_cursor_row (E_TABLE (etable));
1400 	}
1401 
1402 	/* confirm delete */
1403 	if (is_delete && !addressbook_view_confirm_delete (
1404 			GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (view))),
1405 			plural, is_list, name)) {
1406 		g_free (name);
1407 		e_client_util_free_object_slist (list);
1408 		return;
1409 	}
1410 
1411 	if (e_client_check_capability (E_CLIENT (book_client), "bulk-remove")) {
1412 		GSList *ids = NULL;
1413 
1414 		for (l = list; l; l = g_slist_next (l)) {
1415 			const gchar *uid;
1416 
1417 			contact = l->data;
1418 
1419 			uid = e_contact_get_const (contact, E_CONTACT_UID);
1420 			ids = g_slist_prepend (ids, (gpointer) uid);
1421 		}
1422 
1423 		/* Remove the cards all at once. */
1424 		e_book_client_remove_contacts (
1425 			book_client, ids, NULL, remove_contacts_cb, NULL);
1426 
1427 		g_slist_free (ids);
1428 	} else {
1429 		for (l = list; l; l = g_slist_next (l)) {
1430 			contact = l->data;
1431 
1432 			/* Remove the card. */
1433 			e_book_client_remove_contact (
1434 				book_client, contact, NULL,
1435 				remove_contact_cb, NULL);
1436 		}
1437 	}
1438 
1439 	/* Sets the cursor, at the row after the deleted row */
1440 	if (GAL_IS_VIEW_MINICARD (gal_view) && row != 0) {
1441 		select = e_sorter_model_to_sorted (selection_model->sorter, row);
Access to field 'sorter' results in a dereference of a null pointer (loaded from variable 'selection_model')
(emitted by clang-analyzer)

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

Access to field 'sorter' results in a dereference of a null pointer (loaded from variable 'selection_model')
(emitted by clang-analyzer)

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

1442 1443 /* Sets the cursor, before the deleted row if its the last row */ 1444 if (select == e_selection_model_row_count (selection_model) - 1) 1445 select = select - 1; 1446 else 1447 select = select + 1; 1448 1449 row = e_sorter_sorted_to_model (selection_model->sorter, select); 1450 e_selection_model_cursor_changed (selection_model, row, 0); 1451 } 1452 1453 /* Sets the cursor, at the row after the deleted row */ 1454 else if (GAL_IS_VIEW_ETABLE (gal_view) && row != 0) { 1455 select = e_table_model_to_view_row (E_TABLE (etable), row); 1456 1457 /* Sets the cursor, before the deleted row if its the last row */ 1458 if (select == e_table_model_row_count (E_TABLE (etable)->model) - 1) 1459 select = select - 1; 1460 else 1461 select = select + 1; 1462 1463 row = e_table_view_to_model_row (E_TABLE (etable), select); 1464 e_table_set_cursor_row (E_TABLE (etable), row); 1465 } 1466 e_client_util_free_object_slist (list); 1467 } 1468 1469 void 1470 e_addressbook_view_view (EAddressbookView *view) 1471 { 1472 GSList *list, *iter; 1473 gint response; 1474 guint length; 1475 1476 g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); 1477 1478 list = e_addressbook_view_get_selected (view); 1479 length = g_slist_length (list); 1480 response = GTK_RESPONSE_YES; 1481 1482 if (length > 5) { 1483 GtkWidget *dialog; 1484 1485 /* XXX Use e_alert_new(). */ 1486 /* XXX Provide a parent window. */ 1487 dialog = gtk_message_dialog_new ( 1488 NULL, 0, 1489 GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, ngettext ( 1490 /* Translators: This is shown for > 5 contacts. */ 1491 "Opening %d contacts will open %d new windows " 1492 "as well.\nDo you really want to display all of " 1493 "these contacts?", 1494 "Opening %d contacts will open %d new windows " 1495 "as well.\nDo you really want to display all of " 1496 "these contacts?", length), length, length); 1497 gtk_dialog_add_buttons ( 1498 GTK_DIALOG (dialog), 1499 _("_Don't Display"), GTK_RESPONSE_NO, 1500 _("Display _All Contacts"), GTK_RESPONSE_YES, 1501 NULL); 1502 response = gtk_dialog_run (GTK_DIALOG (dialog)); 1503 gtk_widget_destroy (dialog); 1504 } 1505 1506 if (response == GTK_RESPONSE_YES) 1507 for (iter = list; iter != NULL; iter = iter->next) 1508 addressbook_view_emit_open_contact ( 1509 view, iter->data, FALSE); 1510 1511 e_client_util_free_object_slist (list); 1512 } 1513 1514 void 1515 e_addressbook_view_show_all (EAddressbookView *view) 1516 { 1517 g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); 1518 1519 e_addressbook_model_set_query (view->priv->model, ""); 1520 } 1521 1522 void 1523 e_addressbook_view_stop (EAddressbookView *view) 1524 { 1525 g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); 1526 1527 e_addressbook_model_stop (view->priv->model); 1528 } 1529 1530 struct TransferContactsData 1531 { 1532 gboolean delete_from_source; 1533 EAddressbookView *view; 1534 }; 1535 1536 static void 1537 all_contacts_ready_cb (GObject *source_object, 1538 GAsyncResult *result, 1539 gpointer user_data) 1540 { 1541 EBookClient *book_client = E_BOOK_CLIENT (source_object); 1542 struct TransferContactsData *tcd = user_data; 1543 EAddressbookModel *model; 1544 ESourceRegistry *registry; 1545 EShellView *shell_view; 1546 EShellContent *shell_content; 1547 EAlertSink *alert_sink; 1548 GSList *contacts = NULL; 1549 GError *error = NULL; 1550 1551 g_return_if_fail (book_client != NULL); 1552 g_return_if_fail (tcd != NULL); 1553 1554 if (!e_book_client_get_contacts_finish (book_client, result, &contacts, &error)) 1555 contacts = NULL; 1556 1557 shell_view = e_addressbook_view_get_shell_view (tcd->view); 1558 shell_content = e_shell_view_get_shell_content (shell_view); 1559 alert_sink = E_ALERT_SINK (shell_content); 1560 1561 model = e_addressbook_view_get_model (tcd->view); 1562 registry = e_addressbook_model_get_registry (model); 1563 1564 if (error) { 1565 e_alert_submit ( 1566 alert_sink, "addressbook:search-error", 1567 error->message, NULL); 1568 g_error_free (error); 1569 } else if (contacts) { 1570 eab_transfer_contacts ( 1571 registry, book_client, contacts, 1572 tcd->delete_from_source, alert_sink); 1573 } 1574 1575 g_object_unref (tcd->view); 1576 g_free (tcd); 1577 } 1578 1579 static void 1580 view_transfer_contacts (EAddressbookView *view, 1581 gboolean delete_from_source, 1582 gboolean all) 1583 { 1584 EBookClient *book_client; 1585 ESourceRegistry *registry; 1586 1587 registry = e_addressbook_model_get_registry (view->priv->model); 1588 book_client = e_addressbook_model_get_client (view->priv->model); 1589 1590 if (all) { 1591 EBookQuery *query; 1592 gchar *query_str; 1593 struct TransferContactsData *tcd; 1594 1595 query = e_book_query_any_field_contains (""); 1596 query_str = e_book_query_to_string (query); 1597 e_book_query_unref (query); 1598 1599 tcd = g_new0 (struct TransferContactsData, 1); 1600 tcd->delete_from_source = delete_from_source; 1601 tcd->view = g_object_ref (view); 1602 1603 e_book_client_get_contacts ( 1604 book_client, query_str, NULL, 1605 all_contacts_ready_cb, tcd); 1606 } else { 1607 GSList *contacts = NULL; 1608 EShellView *shell_view; 1609 EShellContent *shell_content; 1610 EAlertSink *alert_sink; 1611 1612 shell_view = e_addressbook_view_get_shell_view (view); 1613 shell_content = e_shell_view_get_shell_content (shell_view); 1614 alert_sink = E_ALERT_SINK (shell_content); 1615 1616 contacts = e_addressbook_view_get_selected (view); 1617 1618 eab_transfer_contacts ( 1619 registry, book_client, contacts, 1620 delete_from_source, alert_sink); 1621 } 1622 } 1623 1624 void 1625 e_addressbook_view_copy_to_folder (EAddressbookView *view, 1626 gboolean all) 1627 { 1628 view_transfer_contacts (view, FALSE, all); 1629 } 1630 1631 void 1632 e_addressbook_view_move_to_folder (EAddressbookView *view, 1633 gboolean all) 1634 { 1635 view_transfer_contacts (view, TRUE, all); 1636 } 1637 1638 void 1639 e_addressbook_view_set_search (EAddressbookView *view, 1640 gint filter_id, 1641 gint search_id, 1642 const gchar *search_text, 1643 EFilterRule *advanced_search) 1644 { 1645 EAddressbookViewPrivate *priv; 1646 1647 g_return_if_fail (view != NULL); 1648 g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); 1649 1650 priv = view->priv; 1651 1652 if (priv->search_text) 1653 g_free (priv->search_text); 1654 if (priv->advanced_search) 1655 g_object_unref (priv->advanced_search); 1656 1657 priv->filter_id = filter_id; 1658 priv->search_id = search_id; 1659 priv->search_text = g_strdup (search_text); 1660 1661 if (advanced_search != NULL) 1662 priv->advanced_search = e_filter_rule_clone (advanced_search); 1663 else 1664 priv->advanced_search = NULL; 1665 } 1666 1667 /* Free returned values for search_text and advanced_search, 1668 * if not NULL, as these are new copies. */ 1669 void 1670 e_addressbook_view_get_search (EAddressbookView *view, 1671 gint *filter_id, 1672 gint *search_id, 1673 gchar **search_text, 1674 EFilterRule **advanced_search) 1675 { 1676 EAddressbookViewPrivate *priv; 1677 1678 g_return_if_fail (view != NULL); 1679 g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); 1680 g_return_if_fail (filter_id != NULL); 1681 g_return_if_fail (search_id != NULL); 1682 g_return_if_fail (search_text != NULL); 1683 g_return_if_fail (advanced_search != NULL); 1684 1685 priv = view->priv; 1686 1687 *filter_id = priv->filter_id; 1688 *search_id = priv->search_id; 1689 *search_text = g_strdup (priv->search_text); 1690 1691 if (priv->advanced_search != NULL) 1692 *advanced_search = e_filter_rule_clone (priv->advanced_search); 1693 else 1694 *advanced_search = NULL; 1695 }