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.
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
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/>.
14 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
17 #include "evolution-config.h"
19 #include "e-composer-header-table.h"
21 #include <glib/gi18n-lib.h>
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"
31 #define E_COMPOSER_HEADER_TABLE_GET_PRIVATE(obj) \
32 (G_TYPE_INSTANCE_GET_PRIVATE \
33 ((obj), E_TYPE_COMPOSER_HEADER_TABLE, EComposerHeaderTablePrivate))
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")
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
;
52 gchar
*previous_from_uid
;
58 PROP_DESTINATIONS_BCC
,
64 PROP_SIGNATURE_COMBO_BOX
,
71 e_composer_header_table
,
75 g_value_set_destinations (GValue
*value
,
76 EDestination
**destinations
)
81 /* Preallocate some reasonable number. */
82 array
= g_ptr_array_new_full (64, g_object_unref
);
84 for (ii
= 0; destinations
[ii
] != NULL
; ii
++) {
85 g_ptr_array_add (array
, e_destination_copy (destinations
[ii
]));
88 g_value_take_boxed (value
, array
);
91 static EDestination
**
92 g_value_dup_destinations (const GValue
*value
)
94 EDestination
**destinations
;
95 const EDestination
*dest
;
99 array
= g_value_get_boxed (value
);
100 destinations
= g_new0 (EDestination
*, array
->len
+ 1);
102 for (ii
= 0; ii
< array
->len
; ii
++) {
103 dest
= g_ptr_array_index (array
, ii
);
104 destinations
[ii
] = e_destination_copy (dest
);
111 g_value_set_string_list (GValue
*value
,
116 array
= g_ptr_array_new_full (g_list_length (list
), g_free
);
118 while (list
!= NULL
) {
119 g_ptr_array_add (array
, g_strdup (list
->data
));
123 g_value_take_boxed (value
, array
);
127 g_value_dup_string_list (const GValue
*value
)
133 array
= g_value_get_boxed (value
);
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
));
140 return g_list_reverse (list
);
144 composer_header_table_notify_header (EComposerHeader
*header
,
145 const gchar
*property_name
)
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
);
155 composer_header_table_notify_widget (GtkWidget
*widget
,
156 const gchar
*property_name
)
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
);
166 composer_header_table_bind_header (const gchar
*property_name
,
167 const gchar
*signal_name
,
168 EComposerHeader
*header
)
170 /* Propagate the signal as "notify::property_name". */
174 G_CALLBACK (composer_header_table_notify_header
),
175 (gpointer
) property_name
);
179 composer_header_table_bind_widget (const gchar
*property_name
,
180 const gchar
*signal_name
,
183 /* Propagate the signal as "notify::property_name". */
187 G_CALLBACK (composer_header_table_notify_widget
),
188 (gpointer
) property_name
);
191 static EDestination
**
192 composer_header_table_update_destinations (EDestination
**old_destinations
,
193 const gchar
* const *auto_addresses
)
195 CamelAddress
*address
;
196 CamelInternetAddress
*inet_address
;
197 EDestination
**new_destinations
;
198 EDestination
*destination
;
199 GQueue queue
= G_QUEUE_INIT
;
203 /* Include automatic recipients for the selected account. */
205 if (auto_addresses
== NULL
)
208 inet_address
= camel_internet_address_new ();
209 address
= CAMEL_ADDRESS (inet_address
);
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
]);
217 for (ii
= 0; ii
< camel_address_length (address
); ii
++) {
218 const gchar
*name
, *email
;
220 if (!camel_internet_address_get (
221 inet_address
, ii
, &name
, &email
))
224 destination
= e_destination_new ();
225 e_destination_set_auto_recipient (destination
, TRUE
);
228 e_destination_set_name (destination
, name
);
231 e_destination_set_email (destination
, email
);
233 g_queue_push_tail (&queue
, destination
);
236 g_object_unref (inet_address
);
240 /* Include custom recipients for this message. */
242 if (old_destinations
== NULL
)
245 for (ii
= 0; old_destinations
[ii
] != NULL
; ii
++) {
246 if (e_destination_is_auto_recipient (old_destinations
[ii
]))
249 destination
= e_destination_copy (old_destinations
[ii
]);
250 g_queue_push_tail (&queue
, destination
);
255 length
= g_queue_get_length (&queue
);
256 new_destinations
= g_new0 (EDestination
*, length
+ 1);
258 for (ii
= 0; ii
< length
; ii
++)
259 new_destinations
[ii
] = g_queue_pop_head (&queue
);
262 g_warn_if_fail (g_queue_is_empty (&queue
));
264 return new_destinations
;
268 composer_header_table_setup_mail_headers (EComposerHeaderTable
*table
)
273 settings
= e_util_ref_settings ("org.gnome.evolution.mail");
275 for (ii
= 0; ii
< E_COMPOSER_NUM_HEADERS
; ii
++) {
276 EComposerHeader
*header
;
281 header
= e_composer_header_table_get_header (table
, ii
);
284 case E_COMPOSER_HEADER_FROM
:
285 key
= "composer-show-from-override";
288 case E_COMPOSER_HEADER_BCC
:
289 key
= "composer-show-bcc";
292 case E_COMPOSER_HEADER_CC
:
293 key
= "composer-show-cc";
296 case E_COMPOSER_HEADER_REPLY_TO
:
297 key
= "composer-show-reply-to";
306 g_settings_unbind (header
, "visible");
309 case E_COMPOSER_HEADER_FROM
:
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
:
329 e_composer_header_set_sensitive (header
, sensitive
);
330 e_composer_header_set_visible (header
, visible
);
333 if (ii
== E_COMPOSER_HEADER_FROM
)
336 header
, "override-visible",
337 G_SETTINGS_BIND_DEFAULT
);
342 G_SETTINGS_BIND_DEFAULT
);
346 g_object_unref (settings
);
350 composer_header_table_setup_post_headers (EComposerHeaderTable
*table
)
355 settings
= e_util_ref_settings ("org.gnome.evolution.mail");
357 for (ii
= 0; ii
< E_COMPOSER_NUM_HEADERS
; ii
++) {
358 EComposerHeader
*header
;
361 header
= e_composer_header_table_get_header (table
, ii
);
364 case E_COMPOSER_HEADER_FROM
:
365 key
= "composer-show-post-from";
368 case E_COMPOSER_HEADER_REPLY_TO
:
369 key
= "composer-show-post-reply-to";
378 g_settings_unbind (header
, "visible");
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
);
389 default: /* this includes TO, CC and BCC */
390 e_composer_header_set_sensitive (header
, FALSE
);
391 e_composer_header_set_visible (header
, FALSE
);
399 G_SETTINGS_BIND_DEFAULT
);
402 g_object_unref (settings
);
406 composer_header_table_show_post_headers (EComposerHeaderTable
*table
)
408 EClientCache
*client_cache
;
409 ESourceRegistry
*registry
;
411 const gchar
*extension_name
;
413 gboolean show_post_headers
= FALSE
;
415 client_cache
= e_composer_header_table_ref_client_cache (table
);
416 registry
= e_client_cache_ref_registry (client_cache
);
418 target_uid
= e_composer_header_table_dup_identity_uid (table
, NULL
, NULL
);
420 extension_name
= E_SOURCE_EXTENSION_MAIL_ACCOUNT
;
421 list
= e_source_registry_list_sources (registry
, extension_name
);
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.
427 * XXX What if multiple accounts use this identity but only
428 * one is "nntp"? Maybe it should be indicated by the
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
;
437 extension
= e_source_get_extension (source
, extension_name
);
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
));
444 if (g_strcmp0 (identity_uid
, target_uid
) != 0)
447 if (g_strcmp0 (backend_name
, "nntp") != 0)
450 show_post_headers
= TRUE
;
454 g_list_free_full (list
, (GDestroyNotify
) g_object_unref
);
456 g_object_unref (client_cache
);
457 g_object_unref (registry
);
460 return show_post_headers
;
464 composer_header_table_from_changed_cb (EComposerHeaderTable
*table
)
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
;
476 gchar
*address
= NULL
;
478 const gchar
*reply_to
= NULL
;
479 const gchar
* const *bcc
= NULL
;
480 const gchar
* const *cc
= NULL
;
482 /* Keep "Post-To" and "Reply-To" synchronized with "From" */
484 uid
= e_composer_header_table_dup_identity_uid (table
, &name
, &address
);
486 source
= e_composer_header_table_ref_source (table
, uid
);
489 /* Make sure this is really a mail identity source. */
490 if (source
!= NULL
) {
491 const gchar
*extension_name
;
493 extension_name
= E_SOURCE_EXTENSION_MAIL_IDENTITY
;
494 if (!e_source_has_extension (source
, extension_name
)) {
495 g_object_unref (source
);
500 if (source
!= NULL
) {
501 ESourceMailIdentity
*mi
;
502 ESourceMailComposition
*mc
;
503 const gchar
*extension_name
;
505 extension_name
= E_SOURCE_EXTENSION_MAIL_IDENTITY
;
506 mi
= e_source_get_extension (source
, extension_name
);
508 extension_name
= E_SOURCE_EXTENSION_MAIL_COMPOSITION
;
509 mc
= e_source_get_extension (source
, extension_name
);
514 name
= e_source_mail_identity_dup_name (mi
);
515 address
= e_source_mail_identity_dup_address (mi
);
519 name
= e_source_mail_identity_dup_name (mi
);
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
);
525 if (table
->priv
->previous_from_uid
) {
526 ESource
*previous_source
;
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
;
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
);
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
);
541 matches
= ((!current_reply_to
|| !*current_reply_to
) && (!previous_reply_to
|| !*previous_reply_to
)) ||
542 g_strcmp0 (current_reply_to
, previous_reply_to
) == 0;
544 /* Do not change Reply-To, if the user changed it. */
546 reply_to
= current_reply_to
;
550 g_free (table
->priv
->previous_from_uid
);
551 table
->priv
->previous_from_uid
= g_strdup (e_source_get_uid (source
));
553 g_object_unref (source
);
555 g_free (table
->priv
->previous_from_uid
);
556 table
->priv
->previous_from_uid
= NULL
;
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
);
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
);
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
);
575 /* Update automatic CC destinations. */
577 e_composer_header_table_get_destinations_cc (table
);
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
);
585 /* Update automatic BCC destinations. */
587 e_composer_header_table_get_destinations_bcc (table
);
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
);
595 if (composer_header_table_show_post_headers (table
))
596 composer_header_table_setup_post_headers (table
);
598 composer_header_table_setup_mail_headers (table
);
605 composer_header_table_set_client_cache (EComposerHeaderTable
*table
,
606 EClientCache
*client_cache
)
608 g_return_if_fail (E_IS_CLIENT_CACHE (client_cache
));
609 g_return_if_fail (table
->priv
->client_cache
== NULL
);
611 table
->priv
->client_cache
= g_object_ref (client_cache
);
615 composer_header_table_set_property (GObject
*object
,
620 EDestination
**destinations
;
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
));
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
),
635 e_destination_freev (destinations
);
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
),
643 e_destination_freev (destinations
);
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
),
651 e_destination_freev (destinations
);
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
);
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
);
669 e_composer_header_table_set_reply_to (
670 E_COMPOSER_HEADER_TABLE (object
),
671 g_value_get_string (value
));
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
));
681 e_composer_header_table_set_subject (
682 E_COMPOSER_HEADER_TABLE (object
),
683 g_value_get_string (value
));
687 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
691 composer_header_table_get_property (GObject
*object
,
696 EDestination
**destinations
;
699 switch (property_id
) {
700 case PROP_CLIENT_CACHE
:
701 g_value_take_object (
703 e_composer_header_table_ref_client_cache (
704 E_COMPOSER_HEADER_TABLE (object
)));
707 case PROP_DESTINATIONS_BCC
:
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
);
715 case PROP_DESTINATIONS_CC
:
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
);
723 case PROP_DESTINATIONS_TO
:
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
);
731 case PROP_IDENTITY_UID
:
732 g_value_take_string (
734 e_composer_header_table_dup_identity_uid (
735 E_COMPOSER_HEADER_TABLE (object
), NULL
, NULL
));
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
);
749 e_composer_header_table_get_reply_to (
750 E_COMPOSER_HEADER_TABLE (object
)));
753 case PROP_SIGNATURE_COMBO_BOX
:
756 e_composer_header_table_get_signature_combo_box (
757 E_COMPOSER_HEADER_TABLE (object
)));
760 case PROP_SIGNATURE_UID
:
763 e_composer_header_table_get_signature_uid (
764 E_COMPOSER_HEADER_TABLE (object
)));
770 e_composer_header_table_get_subject (
771 E_COMPOSER_HEADER_TABLE (object
)));
775 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
779 composer_header_table_dispose (GObject
*object
)
781 EComposerHeaderTablePrivate
*priv
;
784 priv
= E_COMPOSER_HEADER_TABLE_GET_PRIVATE (object
);
786 for (ii
= 0; ii
< G_N_ELEMENTS (priv
->headers
); ii
++) {
787 if (priv
->headers
[ii
] != NULL
) {
788 g_object_unref (priv
->headers
[ii
]);
789 priv
->headers
[ii
] = NULL
;
793 if (priv
->signature_combo_box
!= NULL
) {
794 g_object_unref (priv
->signature_combo_box
);
795 priv
->signature_combo_box
= NULL
;
798 if (priv
->name_selector
!= NULL
) {
799 e_name_selector_cancel_loading (priv
->name_selector
);
800 g_object_unref (priv
->name_selector
);
801 priv
->name_selector
= NULL
;
804 if (priv
->client_cache
!= NULL
) {
805 g_object_unref (priv
->client_cache
);
806 priv
->client_cache
= NULL
;
809 g_free (priv
->previous_from_uid
);
810 priv
->previous_from_uid
= NULL
;
812 /* Chain up to parent's dispose() method. */
813 G_OBJECT_CLASS (e_composer_header_table_parent_class
)->dispose (object
);
817 composer_header_table_constructed (GObject
*object
)
819 EComposerHeaderTable
*table
;
820 EComposerFromHeader
*from_header
;
821 ENameSelector
*name_selector
;
822 EClientCache
*client_cache
;
823 ESourceRegistry
*registry
;
824 EComposerHeader
*header
;
829 /* Chain up to parent's constructed() method. */
830 G_OBJECT_CLASS (e_composer_header_table_parent_class
)->constructed (object
);
832 table
= E_COMPOSER_HEADER_TABLE (object
);
834 client_cache
= e_composer_header_table_ref_client_cache (table
);
835 registry
= e_client_cache_ref_registry (client_cache
);
837 name_selector
= e_name_selector_new (client_cache
);
838 table
->priv
->name_selector
= name_selector
;
840 header
= e_composer_from_header_new (registry
, _("Fr_om:"));
841 composer_header_table_bind_header ("identity-uid", "changed", header
);
842 g_signal_connect_swapped (
843 header
, "changed", G_CALLBACK (
844 composer_header_table_from_changed_cb
), table
);
845 table
->priv
->headers
[E_COMPOSER_HEADER_FROM
] = header
;
847 header
= e_composer_text_header_new_label (registry
, _("_Reply-To:"));
848 composer_header_table_bind_header ("reply-to", "changed", header
);
849 table
->priv
->headers
[E_COMPOSER_HEADER_REPLY_TO
] = header
;
851 header
= e_composer_name_header_new (
852 registry
, _("_To:"), name_selector
);
853 e_composer_header_set_input_tooltip (header
, HEADER_TOOLTIP_TO
);
854 composer_header_table_bind_header ("destinations-to", "changed", header
);
855 table
->priv
->headers
[E_COMPOSER_HEADER_TO
] = header
;
857 header
= e_composer_name_header_new (
858 registry
, _("_Cc:"), name_selector
);
859 e_composer_header_set_input_tooltip (header
, HEADER_TOOLTIP_CC
);
860 composer_header_table_bind_header ("destinations-cc", "changed", header
);
861 table
->priv
->headers
[E_COMPOSER_HEADER_CC
] = header
;
863 header
= e_composer_name_header_new (
864 registry
, _("_Bcc:"), name_selector
);
865 e_composer_header_set_input_tooltip (header
, HEADER_TOOLTIP_BCC
);
866 composer_header_table_bind_header ("destinations-bcc", "changed", header
);
867 table
->priv
->headers
[E_COMPOSER_HEADER_BCC
] = header
;
869 header
= e_composer_post_header_new (registry
, _("_Post To:"));
870 composer_header_table_bind_header ("post-to", "changed", header
);
871 table
->priv
->headers
[E_COMPOSER_HEADER_POST_TO
] = header
;
873 header
= e_composer_spell_header_new_label (registry
, _("S_ubject:"));
874 composer_header_table_bind_header ("subject", "changed", header
);
875 e_composer_header_set_title_has_tooltip (header
, FALSE
);
876 e_composer_header_set_input_has_tooltip (header
, FALSE
);
877 table
->priv
->headers
[E_COMPOSER_HEADER_SUBJECT
] = header
;
879 widget
= e_mail_signature_combo_box_new (registry
);
880 composer_header_table_bind_widget ("signature-uid", "changed", widget
);
881 table
->priv
->signature_combo_box
= g_object_ref_sink (widget
);
883 widget
= gtk_label_new_with_mnemonic (_("Si_gnature:"));
884 gtk_label_set_mnemonic_widget (
885 GTK_LABEL (widget
), table
->priv
->signature_combo_box
);
886 table
->priv
->signature_label
= g_object_ref_sink (widget
);
888 /* Use "ypadding" instead of "row-spacing" because some rows may
889 * be invisible and we don't want spacing around them. */
893 for (ii
= 0; ii
< G_N_ELEMENTS (table
->priv
->headers
); ii
++) {
896 if (ii
> E_COMPOSER_HEADER_FROM
)
901 table
->priv
->headers
[ii
]->title_widget
, 0, 1,
902 row
, row
+ 1, GTK_FILL
, GTK_FILL
, 0, row_padding
);
905 table
->priv
->headers
[ii
]->input_widget
, 1, 4,
906 row
, row
+ 1, GTK_FILL
| GTK_EXPAND
, 0, 0, row_padding
);
909 ii
= E_COMPOSER_HEADER_FROM
;
911 /* Leave room in the "From" row for signature stuff. */
912 gtk_container_child_set (
913 GTK_CONTAINER (object
),
914 table
->priv
->headers
[ii
]->input_widget
,
915 "right-attach", 2, NULL
);
917 e_binding_bind_property (
918 table
->priv
->headers
[ii
]->input_widget
, "visible",
919 table
->priv
->signature_label
, "visible",
920 G_BINDING_SYNC_CREATE
);
922 e_binding_bind_property (
923 table
->priv
->headers
[ii
]->input_widget
, "visible",
924 table
->priv
->signature_combo_box
, "visible",
925 G_BINDING_SYNC_CREATE
);
927 /* Now add the signature stuff. */
930 table
->priv
->signature_label
,
931 2, 3, ii
, ii
+ 1, 0, 0, 0, row_padding
);
934 table
->priv
->signature_combo_box
,
935 3, 4, ii
, ii
+ 1, 0, 0, 0, row_padding
);
937 from_header
= E_COMPOSER_FROM_HEADER (e_composer_header_table_get_header (table
, E_COMPOSER_HEADER_FROM
));
941 from_header
->override_widget
, 1, 2,
942 ii
+ 1, ii
+ 2, GTK_FILL
, GTK_FILL
, 0, row_padding
);
944 /* Initialize the headers. */
945 composer_header_table_from_changed_cb (table
);
947 g_object_unref (client_cache
);
948 g_object_unref (registry
);
952 e_composer_header_table_class_init (EComposerHeaderTableClass
*class)
954 GObjectClass
*object_class
;
956 g_type_class_add_private (class, sizeof (EComposerHeaderTablePrivate
));
958 object_class
= G_OBJECT_CLASS (class);
959 object_class
->set_property
= composer_header_table_set_property
;
960 object_class
->get_property
= composer_header_table_get_property
;
961 object_class
->dispose
= composer_header_table_dispose
;
962 object_class
->constructed
= composer_header_table_constructed
;
965 * EComposerHeaderTable:client-cache:
967 * Cache of shared #EClient instances.
969 g_object_class_install_property (
972 g_param_spec_object (
975 "Cache of shared EClient instances",
978 G_PARAM_CONSTRUCT_ONLY
|
979 G_PARAM_STATIC_STRINGS
));
981 g_object_class_install_property (
983 PROP_DESTINATIONS_BCC
,
990 G_PARAM_STATIC_STRINGS
));
992 g_object_class_install_property (
994 PROP_DESTINATIONS_CC
,
1001 G_PARAM_STATIC_STRINGS
));
1003 g_object_class_install_property (
1005 PROP_DESTINATIONS_TO
,
1006 g_param_spec_boxed (
1012 G_PARAM_STATIC_STRINGS
));
1014 g_object_class_install_property (
1017 g_param_spec_string (
1023 G_PARAM_STATIC_STRINGS
));
1025 g_object_class_install_property (
1028 g_param_spec_boxed (
1034 G_PARAM_STATIC_STRINGS
));
1036 g_object_class_install_property (
1039 g_param_spec_string (
1045 G_PARAM_STATIC_STRINGS
));
1047 g_object_class_install_property (
1049 PROP_SIGNATURE_COMBO_BOX
,
1050 g_param_spec_string (
1051 "signature-combo-box",
1056 G_PARAM_STATIC_STRINGS
));
1058 g_object_class_install_property (
1061 g_param_spec_string (
1067 G_PARAM_STATIC_STRINGS
));
1069 g_object_class_install_property (
1072 g_param_spec_string (
1078 G_PARAM_STATIC_STRINGS
));
1082 composer_header_table_realize_cb (EComposerHeaderTable
*table
)
1084 g_return_if_fail (table
!= NULL
);
1085 g_return_if_fail (table
->priv
!= NULL
);
1087 g_signal_handlers_disconnect_by_func (
1088 table
, composer_header_table_realize_cb
, NULL
);
1090 e_name_selector_load_books (table
->priv
->name_selector
);
1094 e_composer_header_table_init (EComposerHeaderTable
*table
)
1098 table
->priv
= E_COMPOSER_HEADER_TABLE_GET_PRIVATE (table
);
1100 rows
= G_N_ELEMENTS (table
->priv
->headers
);
1101 gtk_table_resize (GTK_TABLE (table
), rows
, 4);
1102 gtk_table_set_row_spacings (GTK_TABLE (table
), 0);
1103 gtk_table_set_col_spacings (GTK_TABLE (table
), 6);
1105 /* postpone name_selector loading, do that only when really needed */
1108 G_CALLBACK (composer_header_table_realize_cb
), NULL
);
1112 e_composer_header_table_new (EClientCache
*client_cache
)
1114 g_return_val_if_fail (E_IS_CLIENT_CACHE (client_cache
), NULL
);
1116 return g_object_new (
1117 E_TYPE_COMPOSER_HEADER_TABLE
,
1118 "client-cache", client_cache
, NULL
);
1122 e_composer_header_table_ref_client_cache (EComposerHeaderTable
*table
)
1124 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1126 return g_object_ref (table
->priv
->client_cache
);
1130 e_composer_header_table_get_header (EComposerHeaderTable
*table
,
1131 EComposerHeaderType type
)
1133 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1134 g_return_val_if_fail (type
< E_COMPOSER_NUM_HEADERS
, NULL
);
1136 return table
->priv
->headers
[type
];
1139 EMailSignatureComboBox
*
1140 e_composer_header_table_get_signature_combo_box (EComposerHeaderTable
*table
)
1142 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1144 return E_MAIL_SIGNATURE_COMBO_BOX (table
->priv
->signature_combo_box
);
1148 e_composer_header_table_get_destinations (EComposerHeaderTable
*table
)
1150 EDestination
**destinations
;
1151 EDestination
**to
, **cc
, **bcc
;
1152 gint total
, n_to
, n_cc
, n_bcc
;
1154 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1156 to
= e_composer_header_table_get_destinations_to (table
);
1157 for (n_to
= 0; to
!= NULL
&& to
[n_to
] != NULL
; n_to
++);
1159 cc
= e_composer_header_table_get_destinations_cc (table
);
1160 for (n_cc
= 0; cc
!= NULL
&& cc
[n_cc
] != NULL
; n_cc
++);
1162 bcc
= e_composer_header_table_get_destinations_bcc (table
);
1163 for (n_bcc
= 0; bcc
!= NULL
&& bcc
[n_bcc
] != NULL
; n_bcc
++);
1165 total
= n_to
+ n_cc
+ n_bcc
;
1166 destinations
= g_new0 (EDestination
*, total
+ 1);
1168 while (n_bcc
> 0 && total
> 0)
1169 destinations
[--total
] = g_object_ref (bcc
[--n_bcc
]);
1171 while (n_cc
> 0 && total
> 0)
1172 destinations
[--total
] = g_object_ref (cc
[--n_cc
]);
1174 while (n_to
> 0 && total
> 0)
1175 destinations
[--total
] = g_object_ref (to
[--n_to
]);
1177 /* Counters should all be zero now. */
1178 g_return_val_if_fail (total
== 0 && n_to
== 0 && n_cc
== 0 && n_bcc
== 0, destinations
);
1180 e_destination_freev (to
);
1181 e_destination_freev (cc
);
1182 e_destination_freev (bcc
);
1184 return destinations
;
1188 e_composer_header_table_get_destinations_bcc (EComposerHeaderTable
*table
)
1190 EComposerHeader
*header
;
1191 EComposerHeaderType type
;
1192 EComposerNameHeader
*name_header
;
1194 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1196 type
= E_COMPOSER_HEADER_BCC
;
1197 header
= e_composer_header_table_get_header (table
, type
);
1198 name_header
= E_COMPOSER_NAME_HEADER (header
);
1200 return e_composer_name_header_get_destinations (name_header
);
1204 e_composer_header_table_add_destinations_bcc (EComposerHeaderTable
*table
,
1205 EDestination
**destinations
)
1207 EComposerHeader
*header
;
1208 EComposerHeaderType type
;
1209 EComposerNameHeader
*name_header
;
1211 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1213 type
= E_COMPOSER_HEADER_BCC
;
1214 header
= e_composer_header_table_get_header (table
, type
);
1215 name_header
= E_COMPOSER_NAME_HEADER (header
);
1217 e_composer_name_header_add_destinations (name_header
, destinations
);
1219 if (destinations
!= NULL
&& *destinations
!= NULL
)
1220 e_composer_header_set_visible (header
, TRUE
);
1224 e_composer_header_table_set_destinations_bcc (EComposerHeaderTable
*table
,
1225 EDestination
**destinations
)
1227 EComposerHeader
*header
;
1228 EComposerHeaderType type
;
1229 EComposerNameHeader
*name_header
;
1231 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1233 type
= E_COMPOSER_HEADER_BCC
;
1234 header
= e_composer_header_table_get_header (table
, type
);
1235 name_header
= E_COMPOSER_NAME_HEADER (header
);
1237 e_composer_name_header_set_destinations (name_header
, destinations
);
1239 if (destinations
!= NULL
&& *destinations
!= NULL
)
1240 e_composer_header_set_visible (header
, TRUE
);
1244 e_composer_header_table_get_destinations_cc (EComposerHeaderTable
*table
)
1246 EComposerHeader
*header
;
1247 EComposerHeaderType type
;
1248 EComposerNameHeader
*name_header
;
1250 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1252 type
= E_COMPOSER_HEADER_CC
;
1253 header
= e_composer_header_table_get_header (table
, type
);
1254 name_header
= E_COMPOSER_NAME_HEADER (header
);
1256 return e_composer_name_header_get_destinations (name_header
);
1260 e_composer_header_table_add_destinations_cc (EComposerHeaderTable
*table
,
1261 EDestination
**destinations
)
1263 EComposerHeader
*header
;
1264 EComposerHeaderType type
;
1265 EComposerNameHeader
*name_header
;
1267 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1269 type
= E_COMPOSER_HEADER_CC
;
1270 header
= e_composer_header_table_get_header (table
, type
);
1271 name_header
= E_COMPOSER_NAME_HEADER (header
);
1273 e_composer_name_header_add_destinations (name_header
, destinations
);
1275 if (destinations
!= NULL
&& *destinations
!= NULL
)
1276 e_composer_header_set_visible (header
, TRUE
);
1280 e_composer_header_table_set_destinations_cc (EComposerHeaderTable
*table
,
1281 EDestination
**destinations
)
1283 EComposerHeader
*header
;
1284 EComposerHeaderType type
;
1285 EComposerNameHeader
*name_header
;
1287 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1289 type
= E_COMPOSER_HEADER_CC
;
1290 header
= e_composer_header_table_get_header (table
, type
);
1291 name_header
= E_COMPOSER_NAME_HEADER (header
);
1293 e_composer_name_header_set_destinations (name_header
, destinations
);
1295 if (destinations
!= NULL
&& *destinations
!= NULL
)
1296 e_composer_header_set_visible (header
, TRUE
);
1300 e_composer_header_table_get_destinations_to (EComposerHeaderTable
*table
)
1302 EComposerHeader
*header
;
1303 EComposerHeaderType type
;
1304 EComposerNameHeader
*name_header
;
1306 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1308 type
= E_COMPOSER_HEADER_TO
;
1309 header
= e_composer_header_table_get_header (table
, type
);
1310 name_header
= E_COMPOSER_NAME_HEADER (header
);
1312 return e_composer_name_header_get_destinations (name_header
);
1316 e_composer_header_table_add_destinations_to (EComposerHeaderTable
*table
,
1317 EDestination
**destinations
)
1319 EComposerHeader
*header
;
1320 EComposerHeaderType type
;
1321 EComposerNameHeader
*name_header
;
1323 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1325 type
= E_COMPOSER_HEADER_TO
;
1326 header
= e_composer_header_table_get_header (table
, type
);
1327 name_header
= E_COMPOSER_NAME_HEADER (header
);
1329 e_composer_name_header_add_destinations (name_header
, destinations
);
1333 e_composer_header_table_set_destinations_to (EComposerHeaderTable
*table
,
1334 EDestination
**destinations
)
1336 EComposerHeader
*header
;
1337 EComposerHeaderType type
;
1338 EComposerNameHeader
*name_header
;
1340 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1342 type
= E_COMPOSER_HEADER_TO
;
1343 header
= e_composer_header_table_get_header (table
, type
);
1344 name_header
= E_COMPOSER_NAME_HEADER (header
);
1346 e_composer_name_header_set_destinations (name_header
, destinations
);
1350 e_composer_header_table_dup_identity_uid (EComposerHeaderTable
*table
,
1351 gchar
**chosen_alias_name
,
1352 gchar
**chosen_alias_address
)
1354 EComposerHeader
*header
;
1355 EComposerHeaderType type
;
1356 EComposerFromHeader
*from_header
;
1358 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1360 type
= E_COMPOSER_HEADER_FROM
;
1361 header
= e_composer_header_table_get_header (table
, type
);
1362 from_header
= E_COMPOSER_FROM_HEADER (header
);
1364 return e_composer_from_header_dup_active_id (from_header
, chosen_alias_name
, chosen_alias_address
);
1368 e_composer_header_table_set_identity_uid (EComposerHeaderTable
*table
,
1369 const gchar
*identity_uid
,
1370 const gchar
*alias_name
,
1371 const gchar
*alias_address
)
1373 EComposerHeader
*header
;
1374 EComposerHeaderType type
;
1375 EComposerFromHeader
*from_header
;
1377 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1379 type
= E_COMPOSER_HEADER_FROM
;
1380 header
= e_composer_header_table_get_header (table
, type
);
1381 from_header
= E_COMPOSER_FROM_HEADER (header
);
1383 e_composer_from_header_set_active_id (from_header
, identity_uid
, alias_name
, alias_address
);
1387 e_composer_header_table_get_from_name (EComposerHeaderTable
*table
)
1389 EComposerHeader
*header
;
1390 EComposerHeaderType type
;
1391 EComposerFromHeader
*from_header
;
1393 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1395 type
= E_COMPOSER_HEADER_FROM
;
1396 header
= e_composer_header_table_get_header (table
, type
);
1397 from_header
= E_COMPOSER_FROM_HEADER (header
);
1399 return e_composer_from_header_get_name (from_header
);
1403 e_composer_header_table_get_from_address (EComposerHeaderTable
*table
)
1405 EComposerHeader
*header
;
1406 EComposerHeaderType type
;
1407 EComposerFromHeader
*from_header
;
1409 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1411 type
= E_COMPOSER_HEADER_FROM
;
1412 header
= e_composer_header_table_get_header (table
, type
);
1413 from_header
= E_COMPOSER_FROM_HEADER (header
);
1415 return e_composer_from_header_get_address (from_header
);
1419 e_composer_header_table_get_post_to (EComposerHeaderTable
*table
)
1421 EComposerHeader
*header
;
1422 EComposerHeaderType type
;
1423 EComposerPostHeader
*post_header
;
1425 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1427 type
= E_COMPOSER_HEADER_POST_TO
;
1428 header
= e_composer_header_table_get_header (table
, type
);
1429 post_header
= E_COMPOSER_POST_HEADER (header
);
1431 return e_composer_post_header_get_folders (post_header
);
1435 e_composer_header_table_set_post_to_base (EComposerHeaderTable
*table
,
1436 const gchar
*base_url
,
1437 const gchar
*folders
)
1439 EComposerHeader
*header
;
1440 EComposerHeaderType type
;
1441 EComposerPostHeader
*post_header
;
1443 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1445 type
= E_COMPOSER_HEADER_POST_TO
;
1446 header
= e_composer_header_table_get_header (table
, type
);
1447 post_header
= E_COMPOSER_POST_HEADER (header
);
1449 e_composer_post_header_set_folders_base (post_header
, base_url
, folders
);
1453 e_composer_header_table_set_post_to_list (EComposerHeaderTable
*table
,
1456 EComposerHeader
*header
;
1457 EComposerHeaderType type
;
1458 EComposerPostHeader
*post_header
;
1460 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1462 type
= E_COMPOSER_HEADER_POST_TO
;
1463 header
= e_composer_header_table_get_header (table
, type
);
1464 post_header
= E_COMPOSER_POST_HEADER (header
);
1466 e_composer_post_header_set_folders (post_header
, folders
);
1470 e_composer_header_table_get_reply_to (EComposerHeaderTable
*table
)
1472 EComposerHeader
*header
;
1473 EComposerHeaderType type
;
1474 EComposerTextHeader
*text_header
;
1476 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1478 type
= E_COMPOSER_HEADER_REPLY_TO
;
1479 header
= e_composer_header_table_get_header (table
, type
);
1480 text_header
= E_COMPOSER_TEXT_HEADER (header
);
1482 return e_composer_text_header_get_text (text_header
);
1486 e_composer_header_table_set_reply_to (EComposerHeaderTable
*table
,
1487 const gchar
*reply_to
)
1489 EComposerHeader
*header
;
1490 EComposerHeaderType type
;
1491 EComposerTextHeader
*text_header
;
1493 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1495 type
= E_COMPOSER_HEADER_REPLY_TO
;
1496 header
= e_composer_header_table_get_header (table
, type
);
1497 text_header
= E_COMPOSER_TEXT_HEADER (header
);
1499 e_composer_text_header_set_text (text_header
, reply_to
);
1501 if (reply_to
!= NULL
&& *reply_to
!= '\0')
1502 e_composer_header_set_visible (header
, TRUE
);
1506 e_composer_header_table_get_signature_uid (EComposerHeaderTable
*table
)
1508 EMailSignatureComboBox
*combo_box
;
1510 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1512 combo_box
= e_composer_header_table_get_signature_combo_box (table
);
1514 return gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box
));
1518 e_composer_header_table_set_signature_uid (EComposerHeaderTable
*table
,
1519 const gchar
*signature_uid
)
1521 EMailSignatureComboBox
*combo_box
;
1523 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1525 combo_box
= e_composer_header_table_get_signature_combo_box (table
);
1527 gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box
), signature_uid
);
1531 e_composer_header_table_get_subject (EComposerHeaderTable
*table
)
1533 EComposerHeader
*header
;
1534 EComposerHeaderType type
;
1535 EComposerTextHeader
*text_header
;
1537 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1539 type
= E_COMPOSER_HEADER_SUBJECT
;
1540 header
= e_composer_header_table_get_header (table
, type
);
1541 text_header
= E_COMPOSER_TEXT_HEADER (header
);
1543 return e_composer_text_header_get_text (text_header
);
1547 e_composer_header_table_set_subject (EComposerHeaderTable
*table
,
1548 const gchar
*subject
)
1550 EComposerHeader
*header
;
1551 EComposerHeaderType type
;
1552 EComposerTextHeader
*text_header
;
1554 g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
));
1556 type
= E_COMPOSER_HEADER_SUBJECT
;
1557 header
= e_composer_header_table_get_header (table
, type
);
1558 text_header
= E_COMPOSER_TEXT_HEADER (header
);
1560 e_composer_text_header_set_text (text_header
, subject
);
1564 e_composer_header_table_set_header_visible (EComposerHeaderTable
*table
,
1565 EComposerHeaderType type
,
1568 EComposerHeader
*header
;
1570 header
= e_composer_header_table_get_header (table
, type
);
1571 e_composer_header_set_visible (header
, visible
);
1573 /* Signature widgets track the "From" header. */
1574 if (type
== E_COMPOSER_HEADER_FROM
) {
1576 gtk_widget_show (table
->priv
->signature_label
);
1577 gtk_widget_show (table
->priv
->signature_combo_box
);
1579 gtk_widget_hide (table
->priv
->signature_label
);
1580 gtk_widget_hide (table
->priv
->signature_combo_box
);
1586 * e_composer_header_table_ref_source:
1587 * @table: an #EComposerHeaderTable
1588 * @uid: a unique identifier string
1590 * Convenience function that works just like e_source_registry_ref_source(),
1591 * but spares the caller from digging out the #ESourceRegistry from @table.
1593 * The returned #ESource is referenced for thread-safety and must be
1594 * unreferenced with g_object_unref() when finished with it.
1596 * Returns: an #ESource, or %NULL if no match was found
1599 e_composer_header_table_ref_source (EComposerHeaderTable
*table
,
1602 EClientCache
*client_cache
;
1603 ESourceRegistry
*registry
;
1606 g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table
), NULL
);
1607 g_return_val_if_fail (uid
!= NULL
, NULL
);
1609 client_cache
= e_composer_header_table_ref_client_cache (table
);
1610 registry
= e_client_cache_ref_registry (client_cache
);
1612 source
= e_source_registry_ref_source (registry
, uid
);
1614 g_object_unref (client_cache
);
1615 g_object_unref (registry
);