1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /* e-destination-store.c - EDestination store with GtkTreeModel interface.
4 *
5 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 * Authors: Hans Petter Jansson <hpj@novell.com>
20 */
21
22 #include "evolution-config.h"
23
24 #include <string.h>
25 #include <glib/gi18n-lib.h>
26
27 #include "e-destination-store.h"
28
29 #define ITER_IS_VALID(destination_store, iter) \
30 ((iter)->stamp == (destination_store)->priv->stamp)
31 #define ITER_GET(iter) \
32 GPOINTER_TO_INT (iter->user_data)
33 #define ITER_SET(destination_store, iter, index) \
34 G_STMT_START { \
35 (iter)->stamp = (destination_store)->priv->stamp; \
36 (iter)->user_data = GINT_TO_POINTER (index); \
37 } G_STMT_END
38
39 #define E_DESTINATION_STORE_GET_PRIVATE(obj) \
40 (G_TYPE_INSTANCE_GET_PRIVATE \
41 ((obj), E_TYPE_DESTINATION_STORE, EDestinationStorePrivate))
42
43 struct _EDestinationStorePrivate {
44 GPtrArray *destinations;
45 gint stamp;
46 };
47
48 static GType column_types[E_DESTINATION_STORE_NUM_COLUMNS];
49
50 static void e_destination_store_tree_model_init (GtkTreeModelIface *iface);
51
52 G_DEFINE_TYPE_EXTENDED (
53 EDestinationStore, e_destination_store, G_TYPE_OBJECT, 0,
54 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, e_destination_store_tree_model_init);
55 column_types[E_DESTINATION_STORE_COLUMN_NAME] = G_TYPE_STRING;
56 column_types[E_DESTINATION_STORE_COLUMN_EMAIL] = G_TYPE_STRING;
57 column_types[E_DESTINATION_STORE_COLUMN_ADDRESS] = G_TYPE_STRING;
58 )
59
60 static GtkTreeModelFlags e_destination_store_get_flags (GtkTreeModel *tree_model);
61 static gint e_destination_store_get_n_columns (GtkTreeModel *tree_model);
62 static GType e_destination_store_get_column_type (GtkTreeModel *tree_model,
63 gint index);
64 static gboolean e_destination_store_get_iter (GtkTreeModel *tree_model,
65 GtkTreeIter *iter,
66 GtkTreePath *path);
67 static void e_destination_store_get_value (GtkTreeModel *tree_model,
68 GtkTreeIter *iter,
69 gint column,
70 GValue *value);
71 static gboolean e_destination_store_iter_next (GtkTreeModel *tree_model,
72 GtkTreeIter *iter);
73 static gboolean e_destination_store_iter_children (GtkTreeModel *tree_model,
74 GtkTreeIter *iter,
75 GtkTreeIter *parent);
76 static gboolean e_destination_store_iter_has_child (GtkTreeModel *tree_model,
77 GtkTreeIter *iter);
78 static gint e_destination_store_iter_n_children (GtkTreeModel *tree_model,
79 GtkTreeIter *iter);
80 static gboolean e_destination_store_iter_nth_child (GtkTreeModel *tree_model,
81 GtkTreeIter *iter,
82 GtkTreeIter *parent,
83 gint n);
84 static gboolean e_destination_store_iter_parent (GtkTreeModel *tree_model,
85 GtkTreeIter *iter,
86 GtkTreeIter *child);
87
88 static void destination_changed (EDestinationStore *destination_store, EDestination *destination);
89 static void stop_destination (EDestinationStore *destination_store, EDestination *destination);
90
91 static void
destination_store_dispose(GObject * object)92 destination_store_dispose (GObject *object)
93 {
94 EDestinationStorePrivate *priv;
95 gint ii;
96
97 priv = E_DESTINATION_STORE_GET_PRIVATE (object);
98
99 for (ii = 0; ii < priv->destinations->len; ii++) {
100 EDestination *destination;
101
102 destination = g_ptr_array_index (priv->destinations, ii);
103 stop_destination (E_DESTINATION_STORE (object), destination);
104 g_object_unref (destination);
105 }
106 g_ptr_array_set_size (priv->destinations, 0);
107
108 /* Chain up to parent's dispose() method. */
109 G_OBJECT_CLASS (e_destination_store_parent_class)->dispose (object);
110 }
111
112 static void
destination_store_finalize(GObject * object)113 destination_store_finalize (GObject *object)
114 {
115 EDestinationStorePrivate *priv;
116
117 priv = E_DESTINATION_STORE_GET_PRIVATE (object);
118
119 g_ptr_array_free (priv->destinations, TRUE);
120
121 /* Chain up to parent's finalize() method. */
122 G_OBJECT_CLASS (e_destination_store_parent_class)->finalize (object);
123 }
124
125 static void
e_destination_store_class_init(EDestinationStoreClass * class)126 e_destination_store_class_init (EDestinationStoreClass *class)
127 {
128 GObjectClass *object_class;
129
130 g_type_class_add_private (class, sizeof (EDestinationStorePrivate));
131
132 object_class = G_OBJECT_CLASS (class);
133 object_class->dispose = destination_store_dispose;
134 object_class->finalize = destination_store_finalize;
135 }
136
137 static void
e_destination_store_tree_model_init(GtkTreeModelIface * iface)138 e_destination_store_tree_model_init (GtkTreeModelIface *iface)
139 {
140 iface->get_flags = e_destination_store_get_flags;
141 iface->get_n_columns = e_destination_store_get_n_columns;
142 iface->get_column_type = e_destination_store_get_column_type;
143 iface->get_iter = e_destination_store_get_iter;
144 iface->get_path = e_destination_store_get_path;
145 iface->get_value = e_destination_store_get_value;
146 iface->iter_next = e_destination_store_iter_next;
147 iface->iter_children = e_destination_store_iter_children;
148 iface->iter_has_child = e_destination_store_iter_has_child;
149 iface->iter_n_children = e_destination_store_iter_n_children;
150 iface->iter_nth_child = e_destination_store_iter_nth_child;
151 iface->iter_parent = e_destination_store_iter_parent;
152 }
153
154 static void
e_destination_store_init(EDestinationStore * destination_store)155 e_destination_store_init (EDestinationStore *destination_store)
156 {
157 destination_store->priv =
158 E_DESTINATION_STORE_GET_PRIVATE (destination_store);
159
160 destination_store->priv->destinations = g_ptr_array_new ();
161 destination_store->priv->stamp = g_random_int ();
162 }
163
164 /**
165 * e_destination_store_new:
166 *
167 * Creates a new #EDestinationStore.
168 *
169 * Returns: A new #EDestinationStore.
170 **/
171 EDestinationStore *
e_destination_store_new(void)172 e_destination_store_new (void)
173 {
174 return g_object_new (E_TYPE_DESTINATION_STORE, NULL);
175 }
176
177 /* ------------------ *
178 * Row update helpers *
179 * ------------------ */
180
181 static void
row_deleted(EDestinationStore * destination_store,gint n)182 row_deleted (EDestinationStore *destination_store,
183 gint n)
184 {
185 GtkTreePath *path;
186
187 path = gtk_tree_path_new ();
188 gtk_tree_path_append_index (path, n);
189 gtk_tree_model_row_deleted (GTK_TREE_MODEL (destination_store), path);
190 gtk_tree_path_free (path);
191 }
192
193 static void
row_inserted(EDestinationStore * destination_store,gint n)194 row_inserted (EDestinationStore *destination_store,
195 gint n)
196 {
197 GtkTreePath *path;
198 GtkTreeIter iter;
199
200 path = gtk_tree_path_new ();
201 gtk_tree_path_append_index (path, n);
202
203 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (destination_store), &iter, path))
204 gtk_tree_model_row_inserted (GTK_TREE_MODEL (destination_store), path, &iter);
205
206 gtk_tree_path_free (path);
207 }
208
209 static void
row_changed(EDestinationStore * destination_store,gint n)210 row_changed (EDestinationStore *destination_store,
211 gint n)
212 {
213 GtkTreePath *path;
214 GtkTreeIter iter;
215
216 path = gtk_tree_path_new ();
217 gtk_tree_path_append_index (path, n);
218
219 if (gtk_tree_model_get_iter (GTK_TREE_MODEL (destination_store), &iter, path))
220 gtk_tree_model_row_changed (GTK_TREE_MODEL (destination_store), path, &iter);
221
222 gtk_tree_path_free (path);
223 }
224
225 /* ------------------- *
226 * Destination helpers *
227 * ------------------- */
228
229 static gint
find_destination_by_pointer(EDestinationStore * destination_store,EDestination * destination)230 find_destination_by_pointer (EDestinationStore *destination_store,
231 EDestination *destination)
232 {
233 GPtrArray *array;
234 gint i;
235
236 array = destination_store->priv->destinations;
237
238 for (i = 0; i < array->len; i++) {
239 EDestination *destination_here;
240
241 destination_here = g_ptr_array_index (array, i);
242
243 if (destination_here == destination)
244 return i;
245 }
246
247 return -1;
248 }
249
250 static gint
find_destination_by_email(EDestinationStore * destination_store,EDestination * destination)251 find_destination_by_email (EDestinationStore *destination_store,
252 EDestination *destination)
253 {
254 GPtrArray *array;
255 gint i;
256 const gchar *e_mail = e_destination_get_email (destination);
257
258 array = destination_store->priv->destinations;
259
260 for (i = 0; i < array->len; i++) {
261 EDestination *destination_here;
262 const gchar *mail;
263
264 destination_here = g_ptr_array_index (array, i);
265 mail = e_destination_get_email (destination_here);
266
267 if (g_str_equal (e_mail, mail))
268 return i;
269 }
270
271 return -1;
272 }
273
274 static void
start_destination(EDestinationStore * destination_store,EDestination * destination)275 start_destination (EDestinationStore *destination_store,
276 EDestination *destination)
277 {
278 g_signal_connect_swapped (
279 destination, "changed",
280 G_CALLBACK (destination_changed), destination_store);
281 }
282
283 static void
stop_destination(EDestinationStore * destination_store,EDestination * destination)284 stop_destination (EDestinationStore *destination_store,
285 EDestination *destination)
286 {
287 g_signal_handlers_disconnect_matched (
288 destination, G_SIGNAL_MATCH_DATA,
289 0, 0, NULL, NULL, destination_store);
290 }
291
292 /* --------------- *
293 * Signal handlers *
294 * --------------- */
295
296 static void
destination_changed(EDestinationStore * destination_store,EDestination * destination)297 destination_changed (EDestinationStore *destination_store,
298 EDestination *destination)
299 {
300 gint n;
301
302 n = find_destination_by_pointer (destination_store, destination);
303 if (n < 0) {
304 g_warning ("EDestinationStore got change from unknown EDestination!");
305 return;
306 }
307
308 row_changed (destination_store, n);
309 }
310
311 /* --------------------- *
312 * EDestinationStore API *
313 * --------------------- */
314
315 /**
316 * e_destination_store_get_destination:
317 * @destination_store: an #EDestinationStore
318 * @iter: a #GtkTreeIter
319 *
320 * Gets the #EDestination from @destination_store at @iter.
321 *
322 * Returns: An #EDestination.
323 **/
324 EDestination *
e_destination_store_get_destination(EDestinationStore * destination_store,GtkTreeIter * iter)325 e_destination_store_get_destination (EDestinationStore *destination_store,
326 GtkTreeIter *iter)
327 {
328 GPtrArray *array;
329 gint index;
330
331 g_return_val_if_fail (E_IS_DESTINATION_STORE (destination_store), NULL);
332 g_return_val_if_fail (ITER_IS_VALID (destination_store, iter), NULL);
333
334 array = destination_store->priv->destinations;
335 index = ITER_GET (iter);
336
337 return g_ptr_array_index (array, index);
338 }
339
340 /**
341 * e_destination_store_list_destinations:
342 * @destination_store: an #EDestinationStore
343 *
344 * Gets a list of all the #EDestinations in @destination_store.
345 *
346 * Returns: A #GList of pointers to #EDestination. The list is owned
347 * by the caller, but the #EDestination elements aren't.
348 **/
349 GList *
e_destination_store_list_destinations(EDestinationStore * destination_store)350 e_destination_store_list_destinations (EDestinationStore *destination_store)
351 {
352 GList *destination_list = NULL;
353 GPtrArray *array;
354 gint i;
355
356 g_return_val_if_fail (E_IS_DESTINATION_STORE (destination_store), NULL);
357
358 array = destination_store->priv->destinations;
359
360 for (i = 0; i < array->len; i++) {
361 EDestination *destination;
362
363 destination = g_ptr_array_index (array, i);
364 destination_list = g_list_prepend (destination_list, destination);
365 }
366
367 destination_list = g_list_reverse (destination_list);
368
369 return destination_list;
370 }
371
372 /**
373 * e_destination_store_insert_destination:
374 * @destination_store: an #EDestinationStore
375 * @index: the index at which to insert
376 * @destination: an #EDestination to insert
377 *
378 * Inserts @destination into @destination_store at the position
379 * indicated by @index. @destination_store will ref @destination.
380 **/
381 void
e_destination_store_insert_destination(EDestinationStore * destination_store,gint index,EDestination * destination)382 e_destination_store_insert_destination (EDestinationStore *destination_store,
383 gint index,
384 EDestination *destination)
385 {
386 GPtrArray *array;
387
388 g_return_if_fail (E_IS_DESTINATION_STORE (destination_store));
389 g_return_if_fail (index >= 0);
390
391 if (find_destination_by_pointer (destination_store, destination) >= 0) {
392 g_warning ("Same destination added more than once to EDestinationStore!");
393 return;
394 }
395
396 g_object_ref (destination);
397
398 array = destination_store->priv->destinations;
399 index = MIN (index, array->len);
400
401 g_ptr_array_set_size (array, array->len + 1);
402
403 if (array->len - 1 - index > 0) {
404 memmove (
405 array->pdata + index + 1,
406 array->pdata + index,
407 (array->len - 1 - index) * sizeof (gpointer));
408 }
409
410 array->pdata[index] = destination;
411 start_destination (destination_store, destination);
412 row_inserted (destination_store, index);
413 }
414
415 /**
416 * e_destination_store_append_destination:
417 * @destination_store: an #EDestinationStore
418 * @destination: an #EDestination
419 *
420 * Appends @destination to the list of destinations in @destination_store.
421 * @destination_store will ref @destination.
422 **/
423 void
e_destination_store_append_destination(EDestinationStore * destination_store,EDestination * destination)424 e_destination_store_append_destination (EDestinationStore *destination_store,
425 EDestination *destination)
426 {
427 GPtrArray *array;
428
429 g_return_if_fail (E_IS_DESTINATION_STORE (destination_store));
430
431 if (find_destination_by_email (destination_store, destination) >= 0 && !e_destination_is_evolution_list (destination)) {
432 g_warning ("Same destination added more than once to EDestinationStore!");
433 return;
434 }
435
436 array = destination_store->priv->destinations;
437 g_object_ref (destination);
438
439 g_ptr_array_add (array, destination);
440 start_destination (destination_store, destination);
441 row_inserted (destination_store, array->len - 1);
442 }
443
444 /**
445 * e_destination_store_remove_destination:
446 * @destination_store: an #EDestinationStore
447 * @destination: an #EDestination to remove
448 *
449 * Removes @destination from @destination_store. @destination_store will
450 * unref @destination.
451 **/
452 void
e_destination_store_remove_destination(EDestinationStore * destination_store,EDestination * destination)453 e_destination_store_remove_destination (EDestinationStore *destination_store,
454 EDestination *destination)
455 {
456 GPtrArray *array;
457 gint n;
458
459 g_return_if_fail (E_IS_DESTINATION_STORE (destination_store));
460
461 n = find_destination_by_pointer (destination_store, destination);
462 if (n < 0) {
463 g_warning ("Tried to remove unknown destination from EDestinationStore!");
464 return;
465 }
466
467 stop_destination (destination_store, destination);
468 g_object_unref (destination);
469
470 array = destination_store->priv->destinations;
471 g_ptr_array_remove_index (array, n);
472 row_deleted (destination_store, n);
473 }
474
475 void
e_destination_store_remove_destination_nth(EDestinationStore * destination_store,gint n)476 e_destination_store_remove_destination_nth (EDestinationStore *destination_store,
477 gint n)
478 {
479 EDestination *destination;
480 GPtrArray *array;
481
482 g_return_if_fail (n >= 0);
483
484 array = destination_store->priv->destinations;
485 destination = g_ptr_array_index (array, n);
486 stop_destination (destination_store, destination);
487 g_object_unref (destination);
488
489 g_ptr_array_remove_index (array, n);
490 row_deleted (destination_store, n);
491 }
492
493 guint
e_destination_store_get_destination_count(EDestinationStore * destination_store)494 e_destination_store_get_destination_count (EDestinationStore *destination_store)
495 {
496 return destination_store->priv->destinations->len;
497 }
498
499 /* ---------------- *
500 * GtkTreeModel API *
501 * ---------------- */
502
503 static GtkTreeModelFlags
e_destination_store_get_flags(GtkTreeModel * tree_model)504 e_destination_store_get_flags (GtkTreeModel *tree_model)
505 {
506 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), 0);
507
508 return GTK_TREE_MODEL_LIST_ONLY;
509 }
510
511 static gint
e_destination_store_get_n_columns(GtkTreeModel * tree_model)512 e_destination_store_get_n_columns (GtkTreeModel *tree_model)
513 {
514 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), 0);
515
516 return E_CONTACT_FIELD_LAST;
517 }
518
519 static GType
e_destination_store_get_column_type(GtkTreeModel * tree_model,gint index)520 e_destination_store_get_column_type (GtkTreeModel *tree_model,
521 gint index)
522 {
523 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), G_TYPE_INVALID);
524 g_return_val_if_fail (index >= 0 && index < E_DESTINATION_STORE_NUM_COLUMNS, G_TYPE_INVALID);
525
526 return column_types[index];
527 }
528
529 static gboolean
e_destination_store_get_iter(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreePath * path)530 e_destination_store_get_iter (GtkTreeModel *tree_model,
531 GtkTreeIter *iter,
532 GtkTreePath *path)
533 {
534 EDestinationStore *destination_store;
535 GPtrArray *array;
536 gint index;
537
538 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
539 g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
540
541 destination_store = E_DESTINATION_STORE (tree_model);
542
543 index = gtk_tree_path_get_indices (path)[0];
544 array = destination_store->priv->destinations;
545
546 if (index >= array->len)
547 return FALSE;
548
549 ITER_SET (destination_store, iter, index);
550 return TRUE;
551 }
552
553 GtkTreePath *
e_destination_store_get_path(GtkTreeModel * tree_model,GtkTreeIter * iter)554 e_destination_store_get_path (GtkTreeModel *tree_model,
555 GtkTreeIter *iter)
556 {
557 EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
558 GtkTreePath *path;
559 gint index;
560
561 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), NULL);
562 g_return_val_if_fail (ITER_IS_VALID (destination_store, iter), NULL);
563
564 index = ITER_GET (iter);
565 path = gtk_tree_path_new ();
566 gtk_tree_path_append_index (path, index);
567
568 return path;
569 }
570
571 static gboolean
e_destination_store_iter_next(GtkTreeModel * tree_model,GtkTreeIter * iter)572 e_destination_store_iter_next (GtkTreeModel *tree_model,
573 GtkTreeIter *iter)
574 {
575 EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
576 gint index;
577
578 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
579 g_return_val_if_fail (ITER_IS_VALID (destination_store, iter), FALSE);
580
581 index = ITER_GET (iter);
582
583 if (index + 1 < destination_store->priv->destinations->len) {
584 ITER_SET (destination_store, iter, index + 1);
585 return TRUE;
586 }
587
588 return FALSE;
589 }
590
591 static gboolean
e_destination_store_iter_children(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * parent)592 e_destination_store_iter_children (GtkTreeModel *tree_model,
593 GtkTreeIter *iter,
594 GtkTreeIter *parent)
595 {
596 EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
597
598 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
599
600 /* This is a list, nodes have no children. */
601 if (parent)
602 return FALSE;
603
604 /* But if parent == NULL we return the list itself as children of the root. */
605 if (destination_store->priv->destinations->len <= 0)
606 return FALSE;
607
608 ITER_SET (destination_store, iter, 0);
609 return TRUE;
610 }
611
612 static gboolean
e_destination_store_iter_has_child(GtkTreeModel * tree_model,GtkTreeIter * iter)613 e_destination_store_iter_has_child (GtkTreeModel *tree_model,
614 GtkTreeIter *iter)
615 {
616 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
617
618 if (iter == NULL)
619 return TRUE;
620
621 return FALSE;
622 }
623
624 static gint
e_destination_store_iter_n_children(GtkTreeModel * tree_model,GtkTreeIter * iter)625 e_destination_store_iter_n_children (GtkTreeModel *tree_model,
626 GtkTreeIter *iter)
627 {
628 EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
629
630 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), -1);
631
632 if (iter == NULL)
633 return destination_store->priv->destinations->len;
634
635 g_return_val_if_fail (ITER_IS_VALID (destination_store, iter), -1);
636 return 0;
637 }
638
639 static gboolean
e_destination_store_iter_nth_child(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * parent,gint n)640 e_destination_store_iter_nth_child (GtkTreeModel *tree_model,
641 GtkTreeIter *iter,
642 GtkTreeIter *parent,
643 gint n)
644 {
645 EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
646
647 g_return_val_if_fail (E_IS_DESTINATION_STORE (tree_model), FALSE);
648
649 if (parent)
650 return FALSE;
651
652 if (n < destination_store->priv->destinations->len) {
653 ITER_SET (destination_store, iter, n);
654 return TRUE;
655 }
656
657 return FALSE;
658 }
659
660 static gboolean
e_destination_store_iter_parent(GtkTreeModel * tree_model,GtkTreeIter * iter,GtkTreeIter * child)661 e_destination_store_iter_parent (GtkTreeModel *tree_model,
662 GtkTreeIter *iter,
663 GtkTreeIter *child)
664 {
665 return FALSE;
666 }
667
668 static void
e_destination_store_get_value(GtkTreeModel * tree_model,GtkTreeIter * iter,gint column,GValue * value)669 e_destination_store_get_value (GtkTreeModel *tree_model,
670 GtkTreeIter *iter,
671 gint column,
672 GValue *value)
673 {
674 EDestinationStore *destination_store = E_DESTINATION_STORE (tree_model);
675 EDestination *destination;
676 GString *string_new;
677 EContact *contact;
678 GPtrArray *array;
679 const gchar *string;
680 gint row;
681
682 g_return_if_fail (E_IS_DESTINATION_STORE (tree_model));
683 g_return_if_fail (column < E_DESTINATION_STORE_NUM_COLUMNS);
684 g_return_if_fail (ITER_IS_VALID (destination_store, iter));
685
686 g_value_init (value, column_types[column]);
687
688 array = destination_store->priv->destinations;
689
690 row = ITER_GET (iter);
691 if (row >= array->len)
692 return;
693
694 destination = g_ptr_array_index (array, row);
695 g_return_if_fail (destination);
696
697 switch (column) {
698 case E_DESTINATION_STORE_COLUMN_NAME:
699 string = e_destination_get_name (destination);
700 g_value_set_string (value, string);
701 break;
702
703 case E_DESTINATION_STORE_COLUMN_EMAIL:
704 string = e_destination_get_email (destination);
705 g_value_set_string (value, string);
706 break;
707
708 case E_DESTINATION_STORE_COLUMN_ADDRESS:
709 contact = e_destination_get_contact (destination);
710 if (contact && E_IS_CONTACT (contact)) {
711 if (e_contact_get (contact, E_CONTACT_IS_LIST)) {
712 string = e_destination_get_name (destination);
713 string_new = g_string_new (string);
714 g_string_append (string_new, " mailing list");
715 g_value_set_string (value, string_new->str);
716 g_string_free (string_new, TRUE);
717 }
718 else {
719 string = e_destination_get_address (destination);
720 g_value_set_string (value, string);
721 }
722 }
723 else {
724 string = e_destination_get_address (destination);
725 g_value_set_string (value, string);
726
727 }
728 break;
729
730 default:
731 g_warn_if_reached ();
732 break;
733 }
734 }
735
736 /**
737 * e_destination_store_get_stamp:
738 * @destination_store: an #EDestinationStore
739 *
740 * Since: 2.32
741 **/
742 gint
e_destination_store_get_stamp(EDestinationStore * destination_store)743 e_destination_store_get_stamp (EDestinationStore *destination_store)
744 {
745 g_return_val_if_fail (E_IS_DESTINATION_STORE (destination_store), 0);
746
747 return destination_store->priv->stamp;
748 }
749