1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms of the GNU Lesser General Public License as published by
4  * the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful, but
7  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
9  * for more details.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, see <http://www.gnu.org/licenses/>.
13  *
14  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
15  */
16 
17 #include "evolution-config.h"
18 
19 #include "e-composer-header-table.h"
20 
21 #include <glib/gi18n-lib.h>
22 
23 #include "e-msg-composer.h"
24 #include "e-composer-private.h"
25 #include "e-composer-from-header.h"
26 #include "e-composer-name-header.h"
27 #include "e-composer-post-header.h"
28 #include "e-composer-spell-header.h"
29 #include "e-composer-text-header.h"
30 
31 #define E_COMPOSER_HEADER_TABLE_GET_PRIVATE(obj) \
32 	(G_TYPE_INSTANCE_GET_PRIVATE \
33 	((obj), E_TYPE_COMPOSER_HEADER_TABLE, EComposerHeaderTablePrivate))
34 
35 #define HEADER_TOOLTIP_TO \
36 	_("Enter the recipients of the message")
37 #define HEADER_TOOLTIP_CC \
38 	_("Enter the addresses that will receive a " \
39 	  "carbon copy of the message")
40 #define HEADER_TOOLTIP_BCC \
41 	_("Enter the addresses that will receive a " \
42 	  "carbon copy of the message without appearing " \
43 	  "in the recipient list of the message")
44 
45 struct _EComposerHeaderTablePrivate {
46 	EComposerHeader *headers[E_COMPOSER_NUM_HEADERS];
47 	GtkWidget *signature_label;
48 	GtkWidget *signature_combo_box;
49 	ENameSelector *name_selector;
50 	EClientCache *client_cache;
51 
52 	gchar *previous_from_uid;
53 };
54 
55 enum {
56 	PROP_0,
57 	PROP_CLIENT_CACHE,
58 	PROP_DESTINATIONS_BCC,
59 	PROP_DESTINATIONS_CC,
60 	PROP_DESTINATIONS_TO,
61 	PROP_IDENTITY_UID,
62 	PROP_POST_TO,
63 	PROP_REPLY_TO,
64 	PROP_SIGNATURE_COMBO_BOX,
65 	PROP_SIGNATURE_UID,
66 	PROP_SUBJECT
67 };
68 
G_DEFINE_TYPE(EComposerHeaderTable,e_composer_header_table,GTK_TYPE_TABLE)69 G_DEFINE_TYPE (
70 	EComposerHeaderTable,
71 	e_composer_header_table,
72 	GTK_TYPE_TABLE)
73 
74 static void
75 g_value_set_destinations (GValue *value,
76                           EDestination **destinations)
77 {
78 	GPtrArray *array;
79 	gint ii;
80 
81 	/* Preallocate some reasonable number. */
82 	array = g_ptr_array_new_full (64, g_object_unref);
83 
84 	for (ii = 0; destinations[ii] != NULL; ii++) {
85 		g_ptr_array_add (array, e_destination_copy (destinations[ii]));
86 	}
87 
88 	g_value_take_boxed (value, array);
89 }
90 
91 static EDestination **
g_value_dup_destinations(const GValue * value)92 g_value_dup_destinations (const GValue *value)
93 {
94 	EDestination **destinations;
95 	const EDestination *dest;
96 	GPtrArray *array;
97 	guint ii;
98 
99 	array = g_value_get_boxed (value);
100 	destinations = g_new0 (EDestination *, array->len + 1);
101 
102 	for (ii = 0; ii < array->len; ii++) {
103 		dest = g_ptr_array_index (array, ii);
104 		destinations[ii] = e_destination_copy (dest);
105 	}
106 
107 	return destinations;
108 }
109 
110 static void
g_value_set_string_list(GValue * value,GList * list)111 g_value_set_string_list (GValue *value,
112                          GList *list)
113 {
114 	GPtrArray *array;
115 
116 	array = g_ptr_array_new_full (g_list_length (list), g_free);
117 
118 	while (list != NULL) {
119 		g_ptr_array_add (array, g_strdup (list->data));
120 		list = list->next;
121 	}
122 
123 	g_value_take_boxed (value, array);
124 }
125 
126 static GList *
g_value_dup_string_list(const GValue * value)127 g_value_dup_string_list (const GValue *value)
128 {
129 	GPtrArray *array;
130 	GList *list = NULL;
131 	gint ii;
132 
133 	array = g_value_get_boxed (value);
134 
135 	for (ii = 0; ii < array->len; ii++) {
136 		const gchar *element = g_ptr_array_index (array, ii);
137 		list = g_list_prepend (list, g_strdup (element));
138 	}
139 
140 	return g_list_reverse (list);
141 }
142 
143 static void
composer_header_table_notify_header(EComposerHeader * header,const gchar * property_name)144 composer_header_table_notify_header (EComposerHeader *header,
145                                      const gchar *property_name)
146 {
147 	GtkWidget *parent;
148 
149 	parent = gtk_widget_get_parent (header->input_widget);
150 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (parent));
151 	g_object_notify (G_OBJECT (parent), property_name);
152 }
153 
154 static void
composer_header_table_notify_widget(GtkWidget * widget,const gchar * property_name)155 composer_header_table_notify_widget (GtkWidget *widget,
156                                      const gchar *property_name)
157 {
158 	GtkWidget *parent;
159 
160 	parent = gtk_widget_get_parent (widget);
161 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (parent));
162 	g_object_notify (G_OBJECT (parent), property_name);
163 }
164 
165 static void
composer_header_table_bind_header(const gchar * property_name,const gchar * signal_name,EComposerHeader * header)166 composer_header_table_bind_header (const gchar *property_name,
167                                    const gchar *signal_name,
168                                    EComposerHeader *header)
169 {
170 	/* Propagate the signal as "notify::property_name". */
171 
172 	g_signal_connect (
173 		header, signal_name,
174 		G_CALLBACK (composer_header_table_notify_header),
175 		(gpointer) property_name);
176 }
177 
178 static void
composer_header_table_bind_widget(const gchar * property_name,const gchar * signal_name,GtkWidget * widget)179 composer_header_table_bind_widget (const gchar *property_name,
180                                    const gchar *signal_name,
181                                    GtkWidget *widget)
182 {
183 	/* Propagate the signal as "notify::property_name". */
184 
185 	g_signal_connect (
186 		widget, signal_name,
187 		G_CALLBACK (composer_header_table_notify_widget),
188 		(gpointer) property_name);
189 }
190 
191 static EDestination **
composer_header_table_update_destinations(EDestination ** old_destinations,const gchar * const * auto_addresses)192 composer_header_table_update_destinations (EDestination **old_destinations,
193                                            const gchar * const *auto_addresses)
194 {
195 	CamelAddress *address;
196 	CamelInternetAddress *inet_address;
197 	EDestination **new_destinations;
198 	EDestination *destination;
199 	GQueue queue = G_QUEUE_INIT;
200 	guint length;
201 	gint ii;
202 
203 	/* Include automatic recipients for the selected account. */
204 
205 	if (auto_addresses == NULL)
206 		goto skip_auto;
207 
208 	inet_address = camel_internet_address_new ();
209 	address = CAMEL_ADDRESS (inet_address);
210 
211 	/* XXX Calling camel_address_decode() multiple times on the same
212 	 *     CamelInternetAddress has a cumulative effect, which isn't
213 	 *     well documented. */
214 	for (ii = 0; auto_addresses[ii] != NULL; ii++)
215 		camel_address_decode (address, auto_addresses[ii]);
216 
217 	for (ii = 0; ii < camel_address_length (address); ii++) {
218 		const gchar *name, *email;
219 
220 		if (!camel_internet_address_get (
221 			inet_address, ii, &name, &email))
222 			continue;
223 
224 		destination = e_destination_new ();
225 		e_destination_set_auto_recipient (destination, TRUE);
226 
227 		if (name != NULL)
228 			e_destination_set_name (destination, name);
229 
230 		if (email != NULL)
231 			e_destination_set_email (destination, email);
232 
233 		g_queue_push_tail (&queue, destination);
234 	}
235 
236 	g_object_unref (inet_address);
237 
238 skip_auto:
239 
240 	/* Include custom recipients for this message. */
241 
242 	if (old_destinations == NULL)
243 		goto skip_custom;
244 
245 	for (ii = 0; old_destinations[ii] != NULL; ii++) {
246 		if (e_destination_is_auto_recipient (old_destinations[ii]))
247 			continue;
248 
249 		destination = e_destination_copy (old_destinations[ii]);
250 		g_queue_push_tail (&queue, destination);
251 	}
252 
253 skip_custom:
254 
255 	length = g_queue_get_length (&queue);
256 	new_destinations = g_new0 (EDestination *, length + 1);
257 
258 	for (ii = 0; ii < length; ii++)
259 		new_destinations[ii] = g_queue_pop_head (&queue);
260 
261 	/* Sanity check. */
262 	g_warn_if_fail (g_queue_is_empty (&queue));
263 
264 	return new_destinations;
265 }
266 
267 static void
composer_header_table_setup_mail_headers(EComposerHeaderTable * table)268 composer_header_table_setup_mail_headers (EComposerHeaderTable *table)
269 {
270 	GSettings *settings;
271 	gint ii;
272 
273 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
274 
275 	for (ii = 0; ii < E_COMPOSER_NUM_HEADERS; ii++) {
276 		EComposerHeader *header;
277 		const gchar *key;
278 		gboolean sensitive;
279 		gboolean visible;
280 
281 		header = e_composer_header_table_get_header (table, ii);
282 
283 		switch (ii) {
284 			case E_COMPOSER_HEADER_FROM:
285 				key = "composer-show-from-override";
286 				break;
287 
288 			case E_COMPOSER_HEADER_BCC:
289 				key = "composer-show-bcc";
290 				break;
291 
292 			case E_COMPOSER_HEADER_CC:
293 				key = "composer-show-cc";
294 				break;
295 
296 			case E_COMPOSER_HEADER_REPLY_TO:
297 				key = "composer-show-reply-to";
298 				break;
299 
300 			default:
301 				key = NULL;
302 				break;
303 		}
304 
305 		if (key != NULL)
306 			g_settings_unbind (header, "visible");
307 
308 		switch (ii) {
309 			case E_COMPOSER_HEADER_FROM:
310 				sensitive = TRUE;
311 				visible = TRUE;
312 				break;
313 
314 			case E_COMPOSER_HEADER_BCC:
315 			case E_COMPOSER_HEADER_CC:
316 			case E_COMPOSER_HEADER_REPLY_TO:
317 			case E_COMPOSER_HEADER_SUBJECT:
318 			case E_COMPOSER_HEADER_TO:
319 				sensitive = TRUE;
320 				visible = TRUE;
321 				break;
322 
323 			default:
324 				sensitive = FALSE;
325 				visible = FALSE;
326 				break;
327 		}
328 
329 		e_composer_header_set_sensitive (header, sensitive);
330 		e_composer_header_set_visible (header, visible);
331 
332 		if (key != NULL) {
333 			if (ii == E_COMPOSER_HEADER_FROM)
334 				g_settings_bind (
335 					settings, key,
336 					header, "override-visible",
337 					G_SETTINGS_BIND_DEFAULT);
338 			else
339 				g_settings_bind (
340 					settings, key,
341 					header, "visible",
342 					G_SETTINGS_BIND_DEFAULT);
343 		}
344 	}
345 
346 	g_object_unref (settings);
347 }
348 
349 static void
composer_header_table_setup_post_headers(EComposerHeaderTable * table)350 composer_header_table_setup_post_headers (EComposerHeaderTable *table)
351 {
352 	GSettings *settings;
353 	gint ii;
354 
355 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
356 
357 	for (ii = 0; ii < E_COMPOSER_NUM_HEADERS; ii++) {
358 		EComposerHeader *header;
359 		const gchar *key;
360 
361 		header = e_composer_header_table_get_header (table, ii);
362 
363 		switch (ii) {
364 			case E_COMPOSER_HEADER_FROM:
365 				key = "composer-show-post-from";
366 				break;
367 
368 			case E_COMPOSER_HEADER_REPLY_TO:
369 				key = "composer-show-post-reply-to";
370 				break;
371 
372 			default:
373 				key = NULL;
374 				break;
375 		}
376 
377 		if (key != NULL)
378 			g_settings_unbind (header, "visible");
379 
380 		switch (ii) {
381 			case E_COMPOSER_HEADER_FROM:
382 			case E_COMPOSER_HEADER_POST_TO:
383 			case E_COMPOSER_HEADER_REPLY_TO:
384 			case E_COMPOSER_HEADER_SUBJECT:
385 				e_composer_header_set_sensitive (header, TRUE);
386 				e_composer_header_set_visible (header, TRUE);
387 				break;
388 
389 			default:  /* this includes TO, CC and BCC */
390 				e_composer_header_set_sensitive (header, FALSE);
391 				e_composer_header_set_visible (header, FALSE);
392 				break;
393 		}
394 
395 		if (key != NULL)
396 			g_settings_bind (
397 				settings, key,
398 				header, "visible",
399 				G_SETTINGS_BIND_DEFAULT);
400 	}
401 
402 	g_object_unref (settings);
403 }
404 
405 static gboolean
composer_header_table_show_post_headers(EComposerHeaderTable * table)406 composer_header_table_show_post_headers (EComposerHeaderTable *table)
407 {
408 	EClientCache *client_cache;
409 	ESourceRegistry *registry;
410 	GList *list, *link;
411 	const gchar *extension_name;
412 	gchar *target_uid;
413 	gboolean show_post_headers = FALSE;
414 
415 	client_cache = e_composer_header_table_ref_client_cache (table);
416 	registry = e_client_cache_ref_registry (client_cache);
417 
418 	target_uid = e_composer_header_table_dup_identity_uid (table, NULL, NULL);
419 
420 	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
421 	list = e_source_registry_list_sources (registry, extension_name);
422 
423 	/* Look for a mail account referencing this mail identity.
424 	 * If the mail account's backend name is "nntp", show the
425 	 * post headers.  Otherwise show the mail headers.
426 	 *
427 	 * XXX What if multiple accounts use this identity but only
428 	 *     one is "nntp"?  Maybe it should be indicated by the
429 	 *     transport somehow?
430 	 */
431 	for (link = list; link != NULL; link = link->next) {
432 		ESource *source = E_SOURCE (link->data);
433 		ESourceExtension *extension;
434 		const gchar *backend_name;
435 		const gchar *identity_uid;
436 
437 		extension = e_source_get_extension (source, extension_name);
438 
439 		backend_name = e_source_backend_get_backend_name (
440 			E_SOURCE_BACKEND (extension));
441 		identity_uid = e_source_mail_account_get_identity_uid (
442 			E_SOURCE_MAIL_ACCOUNT (extension));
443 
444 		if (g_strcmp0 (identity_uid, target_uid) != 0)
445 			continue;
446 
447 		if (g_strcmp0 (backend_name, "nntp") != 0)
448 			continue;
449 
450 		show_post_headers = TRUE;
451 		break;
452 	}
453 
454 	g_list_free_full (list, (GDestroyNotify) g_object_unref);
455 
456 	g_object_unref (client_cache);
457 	g_object_unref (registry);
458 	g_free (target_uid);
459 
460 	return show_post_headers;
461 }
462 
463 static void
composer_header_table_from_changed_cb(EComposerHeaderTable * table)464 composer_header_table_from_changed_cb (EComposerHeaderTable *table)
465 {
466 	ESource *source = NULL;
467 	ESource *mail_account = NULL;
468 	EComposerHeader *header;
469 	EComposerHeaderType type;
470 	EComposerFromHeader *from_header;
471 	EComposerPostHeader *post_header;
472 	EComposerTextHeader *text_header;
473 	EDestination **old_destinations;
474 	EDestination **new_destinations;
475 	gchar *name = NULL;
476 	gchar *address = NULL;
477 	gchar *uid;
478 	const gchar *reply_to = NULL;
479 	const gchar * const *bcc = NULL;
480 	const gchar * const *cc = NULL;
481 
482 	/* Keep "Post-To" and "Reply-To" synchronized with "From" */
483 
484 	uid = e_composer_header_table_dup_identity_uid (table, &name, &address);
485 	if (uid != NULL)
486 		source = e_composer_header_table_ref_source (table, uid);
487 	g_free (uid);
488 
489 	/* Make sure this is really a mail identity source. */
490 	if (source != NULL) {
491 		const gchar *extension_name;
492 
493 		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
494 		if (!e_source_has_extension (source, extension_name)) {
495 			g_object_unref (source);
496 			source = NULL;
497 		}
498 	}
499 
500 	if (source != NULL) {
501 		ESourceMailIdentity *mi;
502 		ESourceMailComposition *mc;
503 		const gchar *extension_name;
504 
505 		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
506 		mi = e_source_get_extension (source, extension_name);
507 
508 		extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
509 		mc = e_source_get_extension (source, extension_name);
510 
511 		if (!address) {
512 			g_free (name);
513 
514 			name = e_source_mail_identity_dup_name (mi);
515 			address = e_source_mail_identity_dup_address (mi);
516 		}
517 
518 		if (!name)
519 			name = e_source_mail_identity_dup_name (mi);
520 
521 		reply_to = e_source_mail_identity_get_reply_to (mi);
522 		bcc = e_source_mail_composition_get_bcc (mc);
523 		cc = e_source_mail_composition_get_cc (mc);
524 
525 		if (table->priv->previous_from_uid) {
526 			ESource *previous_source;
527 
528 			previous_source = e_composer_header_table_ref_source (table, table->priv->previous_from_uid);
529 			if (previous_source && e_source_has_extension (previous_source, E_SOURCE_EXTENSION_MAIL_IDENTITY)) {
530 				const gchar *previous_reply_to;
531 				const gchar *current_reply_to;
532 				gboolean matches;
533 
534 				mi = e_source_get_extension (previous_source, E_SOURCE_EXTENSION_MAIL_IDENTITY);
535 				previous_reply_to = e_source_mail_identity_get_reply_to (mi);
536 
537 				header = e_composer_header_table_get_header (table, E_COMPOSER_HEADER_REPLY_TO);
538 				text_header = E_COMPOSER_TEXT_HEADER (header);
539 				current_reply_to = e_composer_text_header_get_text (text_header);
540 
541 				matches = ((!current_reply_to || !*current_reply_to) && (!previous_reply_to || !*previous_reply_to)) ||
542 					g_strcmp0 (current_reply_to, previous_reply_to) == 0;
543 
544 				/* Do not change Reply-To, if the user changed it. */
545 				if (!matches)
546 					reply_to = current_reply_to;
547 			}
548 		}
549 
550 		g_free (table->priv->previous_from_uid);
551 		table->priv->previous_from_uid = g_strdup (e_source_get_uid (source));
552 
553 		g_object_unref (source);
554 	} else {
555 		g_free (table->priv->previous_from_uid);
556 		table->priv->previous_from_uid = NULL;
557 	}
558 
559 	type = E_COMPOSER_HEADER_FROM;
560 	header = e_composer_header_table_get_header (table, type);
561 	from_header = E_COMPOSER_FROM_HEADER (header);
562 	e_composer_from_header_set_name (from_header, name);
563 	e_composer_from_header_set_address (from_header, address);
564 
565 	type = E_COMPOSER_HEADER_POST_TO;
566 	header = e_composer_header_table_get_header (table, type);
567 	post_header = E_COMPOSER_POST_HEADER (header);
568 	e_composer_post_header_set_mail_account (post_header, mail_account);
569 
570 	type = E_COMPOSER_HEADER_REPLY_TO;
571 	header = e_composer_header_table_get_header (table, type);
572 	text_header = E_COMPOSER_TEXT_HEADER (header);
573 	e_composer_text_header_set_text (text_header, reply_to);
574 
575 	/* Update automatic CC destinations. */
576 	old_destinations =
577 		e_composer_header_table_get_destinations_cc (table);
578 	new_destinations =
579 		composer_header_table_update_destinations (
580 		old_destinations, cc);
581 	e_composer_header_table_set_destinations_cc (table, new_destinations);
582 	e_destination_freev (old_destinations);
583 	e_destination_freev (new_destinations);
584 
585 	/* Update automatic BCC destinations. */
586 	old_destinations =
587 		e_composer_header_table_get_destinations_bcc (table);
588 	new_destinations =
589 		composer_header_table_update_destinations (
590 		old_destinations, bcc);
591 	e_composer_header_table_set_destinations_bcc (table, new_destinations);
592 	e_destination_freev (old_destinations);
593 	e_destination_freev (new_destinations);
594 
595 	if (composer_header_table_show_post_headers (table))
596 		composer_header_table_setup_post_headers (table);
597 	else
598 		composer_header_table_setup_mail_headers (table);
599 
600 	g_free (name);
601 	g_free (address);
602 }
603 
604 static void
composer_header_table_set_client_cache(EComposerHeaderTable * table,EClientCache * client_cache)605 composer_header_table_set_client_cache (EComposerHeaderTable *table,
606                                         EClientCache *client_cache)
607 {
608 	g_return_if_fail (E_IS_CLIENT_CACHE (client_cache));
609 	g_return_if_fail (table->priv->client_cache == NULL);
610 
611 	table->priv->client_cache = g_object_ref (client_cache);
612 }
613 
614 static void
composer_header_table_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)615 composer_header_table_set_property (GObject *object,
616                                     guint property_id,
617                                     const GValue *value,
618                                     GParamSpec *pspec)
619 {
620 	EDestination **destinations;
621 	GList *list;
622 
623 	switch (property_id) {
624 		case PROP_CLIENT_CACHE:
625 			composer_header_table_set_client_cache (
626 				E_COMPOSER_HEADER_TABLE (object),
627 				g_value_get_object (value));
628 			return;
629 
630 		case PROP_DESTINATIONS_BCC:
631 			destinations = g_value_dup_destinations (value);
632 			e_composer_header_table_set_destinations_bcc (
633 				E_COMPOSER_HEADER_TABLE (object),
634 				destinations);
635 			e_destination_freev (destinations);
636 			return;
637 
638 		case PROP_DESTINATIONS_CC:
639 			destinations = g_value_dup_destinations (value);
640 			e_composer_header_table_set_destinations_cc (
641 				E_COMPOSER_HEADER_TABLE (object),
642 				destinations);
643 			e_destination_freev (destinations);
644 			return;
645 
646 		case PROP_DESTINATIONS_TO:
647 			destinations = g_value_dup_destinations (value);
648 			e_composer_header_table_set_destinations_to (
649 				E_COMPOSER_HEADER_TABLE (object),
650 				destinations);
651 			e_destination_freev (destinations);
652 			return;
653 
654 		case PROP_IDENTITY_UID:
655 			e_composer_header_table_set_identity_uid (
656 				E_COMPOSER_HEADER_TABLE (object),
657 				g_value_get_string (value), NULL, NULL);
658 			return;
659 
660 		case PROP_POST_TO:
661 			list = g_value_dup_string_list (value);
662 			e_composer_header_table_set_post_to_list (
663 				E_COMPOSER_HEADER_TABLE (object), list);
664 			g_list_foreach (list, (GFunc) g_free, NULL);
665 			g_list_free (list);
666 			return;
667 
668 		case PROP_REPLY_TO:
669 			e_composer_header_table_set_reply_to (
670 				E_COMPOSER_HEADER_TABLE (object),
671 				g_value_get_string (value));
672 			return;
673 
674 		case PROP_SIGNATURE_UID:
675 			e_composer_header_table_set_signature_uid (
676 				E_COMPOSER_HEADER_TABLE (object),
677 				g_value_get_string (value));
678 			return;
679 
680 		case PROP_SUBJECT:
681 			e_composer_header_table_set_subject (
682 				E_COMPOSER_HEADER_TABLE (object),
683 				g_value_get_string (value));
684 			return;
685 	}
686 
687 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
688 }
689 
690 static void
composer_header_table_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)691 composer_header_table_get_property (GObject *object,
692                                     guint property_id,
693                                     GValue *value,
694                                     GParamSpec *pspec)
695 {
696 	EDestination **destinations;
697 	GList *list;
698 
699 	switch (property_id) {
700 		case PROP_CLIENT_CACHE:
701 			g_value_take_object (
702 				value,
703 				e_composer_header_table_ref_client_cache (
704 				E_COMPOSER_HEADER_TABLE (object)));
705 			return;
706 
707 		case PROP_DESTINATIONS_BCC:
708 			destinations =
709 				e_composer_header_table_get_destinations_bcc (
710 				E_COMPOSER_HEADER_TABLE (object));
711 			g_value_set_destinations (value, destinations);
712 			e_destination_freev (destinations);
713 			return;
714 
715 		case PROP_DESTINATIONS_CC:
716 			destinations =
717 				e_composer_header_table_get_destinations_cc (
718 				E_COMPOSER_HEADER_TABLE (object));
719 			g_value_set_destinations (value, destinations);
720 			e_destination_freev (destinations);
721 			return;
722 
723 		case PROP_DESTINATIONS_TO:
724 			destinations =
725 				e_composer_header_table_get_destinations_to (
726 				E_COMPOSER_HEADER_TABLE (object));
727 			g_value_set_destinations (value, destinations);
728 			e_destination_freev (destinations);
729 			return;
730 
731 		case PROP_IDENTITY_UID:
732 			g_value_take_string (
733 				value,
734 				e_composer_header_table_dup_identity_uid (
735 				E_COMPOSER_HEADER_TABLE (object), NULL, NULL));
736 			return;
737 
738 		case PROP_POST_TO:
739 			list = e_composer_header_table_get_post_to (
740 				E_COMPOSER_HEADER_TABLE (object));
741 			g_value_set_string_list (value, list);
742 			g_list_foreach (list, (GFunc) g_free, NULL);
743 			g_list_free (list);
744 			return;
745 
746 		case PROP_REPLY_TO:
747 			g_value_set_string (
748 				value,
749 				e_composer_header_table_get_reply_to (
750 				E_COMPOSER_HEADER_TABLE (object)));
751 			return;
752 
753 		case PROP_SIGNATURE_COMBO_BOX:
754 			g_value_set_object (
755 				value,
756 				e_composer_header_table_get_signature_combo_box (
757 				E_COMPOSER_HEADER_TABLE (object)));
758 			return;
759 
760 		case PROP_SIGNATURE_UID:
761 			g_value_set_string (
762 				value,
763 				e_composer_header_table_get_signature_uid (
764 				E_COMPOSER_HEADER_TABLE (object)));
765 			return;
766 
767 		case PROP_SUBJECT:
768 			g_value_set_string (
769 				value,
770 				e_composer_header_table_get_subject (
771 				E_COMPOSER_HEADER_TABLE (object)));
772 			return;
773 	}
774 
775 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
776 }
777 
778 static void
composer_header_table_dispose(GObject * object)779 composer_header_table_dispose (GObject *object)
780 {
781 	EComposerHeaderTablePrivate *priv;
782 	gint ii;
783 
784 	priv = E_COMPOSER_HEADER_TABLE_GET_PRIVATE (object);
785 
786 	for (ii = 0; ii < G_N_ELEMENTS (priv->headers); ii++) {
787 		g_clear_object (&priv->headers[ii]);
788 	}
789 
790 	g_clear_object (&priv->signature_combo_box);
791 
792 	if (priv->name_selector != NULL) {
793 		e_name_selector_cancel_loading (priv->name_selector);
794 		g_object_unref (priv->name_selector);
795 		priv->name_selector = NULL;
796 	}
797 
798 	g_clear_object (&priv->client_cache);
799 
800 	g_free (priv->previous_from_uid);
801 	priv->previous_from_uid = NULL;
802 
803 	/* Chain up to parent's dispose() method. */
804 	G_OBJECT_CLASS (e_composer_header_table_parent_class)->dispose (object);
805 }
806 
807 static void
composer_header_table_constructed(GObject * object)808 composer_header_table_constructed (GObject *object)
809 {
810 	EComposerHeaderTable *table;
811 	EComposerFromHeader *from_header;
812 	ENameSelector *name_selector;
813 	EClientCache *client_cache;
814 	ESourceRegistry *registry;
815 	EComposerHeader *header;
816 	GtkWidget *widget;
817 	guint ii;
818 	gint row_padding;
819 
820 	/* Chain up to parent's constructed() method. */
821 	G_OBJECT_CLASS (e_composer_header_table_parent_class)->constructed (object);
822 
823 	table = E_COMPOSER_HEADER_TABLE (object);
824 
825 	client_cache = e_composer_header_table_ref_client_cache (table);
826 	registry = e_client_cache_ref_registry (client_cache);
827 
828 	name_selector = e_name_selector_new (client_cache);
829 	table->priv->name_selector = name_selector;
830 
831 	header = e_composer_from_header_new (registry, _("Fr_om:"));
832 	composer_header_table_bind_header ("identity-uid", "changed", header);
833 	g_signal_connect_swapped (
834 		header, "changed", G_CALLBACK (
835 		composer_header_table_from_changed_cb), table);
836 	table->priv->headers[E_COMPOSER_HEADER_FROM] = header;
837 
838 	header = e_composer_text_header_new_label (registry, _("_Reply-To:"));
839 	composer_header_table_bind_header ("reply-to", "changed", header);
840 	table->priv->headers[E_COMPOSER_HEADER_REPLY_TO] = header;
841 
842 	header = e_composer_name_header_new (
843 		registry, _("_To:"), name_selector);
844 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_TO);
845 	composer_header_table_bind_header ("destinations-to", "changed", header);
846 	table->priv->headers[E_COMPOSER_HEADER_TO] = header;
847 
848 	header = e_composer_name_header_new (
849 		registry, _("_Cc:"), name_selector);
850 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_CC);
851 	composer_header_table_bind_header ("destinations-cc", "changed", header);
852 	table->priv->headers[E_COMPOSER_HEADER_CC] = header;
853 
854 	header = e_composer_name_header_new (
855 		registry, _("_Bcc:"), name_selector);
856 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_BCC);
857 	composer_header_table_bind_header ("destinations-bcc", "changed", header);
858 	table->priv->headers[E_COMPOSER_HEADER_BCC] = header;
859 
860 	header = e_composer_post_header_new (registry, _("_Post To:"));
861 	composer_header_table_bind_header ("post-to", "changed", header);
862 	table->priv->headers[E_COMPOSER_HEADER_POST_TO] = header;
863 
864 	header = e_composer_spell_header_new_label (registry, _("S_ubject:"));
865 	composer_header_table_bind_header ("subject", "changed", header);
866 	e_composer_header_set_title_has_tooltip (header, FALSE);
867 	e_composer_header_set_input_has_tooltip (header, FALSE);
868 	table->priv->headers[E_COMPOSER_HEADER_SUBJECT] = header;
869 
870 	widget = e_mail_signature_combo_box_new (registry);
871 	composer_header_table_bind_widget ("signature-uid", "changed", widget);
872 	table->priv->signature_combo_box = g_object_ref_sink (widget);
873 
874 	widget = gtk_label_new_with_mnemonic (_("Si_gnature:"));
875 	gtk_label_set_mnemonic_widget (
876 		GTK_LABEL (widget), table->priv->signature_combo_box);
877 	table->priv->signature_label = g_object_ref_sink (widget);
878 
879 	/* Use "ypadding" instead of "row-spacing" because some rows may
880 	 * be invisible and we don't want spacing around them. */
881 
882 	row_padding = 3;
883 
884 	for (ii = 0; ii < G_N_ELEMENTS (table->priv->headers); ii++) {
885 		gint row = ii;
886 
887 		if (ii > E_COMPOSER_HEADER_FROM)
888 			row++;
889 
890 		gtk_table_attach (
891 			GTK_TABLE (object),
892 			table->priv->headers[ii]->title_widget, 0, 1,
893 			row, row + 1, GTK_FILL, GTK_FILL, 0, row_padding);
894 		gtk_table_attach (
895 			GTK_TABLE (object),
896 			table->priv->headers[ii]->input_widget, 1, 4,
897 			row, row + 1, GTK_FILL | GTK_EXPAND, 0, 0, row_padding);
898 	}
899 
900 	ii = E_COMPOSER_HEADER_FROM;
901 
902 	/* Leave room in the "From" row for signature stuff. */
903 	gtk_container_child_set (
904 		GTK_CONTAINER (object),
905 		table->priv->headers[ii]->input_widget,
906 		"right-attach", 2, NULL);
907 
908 	e_binding_bind_property (
909 		table->priv->headers[ii]->input_widget, "visible",
910 		table->priv->signature_combo_box, "visible",
911 		G_BINDING_SYNC_CREATE);
912 
913 	e_binding_bind_property (
914 		table->priv->signature_combo_box, "visible",
915 		table->priv->signature_label, "visible",
916 		G_BINDING_SYNC_CREATE);
917 
918 	/* Now add the signature stuff. */
919 	gtk_table_attach (
920 		GTK_TABLE (object),
921 		table->priv->signature_label,
922 		2, 3, ii, ii + 1, 0, 0, 0, row_padding);
923 	gtk_table_attach (
924 		GTK_TABLE (object),
925 		table->priv->signature_combo_box,
926 		3, 4, ii, ii + 1, 0, 0, 0, row_padding);
927 
928 	from_header = E_COMPOSER_FROM_HEADER (e_composer_header_table_get_header (table, E_COMPOSER_HEADER_FROM));
929 
930 	gtk_table_attach (
931 		GTK_TABLE (object),
932 		from_header->override_widget, 1, 2,
933 		ii + 1, ii + 2, GTK_FILL, GTK_FILL, 0, row_padding);
934 
935 	/* Initialize the headers. */
936 	composer_header_table_from_changed_cb (table);
937 
938 	g_object_unref (client_cache);
939 	g_object_unref (registry);
940 }
941 
942 static void
e_composer_header_table_class_init(EComposerHeaderTableClass * class)943 e_composer_header_table_class_init (EComposerHeaderTableClass *class)
944 {
945 	GObjectClass *object_class;
946 
947 	g_type_class_add_private (class, sizeof (EComposerHeaderTablePrivate));
948 
949 	object_class = G_OBJECT_CLASS (class);
950 	object_class->set_property = composer_header_table_set_property;
951 	object_class->get_property = composer_header_table_get_property;
952 	object_class->dispose = composer_header_table_dispose;
953 	object_class->constructed = composer_header_table_constructed;
954 
955 	/**
956 	 * EComposerHeaderTable:client-cache:
957 	 *
958 	 * Cache of shared #EClient instances.
959 	 **/
960 	g_object_class_install_property (
961 		object_class,
962 		PROP_CLIENT_CACHE,
963 		g_param_spec_object (
964 			"client-cache",
965 			"Client Cache",
966 			"Cache of shared EClient instances",
967 			E_TYPE_CLIENT_CACHE,
968 			G_PARAM_READWRITE |
969 			G_PARAM_CONSTRUCT_ONLY |
970 			G_PARAM_STATIC_STRINGS));
971 
972 	g_object_class_install_property (
973 		object_class,
974 		PROP_DESTINATIONS_BCC,
975 		g_param_spec_boxed (
976 			"destinations-bcc",
977 			NULL,
978 			NULL,
979 			G_TYPE_PTR_ARRAY,
980 			G_PARAM_READWRITE |
981 			G_PARAM_STATIC_STRINGS));
982 
983 	g_object_class_install_property (
984 		object_class,
985 		PROP_DESTINATIONS_CC,
986 		g_param_spec_boxed (
987 			"destinations-cc",
988 			NULL,
989 			NULL,
990 			G_TYPE_PTR_ARRAY,
991 			G_PARAM_READWRITE |
992 			G_PARAM_STATIC_STRINGS));
993 
994 	g_object_class_install_property (
995 		object_class,
996 		PROP_DESTINATIONS_TO,
997 		g_param_spec_boxed (
998 			"destinations-to",
999 			NULL,
1000 			NULL,
1001 			G_TYPE_PTR_ARRAY,
1002 			G_PARAM_READWRITE |
1003 			G_PARAM_STATIC_STRINGS));
1004 
1005 	g_object_class_install_property (
1006 		object_class,
1007 		PROP_IDENTITY_UID,
1008 		g_param_spec_string (
1009 			"identity-uid",
1010 			NULL,
1011 			NULL,
1012 			NULL,
1013 			G_PARAM_READWRITE |
1014 			G_PARAM_STATIC_STRINGS));
1015 
1016 	g_object_class_install_property (
1017 		object_class,
1018 		PROP_POST_TO,
1019 		g_param_spec_boxed (
1020 			"post-to",
1021 			NULL,
1022 			NULL,
1023 			G_TYPE_PTR_ARRAY,
1024 			G_PARAM_READWRITE |
1025 			G_PARAM_STATIC_STRINGS));
1026 
1027 	g_object_class_install_property (
1028 		object_class,
1029 		PROP_REPLY_TO,
1030 		g_param_spec_string (
1031 			"reply-to",
1032 			NULL,
1033 			NULL,
1034 			NULL,
1035 			G_PARAM_READWRITE |
1036 			G_PARAM_STATIC_STRINGS));
1037 
1038 	g_object_class_install_property (
1039 		object_class,
1040 		PROP_SIGNATURE_COMBO_BOX,
1041 		g_param_spec_string (
1042 			"signature-combo-box",
1043 			NULL,
1044 			NULL,
1045 			NULL,
1046 			G_PARAM_READABLE |
1047 			G_PARAM_STATIC_STRINGS));
1048 
1049 	g_object_class_install_property (
1050 		object_class,
1051 		PROP_SIGNATURE_UID,
1052 		g_param_spec_string (
1053 			"signature-uid",
1054 			NULL,
1055 			NULL,
1056 			NULL,
1057 			G_PARAM_READWRITE |
1058 			G_PARAM_STATIC_STRINGS));
1059 
1060 	g_object_class_install_property (
1061 		object_class,
1062 		PROP_SUBJECT,
1063 		g_param_spec_string (
1064 			"subject",
1065 			NULL,
1066 			NULL,
1067 			NULL,
1068 			G_PARAM_READWRITE |
1069 			G_PARAM_STATIC_STRINGS));
1070 }
1071 
1072 static void
composer_header_table_realize_cb(EComposerHeaderTable * table)1073 composer_header_table_realize_cb (EComposerHeaderTable *table)
1074 {
1075 	g_return_if_fail (table != NULL);
1076 	g_return_if_fail (table->priv != NULL);
1077 
1078 	g_signal_handlers_disconnect_by_func (
1079 		table, composer_header_table_realize_cb, NULL);
1080 
1081 	e_name_selector_load_books (table->priv->name_selector);
1082 }
1083 
1084 static void
e_composer_header_table_init(EComposerHeaderTable * table)1085 e_composer_header_table_init (EComposerHeaderTable *table)
1086 {
1087 	gint rows;
1088 
1089 	table->priv = E_COMPOSER_HEADER_TABLE_GET_PRIVATE (table);
1090 
1091 	rows = G_N_ELEMENTS (table->priv->headers);
1092 	gtk_table_resize (GTK_TABLE (table), rows, 4);
1093 	gtk_table_set_row_spacings (GTK_TABLE (table), 0);
1094 	gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1095 
1096 	/* postpone name_selector loading, do that only when really needed */
1097 	g_signal_connect (
1098 		table, "realize",
1099 		G_CALLBACK (composer_header_table_realize_cb), NULL);
1100 }
1101 
1102 GtkWidget *
e_composer_header_table_new(EClientCache * client_cache)1103 e_composer_header_table_new (EClientCache *client_cache)
1104 {
1105 	g_return_val_if_fail (E_IS_CLIENT_CACHE (client_cache), NULL);
1106 
1107 	return g_object_new (
1108 		E_TYPE_COMPOSER_HEADER_TABLE,
1109 		"client-cache", client_cache, NULL);
1110 }
1111 
1112 EClientCache *
e_composer_header_table_ref_client_cache(EComposerHeaderTable * table)1113 e_composer_header_table_ref_client_cache (EComposerHeaderTable *table)
1114 {
1115 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1116 
1117 	return g_object_ref (table->priv->client_cache);
1118 }
1119 
1120 EComposerHeader *
e_composer_header_table_get_header(EComposerHeaderTable * table,EComposerHeaderType type)1121 e_composer_header_table_get_header (EComposerHeaderTable *table,
1122                                     EComposerHeaderType type)
1123 {
1124 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1125 	g_return_val_if_fail (type < E_COMPOSER_NUM_HEADERS, NULL);
1126 
1127 	return table->priv->headers[type];
1128 }
1129 
1130 EMailSignatureComboBox *
e_composer_header_table_get_signature_combo_box(EComposerHeaderTable * table)1131 e_composer_header_table_get_signature_combo_box (EComposerHeaderTable *table)
1132 {
1133 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1134 
1135 	return E_MAIL_SIGNATURE_COMBO_BOX (table->priv->signature_combo_box);
1136 }
1137 
1138 EDestination **
e_composer_header_table_get_destinations(EComposerHeaderTable * table)1139 e_composer_header_table_get_destinations (EComposerHeaderTable *table)
1140 {
1141 	EDestination **destinations;
1142 	EDestination **to, **cc, **bcc;
1143 	gint total, n_to, n_cc, n_bcc;
1144 
1145 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1146 
1147 	to = e_composer_header_table_get_destinations_to (table);
1148 	for (n_to = 0; to != NULL && to[n_to] != NULL; n_to++);
1149 
1150 	cc = e_composer_header_table_get_destinations_cc (table);
1151 	for (n_cc = 0; cc != NULL && cc[n_cc] != NULL; n_cc++);
1152 
1153 	bcc = e_composer_header_table_get_destinations_bcc (table);
1154 	for (n_bcc = 0; bcc != NULL && bcc[n_bcc] != NULL; n_bcc++);
1155 
1156 	total = n_to + n_cc + n_bcc;
1157 	destinations = g_new0 (EDestination *, total + 1);
1158 
1159 	while (n_bcc > 0 && total > 0)
1160 		destinations[--total] = g_object_ref (bcc[--n_bcc]);
1161 
1162 	while (n_cc > 0 && total > 0)
1163 		destinations[--total] = g_object_ref (cc[--n_cc]);
1164 
1165 	while (n_to > 0 && total > 0)
1166 		destinations[--total] = g_object_ref (to[--n_to]);
1167 
1168 	/* Counters should all be zero now. */
1169 	g_return_val_if_fail (total == 0 && n_to == 0 && n_cc == 0 && n_bcc == 0, destinations);
1170 
1171 	e_destination_freev (to);
1172 	e_destination_freev (cc);
1173 	e_destination_freev (bcc);
1174 
1175 	return destinations;
1176 }
1177 
1178 EDestination **
e_composer_header_table_get_destinations_bcc(EComposerHeaderTable * table)1179 e_composer_header_table_get_destinations_bcc (EComposerHeaderTable *table)
1180 {
1181 	EComposerHeader *header;
1182 	EComposerHeaderType type;
1183 	EComposerNameHeader *name_header;
1184 
1185 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1186 
1187 	type = E_COMPOSER_HEADER_BCC;
1188 	header = e_composer_header_table_get_header (table, type);
1189 	name_header = E_COMPOSER_NAME_HEADER (header);
1190 
1191 	return e_composer_name_header_get_destinations (name_header);
1192 }
1193 
1194 void
e_composer_header_table_add_destinations_bcc(EComposerHeaderTable * table,EDestination ** destinations)1195 e_composer_header_table_add_destinations_bcc (EComposerHeaderTable *table,
1196                                               EDestination **destinations)
1197 {
1198 	EComposerHeader *header;
1199 	EComposerHeaderType type;
1200 	EComposerNameHeader *name_header;
1201 
1202 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1203 
1204 	type = E_COMPOSER_HEADER_BCC;
1205 	header = e_composer_header_table_get_header (table, type);
1206 	name_header = E_COMPOSER_NAME_HEADER (header);
1207 
1208 	e_composer_name_header_add_destinations (name_header, destinations);
1209 
1210 	if (destinations != NULL && *destinations != NULL)
1211 		e_composer_header_set_visible (header, TRUE);
1212 }
1213 
1214 void
e_composer_header_table_set_destinations_bcc(EComposerHeaderTable * table,EDestination ** destinations)1215 e_composer_header_table_set_destinations_bcc (EComposerHeaderTable *table,
1216                                               EDestination **destinations)
1217 {
1218 	EComposerHeader *header;
1219 	EComposerHeaderType type;
1220 	EComposerNameHeader *name_header;
1221 
1222 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1223 
1224 	type = E_COMPOSER_HEADER_BCC;
1225 	header = e_composer_header_table_get_header (table, type);
1226 	name_header = E_COMPOSER_NAME_HEADER (header);
1227 
1228 	e_composer_name_header_set_destinations (name_header, destinations);
1229 
1230 	if (destinations != NULL && *destinations != NULL)
1231 		e_composer_header_set_visible (header, TRUE);
1232 }
1233 
1234 EDestination **
e_composer_header_table_get_destinations_cc(EComposerHeaderTable * table)1235 e_composer_header_table_get_destinations_cc (EComposerHeaderTable *table)
1236 {
1237 	EComposerHeader *header;
1238 	EComposerHeaderType type;
1239 	EComposerNameHeader *name_header;
1240 
1241 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1242 
1243 	type = E_COMPOSER_HEADER_CC;
1244 	header = e_composer_header_table_get_header (table, type);
1245 	name_header = E_COMPOSER_NAME_HEADER (header);
1246 
1247 	return e_composer_name_header_get_destinations (name_header);
1248 }
1249 
1250 void
e_composer_header_table_add_destinations_cc(EComposerHeaderTable * table,EDestination ** destinations)1251 e_composer_header_table_add_destinations_cc (EComposerHeaderTable *table,
1252                                              EDestination **destinations)
1253 {
1254 	EComposerHeader *header;
1255 	EComposerHeaderType type;
1256 	EComposerNameHeader *name_header;
1257 
1258 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1259 
1260 	type = E_COMPOSER_HEADER_CC;
1261 	header = e_composer_header_table_get_header (table, type);
1262 	name_header = E_COMPOSER_NAME_HEADER (header);
1263 
1264 	e_composer_name_header_add_destinations (name_header, destinations);
1265 
1266 	if (destinations != NULL && *destinations != NULL)
1267 		e_composer_header_set_visible (header, TRUE);
1268 }
1269 
1270 void
e_composer_header_table_set_destinations_cc(EComposerHeaderTable * table,EDestination ** destinations)1271 e_composer_header_table_set_destinations_cc (EComposerHeaderTable *table,
1272                                              EDestination **destinations)
1273 {
1274 	EComposerHeader *header;
1275 	EComposerHeaderType type;
1276 	EComposerNameHeader *name_header;
1277 
1278 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1279 
1280 	type = E_COMPOSER_HEADER_CC;
1281 	header = e_composer_header_table_get_header (table, type);
1282 	name_header = E_COMPOSER_NAME_HEADER (header);
1283 
1284 	e_composer_name_header_set_destinations (name_header, destinations);
1285 
1286 	if (destinations != NULL && *destinations != NULL)
1287 		e_composer_header_set_visible (header, TRUE);
1288 }
1289 
1290 EDestination **
e_composer_header_table_get_destinations_to(EComposerHeaderTable * table)1291 e_composer_header_table_get_destinations_to (EComposerHeaderTable *table)
1292 {
1293 	EComposerHeader *header;
1294 	EComposerHeaderType type;
1295 	EComposerNameHeader *name_header;
1296 
1297 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1298 
1299 	type = E_COMPOSER_HEADER_TO;
1300 	header = e_composer_header_table_get_header (table, type);
1301 	name_header = E_COMPOSER_NAME_HEADER (header);
1302 
1303 	return e_composer_name_header_get_destinations (name_header);
1304 }
1305 
1306 void
e_composer_header_table_add_destinations_to(EComposerHeaderTable * table,EDestination ** destinations)1307 e_composer_header_table_add_destinations_to (EComposerHeaderTable *table,
1308                                              EDestination **destinations)
1309 {
1310 	EComposerHeader *header;
1311 	EComposerHeaderType type;
1312 	EComposerNameHeader *name_header;
1313 
1314 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1315 
1316 	type = E_COMPOSER_HEADER_TO;
1317 	header = e_composer_header_table_get_header (table, type);
1318 	name_header = E_COMPOSER_NAME_HEADER (header);
1319 
1320 	e_composer_name_header_add_destinations (name_header, destinations);
1321 }
1322 
1323 void
e_composer_header_table_set_destinations_to(EComposerHeaderTable * table,EDestination ** destinations)1324 e_composer_header_table_set_destinations_to (EComposerHeaderTable *table,
1325                                              EDestination **destinations)
1326 {
1327 	EComposerHeader *header;
1328 	EComposerHeaderType type;
1329 	EComposerNameHeader *name_header;
1330 
1331 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1332 
1333 	type = E_COMPOSER_HEADER_TO;
1334 	header = e_composer_header_table_get_header (table, type);
1335 	name_header = E_COMPOSER_NAME_HEADER (header);
1336 
1337 	e_composer_name_header_set_destinations (name_header, destinations);
1338 }
1339 
1340 gchar *
e_composer_header_table_dup_identity_uid(EComposerHeaderTable * table,gchar ** chosen_alias_name,gchar ** chosen_alias_address)1341 e_composer_header_table_dup_identity_uid (EComposerHeaderTable *table,
1342 					  gchar **chosen_alias_name,
1343 					  gchar **chosen_alias_address)
1344 {
1345 	EComposerHeader *header;
1346 	EComposerHeaderType type;
1347 	EComposerFromHeader *from_header;
1348 
1349 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1350 
1351 	type = E_COMPOSER_HEADER_FROM;
1352 	header = e_composer_header_table_get_header (table, type);
1353 	from_header = E_COMPOSER_FROM_HEADER (header);
1354 
1355 	return e_composer_from_header_dup_active_id (from_header, chosen_alias_name, chosen_alias_address);
1356 }
1357 
1358 void
e_composer_header_table_set_identity_uid(EComposerHeaderTable * table,const gchar * identity_uid,const gchar * alias_name,const gchar * alias_address)1359 e_composer_header_table_set_identity_uid (EComposerHeaderTable *table,
1360 					  const gchar *identity_uid,
1361 					  const gchar *alias_name,
1362 					  const gchar *alias_address)
1363 {
1364 	EComposerHeader *header;
1365 	EComposerHeaderType type;
1366 	EComposerFromHeader *from_header;
1367 
1368 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1369 
1370 	type = E_COMPOSER_HEADER_FROM;
1371 	header = e_composer_header_table_get_header (table, type);
1372 	from_header = E_COMPOSER_FROM_HEADER (header);
1373 
1374 	e_composer_from_header_set_active_id (from_header, identity_uid, alias_name, alias_address);
1375 }
1376 
1377 const gchar *
e_composer_header_table_get_from_name(EComposerHeaderTable * table)1378 e_composer_header_table_get_from_name (EComposerHeaderTable *table)
1379 {
1380 	EComposerHeader *header;
1381 	EComposerHeaderType type;
1382 	EComposerFromHeader *from_header;
1383 
1384 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1385 
1386 	type = E_COMPOSER_HEADER_FROM;
1387 	header = e_composer_header_table_get_header (table, type);
1388 	from_header = E_COMPOSER_FROM_HEADER (header);
1389 
1390 	return e_composer_from_header_get_name (from_header);
1391 }
1392 
1393 const gchar *
e_composer_header_table_get_from_address(EComposerHeaderTable * table)1394 e_composer_header_table_get_from_address (EComposerHeaderTable *table)
1395 {
1396 	EComposerHeader *header;
1397 	EComposerHeaderType type;
1398 	EComposerFromHeader *from_header;
1399 
1400 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1401 
1402 	type = E_COMPOSER_HEADER_FROM;
1403 	header = e_composer_header_table_get_header (table, type);
1404 	from_header = E_COMPOSER_FROM_HEADER (header);
1405 
1406 	return e_composer_from_header_get_address (from_header);
1407 }
1408 
1409 GList *
e_composer_header_table_get_post_to(EComposerHeaderTable * table)1410 e_composer_header_table_get_post_to (EComposerHeaderTable *table)
1411 {
1412 	EComposerHeader *header;
1413 	EComposerHeaderType type;
1414 	EComposerPostHeader *post_header;
1415 
1416 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1417 
1418 	type = E_COMPOSER_HEADER_POST_TO;
1419 	header = e_composer_header_table_get_header (table, type);
1420 	post_header = E_COMPOSER_POST_HEADER (header);
1421 
1422 	return e_composer_post_header_get_folders (post_header);
1423 }
1424 
1425 void
e_composer_header_table_set_post_to_base(EComposerHeaderTable * table,const gchar * base_url,const gchar * folders)1426 e_composer_header_table_set_post_to_base (EComposerHeaderTable *table,
1427                                           const gchar *base_url,
1428                                           const gchar *folders)
1429 {
1430 	EComposerHeader *header;
1431 	EComposerHeaderType type;
1432 	EComposerPostHeader *post_header;
1433 
1434 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1435 
1436 	type = E_COMPOSER_HEADER_POST_TO;
1437 	header = e_composer_header_table_get_header (table, type);
1438 	post_header = E_COMPOSER_POST_HEADER (header);
1439 
1440 	e_composer_post_header_set_folders_base (post_header, base_url, folders);
1441 }
1442 
1443 void
e_composer_header_table_set_post_to_list(EComposerHeaderTable * table,GList * folders)1444 e_composer_header_table_set_post_to_list (EComposerHeaderTable *table,
1445                                           GList *folders)
1446 {
1447 	EComposerHeader *header;
1448 	EComposerHeaderType type;
1449 	EComposerPostHeader *post_header;
1450 
1451 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1452 
1453 	type = E_COMPOSER_HEADER_POST_TO;
1454 	header = e_composer_header_table_get_header (table, type);
1455 	post_header = E_COMPOSER_POST_HEADER (header);
1456 
1457 	e_composer_post_header_set_folders (post_header, folders);
1458 }
1459 
1460 const gchar *
e_composer_header_table_get_reply_to(EComposerHeaderTable * table)1461 e_composer_header_table_get_reply_to (EComposerHeaderTable *table)
1462 {
1463 	EComposerHeader *header;
1464 	EComposerHeaderType type;
1465 	EComposerTextHeader *text_header;
1466 
1467 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1468 
1469 	type = E_COMPOSER_HEADER_REPLY_TO;
1470 	header = e_composer_header_table_get_header (table, type);
1471 	text_header = E_COMPOSER_TEXT_HEADER (header);
1472 
1473 	return e_composer_text_header_get_text (text_header);
1474 }
1475 
1476 void
e_composer_header_table_set_reply_to(EComposerHeaderTable * table,const gchar * reply_to)1477 e_composer_header_table_set_reply_to (EComposerHeaderTable *table,
1478                                       const gchar *reply_to)
1479 {
1480 	EComposerHeader *header;
1481 	EComposerHeaderType type;
1482 	EComposerTextHeader *text_header;
1483 
1484 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1485 
1486 	type = E_COMPOSER_HEADER_REPLY_TO;
1487 	header = e_composer_header_table_get_header (table, type);
1488 	text_header = E_COMPOSER_TEXT_HEADER (header);
1489 
1490 	e_composer_text_header_set_text (text_header, reply_to);
1491 
1492 	if (reply_to != NULL && *reply_to != '\0')
1493 		e_composer_header_set_visible (header, TRUE);
1494 }
1495 
1496 const gchar *
e_composer_header_table_get_signature_uid(EComposerHeaderTable * table)1497 e_composer_header_table_get_signature_uid (EComposerHeaderTable *table)
1498 {
1499 	EMailSignatureComboBox *combo_box;
1500 
1501 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1502 
1503 	combo_box = e_composer_header_table_get_signature_combo_box (table);
1504 
1505 	return gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box));
1506 }
1507 
1508 void
e_composer_header_table_set_signature_uid(EComposerHeaderTable * table,const gchar * signature_uid)1509 e_composer_header_table_set_signature_uid (EComposerHeaderTable *table,
1510                                            const gchar *signature_uid)
1511 {
1512 	EMailSignatureComboBox *combo_box;
1513 
1514 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1515 
1516 	combo_box = e_composer_header_table_get_signature_combo_box (table);
1517 
1518 	gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), signature_uid);
1519 }
1520 
1521 const gchar *
e_composer_header_table_get_subject(EComposerHeaderTable * table)1522 e_composer_header_table_get_subject (EComposerHeaderTable *table)
1523 {
1524 	EComposerHeader *header;
1525 	EComposerHeaderType type;
1526 	EComposerTextHeader *text_header;
1527 
1528 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1529 
1530 	type = E_COMPOSER_HEADER_SUBJECT;
1531 	header = e_composer_header_table_get_header (table, type);
1532 	text_header = E_COMPOSER_TEXT_HEADER (header);
1533 
1534 	return e_composer_text_header_get_text (text_header);
1535 }
1536 
1537 void
e_composer_header_table_set_subject(EComposerHeaderTable * table,const gchar * subject)1538 e_composer_header_table_set_subject (EComposerHeaderTable *table,
1539                                      const gchar *subject)
1540 {
1541 	EComposerHeader *header;
1542 	EComposerHeaderType type;
1543 	EComposerTextHeader *text_header;
1544 
1545 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1546 
1547 	type = E_COMPOSER_HEADER_SUBJECT;
1548 	header = e_composer_header_table_get_header (table, type);
1549 	text_header = E_COMPOSER_TEXT_HEADER (header);
1550 
1551 	e_composer_text_header_set_text (text_header, subject);
1552 }
1553 
1554 void
e_composer_header_table_set_header_visible(EComposerHeaderTable * table,EComposerHeaderType type,gboolean visible)1555 e_composer_header_table_set_header_visible (EComposerHeaderTable *table,
1556                                             EComposerHeaderType type,
1557                                             gboolean visible)
1558 {
1559 	EComposerHeader *header;
1560 
1561 	header = e_composer_header_table_get_header (table, type);
1562 	e_composer_header_set_visible (header, visible);
1563 
1564 	/* Signature widgets track the "From" header. */
1565 	if (type == E_COMPOSER_HEADER_FROM) {
1566 		if (visible) {
1567 			gtk_widget_show (table->priv->signature_label);
1568 			gtk_widget_show (table->priv->signature_combo_box);
1569 		} else {
1570 			gtk_widget_hide (table->priv->signature_label);
1571 			gtk_widget_hide (table->priv->signature_combo_box);
1572 		}
1573 	}
1574 }
1575 
1576 /**
1577  * e_composer_header_table_ref_source:
1578  * @table: an #EComposerHeaderTable
1579  * @uid: a unique identifier string
1580  *
1581  * Convenience function that works just like e_source_registry_ref_source(),
1582  * but spares the caller from digging out the #ESourceRegistry from @table.
1583  *
1584  * The returned #ESource is referenced for thread-safety and must be
1585  * unreferenced with g_object_unref() when finished with it.
1586  *
1587  * Returns: an #ESource, or %NULL if no match was found
1588  **/
1589 ESource *
e_composer_header_table_ref_source(EComposerHeaderTable * table,const gchar * uid)1590 e_composer_header_table_ref_source (EComposerHeaderTable *table,
1591                                     const gchar *uid)
1592 {
1593 	EClientCache *client_cache;
1594 	ESourceRegistry *registry;
1595 	ESource *source;
1596 
1597 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1598 	g_return_val_if_fail (uid != NULL, NULL);
1599 
1600 	client_cache = e_composer_header_table_ref_client_cache (table);
1601 	registry = e_client_cache_ref_registry (client_cache);
1602 
1603 	source = e_source_registry_ref_source (registry, uid);
1604 
1605 	g_object_unref (client_cache);
1606 	g_object_unref (registry);
1607 
1608 	return source;
1609 }
1610 
1611