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);
(emitted by clang-analyzer)TODO: a detailed trace is available in the data model (not yet rendered in this report)
(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 }