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/>.
16 * Chris Lahey <clahey@ximian.com>
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
22 #include "evolution-config.h"
24 #include "eab-editor.h"
25 #include "e-contact-editor.h"
32 #include <glib/gi18n.h>
33 #include <gdk/gdkkeysyms.h>
34 #include <gdk-pixbuf/gdk-pixbuf.h>
36 #define GCR_API_SUBJECT_TO_CHANGE
38 #undef GCR_API_SUBJECT_TO_CHANGE
40 #include "shell/e-shell.h"
41 #include "e-util/e-util.h"
43 #include "addressbook/printing/e-contact-print.h"
44 #include "addressbook/gui/widgets/eab-gui-util.h"
45 #include "addressbook/util/eab-book-util.h"
47 #include "eab-contact-merging.h"
49 #include "e-contact-editor-fullname.h"
50 #include "e-contact-editor-dyntable.h"
52 #define SLOTS_PER_LINE 2
53 #define SLOTS_IN_COLLAPSED_STATE SLOTS_PER_LINE
54 #define EMAIL_SLOTS 50
55 #define PHONE_SLOTS 50
58 #define ADDRESS_SLOTS 3
60 /* represents index in address_name */
61 #define ADDRESS_SLOT_HOME 1
62 #define ADDRESS_SLOT_WORK 0
63 #define ADDRESS_SLOT_OTHER 2
65 #define EVOLUTION_UI_SLOT_PARAM "X-EVOLUTION-UI-SLOT"
77 #define CHECK_CERTS 11
85 COLUMN_IM_LOCATION_TYPE
,
86 COLUMN_IM_SERVICE_FIELD
,
91 EContactEditor
*editor
;
95 static void e_contact_editor_set_property (GObject
*object
,
99 static void e_contact_editor_get_property (GObject
*object
,
103 static void e_contact_editor_constructed (GObject
*object
);
104 static void e_contact_editor_dispose (GObject
*object
);
105 static void e_contact_editor_raise (EABEditor
*editor
);
106 static void e_contact_editor_show (EABEditor
*editor
);
107 static void e_contact_editor_save_contact (EABEditor
*editor
,
108 gboolean should_close
);
109 static void e_contact_editor_close (EABEditor
*editor
);
110 static gboolean
e_contact_editor_is_valid (EABEditor
*editor
);
111 static gboolean
e_contact_editor_is_changed (EABEditor
*editor
);
113 e_contact_editor_get_window (EABEditor
*editor
);
114 static void save_contact (EContactEditor
*ce
,
115 gboolean should_close
);
116 static void entry_activated (EContactEditor
*editor
);
118 static void set_entry_text (EContactEditor
*editor
,
120 const gchar
*string
);
121 static void sensitize_ok (EContactEditor
*ce
);
123 static EABEditorClass
*parent_class
= NULL
;
133 PROP_WRITABLE_FIELDS
,
143 /* Defaults selected from eab_phone_types */
144 static const gint phones_default
[] = { 1, 6, 9, 2, 7, 12, 10, 10 };
146 static EContactField addresses
[] = {
147 E_CONTACT_ADDRESS_WORK
,
148 E_CONTACT_ADDRESS_HOME
,
149 E_CONTACT_ADDRESS_OTHER
152 static EContactField address_labels
[] = {
153 E_CONTACT_ADDRESS_LABEL_WORK
,
154 E_CONTACT_ADDRESS_LABEL_HOME
,
155 E_CONTACT_ADDRESS_LABEL_OTHER
158 static const gchar
*address_name
[] = {
165 * keep fetch_set in sync with labels from eab_im_service
168 im_service_fetch_set
[] =
173 E_CONTACT_IM_GADUGADU
,
176 E_CONTACT_IM_GROUPWISE
,
178 E_CONTACT_IM_TWITTER
,
179 E_CONTACT_IM_GOOGLE_TALK
182 /* Defaults selected from eab_get_im_type_labels */
183 static const gint im_service_default
[] = { 0, 2, 4, 5 };
186 /* Default from the table above */
187 static const gint email_default
[] = { 0, 1, 2, 2 };
188 static const gint sips_default
[] = { 0, 1, 2, 2 };
190 #define STRING_IS_EMPTY(x) (!(x) || !(*(x)))
191 #define STRING_MAKE_NON_NULL(x) ((x) ? (x) : "")
193 struct _EContactEditorPrivate
195 /* item specific fields */
196 EBookClient
*source_client
;
197 EBookClient
*target_client
;
203 GtkWidget
*file_selector
;
207 /* Whether we are editing a new contact or an existing one */
208 guint is_new_contact
: 1;
210 /* Whether an image is associated with a contact. */
213 /* Whether the contact has been changed since bringing up the contact editor */
216 /* Wheter should check for contact to merge. Only when name or email are changed */
217 guint check_merge
: 1;
219 /* Whether the contact editor will accept modifications, save */
220 guint target_editable
: 1;
222 /* Whether an async wombat call is in progress */
223 guint in_async_call
: 1;
225 /* Whether an image is changed */
226 guint image_changed
: 1;
228 /* Whether to try to reduce space used */
229 guint compress_ui
: 1;
231 GSList
*writable_fields
;
233 GSList
*required_fields
;
235 GCancellable
*cancellable
;
237 /* signal ids for "writable_status" */
238 gint target_editable_id
;
240 GtkWidget
*fullname_dialog
;
241 GtkWidget
*categories_dialog
;
243 GtkUIManager
*ui_manager
;
244 EFocusTracker
*focus_tracker
;
247 G_DEFINE_TYPE (EContactEditor
, e_contact_editor
, EAB_TYPE_EDITOR
)
249 static GtkActionEntry undo_entries
[] = {
256 NULL
}, /* just a fake undo menu, to get shortcuts working */
263 NULL
}, /* Handled by EFocusTracker */
270 NULL
} /* Handled by EFocusTracker */
275 connect_closure_free (ConnectClosure
*connect_closure
)
277 if (connect_closure
->editor
!= NULL
)
278 g_object_unref (connect_closure
->editor
);
280 if (connect_closure
->source
!= NULL
)
281 g_object_unref (connect_closure
->source
);
283 g_slice_free (ConnectClosure
, connect_closure
);
287 e_contact_editor_contact_added (EABEditor
*editor
,
292 const gchar
*message
;
297 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
300 window
= eab_editor_get_window (editor
);
301 message
= _("Error adding contact");
303 eab_error_dialog (NULL
, window
, message
, error
);
307 e_contact_editor_contact_modified (EABEditor
*editor
,
312 const gchar
*message
;
317 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
320 window
= eab_editor_get_window (editor
);
321 message
= _("Error modifying contact");
323 eab_error_dialog (NULL
, window
, message
, error
);
327 e_contact_editor_contact_deleted (EABEditor
*editor
,
332 const gchar
*message
;
337 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
))
340 window
= eab_editor_get_window (editor
);
341 message
= _("Error removing contact");
343 eab_error_dialog (NULL
, window
, message
, error
);
347 e_contact_editor_closed (EABEditor
*editor
)
349 g_object_unref (editor
);
353 e_contact_editor_class_init (EContactEditorClass
*class)
355 GObjectClass
*object_class
= G_OBJECT_CLASS (class);
356 EABEditorClass
*editor_class
= EAB_EDITOR_CLASS (class);
358 g_type_class_add_private (class, sizeof (EContactEditorPrivate
));
360 parent_class
= g_type_class_ref (EAB_TYPE_EDITOR
);
362 object_class
->set_property
= e_contact_editor_set_property
;
363 object_class
->get_property
= e_contact_editor_get_property
;
364 object_class
->constructed
= e_contact_editor_constructed
;
365 object_class
->dispose
= e_contact_editor_dispose
;
367 editor_class
->raise
= e_contact_editor_raise
;
368 editor_class
->show
= e_contact_editor_show
;
369 editor_class
->close
= e_contact_editor_close
;
370 editor_class
->is_valid
= e_contact_editor_is_valid
;
371 editor_class
->save_contact
= e_contact_editor_save_contact
;
372 editor_class
->is_changed
= e_contact_editor_is_changed
;
373 editor_class
->get_window
= e_contact_editor_get_window
;
374 editor_class
->contact_added
= e_contact_editor_contact_added
;
375 editor_class
->contact_modified
= e_contact_editor_contact_modified
;
376 editor_class
->contact_deleted
= e_contact_editor_contact_deleted
;
377 editor_class
->editor_closed
= e_contact_editor_closed
;
379 g_object_class_install_property (
382 g_param_spec_object (
384 "Source EBookClient",
389 g_object_class_install_property (
392 g_param_spec_object (
394 "Target EBookClient",
399 g_object_class_install_property (
402 g_param_spec_object (
409 g_object_class_install_property (
412 g_param_spec_boolean (
419 g_object_class_install_property (
421 PROP_WRITABLE_FIELDS
,
422 g_param_spec_pointer (
428 g_object_class_install_property (
430 PROP_REQUIRED_FIELDS
,
431 g_param_spec_pointer (
437 g_object_class_install_property (
440 g_param_spec_boolean (
447 g_object_class_install_property (
450 g_param_spec_boolean (
459 entry_activated (EContactEditor
*editor
)
461 save_contact (editor
, TRUE
);
464 /* FIXME: Linear time... */
466 is_field_supported (EContactEditor
*editor
,
467 EContactField field_id
)
469 GSList
*fields
, *iter
;
472 fields
= editor
->priv
->writable_fields
;
476 field
= e_contact_field_name (field_id
);
480 for (iter
= fields
; iter
; iter
= iter
->next
) {
481 const gchar
*this_field
= iter
->data
;
486 if (!strcmp (field
, this_field
))
493 /* This function tells you whether name_to_style will make sense. */
495 style_makes_sense (const EContactName
*name
,
496 const gchar
*company
,
500 case 0: /* Fall Through */
505 if (name
->additional
&& *name
->additional
)
512 if (company
&& *company
)
516 case 4: /* Fall Through */
518 if (company
&& *company
&& name
&&
519 ((name
->given
&& *name
->given
) ||
520 (name
->family
&& *name
->family
)))
530 name_to_style (const EContactName
*name
,
531 const gchar
*company
,
535 gchar
*strings
[4], **stringptr
;
536 gchar
*midstring
[4], **midstrptr
;
542 if (name
->family
&& *name
->family
)
543 *(stringptr
++) = name
->family
;
544 if (name
->given
&& *name
->given
)
545 *(stringptr
++) = name
->given
;
548 string
= g_strjoinv (", ", strings
);
553 if (name
->given
&& *name
->given
)
554 *(stringptr
++) = name
->given
;
555 if (name
->family
&& *name
->family
)
556 *(stringptr
++) = name
->family
;
559 string
= g_strjoinv (" ", strings
);
562 midstrptr
= midstring
;
564 if (name
->family
&& *name
->family
)
565 *(midstrptr
++) = name
->family
;
566 if (name
->given
&& *name
->given
)
567 *(midstrptr
++) = name
->given
;
571 *(stringptr
++) = g_strjoinv(", ", midstring
);
573 if (name
->additional
&& *name
->additional
)
574 *(stringptr
++) = name
->additional
;
577 string
= g_strjoinv (" ", strings
);
580 string
= g_strdup (company
);
582 case 4: /* Fall Through */
586 if (name
->family
&& *name
->family
)
587 *(stringptr
++) = name
->family
;
588 if (name
->given
&& *name
->given
)
589 *(stringptr
++) = name
->given
;
592 substring
= g_strjoinv (", ", strings
);
593 if (!(company
&& *company
))
596 string
= g_strdup_printf ("%s (%s)", substring
, company
);
598 string
= g_strdup_printf ("%s (%s)", company
, substring
);
602 string
= g_strdup ("");
608 file_as_get_style (EContactEditor
*editor
)
610 GtkEntry
*file_as
= GTK_ENTRY (
611 gtk_bin_get_child (GTK_BIN (
612 e_builder_get_widget (editor
->priv
->builder
, "combo-file-as"))));
613 GtkEntry
*company_w
= GTK_ENTRY (
614 e_builder_get_widget (editor
->priv
->builder
, "entry-company"));
617 EContactName
*name
= editor
->priv
->name
;
618 const gchar
*company
;
621 if (!(file_as
&& GTK_IS_ENTRY (file_as
)))
624 company
= gtk_entry_get_text (GTK_ENTRY (company_w
));
625 filestring
= g_strdup (gtk_entry_get_text (file_as
));
627 for (i
= 0; i
< 6; i
++) {
628 trystring
= name_to_style (name
, company
, i
);
629 if (!strcmp (trystring
, filestring
)) {
641 file_as_set_style (EContactEditor
*editor
,
646 GList
*strings
= NULL
;
647 GtkComboBox
*combo_file_as
= GTK_COMBO_BOX (
648 e_builder_get_widget (editor
->priv
->builder
, "combo-file-as"));
649 GtkEntry
*company_w
= GTK_ENTRY (
650 e_builder_get_widget (editor
->priv
->builder
, "entry-company"));
651 const gchar
*company
;
653 if (!(combo_file_as
&& GTK_IS_COMBO_BOX (combo_file_as
)))
656 company
= gtk_entry_get_text (GTK_ENTRY (company_w
));
661 entry
= gtk_bin_get_child (GTK_BIN (combo_file_as
));
663 string
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
664 strings
= g_list_append (strings
, string
);
668 for (i
= 0; i
< 6; i
++) {
669 if (style_makes_sense (editor
->priv
->name
, company
, i
)) {
671 u
= name_to_style (editor
->priv
->name
, company
, i
);
672 if (!STRING_IS_EMPTY (u
))
673 strings
= g_list_append (strings
, u
);
681 GtkListStore
*list_store
;
684 list_store
= GTK_LIST_STORE (
685 gtk_combo_box_get_model (combo_file_as
));
687 gtk_list_store_clear (list_store
);
689 for (l
= strings
; l
; l
= l
->next
) {
690 gtk_list_store_append (list_store
, &iter
);
691 gtk_list_store_set (list_store
, &iter
, 0, l
->data
, -1);
695 g_list_foreach (strings
, (GFunc
) g_free
, NULL
);
696 g_list_free (strings
);
699 string
= name_to_style (editor
->priv
->name
, company
, style
);
701 editor
, GTK_ENTRY (gtk_bin_get_child (
702 GTK_BIN (combo_file_as
))), string
);
708 name_entry_changed (GtkWidget
*widget
,
709 EContactEditor
*editor
)
714 style
= file_as_get_style (editor
);
715 e_contact_name_free (editor
->priv
->name
);
716 string
= gtk_entry_get_text (GTK_ENTRY (widget
));
717 editor
->priv
->name
= e_contact_name_from_string (string
);
718 file_as_set_style (editor
, style
);
720 editor
->priv
->check_merge
= TRUE
;
722 sensitize_ok (editor
);
723 if (string
&& !*string
)
724 gtk_window_set_title (
725 GTK_WINDOW (editor
->priv
->app
), _("Contact Editor"));
729 file_as_combo_changed (GtkWidget
*widget
,
730 EContactEditor
*editor
)
733 gchar
*string
= NULL
;
735 entry
= gtk_bin_get_child (GTK_BIN (widget
));
737 string
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
739 if (string
&& *string
) {
741 title
= g_strdup_printf (_("Contact Editor — %s"), string
);
742 gtk_window_set_title (GTK_WINDOW (editor
->priv
->app
), title
);
746 gtk_window_set_title (
747 GTK_WINDOW (editor
->priv
->app
), _("Contact Editor"));
749 sensitize_ok (editor
);
755 company_entry_changed (GtkWidget
*widget
,
756 EContactEditor
*editor
)
760 style
= file_as_get_style (editor
);
761 file_as_set_style (editor
, style
);
765 update_file_as_combo (EContactEditor
*editor
)
767 file_as_set_style (editor
, file_as_get_style (editor
));
771 fill_in_source_field (EContactEditor
*editor
)
773 GtkWidget
*source_menu
;
775 if (!editor
->priv
->target_client
)
778 source_menu
= e_builder_get_widget (
779 editor
->priv
->builder
, "client-combo-box");
781 e_source_combo_box_set_active (
782 E_SOURCE_COMBO_BOX (source_menu
),
783 e_client_get_source (E_CLIENT (editor
->priv
->target_client
)));
787 sensitize_ok (EContactEditor
*ce
)
791 GtkWidget
*entry_fullname
=
792 e_builder_get_widget (ce
->priv
->builder
, "entry-fullname");
793 GtkWidget
*entry_file_as
=
794 gtk_bin_get_child (GTK_BIN (
795 e_builder_get_widget (ce
->priv
->builder
, "combo-file-as")));
796 GtkWidget
*company_name
=
797 e_builder_get_widget (ce
->priv
->builder
, "entry-company");
798 const gchar
*name_entry_string
=
799 gtk_entry_get_text (GTK_ENTRY (entry_fullname
));
800 const gchar
*file_as_entry_string
=
801 gtk_entry_get_text (GTK_ENTRY (entry_file_as
));
802 const gchar
*company_name_string
=
803 gtk_entry_get_text (GTK_ENTRY (company_name
));
805 allow_save
= ce
->priv
->target_editable
&& ce
->priv
->changed
;
807 if (!strcmp (name_entry_string
, "") ||
808 !strcmp (file_as_entry_string
, "")) {
809 if (strcmp (company_name_string
, "")) {
815 widget
= e_builder_get_widget (ce
->priv
->builder
, "button-ok");
816 gtk_widget_set_sensitive (widget
, allow_save
);
820 object_changed (GObject
*object
,
821 EContactEditor
*editor
)
823 if (!editor
->priv
->target_editable
) {
824 g_warning ("non-editable contact editor has an editable field in it.");
828 if (!editor
->priv
->check_merge
&& GTK_IS_WIDGET (object
)) {
829 const gchar
*widget_name
;
831 widget_name
= gtk_widget_get_name (GTK_WIDGET (object
));
834 ((g_str_equal (widget_name
, "fullname")) ||
835 (g_str_equal (widget_name
, "nickname")) ||
836 (g_str_equal (widget_name
, "file-as")) ||
837 (g_str_has_prefix (widget_name
, "email-"))))
838 editor
->priv
->check_merge
= TRUE
;
841 if (!editor
->priv
->changed
) {
842 editor
->priv
->changed
= TRUE
;
843 sensitize_ok (editor
);
848 image_chooser_changed (GtkWidget
*widget
,
849 EContactEditor
*editor
)
851 editor
->priv
->image_set
= TRUE
;
852 editor
->priv
->image_changed
= TRUE
;
856 set_entry_text (EContactEditor
*editor
,
860 const gchar
*oldstring
= gtk_entry_get_text (entry
);
865 if (strcmp (string
, oldstring
)) {
866 g_signal_handlers_block_matched (
867 entry
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, editor
);
868 gtk_entry_set_text (entry
, string
);
869 g_signal_handlers_unblock_matched (
870 entry
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, editor
);
875 init_email_record_location (EContactEditor
*editor
)
880 EContactEditorDynTable
*dyntable
;
881 const EABTypeLabel
*email_types
= eab_get_email_type_labels (&n_elements
);
883 w
= e_builder_get_widget (editor
->priv
->builder
, "mail-dyntable");
884 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
885 store
= e_contact_editor_dyntable_get_combo_store (dyntable
);
887 for (i
= 0; i
< n_elements
; i
++) {
890 gtk_list_store_append (store
, &iter
);
891 gtk_list_store_set (store
, &iter
,
892 DYNTABLE_COMBO_COLUMN_TEXT
, _(email_types
[i
].text
),
893 DYNTABLE_COMBO_COLUMN_SENSITIVE
, TRUE
,
897 e_contact_editor_dyntable_set_combo_defaults (dyntable
, email_default
, G_N_ELEMENTS (email_default
));
900 static EVCardAttributeParam
*
901 get_ui_slot_param (EVCardAttribute
*attr
)
903 EVCardAttributeParam
*param
= NULL
;
907 param_list
= e_vcard_attribute_get_params (attr
);
909 for (l
= param_list
; l
; l
= g_list_next (l
)) {
914 str
= e_vcard_attribute_param_get_name (param
);
915 if (!g_ascii_strcasecmp (str
, EVOLUTION_UI_SLOT_PARAM
))
925 get_ui_slot (EVCardAttribute
*attr
)
927 EVCardAttributeParam
*param
;
930 param
= get_ui_slot_param (attr
);
935 value_list
= e_vcard_attribute_param_get_values (param
);
936 slot
= atoi (value_list
->data
);
943 set_ui_slot (EVCardAttribute
*attr
,
946 EVCardAttributeParam
*param
;
949 param
= get_ui_slot_param (attr
);
951 param
= e_vcard_attribute_param_new (EVOLUTION_UI_SLOT_PARAM
);
952 e_vcard_attribute_add_param (attr
, param
);
955 e_vcard_attribute_param_remove_values (param
);
957 slot_str
= g_strdup_printf ("%d", slot
);
958 e_vcard_attribute_param_add_value (param
, slot_str
);
963 fill_in_email (EContactEditor
*editor
)
965 GList
*email_attr_list
;
968 EContactEditorDynTable
*dyntable
;
969 GtkListStore
*data_store
;
972 w
= e_builder_get_widget (editor
->priv
->builder
, "mail-dyntable");
973 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
977 e_contact_editor_dyntable_clear_data (dyntable
);
981 data_store
= e_contact_editor_dyntable_extract_data (dyntable
);
983 email_attr_list
= e_contact_get_attributes (
984 editor
->priv
->contact
, E_CONTACT_EMAIL
);
986 for (l
= email_attr_list
; l
; l
= g_list_next (l
)) {
987 EVCardAttribute
*attr
= l
->data
;
988 gchar
*email_address
;
992 email_address
= e_vcard_attribute_get_value (attr
);
993 email_location
= eab_get_email_type_index (attr
);
994 slot
= get_ui_slot (attr
);
996 slot
= EMAIL_SLOTS
+ 1; /* add at the end */
998 gtk_list_store_append (data_store
, &iter
);
999 gtk_list_store_set (data_store
, &iter
,
1000 DYNTABLE_STORE_COLUMN_SORTORDER
, slot
,
1001 DYNTABLE_STORE_COLUMN_SELECTED_ITEM
, email_location
,
1002 DYNTABLE_STORE_COLUMN_ENTRY_STRING
, email_address
,
1005 g_free (email_address
);
1008 g_list_free_full (email_attr_list
, (GDestroyNotify
) e_vcard_attribute_free
);
1010 e_contact_editor_dyntable_fill_in_data (dyntable
);
1014 extract_email (EContactEditor
*editor
)
1016 GList
*attr_list
= NULL
;
1017 GList
*old_attr_list
;
1021 EContactEditorDynTable
*dyntable
;
1022 GtkListStore
*data_store
;
1023 GtkTreeModel
*tree_model
;
1027 w
= e_builder_get_widget (editor
->priv
->builder
, "mail-dyntable");
1028 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
1029 data_store
= e_contact_editor_dyntable_extract_data (dyntable
);
1030 tree_model
= GTK_TREE_MODEL (data_store
);
1032 valid
= gtk_tree_model_get_iter_first (tree_model
, &iter
);
1036 EVCardAttribute
*attr
;
1038 attr
= e_vcard_attribute_new (
1039 "", e_contact_vcard_attribute (E_CONTACT_EMAIL
));
1041 gtk_tree_model_get (tree_model
,&iter
,
1042 DYNTABLE_STORE_COLUMN_SELECTED_ITEM
, &location
,
1043 DYNTABLE_STORE_COLUMN_ENTRY_STRING
, &address
,
1046 if (location
>= 0) {
1048 eab_email_index_to_type (location
, &type
);
1049 e_vcard_attribute_add_param_with_value (
1051 e_vcard_attribute_param_new (EVC_TYPE
),
1055 e_vcard_attribute_add_value (attr
, address
);
1057 attr_list
= g_list_prepend (attr_list
, attr
);
1059 valid
= gtk_tree_model_iter_next (tree_model
, &iter
);
1061 attr_list
= g_list_reverse (attr_list
);
1063 /* Splice in the old attributes, minus the EMAIL_SLOTS first */
1065 old_attr_list
= e_contact_get_attributes (editor
->priv
->contact
, E_CONTACT_EMAIL
);
1066 for (ll
= old_attr_list
, i
= 1; ll
&& i
<= EMAIL_SLOTS
; i
++) {
1067 e_vcard_attribute_free (ll
->data
);
1068 ll
= g_list_delete_link (ll
, ll
);
1072 attr_list
= g_list_concat (attr_list
, old_attr_list
);
1074 e_contact_set_attributes (editor
->priv
->contact
, E_CONTACT_EMAIL
, attr_list
);
1076 g_list_free_full (attr_list
, (GDestroyNotify
) e_vcard_attribute_free
);
1080 sensitize_email (EContactEditor
*editor
)
1082 gboolean enabled
= FALSE
;
1084 EContactEditorDynTable
*dyntable
;
1085 guint max_entries
= SLOTS_IN_COLLAPSED_STATE
;
1087 w
= e_builder_get_widget (editor
->priv
->builder
, "mail-dyntable");
1088 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
1090 if (editor
->priv
->target_editable
) {
1091 if (is_field_supported (editor
, E_CONTACT_EMAIL
)) {
1093 max_entries
= EMAIL_SLOTS
;
1094 } else if (is_field_supported (editor
, E_CONTACT_EMAIL_4
)) {
1097 } else if (is_field_supported (editor
, E_CONTACT_EMAIL_3
)) {
1100 } else if (is_field_supported (editor
, E_CONTACT_EMAIL_2
)) {
1103 } else if (is_field_supported (editor
, E_CONTACT_EMAIL_1
)) {
1109 gtk_widget_set_sensitive (w
, enabled
);
1110 e_contact_editor_dyntable_set_max_entries (dyntable
, max_entries
);
1114 row_added_cb (GtkExpander
*expander
)
1116 /* newly added row is always visible, setting expanded=true */
1117 gtk_expander_set_expanded (expander
, TRUE
);
1121 init_email (EContactEditor
*editor
)
1123 EContactEditorDynTable
*dyntable
;
1124 GtkExpander
*expander
;
1126 expander
= GTK_EXPANDER (
1127 e_builder_get_widget (editor
->priv
->builder
, "expander-contact-email"));
1128 dyntable
= E_CONTACT_EDITOR_DYNTABLE (
1129 e_builder_get_widget (editor
->priv
->builder
, "mail-dyntable"));
1131 e_contact_editor_dyntable_set_max_entries (dyntable
, EMAIL_SLOTS
);
1132 e_contact_editor_dyntable_set_num_columns (dyntable
, SLOTS_PER_LINE
, TRUE
);
1133 e_contact_editor_dyntable_set_show_min (dyntable
, SLOTS_IN_COLLAPSED_STATE
);
1136 dyntable
, "changed",
1137 G_CALLBACK (object_changed
), editor
);
1138 g_signal_connect_swapped (
1139 dyntable
, "activate",
1140 G_CALLBACK (entry_activated
), editor
);
1141 g_signal_connect_swapped (
1142 dyntable
, "row-added",
1143 G_CALLBACK (row_added_cb
), expander
);
1145 init_email_record_location (editor
);
1147 gtk_expander_set_expanded (expander
, TRUE
);
1151 fill_in_phone (EContactEditor
*editor
)
1153 GList
*tel_attr_list
;
1156 EContactEditorDynTable
*dyntable
;
1157 GtkListStore
*data_store
;
1160 w
= e_builder_get_widget (editor
->priv
->builder
, "phone-dyntable");
1161 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
1165 e_contact_editor_dyntable_clear_data (dyntable
);
1169 tel_attr_list
= e_contact_get_attributes (editor
->priv
->contact
, E_CONTACT_TEL
);
1171 data_store
= e_contact_editor_dyntable_extract_data (dyntable
);
1173 for (l
= tel_attr_list
; l
; l
= g_list_next (l
)) {
1174 EVCardAttribute
*attr
= l
->data
;
1179 slot
= get_ui_slot (attr
);
1181 slot
= PHONE_SLOTS
+ 1; /* append at the end */
1183 phone_type
= eab_get_phone_type_index (attr
);
1184 phone
= e_vcard_attribute_get_value (attr
);
1186 gtk_list_store_append (data_store
, &iter
);
1187 gtk_list_store_set (data_store
,&iter
,
1188 DYNTABLE_STORE_COLUMN_SORTORDER
, slot
,
1189 DYNTABLE_STORE_COLUMN_SELECTED_ITEM
, phone_type
,
1190 DYNTABLE_STORE_COLUMN_ENTRY_STRING
, phone
,
1196 e_contact_editor_dyntable_fill_in_data (dyntable
);
1198 g_list_free_full (tel_attr_list
, (GDestroyNotify
) e_vcard_attribute_free
);
1202 extract_phone (EContactEditor
*editor
)
1204 GList
*tel_attr_list
= NULL
;
1205 GList
*old_attr_list
;
1209 EContactEditorDynTable
*dyntable
;
1210 GtkListStore
*data_store
;
1211 GtkTreeModel
*tree_model
;
1215 w
= e_builder_get_widget (editor
->priv
->builder
, "phone-dyntable");
1216 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
1217 data_store
= e_contact_editor_dyntable_extract_data (dyntable
);
1218 tree_model
= GTK_TREE_MODEL (data_store
);
1220 valid
= gtk_tree_model_get_iter_first (tree_model
, &iter
);
1224 EVCardAttribute
*attr
;
1226 gtk_tree_model_get (tree_model
,&iter
,
1227 DYNTABLE_STORE_COLUMN_SELECTED_ITEM
, &phone_type
,
1228 DYNTABLE_STORE_COLUMN_ENTRY_STRING
, &phone
,
1231 attr
= e_vcard_attribute_new ("", EVC_TEL
);
1232 if (phone_type
>= 0) {
1233 const gchar
*type_1
;
1234 const gchar
*type_2
;
1236 eab_phone_index_to_type (phone_type
, &type_1
, &type_2
);
1238 e_vcard_attribute_add_param_with_value (
1239 attr
, e_vcard_attribute_param_new (EVC_TYPE
), type_1
);
1242 e_vcard_attribute_add_param_with_value (
1243 attr
, e_vcard_attribute_param_new (EVC_TYPE
), type_2
);
1246 e_vcard_attribute_add_value (attr
, phone
);
1248 tel_attr_list
= g_list_prepend (tel_attr_list
, attr
);
1250 valid
= gtk_tree_model_iter_next (tree_model
, &iter
);
1253 /* Splice in the old attributes, minus the PHONE_SLOTS first */
1255 tel_attr_list
= g_list_reverse (tel_attr_list
);
1256 old_attr_list
= e_contact_get_attributes (editor
->priv
->contact
, E_CONTACT_TEL
);
1257 for (ll
= old_attr_list
, i
= 1; ll
&& i
<= PHONE_SLOTS
; i
++) {
1258 e_vcard_attribute_free (ll
->data
);
1259 ll
= g_list_delete_link (ll
, ll
);
1263 tel_attr_list
= g_list_concat (tel_attr_list
, old_attr_list
);
1265 e_contact_set_attributes (editor
->priv
->contact
, E_CONTACT_TEL
, tel_attr_list
);
1267 g_list_free_full (tel_attr_list
, (GDestroyNotify
) e_vcard_attribute_free
);
1271 init_phone_record_type (EContactEditor
*editor
)
1274 GtkListStore
*store
;
1276 EContactEditorDynTable
*dyntable
;
1277 const EABTypeLabel
*eab_phone_types
;
1279 w
= e_builder_get_widget (editor
->priv
->builder
, "phone-dyntable");
1280 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
1281 store
= e_contact_editor_dyntable_get_combo_store (dyntable
);
1282 eab_phone_types
= eab_get_phone_type_labels (&n_elements
);
1284 for (i
= 0; i
< n_elements
; i
++) {
1287 gtk_list_store_append (store
, &iter
);
1288 gtk_list_store_set (store
, &iter
,
1289 DYNTABLE_COMBO_COLUMN_TEXT
, _(eab_phone_types
[i
].text
),
1290 DYNTABLE_COMBO_COLUMN_SENSITIVE
, TRUE
,
1294 e_contact_editor_dyntable_set_combo_defaults (dyntable
, phones_default
, G_N_ELEMENTS (phones_default
));
1298 init_phone (EContactEditor
*editor
)
1300 EContactEditorDynTable
*dyntable
;
1301 GtkExpander
*expander
;
1303 expander
= GTK_EXPANDER (
1304 e_builder_get_widget (editor
->priv
->builder
, "expander-contact-phone"));
1305 dyntable
= E_CONTACT_EDITOR_DYNTABLE (
1306 e_builder_get_widget (editor
->priv
->builder
, "phone-dyntable"));
1308 e_contact_editor_dyntable_set_max_entries (dyntable
, PHONE_SLOTS
);
1309 e_contact_editor_dyntable_set_num_columns (dyntable
, SLOTS_PER_LINE
, TRUE
);
1310 e_contact_editor_dyntable_set_show_min (dyntable
, SLOTS_IN_COLLAPSED_STATE
);
1313 dyntable
, "changed",
1314 G_CALLBACK (object_changed
), editor
);
1315 g_signal_connect_swapped (
1316 dyntable
, "activate",
1317 G_CALLBACK (entry_activated
), editor
);
1318 g_signal_connect_swapped (
1319 dyntable
, "row-added",
1320 G_CALLBACK (row_added_cb
), expander
);
1322 init_phone_record_type (editor
);
1324 gtk_expander_set_expanded (expander
, TRUE
);
1328 sensitize_phone_types (EContactEditor
*editor
)
1331 GtkListStore
*listStore
;
1332 GtkTreeModel
*model
;
1336 const EABTypeLabel
*eab_phone_types
;
1338 w
= e_builder_get_widget (editor
->priv
->builder
, "phone-dyntable");
1339 listStore
= e_contact_editor_dyntable_get_combo_store (E_CONTACT_EDITOR_DYNTABLE (w
));
1340 model
= GTK_TREE_MODEL (listStore
);
1342 valid
= gtk_tree_model_get_iter_first (model
, &iter
);
1344 eab_phone_types
= eab_get_phone_type_labels (&n_elements
);
1345 for (i
= 0; i
< n_elements
; i
++) {
1347 g_warning (G_STRLOC
": Unexpected end of phone items in combo box");
1351 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
1352 DYNTABLE_COMBO_COLUMN_SENSITIVE
,
1353 is_field_supported (editor
, eab_phone_types
[i
].field_id
),
1356 valid
= gtk_tree_model_iter_next (model
, &iter
);
1361 sensitize_phone (EContactEditor
*editor
)
1364 gboolean enabled
= FALSE
;
1366 const EABTypeLabel
*eab_phone_types
;
1368 w
= e_builder_get_widget (editor
->priv
->builder
, "phone-dyntable");
1370 eab_phone_types
= eab_get_phone_type_labels (&n_elements
);
1371 if (editor
->priv
->target_editable
) {
1372 enabled
= is_field_supported (editor
, E_CONTACT_TEL
);
1373 for (i
= 0; i
< n_elements
&& !enabled
; i
++) {
1374 enabled
= is_field_supported (editor
, eab_phone_types
[i
].field_id
);
1378 gtk_widget_set_sensitive (w
, enabled
);
1380 sensitize_phone_types (editor
);
1384 fill_in_sip (EContactEditor
*editor
)
1386 GList
*sip_attr_list
;
1389 EContactEditorDynTable
*dyntable
;
1390 GtkListStore
*data_store
;
1393 w
= e_builder_get_widget (editor
->priv
->builder
, "sip-dyntable");
1394 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
1398 e_contact_editor_dyntable_clear_data (dyntable
);
1402 sip_attr_list
= e_contact_get_attributes (editor
->priv
->contact
, E_CONTACT_SIP
);
1404 data_store
= e_contact_editor_dyntable_extract_data (dyntable
);
1406 for (l
= sip_attr_list
; l
; l
= g_list_next (l
)) {
1407 EVCardAttribute
*attr
= l
->data
;
1411 sip_type
= eab_get_sip_type_index (attr
);
1412 sip
= e_vcard_attribute_get_value (attr
);
1417 gtk_list_store_append (data_store
, &iter
);
1418 gtk_list_store_set (data_store
,&iter
,
1419 DYNTABLE_STORE_COLUMN_SORTORDER
, -1,
1420 DYNTABLE_STORE_COLUMN_SELECTED_ITEM
, sip_type
,
1421 DYNTABLE_STORE_COLUMN_ENTRY_STRING
, sip
,
1427 e_contact_editor_dyntable_fill_in_data (dyntable
);
1428 g_list_free_full (sip_attr_list
, (GDestroyNotify
) e_vcard_attribute_free
);
1432 extract_sip (EContactEditor
*editor
)
1434 GList
*sip_attr_list
= NULL
;
1435 GList
*old_attr_list
;
1439 EContactEditorDynTable
*dyntable
;
1440 GtkListStore
*data_store
;
1441 GtkTreeModel
*tree_model
;
1445 w
= e_builder_get_widget (editor
->priv
->builder
, "sip-dyntable");
1446 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
1447 data_store
= e_contact_editor_dyntable_extract_data (dyntable
);
1448 tree_model
= GTK_TREE_MODEL (data_store
);
1450 valid
= gtk_tree_model_get_iter_first (tree_model
, &iter
);
1454 EVCardAttribute
*attr
;
1456 gtk_tree_model_get (tree_model
,&iter
,
1457 DYNTABLE_STORE_COLUMN_SELECTED_ITEM
, &sip_type
,
1458 DYNTABLE_STORE_COLUMN_ENTRY_STRING
, &sip
,
1461 attr
= e_vcard_attribute_new ("", EVC_X_SIP
);
1462 if (sip_type
>= 0) {
1463 const gchar
*type_1
;
1465 eab_sip_index_to_type (sip_type
, &type_1
);
1467 e_vcard_attribute_add_param_with_value (
1468 attr
, e_vcard_attribute_param_new (EVC_TYPE
), type_1
);
1471 e_vcard_attribute_add_value (attr
, sip
);
1473 sip_attr_list
= g_list_prepend (sip_attr_list
, attr
);
1475 valid
= gtk_tree_model_iter_next (tree_model
, &iter
);
1478 /* Splice in the old attributes, minus the SIP_SLOTS first */
1480 sip_attr_list
= g_list_reverse (sip_attr_list
);
1481 old_attr_list
= e_contact_get_attributes (editor
->priv
->contact
, E_CONTACT_SIP
);
1482 for (ll
= old_attr_list
, i
= 1; ll
&& i
<= SIP_SLOTS
; i
++) {
1483 e_vcard_attribute_free (ll
->data
);
1484 ll
= g_list_delete_link (ll
, ll
);
1488 sip_attr_list
= g_list_concat (sip_attr_list
, old_attr_list
);
1490 e_contact_set_attributes (editor
->priv
->contact
, E_CONTACT_SIP
, sip_attr_list
);
1492 g_list_free_full (sip_attr_list
, (GDestroyNotify
) e_vcard_attribute_free
);
1496 init_sip_record_type (EContactEditor
*editor
)
1499 GtkListStore
*store
;
1501 EContactEditorDynTable
*dyntable
;
1502 const EABTypeLabel
*sip_types
= eab_get_sip_type_labels (&n_elements
);
1504 w
= e_builder_get_widget (editor
->priv
->builder
, "sip-dyntable");
1505 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
1506 store
= e_contact_editor_dyntable_get_combo_store (dyntable
);
1508 for (i
= 0; i
< n_elements
; i
++) {
1511 gtk_list_store_append (store
, &iter
);
1512 gtk_list_store_set (store
, &iter
,
1513 DYNTABLE_COMBO_COLUMN_TEXT
, _(sip_types
[i
].text
),
1514 DYNTABLE_COMBO_COLUMN_SENSITIVE
, TRUE
,
1518 e_contact_editor_dyntable_set_combo_defaults (dyntable
, sips_default
, G_N_ELEMENTS (sips_default
));
1522 init_sip (EContactEditor
*editor
)
1524 EContactEditorDynTable
*dyntable
;
1525 GtkExpander
*expander
;
1527 expander
= GTK_EXPANDER (
1528 e_builder_get_widget (editor
->priv
->builder
, "expander-contact-sip"));
1529 dyntable
= E_CONTACT_EDITOR_DYNTABLE (
1530 e_builder_get_widget (editor
->priv
->builder
, "sip-dyntable"));
1532 e_contact_editor_dyntable_set_max_entries (dyntable
, SIP_SLOTS
);
1533 e_contact_editor_dyntable_set_num_columns (dyntable
, SLOTS_PER_LINE
, TRUE
);
1534 e_contact_editor_dyntable_set_show_min (dyntable
, SLOTS_IN_COLLAPSED_STATE
);
1537 dyntable
, "changed",
1538 G_CALLBACK (object_changed
), editor
);
1539 g_signal_connect_swapped (
1540 dyntable
, "activate",
1541 G_CALLBACK (entry_activated
), editor
);
1542 g_signal_connect_swapped (
1543 dyntable
, "row-added",
1544 G_CALLBACK (row_added_cb
), expander
);
1546 init_sip_record_type (editor
);
1548 gtk_expander_set_expanded (expander
, TRUE
);
1552 check_dyntable_for_data (EContactEditor
*editor
,
1555 EContactEditorDynTable
*dyntable
;
1556 GtkTreeModel
*tree_model
;
1559 dyntable
= E_CONTACT_EDITOR_DYNTABLE (e_builder_get_widget (editor
->priv
->builder
, name
));
1560 tree_model
= GTK_TREE_MODEL (e_contact_editor_dyntable_extract_data (dyntable
));
1562 return gtk_tree_model_get_iter_first (tree_model
, &iter
);
1566 extract_address_textview (EContactEditor
*editor
,
1568 EContactAddress
*address
)
1570 gchar
*textview_name
;
1571 GtkWidget
*textview
;
1572 GtkTextBuffer
*text_buffer
;
1573 GtkTextIter iter_1
, iter_2
;
1575 textview_name
= g_strdup_printf ("textview-%s-address", address_name
[record
]);
1576 textview
= e_builder_get_widget (editor
->priv
->builder
, textview_name
);
1577 g_free (textview_name
);
1579 text_buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview
));
1580 gtk_text_buffer_get_start_iter (text_buffer
, &iter_1
);
1582 /* Skip blank lines */
1583 while (gtk_text_iter_get_chars_in_line (&iter_1
) < 1 &&
1584 !gtk_text_iter_is_end (&iter_1
))
1585 gtk_text_iter_forward_line (&iter_1
);
1587 if (gtk_text_iter_is_end (&iter_1
))
1591 gtk_text_iter_forward_to_line_end (&iter_2
);
1593 /* Extract street (first line of text) */
1594 address
->street
= gtk_text_iter_get_text (&iter_1
, &iter_2
);
1597 gtk_text_iter_forward_line (&iter_1
);
1599 if (gtk_text_iter_is_end (&iter_1
))
1602 gtk_text_iter_forward_to_end (&iter_2
);
1604 /* Extract extended address (remaining lines of text) */
1605 address
->ext
= gtk_text_iter_get_text (&iter_1
, &iter_2
);
1609 extract_address_field (EContactEditor
*editor
,
1611 const gchar
*widget_field_name
)
1616 entry_name
= g_strdup_printf (
1617 "entry-%s-%s", address_name
[record
], widget_field_name
);
1618 entry
= e_builder_get_widget (editor
->priv
->builder
, entry_name
);
1619 g_free (entry_name
);
1621 return g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
1625 extract_address_from_gui (EContactEditor
* editor
,
1626 EContactAddress
* address
,
1629 extract_address_textview (editor
, record
, address
);
1630 address
->locality
= extract_address_field (editor
, record
, "city");
1631 address
->region
= extract_address_field (editor
, record
, "state");
1632 address
->code
= extract_address_field (editor
, record
, "zip");
1633 address
->country
= extract_address_field (editor
, record
, "country");
1634 address
->po
= extract_address_field (editor
, record
, "pobox");
1638 check_address_for_data (EContactEditor
*editor
,
1641 gboolean has_data
= FALSE
;
1642 EContactAddress
*address
;
1644 address
= g_new0 (EContactAddress
, 1);
1646 extract_address_from_gui (editor
, address
, record
);
1647 if (!STRING_IS_EMPTY (address
->street
) ||
1648 !STRING_IS_EMPTY (address
->ext
) ||
1649 !STRING_IS_EMPTY (address
->locality
) ||
1650 !STRING_IS_EMPTY (address
->region
) ||
1651 !STRING_IS_EMPTY (address
->code
) ||
1652 !STRING_IS_EMPTY (address
->po
) ||
1653 !STRING_IS_EMPTY (address
->country
)) {
1663 check_web_for_data (EContactEditor
*editor
)
1665 GtkBuilder
*b
= editor
->priv
->builder
;
1667 return !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-homepage")))) ||
1668 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-weblog")))) ||
1669 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-caluri")))) ||
1670 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-fburl")))) ||
1671 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-videourl")))) ;
1675 check_job_for_data (EContactEditor
*editor
)
1677 GtkBuilder
*b
= editor
->priv
->builder
;
1679 return !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-manager")))) ||
1680 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-assistant")))) ||
1681 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-profession")))) ||
1682 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-jobtitle")))) ||
1683 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-company")))) ||
1684 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-department")))) ||
1685 !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-office"))));
1689 check_misc_for_data (EContactEditor
*editor
)
1691 GtkBuilder
*b
= editor
->priv
->builder
;
1692 gint year
, month
, day
;
1694 return !STRING_IS_EMPTY (gtk_entry_get_text (GTK_ENTRY (e_builder_get_widget (b
, "entry-spouse")))) ||
1695 e_date_edit_get_date (E_DATE_EDIT (e_builder_get_widget (b
, "dateedit-birthday")), &year
, &month
, &day
) ||
1696 e_date_edit_get_date (E_DATE_EDIT (e_builder_get_widget (b
, "dateedit-anniversary")), &year
, &month
, &day
);
1700 check_notes_for_data (EContactEditor
*editor
)
1702 GtkWidget
*tv
= e_builder_get_widget (editor
->priv
->builder
, "text-comments");
1703 GtkTextBuffer
*buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv
));
1705 return gtk_text_buffer_get_char_count (buffer
) > 0;
1709 check_certs_for_data (EContactEditor
*editor
)
1711 GtkWidget
*treeview
= e_builder_get_widget (editor
->priv
->builder
, "certs-treeview");
1712 GtkTreeModel
*model
;
1715 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (treeview
));
1716 return model
&& gtk_tree_model_get_iter_first (model
, &iter
);
1720 check_section_for_data (EContactEditor
*editor
,
1723 gboolean has_data
= TRUE
;
1727 has_data
= check_dyntable_for_data (editor
, "phone-dyntable");
1730 has_data
= check_dyntable_for_data (editor
, "sip-dyntable");
1733 has_data
= check_dyntable_for_data (editor
, "im-dyntable");
1736 has_data
= check_address_for_data (editor
, ADDRESS_SLOT_HOME
);
1739 has_data
= check_address_for_data (editor
, ADDRESS_SLOT_WORK
);
1742 has_data
= check_address_for_data (editor
, ADDRESS_SLOT_OTHER
);
1745 has_data
= check_web_for_data (editor
);
1748 has_data
= check_job_for_data (editor
);
1751 has_data
= check_misc_for_data (editor
);
1754 has_data
= check_notes_for_data (editor
);
1757 has_data
= check_certs_for_data (editor
);
1760 g_warning ("unknown data check requested");
1767 config_sensitize_item (EContactEditor
*editor
,
1768 const gchar
*item_name
,
1774 has_data
= check_section_for_data (editor
, check
);
1775 item
= e_builder_get_widget (editor
->priv
->builder
, item_name
);
1778 gtk_widget_set_sensitive (item
, FALSE
);
1779 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item
), TRUE
);
1781 gtk_widget_set_sensitive (item
, TRUE
);
1786 config_sensitize_cb (GtkWidget
*button
,
1787 EContactEditor
*editor
)
1789 config_sensitize_item (editor
, "menuitem-config-phone", CHECK_PHONE
);
1790 config_sensitize_item (editor
, "menuitem-config-sip", CHECK_SIP
);
1791 config_sensitize_item (editor
, "menuitem-config-im", CHECK_IM
);
1793 config_sensitize_item (editor
, "menuitem-config-web", CHECK_WEB
);
1794 config_sensitize_item (editor
, "menuitem-config-job", CHECK_JOB
);
1795 config_sensitize_item (editor
, "menuitem-config-misc", CHECK_MISC
);
1797 config_sensitize_item (editor
, "menuitem-config-home", CHECK_HOME
);
1798 config_sensitize_item (editor
, "menuitem-config-work", CHECK_WORK
);
1799 config_sensitize_item (editor
, "menuitem-config-other", CHECK_OTHER
);
1801 config_sensitize_item (editor
, "menuitem-config-notes", CHECK_NOTE
);
1802 config_sensitize_item (editor
, "menuitem-config-certs", CHECK_CERTS
);
1806 * get the value from GSettings and check if there is data in the widget.
1807 * if no data is found set_visible (value), set_visible (true) otherwise
1809 * Returns: the new visibility
1812 configure_widget_visibility (EContactEditor
*editor
,
1813 GSettings
*settings
,
1814 const gchar
*widget_name
,
1815 const gchar
*settings_name
,
1818 gboolean config
, has_data
;
1821 config
= g_settings_get_boolean (settings
, settings_name
);
1822 widget
= e_builder_get_widget (editor
->priv
->builder
, widget_name
);
1823 has_data
= check_section_for_data (editor
, check
);
1825 gtk_widget_set_visible (widget
, config
|| has_data
);
1827 return config
|| has_data
;
1831 configure_visibility (EContactEditor
*editor
)
1834 GSettings
*settings
= e_util_ref_settings ("org.gnome.evolution.addressbook");
1836 configure_widget_visibility (editor
, settings
, "vbox-contact-phone", "editor-show-contact-phone", CHECK_PHONE
);
1837 configure_widget_visibility (editor
, settings
, "vbox-contact-sip", "editor-show-contact-sip", CHECK_SIP
);
1838 configure_widget_visibility (editor
, settings
, "vbox-contact-im", "editor-show-contact-im", CHECK_IM
);
1840 show_tab
= configure_widget_visibility (editor
, settings
, "frame-mailing-home", "editor-show-mailing-home", CHECK_HOME
);
1841 show_tab
|= configure_widget_visibility (editor
, settings
, "frame-mailing-work", "editor-show-mailing-work", CHECK_WORK
);
1842 show_tab
|= configure_widget_visibility (editor
, settings
, "expander-address-other", "editor-show-mailing-other", CHECK_OTHER
);
1843 gtk_widget_set_visible (
1844 e_builder_get_widget (editor
->priv
->builder
, "scrolledwindow-mailing"),
1847 show_tab
= configure_widget_visibility (editor
, settings
, "expander-personal-web", "editor-show-personal-web", CHECK_WEB
);
1848 show_tab
|= configure_widget_visibility (editor
, settings
, "expander-personal-job", "editor-show-personal-job", CHECK_JOB
);
1849 show_tab
|= configure_widget_visibility (editor
, settings
, "expander-personal-misc", "editor-show-personal-misc", CHECK_MISC
);
1850 gtk_widget_set_visible (
1851 e_builder_get_widget (editor
->priv
->builder
, "scrolledwindow-personal"),
1854 configure_widget_visibility (editor
, settings
, "scrolledwindow-notes", "editor-show-notes", CHECK_NOTE
);
1855 configure_widget_visibility (editor
, settings
, "certs-grid", "editor-show-certs", CHECK_CERTS
);
1857 g_object_unref (settings
);
1861 config_menuitem_save (EContactEditor
*editor
,
1862 GSettings
*settings
,
1863 const gchar
*item_name
,
1867 gboolean active
, sensitive
;
1869 item
= e_builder_get_widget (editor
->priv
->builder
, item_name
);
1870 active
= gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item
));
1871 sensitive
= gtk_widget_get_sensitive (item
);
1874 g_settings_set_boolean (settings
, key
, active
);
1878 config_save_cb (GtkWidget
*button
,
1879 EContactEditor
*editor
)
1881 GSettings
*settings
;
1883 settings
= e_util_ref_settings ("org.gnome.evolution.addressbook");
1885 config_menuitem_save (editor
, settings
, "menuitem-config-phone", "editor-show-contact-phone");
1886 config_menuitem_save (editor
, settings
, "menuitem-config-sip", "editor-show-contact-sip");
1887 config_menuitem_save (editor
, settings
, "menuitem-config-im", "editor-show-contact-im");
1889 config_menuitem_save (editor
, settings
, "menuitem-config-web", "editor-show-personal-web");
1890 config_menuitem_save (editor
, settings
, "menuitem-config-job", "editor-show-personal-job");
1891 config_menuitem_save (editor
, settings
, "menuitem-config-misc", "editor-show-personal-misc");
1893 config_menuitem_save (editor
, settings
, "menuitem-config-home", "editor-show-mailing-home");
1894 config_menuitem_save (editor
, settings
, "menuitem-config-work", "editor-show-mailing-work");
1895 config_menuitem_save (editor
, settings
, "menuitem-config-other", "editor-show-mailing-other");
1897 config_menuitem_save (editor
, settings
, "menuitem-config-notes", "editor-show-notes");
1898 config_menuitem_save (editor
, settings
, "menuitem-config-certs", "editor-show-certs");
1900 g_object_unref (settings
);
1902 configure_visibility (editor
);
1906 init_config_menuitem (EContactEditor
*editor
,
1907 GSettings
*settings
,
1908 const gchar
*item_name
,
1914 show
= g_settings_get_boolean (settings
, key
);
1915 item
= e_builder_get_widget (editor
->priv
->builder
, item_name
);
1916 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item
), show
);
1920 G_CALLBACK (config_save_cb
), editor
);
1924 init_config (EContactEditor
*editor
)
1926 GtkWidget
*button
, *menu
;
1927 GSettings
*settings
;
1929 button
= e_builder_get_widget (editor
->priv
->builder
, "button-config");
1930 menu
= e_builder_get_widget (editor
->priv
->builder
, "menu-editor-config");
1931 gtk_menu_button_set_popup (GTK_MENU_BUTTON (button
), menu
);
1933 /* save resources by only doing the data checks and sensitizing upon request,
1934 * instead of doing it with each change in object_changed()
1938 G_CALLBACK (config_sensitize_cb
), editor
);
1940 settings
= e_util_ref_settings ("org.gnome.evolution.addressbook");
1942 init_config_menuitem (editor
, settings
, "menuitem-config-phone", "editor-show-contact-phone");
1943 init_config_menuitem (editor
, settings
, "menuitem-config-sip", "editor-show-contact-sip");
1944 init_config_menuitem (editor
, settings
, "menuitem-config-im", "editor-show-contact-im");
1946 init_config_menuitem (editor
, settings
, "menuitem-config-web", "editor-show-personal-web");
1947 init_config_menuitem (editor
, settings
, "menuitem-config-job", "editor-show-personal-job");
1948 init_config_menuitem (editor
, settings
, "menuitem-config-misc", "editor-show-personal-misc");
1950 init_config_menuitem (editor
, settings
, "menuitem-config-home", "editor-show-mailing-home");
1951 init_config_menuitem (editor
, settings
, "menuitem-config-work", "editor-show-mailing-work");
1952 init_config_menuitem (editor
, settings
, "menuitem-config-other", "editor-show-mailing-other");
1954 init_config_menuitem (editor
, settings
, "menuitem-config-notes", "editor-show-notes");
1955 init_config_menuitem (editor
, settings
, "menuitem-config-certs", "editor-show-certs");
1957 g_object_unref (settings
);
1961 sensitize_sip_types (EContactEditor
*editor
)
1964 GtkListStore
*listStore
;
1965 GtkTreeModel
*model
;
1969 const EABTypeLabel
*sip_types
= eab_get_sip_type_labels (&n_elements
);
1971 w
= e_builder_get_widget (editor
->priv
->builder
, "sip-dyntable");
1972 listStore
= e_contact_editor_dyntable_get_combo_store (E_CONTACT_EDITOR_DYNTABLE (w
));
1973 model
= GTK_TREE_MODEL (listStore
);
1975 valid
= gtk_tree_model_get_iter_first (model
, &iter
);
1977 for (i
= 0; i
< n_elements
; i
++) {
1979 g_warning (G_STRLOC
": Unexpected end of sip items in combo box");
1983 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
1984 DYNTABLE_COMBO_COLUMN_SENSITIVE
,
1985 is_field_supported (editor
, sip_types
[i
].field_id
),
1988 valid
= gtk_tree_model_iter_next (model
, &iter
);
1993 sensitize_sip (EContactEditor
*editor
)
1996 gboolean enabled
= TRUE
;
1998 w
= e_builder_get_widget (editor
->priv
->builder
, "sip-dyntable");
2000 if (!editor
->priv
->target_editable
||
2001 !is_field_supported (editor
, E_CONTACT_SIP
))
2004 gtk_widget_set_sensitive (w
, enabled
);
2006 sensitize_sip_types (editor
);
2010 init_im_record_type (EContactEditor
*editor
)
2013 GtkListStore
*store
;
2015 EContactEditorDynTable
*dyntable
;
2016 const EABTypeLabel
*im_service
;
2018 w
= e_builder_get_widget (editor
->priv
->builder
, "im-dyntable");
2019 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
2020 store
= e_contact_editor_dyntable_get_combo_store (dyntable
);
2022 im_service
= eab_get_im_type_labels (&n_elements
);
2023 for (i
= 0; i
< n_elements
; i
++) {
2026 gtk_list_store_append (store
, &iter
);
2027 gtk_list_store_set (store
, &iter
,
2028 DYNTABLE_COMBO_COLUMN_TEXT
, _(im_service
[i
].text
),
2029 DYNTABLE_COMBO_COLUMN_SENSITIVE
, TRUE
,
2033 e_contact_editor_dyntable_set_combo_defaults (dyntable
, im_service_default
, G_N_ELEMENTS (im_service_default
));
2037 init_im (EContactEditor
*editor
)
2039 EContactEditorDynTable
*dyntable
;
2040 GtkExpander
*expander
;
2042 expander
= GTK_EXPANDER (
2043 e_builder_get_widget (editor
->priv
->builder
, "expander-contact-im"));
2044 dyntable
= E_CONTACT_EDITOR_DYNTABLE (
2045 e_builder_get_widget (editor
->priv
->builder
, "im-dyntable"));
2047 e_contact_editor_dyntable_set_max_entries (dyntable
, IM_SLOTS
);
2048 e_contact_editor_dyntable_set_num_columns (dyntable
, SLOTS_PER_LINE
, TRUE
);
2049 e_contact_editor_dyntable_set_show_min (dyntable
, SLOTS_IN_COLLAPSED_STATE
);
2052 dyntable
, "changed",
2053 G_CALLBACK (object_changed
), editor
);
2054 g_signal_connect_swapped (
2055 dyntable
, "activate",
2056 G_CALLBACK (entry_activated
), editor
);
2057 g_signal_connect_swapped (
2058 dyntable
, "row-added",
2059 G_CALLBACK (row_added_cb
), expander
);
2061 init_im_record_type (editor
);
2063 gtk_expander_set_expanded (expander
, TRUE
);
2067 fill_in_im (EContactEditor
*editor
)
2069 GList
*im_attr_list
;
2072 EContactEditorDynTable
*dyntable
;
2073 GtkListStore
*data_store
;
2076 w
= e_builder_get_widget (editor
->priv
->builder
, "im-dyntable");
2077 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
2081 e_contact_editor_dyntable_clear_data (dyntable
);
2085 data_store
= e_contact_editor_dyntable_extract_data (dyntable
);
2087 im_attr_list
= e_contact_get_attributes_set (
2088 editor
->priv
->contact
,
2089 im_service_fetch_set
,
2090 G_N_ELEMENTS (im_service_fetch_set
)
2093 for (l
= im_attr_list
; l
; l
= g_list_next(l
)) {
2094 EVCardAttribute
*attr
= l
->data
;
2099 im_name
= e_vcard_attribute_get_value (attr
);
2100 service_type
= eab_get_im_type_index (attr
);
2102 slot
= get_ui_slot (attr
);
2104 slot
= IM_SLOTS
+ 1; /* attach at the end */
2106 gtk_list_store_append (data_store
, &iter
);
2107 gtk_list_store_set (data_store
, &iter
,
2108 DYNTABLE_STORE_COLUMN_SORTORDER
, slot
,
2109 DYNTABLE_STORE_COLUMN_SELECTED_ITEM
, service_type
,
2110 DYNTABLE_STORE_COLUMN_ENTRY_STRING
, im_name
,
2116 g_list_free_full (im_attr_list
, (GDestroyNotify
) e_vcard_attribute_free
);
2118 e_contact_editor_dyntable_fill_in_data (dyntable
);
2122 extract_im (EContactEditor
*editor
)
2124 GList
*attr_list
= NULL
;
2125 GList
*old_attr_list
= NULL
;
2129 EContactEditorDynTable
*dyntable
;
2130 GtkListStore
*data_store
;
2131 GtkTreeModel
*tree_model
;
2135 w
= e_builder_get_widget (editor
->priv
->builder
, "im-dyntable");
2136 dyntable
= E_CONTACT_EDITOR_DYNTABLE (w
);
2137 data_store
= e_contact_editor_dyntable_extract_data (dyntable
);
2138 tree_model
= GTK_TREE_MODEL (data_store
);
2140 valid
= gtk_tree_model_get_iter_first (tree_model
, &iter
);
2145 EVCardAttribute
*attr
;
2146 const EABTypeLabel
*im_service
= eab_get_im_type_labels (&service_type
);
2148 gtk_tree_model_get (tree_model
,&iter
,
2149 DYNTABLE_STORE_COLUMN_SORTORDER
, &slot
,
2150 DYNTABLE_STORE_COLUMN_SELECTED_ITEM
, &service_type
,
2151 DYNTABLE_STORE_COLUMN_ENTRY_STRING
, &im_name
,
2154 attr
= e_vcard_attribute_new ("",
2155 e_contact_vcard_attribute (
2156 im_service
[service_type
].field_id
));
2158 /* older evolution versions (<=3.12) will crash if SLOT>4 is stored,
2159 * but if we don't store the slot we loose sortorder.
2160 * this works only for <=4 IM slots. for more, old evolution
2161 * will go through types (AIM, Jabber, ...) and stop after 4
2162 * no matter what x-evo-slot says.
2165 set_ui_slot (attr
, slot
+ 1);
2167 e_vcard_attribute_add_value (attr
, im_name
);
2169 attr_list
= g_list_prepend (attr_list
, attr
);
2171 valid
= gtk_tree_model_iter_next (tree_model
, &iter
);
2173 attr_list
= g_list_reverse (attr_list
);
2175 /* Splice in the old attributes, minus the IM_SLOTS first */
2177 old_attr_list
= e_contact_get_attributes_set (
2178 editor
->priv
->contact
,
2179 im_service_fetch_set
,
2180 G_N_ELEMENTS (im_service_fetch_set
)
2182 for (ll
= old_attr_list
, ii
= 0; ll
&& ii
< IM_SLOTS
; ii
++) {
2183 e_vcard_attribute_free (ll
->data
);
2184 ll
= g_list_delete_link (ll
, ll
);
2188 attr_list
= g_list_concat (attr_list
, old_attr_list
);
2190 for (ii
= 0; ii
< G_N_ELEMENTS (im_service_fetch_set
); ii
++) {
2191 e_contact_set_attributes (editor
->priv
->contact
, im_service_fetch_set
[ii
], NULL
);
2194 for (ll
= attr_list
; ll
; ll
= ll
->next
) {
2196 vcard
= E_VCARD (editor
->priv
->contact
);
2197 e_vcard_append_attribute (vcard
, e_vcard_attribute_copy ((EVCardAttribute
*) ll
->data
));
2200 g_list_free_full (attr_list
, (GDestroyNotify
) e_vcard_attribute_free
);
2204 sensitize_im_types (EContactEditor
*editor
)
2207 GtkListStore
*list_store
;
2208 GtkTreeModel
*model
;
2212 const EABTypeLabel
*im_service
= eab_get_im_type_labels (&n_elements
);
2214 w
= e_builder_get_widget (editor
->priv
->builder
, "im-dyntable");
2215 list_store
= e_contact_editor_dyntable_get_combo_store (E_CONTACT_EDITOR_DYNTABLE (w
));
2216 model
= GTK_TREE_MODEL (list_store
);
2218 valid
= gtk_tree_model_get_iter_first (model
, &iter
);
2220 for (i
= 0; i
< n_elements
; i
++) {
2222 g_warning (G_STRLOC
": Unexpected end of im items in combo box");
2226 gtk_list_store_set (
2227 GTK_LIST_STORE (model
), &iter
,
2228 DYNTABLE_COMBO_COLUMN_SENSITIVE
,
2229 is_field_supported (editor
, im_service
[i
].field_id
),
2232 valid
= gtk_tree_model_iter_next (model
, &iter
);
2237 sensitize_im (EContactEditor
*editor
)
2241 gboolean no_ims_supported
;
2243 const EABTypeLabel
*im_service
= eab_get_im_type_labels (&n_elements
);
2245 enabled
= editor
->priv
->target_editable
;
2246 no_ims_supported
= TRUE
;
2248 for (i
= 0; i
< n_elements
; i
++)
2249 if (is_field_supported (editor
, im_service
[i
].field_id
)) {
2250 no_ims_supported
= FALSE
;
2254 if (no_ims_supported
)
2257 w
= e_builder_get_widget (editor
->priv
->builder
, "im-dyntable");
2258 gtk_widget_set_sensitive (w
, enabled
);
2260 sensitize_im_types (editor
);
2264 init_address_textview (EContactEditor
*editor
,
2267 gchar
*textview_name
;
2268 GtkWidget
*textview
;
2269 GtkTextBuffer
*text_buffer
;
2271 textview_name
= g_strdup_printf (
2272 "textview-%s-address", address_name
[record
]);
2273 textview
= e_builder_get_widget (editor
->priv
->builder
, textview_name
);
2274 g_free (textview_name
);
2276 text_buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview
));
2279 text_buffer
, "changed",
2280 G_CALLBACK (object_changed
), editor
);
2284 init_address_field (EContactEditor
*editor
,
2286 const gchar
*widget_field_name
)
2291 entry_name
= g_strdup_printf (
2292 "entry-%s-%s", address_name
[record
], widget_field_name
);
2293 entry
= e_builder_get_widget (editor
->priv
->builder
, entry_name
);
2294 g_free (entry_name
);
2298 G_CALLBACK (object_changed
), editor
);
2299 g_signal_connect_swapped (
2301 G_CALLBACK (entry_activated
), editor
);
2305 init_address_record (EContactEditor
*editor
,
2308 init_address_textview (editor
, record
);
2309 init_address_field (editor
, record
, "city");
2310 init_address_field (editor
, record
, "state");
2311 init_address_field (editor
, record
, "zip");
2312 init_address_field (editor
, record
, "country");
2313 init_address_field (editor
, record
, "pobox");
2317 init_address (EContactEditor
*editor
)
2321 for (i
= 0; i
< ADDRESS_SLOTS
; i
++)
2322 init_address_record (editor
, i
);
2324 gtk_expander_set_expanded (
2325 GTK_EXPANDER (e_builder_get_widget (editor
->priv
->builder
, "expander-address-other")),
2326 !editor
->priv
->compress_ui
);
2330 fill_in_address_textview (EContactEditor
*editor
,
2332 EContactAddress
*address
)
2334 gchar
*textview_name
;
2335 GtkWidget
*textview
;
2336 GtkTextBuffer
*text_buffer
;
2337 GtkTextIter iter_end
, iter_start
;
2339 textview_name
= g_strdup_printf ("textview-%s-address", address_name
[record
]);
2340 textview
= e_builder_get_widget (editor
->priv
->builder
, textview_name
);
2341 g_free (textview_name
);
2343 text_buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview
));
2344 gtk_text_buffer_set_text (text_buffer
, address
->street
? address
->street
: "", -1);
2346 gtk_text_buffer_get_end_iter (text_buffer
, &iter_end
);
2347 if (address
->ext
&& *address
->ext
) {
2348 gtk_text_buffer_insert (text_buffer
, &iter_end
, "\n", -1);
2349 gtk_text_buffer_insert (text_buffer
, &iter_end
, address
->ext
, -1);
2351 gtk_text_buffer_insert (text_buffer
, &iter_end
, "", -1);
2353 gtk_text_buffer_get_iter_at_line (text_buffer
, &iter_start
, 0);
2354 gtk_text_buffer_place_cursor (text_buffer
, &iter_start
);
2358 fill_in_address_label_textview (EContactEditor
*editor
,
2362 gchar
*textview_name
;
2363 GtkWidget
*textview
;
2364 GtkTextBuffer
*text_buffer
;
2366 textview_name
= g_strdup_printf (
2367 "textview-%s-address", address_name
[record
]);
2368 textview
= e_builder_get_widget (editor
->priv
->builder
, textview_name
);
2369 g_free (textview_name
);
2371 text_buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview
));
2372 gtk_text_buffer_set_text (text_buffer
, label
? label
: "", -1);
2376 fill_in_address_field (EContactEditor
*editor
,
2378 const gchar
*widget_field_name
,
2379 const gchar
*string
)
2384 entry_name
= g_strdup_printf (
2385 "entry-%s-%s", address_name
[record
], widget_field_name
);
2386 entry
= e_builder_get_widget (editor
->priv
->builder
, entry_name
);
2387 g_free (entry_name
);
2389 set_entry_text (editor
, GTK_ENTRY (entry
), string
);
2393 fill_in_address_record (EContactEditor
*editor
,
2396 EContactAddress
*address
;
2397 gchar
*address_label
;
2399 address
= e_contact_get (editor
->priv
->contact
, addresses
[record
]);
2400 address_label
= e_contact_get (editor
->priv
->contact
, address_labels
[record
]);
2403 (!STRING_IS_EMPTY (address
->street
) ||
2404 !STRING_IS_EMPTY (address
->ext
) ||
2405 !STRING_IS_EMPTY (address
->locality
) ||
2406 !STRING_IS_EMPTY (address
->region
) ||
2407 !STRING_IS_EMPTY (address
->code
) ||
2408 !STRING_IS_EMPTY (address
->po
) ||
2409 !STRING_IS_EMPTY (address
->country
))) {
2410 fill_in_address_textview (editor
, record
, address
);
2411 fill_in_address_field (editor
, record
, "city", address
->locality
);
2412 fill_in_address_field (editor
, record
, "state", address
->region
);
2413 fill_in_address_field (editor
, record
, "zip", address
->code
);
2414 fill_in_address_field (editor
, record
, "country", address
->country
);
2415 fill_in_address_field (editor
, record
, "pobox", address
->po
);
2416 } else if (!STRING_IS_EMPTY (address_label
)) {
2417 fill_in_address_label_textview (editor
, record
, address_label
);
2420 g_free (address_label
);
2422 g_boxed_free (e_contact_address_get_type (), address
);
2426 fill_in_address (EContactEditor
*editor
)
2430 for (i
= 0; i
< ADDRESS_SLOTS
; i
++)
2431 fill_in_address_record (editor
, i
);
2435 append_to_address_label (gchar
*address_label
,
2439 gchar
*new_address_label
;
2441 if (STRING_IS_EMPTY (part
))
2442 return address_label
;
2445 new_address_label
= g_strjoin (
2446 newline
? "\n" : ", ",
2447 address_label
, part
, NULL
);
2449 new_address_label
= g_strdup (part
);
2451 g_free (address_label
);
2452 return new_address_label
;
2456 set_address_label (EContact
*contact
,
2457 EContactField field
,
2458 EContactAddress
*address
)
2460 gchar
*address_label
= NULL
;
2461 gboolean format_address
;
2462 GSettings
*settings
;
2465 e_contact_set (contact
, field
, NULL
);
2469 settings
= e_util_ref_settings ("org.gnome.evolution.addressbook");
2470 format_address
= g_settings_get_boolean (settings
, "address-formatting");
2471 g_object_unref (settings
);
2473 if (format_address
) {
2474 address_label
= eab_format_address (
2476 (field
== E_CONTACT_ADDRESS_LABEL_WORK
) ?
2477 E_CONTACT_ADDRESS_WORK
:
2478 E_CONTACT_ADDRESS_HOME
);
2481 if (!format_address
|| !address_label
) {
2482 address_label
= append_to_address_label (
2483 address_label
, address
->street
, TRUE
);
2484 address_label
= append_to_address_label (
2485 address_label
, address
->ext
, TRUE
);
2486 address_label
= append_to_address_label (
2487 address_label
, address
->locality
, TRUE
);
2488 address_label
= append_to_address_label (
2489 address_label
, address
->region
, FALSE
);
2490 address_label
= append_to_address_label (
2491 address_label
, address
->code
, TRUE
);
2492 address_label
= append_to_address_label (
2493 address_label
, address
->po
, TRUE
);
2494 address_label
= append_to_address_label (
2495 address_label
, address
->country
, TRUE
);
2498 e_contact_set (contact
, field
, address_label
);
2499 g_free (address_label
);
2503 extract_address_record (EContactEditor
*editor
,
2506 EContactAddress
*address
;
2508 address
= g_new0 (EContactAddress
, 1);
2510 extract_address_from_gui (editor
, address
, record
);
2511 if (!STRING_IS_EMPTY (address
->street
) ||
2512 !STRING_IS_EMPTY (address
->ext
) ||
2513 !STRING_IS_EMPTY (address
->locality
) ||
2514 !STRING_IS_EMPTY (address
->region
) ||
2515 !STRING_IS_EMPTY (address
->code
) ||
2516 !STRING_IS_EMPTY (address
->po
) ||
2517 !STRING_IS_EMPTY (address
->country
)) {
2518 e_contact_set (editor
->priv
->contact
, addresses
[record
], address
);
2519 set_address_label (editor
->priv
->contact
, address_labels
[record
], address
);
2522 e_contact_set (editor
->priv
->contact
, addresses
[record
], NULL
);
2523 set_address_label (editor
->priv
->contact
, address_labels
[record
], NULL
);
2526 g_boxed_free (e_contact_address_get_type (), address
);
2530 extract_address (EContactEditor
*editor
)
2534 for (i
= 0; i
< ADDRESS_SLOTS
; i
++)
2535 extract_address_record (editor
, i
);
2539 sensitize_address_textview (EContactEditor
*editor
,
2544 GtkWidget
*textview
;
2547 widget_name
= g_strdup_printf ("textview-%s-address", address_name
[record
]);
2548 textview
= e_builder_get_widget (editor
->priv
->builder
, widget_name
);
2549 g_free (widget_name
);
2551 widget_name
= g_strdup_printf ("label-%s-address", address_name
[record
]);
2552 label
= e_builder_get_widget (editor
->priv
->builder
, widget_name
);
2553 g_free (widget_name
);
2555 gtk_text_view_set_editable (GTK_TEXT_VIEW (textview
), enabled
);
2556 gtk_widget_set_sensitive (label
, enabled
);
2560 sensitize_address_field (EContactEditor
*editor
,
2562 const gchar
*widget_field_name
,
2569 widget_name
= g_strdup_printf (
2570 "entry-%s-%s", address_name
[record
], widget_field_name
);
2571 entry
= e_builder_get_widget (editor
->priv
->builder
, widget_name
);
2572 g_free (widget_name
);
2574 widget_name
= g_strdup_printf (
2575 "label-%s-%s", address_name
[record
], widget_field_name
);
2576 label
= e_builder_get_widget (editor
->priv
->builder
, widget_name
);
2577 g_free (widget_name
);
2579 gtk_editable_set_editable (GTK_EDITABLE (entry
), enabled
);
2580 gtk_widget_set_sensitive (label
, enabled
);
2584 sensitize_address_record (EContactEditor
*editor
,
2588 sensitize_address_textview (editor
, record
, enabled
);
2589 sensitize_address_field (editor
, record
, "city", enabled
);
2590 sensitize_address_field (editor
, record
, "state", enabled
);
2591 sensitize_address_field (editor
, record
, "zip", enabled
);
2592 sensitize_address_field (editor
, record
, "country", enabled
);
2593 sensitize_address_field (editor
, record
, "pobox", enabled
);
2597 sensitize_address (EContactEditor
*editor
)
2601 for (i
= 0; i
< ADDRESS_SLOTS
; i
++) {
2602 gboolean enabled
= TRUE
;
2604 if (!editor
->priv
->target_editable
||
2605 !(is_field_supported (editor
, addresses
[i
]) ||
2606 is_field_supported (editor
, address_labels
[i
])))
2609 sensitize_address_record (editor
, i
, enabled
);
2614 const gchar
*widget_name
;
2615 gint field_id
; /* EContactField or -1 */
2616 gboolean process_data
; /* If we should extract/fill in contents */
2617 gboolean desensitize_for_read_only
;
2621 /* Table of widgets that interact with simple fields. This table is used to:
2625 * - Set sensitivity based on backend capabilities.
2626 * - Set sensitivity based on book writeability. */
2628 static FieldMapping simple_field_map
[] = {
2629 { "entry-homepage", E_CONTACT_HOMEPAGE_URL
, TRUE
, TRUE
},
2630 { "accellabel-homepage", E_CONTACT_HOMEPAGE_URL
, FALSE
, TRUE
},
2632 { "entry-jobtitle", E_CONTACT_TITLE
, TRUE
, TRUE
},
2633 { "label-jobtitle", E_CONTACT_TITLE
, FALSE
, TRUE
},
2635 { "entry-company", E_CONTACT_ORG
, TRUE
, TRUE
},
2636 { "label-company", E_CONTACT_ORG
, FALSE
, TRUE
},
2638 { "entry-department", E_CONTACT_ORG_UNIT
, TRUE
, TRUE
},
2639 { "label-department", E_CONTACT_ORG_UNIT
, FALSE
, TRUE
},
2641 { "entry-profession", E_CONTACT_ROLE
, TRUE
, TRUE
},
2642 { "label-profession", E_CONTACT_ROLE
, FALSE
, TRUE
},
2644 { "entry-manager", E_CONTACT_MANAGER
, TRUE
, TRUE
},
2645 { "label-manager", E_CONTACT_MANAGER
, FALSE
, TRUE
},
2647 { "entry-assistant", E_CONTACT_ASSISTANT
, TRUE
, TRUE
},
2648 { "label-assistant", E_CONTACT_ASSISTANT
, FALSE
, TRUE
},
2650 { "entry-nickname", E_CONTACT_NICKNAME
, TRUE
, TRUE
},
2651 { "label-nickname", E_CONTACT_NICKNAME
, FALSE
, TRUE
},
2653 { "dateedit-birthday", E_CONTACT_BIRTH_DATE
, TRUE
, TRUE
},
2654 { "label-birthday", E_CONTACT_BIRTH_DATE
, FALSE
, TRUE
},
2656 { "dateedit-anniversary", E_CONTACT_ANNIVERSARY
, TRUE
, TRUE
},
2657 { "label-anniversary", E_CONTACT_ANNIVERSARY
, FALSE
, TRUE
},
2659 { "entry-spouse", E_CONTACT_SPOUSE
, TRUE
, TRUE
},
2660 { "label-spouse", E_CONTACT_SPOUSE
, FALSE
, TRUE
},
2662 { "entry-office", E_CONTACT_OFFICE
, TRUE
, TRUE
},
2663 { "label-office", E_CONTACT_OFFICE
, FALSE
, TRUE
},
2665 { "text-comments", E_CONTACT_NOTE
, TRUE
, TRUE
},
2667 { "entry-fullname", E_CONTACT_FULL_NAME
, TRUE
, TRUE
},
2668 { "button-fullname", E_CONTACT_FULL_NAME
, FALSE
, TRUE
},
2670 { "entry-categories", E_CONTACT_CATEGORIES
, TRUE
, TRUE
},
2671 { "button-categories", E_CONTACT_CATEGORIES
, FALSE
, TRUE
},
2673 { "entry-weblog", E_CONTACT_BLOG_URL
, TRUE
, TRUE
},
2674 { "label-weblog", E_CONTACT_BLOG_URL
, FALSE
, TRUE
},
2676 { "entry-caluri", E_CONTACT_CALENDAR_URI
, TRUE
, TRUE
},
2677 { "label-caluri", E_CONTACT_CALENDAR_URI
, FALSE
, TRUE
},
2679 { "entry-fburl", E_CONTACT_FREEBUSY_URL
, TRUE
, TRUE
},
2680 { "label-fburl", E_CONTACT_FREEBUSY_URL
, FALSE
, TRUE
},
2682 { "entry-videourl", E_CONTACT_VIDEO_URL
, TRUE
, TRUE
},
2683 { "label-videourl", E_CONTACT_VIDEO_URL
, FALSE
, TRUE
},
2685 { "checkbutton-htmlmail", E_CONTACT_WANTS_HTML
, TRUE
, TRUE
},
2687 { "image-chooser", E_CONTACT_PHOTO
, TRUE
, TRUE
},
2688 { "button-image", E_CONTACT_PHOTO
, FALSE
, TRUE
},
2690 { "combo-file-as", E_CONTACT_FILE_AS
, TRUE
, TRUE
},
2691 { "accellabel-fileas", E_CONTACT_FILE_AS
, FALSE
, TRUE
},
2695 init_simple_field (EContactEditor
*editor
,
2698 GObject
*changed_object
= NULL
;
2700 if (GTK_IS_ENTRY (widget
)) {
2701 changed_object
= G_OBJECT (widget
);
2702 g_signal_connect_swapped (
2704 G_CALLBACK (entry_activated
), editor
);
2706 } else if (GTK_IS_COMBO_BOX (widget
)) {
2707 changed_object
= G_OBJECT (widget
);
2708 g_signal_connect_swapped (
2709 gtk_bin_get_child (GTK_BIN (widget
)), "activate",
2710 G_CALLBACK (entry_activated
), editor
);
2712 } else if (GTK_IS_TEXT_VIEW (widget
)) {
2713 changed_object
= G_OBJECT (
2714 gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget
)));
2716 } else if (E_IS_URL_ENTRY (widget
)) {
2717 changed_object
= G_OBJECT (widget
);
2718 g_signal_connect_swapped (
2719 changed_object
, "activate",
2720 G_CALLBACK (entry_activated
), editor
);
2722 } else if (E_IS_DATE_EDIT (widget
)) {
2723 changed_object
= G_OBJECT (widget
);
2725 } else if (E_IS_IMAGE_CHOOSER (widget
)) {
2726 changed_object
= G_OBJECT (widget
);
2729 G_CALLBACK (image_chooser_changed
), editor
);
2731 } else if (GTK_IS_TOGGLE_BUTTON (widget
)) {
2734 G_CALLBACK (object_changed
), editor
);
2739 changed_object
, "changed",
2740 G_CALLBACK (object_changed
), editor
);
2744 fill_in_simple_field (EContactEditor
*editor
,
2750 contact
= editor
->priv
->contact
;
2752 g_signal_handlers_block_matched (
2753 widget
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, editor
);
2755 if (GTK_IS_ENTRY (widget
)) {
2756 gchar
*text
= e_contact_get (contact
, field_id
);
2757 gtk_entry_set_text (GTK_ENTRY (widget
), STRING_MAKE_NON_NULL (text
));
2760 } else if (GTK_IS_COMBO_BOX (widget
)) {
2761 gchar
*text
= e_contact_get (contact
, field_id
);
2762 gtk_entry_set_text (
2763 GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget
))),
2764 STRING_MAKE_NON_NULL (text
));
2767 } else if (GTK_IS_TEXT_VIEW (widget
)) {
2768 GtkTextBuffer
*buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget
));
2769 gchar
*text
= e_contact_get (contact
, field_id
);
2770 gtk_text_buffer_set_text (buffer
, STRING_MAKE_NON_NULL (text
), -1);
2773 } else if (E_IS_URL_ENTRY (widget
)) {
2774 gchar
*text
= e_contact_get (contact
, field_id
);
2775 gtk_entry_set_text (
2776 GTK_ENTRY (widget
), STRING_MAKE_NON_NULL (text
));
2779 } else if (E_IS_DATE_EDIT (widget
)) {
2780 EContactDate
*date
= e_contact_get (contact
, field_id
);
2782 e_date_edit_set_date (
2783 E_DATE_EDIT (widget
),
2784 date
->year
, date
->month
, date
->day
);
2786 e_date_edit_set_time (E_DATE_EDIT (widget
), -1);
2788 e_contact_date_free (date
);
2790 } else if (E_IS_IMAGE_CHOOSER (widget
)) {
2791 EContactPhoto
*photo
= e_contact_get (contact
, field_id
);
2792 editor
->priv
->image_set
= FALSE
;
2793 if (photo
&& photo
->type
== E_CONTACT_PHOTO_TYPE_INLINED
) {
2794 e_image_chooser_set_image_data (
2795 E_IMAGE_CHOOSER (widget
),
2796 (gchar
*) photo
->data
.inlined
.data
,
2797 photo
->data
.inlined
.length
);
2798 editor
->priv
->image_set
= TRUE
;
2799 } else if (photo
&& photo
->type
== E_CONTACT_PHOTO_TYPE_URI
) {
2800 gchar
*file_name
= g_filename_from_uri (photo
->data
.uri
, NULL
, NULL
);
2802 e_image_chooser_set_from_file (
2803 E_IMAGE_CHOOSER (widget
),
2805 editor
->priv
->image_set
= TRUE
;
2810 if (!editor
->priv
->image_set
) {
2813 file_name
= e_icon_factory_get_icon_filename (
2814 "avatar-default", GTK_ICON_SIZE_DIALOG
);
2815 e_image_chooser_set_from_file (
2816 E_IMAGE_CHOOSER (widget
), file_name
);
2817 editor
->priv
->image_set
= FALSE
;
2821 editor
->priv
->image_changed
= FALSE
;
2822 e_contact_photo_free (photo
);
2824 } else if (GTK_IS_TOGGLE_BUTTON (widget
)) {
2825 gboolean val
= e_contact_get (contact
, field_id
) != NULL
;
2827 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget
), val
);
2830 g_warning (G_STRLOC
": Unhandled widget class in mappings!");
2833 g_signal_handlers_unblock_matched (
2834 widget
, G_SIGNAL_MATCH_DATA
, 0, 0, NULL
, NULL
, editor
);
2838 extract_simple_field (EContactEditor
*editor
,
2844 contact
= editor
->priv
->contact
;
2846 if (GTK_IS_ENTRY (widget
)) {
2847 const gchar
*text
= gtk_entry_get_text (GTK_ENTRY (widget
));
2848 e_contact_set (contact
, field_id
, (gchar
*) text
);
2850 } else if (GTK_IS_COMBO_BOX_TEXT (widget
)) {
2853 if (gtk_combo_box_get_has_entry (GTK_COMBO_BOX (widget
))) {
2854 GtkWidget
*entry
= gtk_bin_get_child (GTK_BIN (widget
));
2856 text
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
2860 text
= gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (widget
));
2862 e_contact_set (contact
, field_id
, text
);
2865 } else if (GTK_IS_COMBO_BOX (widget
)) {
2869 if (gtk_combo_box_get_has_entry (GTK_COMBO_BOX (widget
))) {
2870 GtkWidget
*entry
= gtk_bin_get_child (GTK_BIN (widget
));
2872 text
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
2875 if (!text
&& gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget
), &iter
)) {
2876 GtkListStore
*store
;
2878 store
= GTK_LIST_STORE (
2879 gtk_combo_box_get_model (
2880 GTK_COMBO_BOX (widget
)));
2882 gtk_tree_model_get (
2883 GTK_TREE_MODEL (store
), &iter
,
2888 e_contact_set (contact
, field_id
, text
);
2892 } else if (GTK_IS_TEXT_VIEW (widget
)) {
2893 GtkTextBuffer
*buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget
));
2894 GtkTextIter start
, end
;
2897 gtk_text_buffer_get_start_iter (buffer
, &start
);
2898 gtk_text_buffer_get_end_iter (buffer
, &end
);
2899 text
= gtk_text_buffer_get_text (buffer
, &start
, &end
, FALSE
);
2900 e_contact_set (contact
, field_id
, text
);
2903 } else if (E_IS_URL_ENTRY (widget
)) {
2904 const gchar
*text
= gtk_entry_get_text (GTK_ENTRY (widget
));
2905 e_contact_set (contact
, field_id
, (gchar
*) text
);
2907 } else if (E_IS_DATE_EDIT (widget
)) {
2909 if (e_date_edit_get_date (
2910 E_DATE_EDIT (widget
),
2911 (gint
*) &date
.year
,
2912 (gint
*) &date
.month
,
2913 (gint
*) &date
.day
))
2914 e_contact_set (contact
, field_id
, &date
);
2916 e_contact_set (contact
, field_id
, NULL
);
2918 } else if (E_IS_IMAGE_CHOOSER (widget
)) {
2919 EContactPhoto photo
;
2920 photo
.type
= E_CONTACT_PHOTO_TYPE_INLINED
;
2921 photo
.data
.inlined
.mime_type
= NULL
;
2922 if (editor
->priv
->image_changed
) {
2923 gchar
*img_buff
= NULL
;
2924 if (editor
->priv
->image_set
&&
2925 e_image_chooser_get_image_data (
2926 E_IMAGE_CHOOSER (widget
),
2927 &img_buff
, &photo
.data
.inlined
.length
)) {
2928 GdkPixbuf
*pixbuf
, *new;
2929 GdkPixbufLoader
*loader
= gdk_pixbuf_loader_new ();
2931 photo
.data
.inlined
.data
= (guchar
*) img_buff
;
2933 gdk_pixbuf_loader_write (
2935 photo
.data
.inlined
.data
,
2936 photo
.data
.inlined
.length
, NULL
);
2937 gdk_pixbuf_loader_close (loader
, NULL
);
2939 pixbuf
= gdk_pixbuf_loader_get_pixbuf (loader
);
2941 gint width
, height
, prompt_response
;
2943 g_object_ref (pixbuf
);
2945 height
= gdk_pixbuf_get_height (pixbuf
);
2946 width
= gdk_pixbuf_get_width (pixbuf
);
2947 if ((height
> 96 || width
> 96)) {
2950 e_alert_run_dialog_for_args
2951 (GTK_WINDOW (editor
->priv
->app
),
2952 "addressbook:prompt-resize",
2955 if (prompt_response
== GTK_RESPONSE_YES
) {
2956 if (width
> height
) {
2957 height
= height
* 96 / width
;
2960 width
= width
*96 / height
;
2964 new = e_icon_factory_pixbuf_scale (pixbuf
, width
, height
);
2966 GdkPixbufFormat
*format
=
2967 gdk_pixbuf_loader_get_format (loader
);
2968 gchar
*format_name
=
2969 gdk_pixbuf_format_get_name (format
);
2970 g_free (photo
.data
.inlined
.data
);
2971 gdk_pixbuf_save_to_buffer (
2973 &photo
.data
.inlined
.length
,
2974 format_name
, NULL
, NULL
);
2975 photo
.data
.inlined
.data
= (guchar
*) img_buff
;
2977 g_free (format_name
);
2978 g_object_unref (new);
2980 } else if (prompt_response
== GTK_RESPONSE_CANCEL
) {
2981 g_object_unref (pixbuf
);
2982 g_object_unref (loader
);
2986 g_object_unref (pixbuf
);
2988 editor
->priv
->image_changed
= FALSE
;
2989 g_object_unref (loader
);
2991 e_contact_set (contact
, field_id
, &photo
);
2993 g_free (photo
.data
.inlined
.data
);
2996 editor
->priv
->image_changed
= FALSE
;
2997 e_contact_set (contact
, E_CONTACT_PHOTO
, NULL
);
3001 } else if (GTK_IS_TOGGLE_BUTTON (widget
)) {
3004 val
= gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget
));
3005 e_contact_set (contact
, field_id
, val
? (gpointer
) 1 : NULL
);
3008 g_warning (G_STRLOC
": Unhandled widget class in mappings!");
3013 sensitize_simple_field (GtkWidget
*widget
,
3016 if (GTK_IS_ENTRY (widget
))
3017 gtk_editable_set_editable (GTK_EDITABLE (widget
), enabled
);
3018 else if (GTK_IS_TEXT_VIEW (widget
))
3019 gtk_text_view_set_editable (GTK_TEXT_VIEW (widget
), enabled
);
3020 else if (E_IS_DATE_EDIT (widget
))
3021 e_date_edit_set_editable (E_DATE_EDIT (widget
), enabled
);
3023 gtk_widget_set_sensitive (widget
, enabled
);
3027 init_simple (EContactEditor
*editor
)
3032 for (i
= 0; i
< G_N_ELEMENTS (simple_field_map
); i
++) {
3033 widget
= e_builder_get_widget (
3034 editor
->priv
->builder
, simple_field_map
[i
].widget_name
);
3038 init_simple_field (editor
, widget
);
3041 /* --- Special cases --- */
3043 /* Update file_as */
3045 widget
= e_builder_get_widget (editor
->priv
->builder
, "entry-fullname");
3048 G_CALLBACK (name_entry_changed
), editor
);
3050 widget
= e_builder_get_widget (editor
->priv
->builder
, "combo-file-as");
3051 gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (widget
), 0);
3054 G_CALLBACK (file_as_combo_changed
), editor
);
3056 widget
= e_builder_get_widget (editor
->priv
->builder
, "entry-company");
3059 G_CALLBACK (company_entry_changed
), editor
);
3063 fill_in_simple (EContactEditor
*editor
)
3069 for (i
= 0; i
< G_N_ELEMENTS (simple_field_map
); i
++) {
3072 if (simple_field_map
[i
].field_id
< 0 ||
3073 !simple_field_map
[i
].process_data
)
3076 widget
= e_builder_get_widget (
3077 editor
->priv
->builder
, simple_field_map
[i
].widget_name
);
3081 fill_in_simple_field (
3082 editor
, widget
, simple_field_map
[i
].field_id
);
3085 /* --- Special cases --- */
3087 /* Update broken-up name */
3089 g_object_get (editor
->priv
->contact
, "name", &name
, NULL
);
3091 if (editor
->priv
->name
)
3092 e_contact_name_free (editor
->priv
->name
);
3094 editor
->priv
->name
= name
;
3096 /* Update the contact editor title */
3098 filename
= (gchar
*) e_contact_get (editor
->priv
->contact
, E_CONTACT_FILE_AS
);
3102 title
= g_strdup_printf (_("Contact Editor — %s"), filename
);
3103 gtk_window_set_title (GTK_WINDOW (editor
->priv
->app
), title
);
3107 gtk_window_set_title (
3108 GTK_WINDOW (editor
->priv
->app
), _("Contact Editor"));
3110 /* Update file_as combo options */
3112 update_file_as_combo (editor
);
3116 extract_simple (EContactEditor
*editor
)
3120 for (i
= 0; i
< G_N_ELEMENTS (simple_field_map
); i
++) {
3123 if (simple_field_map
[i
].field_id
< 0 ||
3124 !simple_field_map
[i
].process_data
)
3127 widget
= e_builder_get_widget (
3128 editor
->priv
->builder
, simple_field_map
[i
].widget_name
);
3132 extract_simple_field (
3133 editor
, widget
, simple_field_map
[i
].field_id
);
3138 e_contact_set (editor
->priv
->contact
, E_CONTACT_NAME
, editor
->priv
->name
);
3142 sensitize_simple (EContactEditor
*editor
)
3146 for (i
= 0; i
< G_N_ELEMENTS (simple_field_map
); i
++) {
3148 gboolean enabled
= TRUE
;
3150 widget
= e_builder_get_widget (
3151 editor
->priv
->builder
, simple_field_map
[i
].widget_name
);
3155 if (simple_field_map
[i
].field_id
>= 0 &&
3156 !is_field_supported (editor
, simple_field_map
[i
].field_id
))
3159 if (simple_field_map
[i
].desensitize_for_read_only
&&
3160 !editor
->priv
->target_editable
)
3163 sensitize_simple_field (widget
, enabled
);
3173 CERT_COLUMN_SUBJECT_STRING
,
3174 CERT_COLUMN_KIND_STRING
,
3175 CERT_COLUMN_KIND_INT
,
3176 CERT_COLUMN_DATA_ECONTACTCERT
,
3177 CERT_COLUMN_CERT_GCRCERTIFICATE
,
3182 cert_tab_selection_changed_cb (GtkTreeSelection
*selection
,
3183 EContactEditor
*editor
)
3186 GtkTreeModel
*model
;
3188 gboolean has_selected
;
3190 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3192 has_selected
= gtk_tree_selection_get_selected (selection
, &model
, &iter
);
3194 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-remove-btn");
3195 gtk_widget_set_sensitive (widget
, has_selected
);
3197 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-load-pgp-btn");
3198 gtk_widget_set_sensitive (widget
, has_selected
&& is_field_supported (editor
, E_CONTACT_PGP_CERT
));
3200 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-load-x509-btn");
3201 gtk_widget_set_sensitive (widget
, has_selected
&& is_field_supported (editor
, E_CONTACT_X509_CERT
));
3203 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-save-btn");
3204 gtk_widget_set_sensitive (widget
, has_selected
);
3206 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-preview-scw");
3207 widget
= gtk_bin_get_child (GTK_BIN (widget
));
3209 if (GTK_IS_VIEWPORT (widget
))
3210 widget
= gtk_bin_get_child (GTK_BIN (widget
));
3212 g_return_if_fail (GCR_IS_CERTIFICATE_WIDGET (widget
));
3215 GcrCertificate
*cert
= NULL
;
3217 gtk_tree_model_get (model
, &iter
, CERT_COLUMN_CERT_GCRCERTIFICATE
, &cert
, -1);
3219 gcr_certificate_widget_set_certificate (GCR_CERTIFICATE_WIDGET (widget
), cert
);
3221 g_clear_object (&cert
);
3223 gcr_certificate_widget_set_certificate (GCR_CERTIFICATE_WIDGET (widget
), NULL
);
3228 cert_add_filters_for_kind (GtkFileChooser
*file_chooser
,
3231 GtkFileFilter
*filter
;
3233 g_return_if_fail (GTK_IS_FILE_CHOOSER (file_chooser
));
3234 g_return_if_fail (kind
== CERT_KIND_PGP
|| kind
== CERT_KIND_X509
);
3236 if (kind
== CERT_KIND_X509
) {
3237 filter
= gtk_file_filter_new ();
3238 gtk_file_filter_set_name (filter
, _("X.509 certificates"));
3239 gtk_file_filter_add_mime_type (filter
, "application/x-x509-user-cert");
3240 gtk_file_chooser_add_filter (file_chooser
, filter
);
3242 filter
= gtk_file_filter_new ();
3243 gtk_file_filter_set_name (filter
, _("PGP keys"));
3244 gtk_file_filter_add_mime_type (filter
, "application/pgp-keys");
3245 gtk_file_chooser_add_filter (file_chooser
, filter
);
3248 filter
= gtk_file_filter_new ();
3249 gtk_file_filter_set_name (filter
, _("All files"));
3250 gtk_file_filter_add_pattern (filter
, "*");
3251 gtk_file_chooser_add_filter (file_chooser
, filter
);
3254 static EContactCert
*
3255 cert_load_for_kind (EContactEditor
*editor
,
3258 EContactCert
*cert
= NULL
;
3261 GtkFileChooser
*file_chooser
;
3262 GError
*error
= NULL
;
3264 g_return_val_if_fail (E_IS_CONTACT_EDITOR (editor
), NULL
);
3265 g_return_val_if_fail (kind
== CERT_KIND_PGP
|| kind
== CERT_KIND_X509
, NULL
);
3267 parent
= eab_editor_get_window (EAB_EDITOR (editor
));
3268 dialog
= gtk_file_chooser_dialog_new (
3269 kind
== CERT_KIND_PGP
? _("Open PGP key") : _("Open X.509 certificate"), parent
,
3270 GTK_FILE_CHOOSER_ACTION_OPEN
,
3271 _("_Cancel"), GTK_RESPONSE_CANCEL
,
3272 _("_Open"), GTK_RESPONSE_OK
,
3275 file_chooser
= GTK_FILE_CHOOSER (dialog
);
3276 gtk_file_chooser_set_local_only (file_chooser
, TRUE
);
3277 gtk_file_chooser_set_select_multiple (file_chooser
, FALSE
);
3278 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
3280 cert_add_filters_for_kind (file_chooser
, kind
);
3282 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_OK
) {
3284 gchar
*content
= NULL
;
3287 filename
= gtk_file_chooser_get_filename (file_chooser
);
3289 g_set_error_literal (&error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
, _("Chosen file is not a local file."));
3290 } else if (g_file_get_contents (filename
, &content
, &length
, &error
) && length
> 0) {
3291 cert
= e_contact_cert_new ();
3292 cert
->length
= length
;
3293 cert
->data
= content
;
3299 gtk_widget_destroy (dialog
);
3302 e_notice (parent
, GTK_MESSAGE_ERROR
, _("Failed to load certificate: %s"), error
->message
);
3303 g_clear_error (&error
);
3310 cert_update_row_with_cert (GtkListStore
*list_store
,
3315 GcrCertificate
*gcr_cert
= NULL
;
3316 gchar
*subject
= NULL
;
3318 g_return_if_fail (GTK_IS_LIST_STORE (list_store
));
3319 g_return_if_fail (iter
!= NULL
);
3320 g_return_if_fail (cert
!= NULL
);
3321 g_return_if_fail (kind
== CERT_KIND_PGP
|| kind
== CERT_KIND_X509
);
3323 if (kind
== CERT_KIND_X509
) {
3324 gcr_cert
= gcr_simple_certificate_new ((const guchar
*) cert
->data
, cert
->length
);
3326 subject
= gcr_certificate_get_subject_name (gcr_cert
);
3329 gtk_list_store_set (list_store
, iter
,
3330 CERT_COLUMN_SUBJECT_STRING
, subject
,
3331 CERT_COLUMN_KIND_STRING
, kind
== CERT_KIND_X509
? C_("cert-kind", "X.509") : C_("cert-kind", "PGP"),
3332 CERT_COLUMN_KIND_INT
, kind
,
3333 CERT_COLUMN_DATA_ECONTACTCERT
, cert
,
3334 CERT_COLUMN_CERT_GCRCERTIFICATE
, gcr_cert
,
3337 g_clear_object (&gcr_cert
);
3342 cert_add_kind (EContactEditor
*editor
,
3345 GtkTreeView
*tree_view
;
3346 GtkTreeSelection
*selection
;
3347 GtkTreeModel
*model
;
3351 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3352 g_return_if_fail (kind
== CERT_KIND_PGP
|| kind
== CERT_KIND_X509
);
3354 tree_view
= GTK_TREE_VIEW (e_builder_get_widget (editor
->priv
->builder
, "certs-treeview"));
3355 g_return_if_fail (tree_view
!= NULL
);
3357 model
= gtk_tree_view_get_model (tree_view
);
3358 selection
= gtk_tree_view_get_selection (tree_view
);
3360 cert
= cert_load_for_kind (editor
, kind
);
3362 gtk_list_store_append (GTK_LIST_STORE (model
), &iter
);
3363 cert_update_row_with_cert (GTK_LIST_STORE (model
), &iter
, cert
, kind
);
3364 e_contact_cert_free (cert
);
3366 gtk_tree_selection_select_iter (selection
, &iter
);
3368 object_changed (G_OBJECT (tree_view
), editor
);
3373 cert_add_pgp_btn_clicked_cb (GtkWidget
*button
,
3374 EContactEditor
*editor
)
3376 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3378 cert_add_kind (editor
, CERT_KIND_PGP
);
3382 cert_add_x509_btn_clicked_cb (GtkWidget
*button
,
3383 EContactEditor
*editor
)
3385 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3387 cert_add_kind (editor
, CERT_KIND_X509
);
3391 cert_remove_btn_clicked_cb (GtkWidget
*button
,
3392 EContactEditor
*editor
)
3394 GtkTreeView
*tree_view
;
3395 GtkTreeSelection
*selection
;
3396 GtkTreeModel
*model
;
3397 GtkTreeIter iter
, select
;
3398 gboolean have_select
;
3400 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3402 tree_view
= GTK_TREE_VIEW (e_builder_get_widget (editor
->priv
->builder
, "certs-treeview"));
3403 g_return_if_fail (tree_view
!= NULL
);
3405 selection
= gtk_tree_view_get_selection (tree_view
);
3406 g_return_if_fail (gtk_tree_selection_get_selected (selection
, &model
, &iter
));
3409 have_select
= gtk_tree_model_iter_next (model
, &select
);
3412 have_select
= gtk_tree_model_iter_previous (model
, &select
);
3416 gtk_tree_selection_select_iter (selection
, &select
);
3418 gtk_list_store_remove (GTK_LIST_STORE (model
), &iter
);
3420 object_changed (G_OBJECT (tree_view
), editor
);
3424 cert_load_kind (EContactEditor
*editor
,
3427 GtkTreeView
*tree_view
;
3428 GtkTreeSelection
*selection
;
3429 GtkTreeModel
*model
;
3433 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3434 g_return_if_fail (kind
== CERT_KIND_PGP
|| kind
== CERT_KIND_X509
);
3436 tree_view
= GTK_TREE_VIEW (e_builder_get_widget (editor
->priv
->builder
, "certs-treeview"));
3437 g_return_if_fail (tree_view
!= NULL
);
3439 selection
= gtk_tree_view_get_selection (tree_view
);
3440 g_return_if_fail (gtk_tree_selection_get_selected (selection
, &model
, &iter
));
3442 cert
= cert_load_for_kind (editor
, kind
);
3444 cert_update_row_with_cert (GTK_LIST_STORE (model
), &iter
, cert
, kind
);
3445 e_contact_cert_free (cert
);
3447 object_changed (G_OBJECT (tree_view
), editor
);
3452 cert_load_pgp_btn_clicked_cb (GtkWidget
*button
,
3453 EContactEditor
*editor
)
3455 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3457 cert_load_kind (editor
, CERT_KIND_PGP
);
3461 cert_load_x509_btn_clicked_cb (GtkWidget
*button
,
3462 EContactEditor
*editor
)
3464 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3466 cert_load_kind (editor
, CERT_KIND_X509
);
3470 cert_save_btn_clicked_cb (GtkWidget
*button
,
3471 EContactEditor
*editor
)
3473 GtkTreeView
*tree_view
;
3474 GtkTreeSelection
*selection
;
3475 GtkTreeModel
*model
;
3477 EContactCert
*cert
= NULL
;
3481 GtkFileChooser
*file_chooser
;
3482 GError
*error
= NULL
;
3484 g_return_if_fail (E_IS_CONTACT_EDITOR (editor
));
3486 tree_view
= GTK_TREE_VIEW (e_builder_get_widget (editor
->priv
->builder
, "certs-treeview"));
3487 g_return_if_fail (tree_view
!= NULL
);
3489 selection
= gtk_tree_view_get_selection (tree_view
);
3490 g_return_if_fail (gtk_tree_selection_get_selected (selection
, &model
, &iter
));
3492 gtk_tree_model_get (model
, &iter
,
3493 CERT_COLUMN_KIND_INT
, &kind
,
3494 CERT_COLUMN_DATA_ECONTACTCERT
, &cert
,
3497 g_return_if_fail (kind
== CERT_KIND_X509
|| kind
== CERT_KIND_PGP
);
3498 g_return_if_fail (cert
!= NULL
);
3500 parent
= eab_editor_get_window (EAB_EDITOR (editor
));
3501 dialog
= gtk_file_chooser_dialog_new (
3502 kind
== CERT_KIND_PGP
? _("Save PGP key") : _("Save X.509 certificate"), parent
,
3503 GTK_FILE_CHOOSER_ACTION_SAVE
,
3504 _("_Cancel"), GTK_RESPONSE_CANCEL
,
3505 _("_Save"), GTK_RESPONSE_OK
,
3508 file_chooser
= GTK_FILE_CHOOSER (dialog
);
3509 gtk_file_chooser_set_local_only (file_chooser
, TRUE
);
3510 gtk_file_chooser_set_select_multiple (file_chooser
, FALSE
);
3511 gtk_dialog_set_default_response (GTK_DIALOG (dialog
), GTK_RESPONSE_OK
);
3513 cert_add_filters_for_kind (file_chooser
, kind
);
3515 if (gtk_dialog_run (GTK_DIALOG (dialog
)) == GTK_RESPONSE_OK
) {
3518 filename
= gtk_file_chooser_get_filename (file_chooser
);
3520 g_set_error_literal (&error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
, _("Chosen file is not a local file."));
3522 g_file_set_contents (filename
, cert
->data
, cert
->length
, &error
);
3528 gtk_widget_destroy (dialog
);
3529 e_contact_cert_free (cert
);
3532 e_notice (parent
, GTK_MESSAGE_ERROR
, _("Failed to save certificate: %s"), error
->message
);
3533 g_clear_error (&error
);
3538 init_certs (EContactEditor
*editor
)
3540 GtkListStore
*list_store
;
3541 GtkTreeView
*tree_view
;
3542 GtkTreeViewColumn
*column
;
3543 GtkTreeSelection
*selection
;
3544 GtkCellRenderer
*renderer
;
3545 GcrCertificateWidget
*certificate_widget
;
3548 tree_view
= GTK_TREE_VIEW (e_builder_get_widget (editor
->priv
->builder
, "certs-treeview"));
3549 g_return_if_fail (tree_view
!= NULL
);
3551 gtk_tree_view_set_headers_visible (tree_view
, FALSE
);
3553 column
= gtk_tree_view_column_new ();
3554 gtk_tree_view_append_column (tree_view
, column
);
3556 renderer
= gtk_cell_renderer_text_new ();
3557 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
3558 gtk_tree_view_column_add_attribute (column
, renderer
, "text", CERT_COLUMN_KIND_STRING
);
3560 column
= gtk_tree_view_column_new ();
3561 gtk_tree_view_column_set_expand (column
, TRUE
);
3562 gtk_tree_view_append_column (tree_view
, column
);
3564 renderer
= gtk_cell_renderer_text_new ();
3565 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
3566 gtk_tree_view_column_add_attribute (column
, renderer
, "text", CERT_COLUMN_SUBJECT_STRING
);
3568 list_store
= gtk_list_store_new (N_CERT_COLUMNS
,
3569 G_TYPE_STRING
, /* CERT_COLUMN_SUBJECT_STRING */
3570 G_TYPE_STRING
, /* CERT_COLUMN_KIND_STRING */
3571 G_TYPE_INT
, /* CERT_COLUMN_KIND_INT */
3572 E_TYPE_CONTACT_CERT
, /* CERT_COLUMN_DATA_ECONTACTCERT */
3573 GCR_TYPE_CERTIFICATE
); /* CERT_COLUMN_CERT_GCRCERTIFICATE */
3575 gtk_tree_view_set_model (tree_view
, GTK_TREE_MODEL (list_store
));
3577 certificate_widget
= gcr_certificate_widget_new (NULL
);
3578 gtk_widget_show (GTK_WIDGET (certificate_widget
));
3579 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-preview-scw");
3580 gtk_container_add (GTK_CONTAINER (widget
), GTK_WIDGET (certificate_widget
));
3582 selection
= gtk_tree_view_get_selection (tree_view
);
3583 gtk_tree_selection_set_mode (selection
, GTK_SELECTION_SINGLE
);
3584 g_signal_connect (selection
, "changed", G_CALLBACK (cert_tab_selection_changed_cb
), editor
);
3586 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-add-pgp-btn");
3587 g_signal_connect (widget
, "clicked", G_CALLBACK (cert_add_pgp_btn_clicked_cb
), editor
);
3589 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-add-x509-btn");
3590 g_signal_connect (widget
, "clicked", G_CALLBACK (cert_add_x509_btn_clicked_cb
), editor
);
3592 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-remove-btn");
3593 g_signal_connect (widget
, "clicked", G_CALLBACK (cert_remove_btn_clicked_cb
), editor
);
3595 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-load-pgp-btn");
3596 g_signal_connect (widget
, "clicked", G_CALLBACK (cert_load_pgp_btn_clicked_cb
), editor
);
3598 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-load-x509-btn");
3599 g_signal_connect (widget
, "clicked", G_CALLBACK (cert_load_x509_btn_clicked_cb
), editor
);
3601 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-save-btn");
3602 g_signal_connect (widget
, "clicked", G_CALLBACK (cert_save_btn_clicked_cb
), editor
);
3606 fill_in_certs (EContactEditor
*editor
)
3608 GtkTreeModel
*model
;
3609 GtkListStore
*list_store
;
3611 GList
*attrs
, *link
;
3615 widget
= e_builder_get_widget (editor
->priv
->builder
, "certs-treeview");
3616 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (widget
));
3617 list_store
= GTK_LIST_STORE (model
);
3621 gtk_list_store_clear (list_store
);
3625 attrs
= e_vcard_get_attributes (E_VCARD (editor
->priv
->contact
));
3626 for (link
= attrs
; link
; link
= g_list_next (link
)) {
3627 EVCardAttribute
*attr
= link
->data
;
3632 if (e_vcard_attribute_has_type (attr
, "X509"))
3633 kind
= CERT_KIND_X509
;
3634 else if (e_vcard_attribute_has_type (attr
, "PGP"))
3635 kind
= CERT_KIND_PGP
;
3639 value
= e_vcard_attribute_get_value_decoded (attr
);
3640 if (!value
|| !value
->len
) {
3642 g_string_free (value
, TRUE
);
3646 cert
= e_contact_cert_new ();
3647 cert
->length
= value
->len
;
3648 cert
->data
= g_malloc (cert
->length
);
3649 memcpy (cert
->data
, value
->str
, cert
->length
);
3651 gtk_list_store_append (list_store
, &iter
);
3653 cert_update_row_with_cert (list_store
, &iter
, cert
, kind
);
3655 e_contact_cert_free (cert
);
3656 g_string_free (value
, TRUE
);
3659 if (gtk_tree_model_get_iter_first (model
, &iter
)) {
3660 GtkTreeSelection
*selection
;
3662 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (widget
));
3663 gtk_tree_selection_select_iter (selection
, &iter
);
3668 extract_certs_for_kind (EContactEditor
*editor
,
3670 EContactField field
,
3671 GtkTreeModel
*model
)
3676 GList
*attrs
= NULL
, *link
;
3678 if (is_field_supported (editor
, field
)) {
3679 valid
= gtk_tree_model_get_iter_first (model
, &iter
);
3681 EContactCert
*cert
= NULL
;
3684 gtk_tree_model_get (model
, &iter
,
3685 CERT_COLUMN_KIND_INT
, &set_kind
,
3686 CERT_COLUMN_DATA_ECONTACTCERT
, &cert
,
3689 if (cert
&& set_kind
== kind
) {
3690 EVCardAttribute
*attr
;
3692 attr
= e_vcard_attribute_new ("", e_contact_vcard_attribute (field
));
3693 e_vcard_attribute_add_param_with_value (
3694 attr
, e_vcard_attribute_param_new (EVC_TYPE
),
3695 field
== E_CONTACT_X509_CERT
? "X509" : "PGP");
3696 e_vcard_attribute_add_param_with_value (
3698 e_vcard_attribute_param_new (EVC_ENCODING
),
3701 e_vcard_attribute_add_value_decoded (attr
, cert
->data
, cert
->length
);
3703 attrs
= g_list_prepend (attrs
, attr
);
3706 e_contact_cert_free (cert
);
3708 valid
= gtk_tree_model_iter_next (model
, &iter
);
3712 attrs
= g_list_reverse (attrs
);
3714 vcard
= E_VCARD (editor
->priv
->contact
);
3716 for (link
= attrs
; link
; link
= g_list_next (link
)) {
3717 /* takes ownership of the attribute */
3718 e_vcard_append_attribute (vcard
, link
->data
);
3721 g_list_free (attrs
);
3725 extract_certs (EContactEditor
*editor
)
3728 GtkTreeModel
*model
;
3729 GList
*attrs
, *link
;
3732 widget
= e_builder_get_widget (editor
->priv
->builder
, "certs-treeview");
3733 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (widget
));
3735 vcard
= E_VCARD (editor
->priv
->contact
);
3736 attrs
= g_list_copy (e_vcard_get_attributes (vcard
));
3738 for (link
= attrs
; link
; link
= g_list_next (link
)) {
3739 EVCardAttribute
*attr
= link
->data
;
3741 /* Remove only those types the editor can work with. */
3742 if ((!e_vcard_attribute_get_name (attr
) ||
3743 g_ascii_strcasecmp (EVC_KEY
, e_vcard_attribute_get_name (attr
)) == 0) &&
3744 (e_vcard_attribute_has_type (attr
, "X509") ||
3745 e_vcard_attribute_has_type (attr
, "PGP"))) {
3746 e_vcard_remove_attribute (vcard
, attr
);
3750 g_list_free (attrs
);
3752 /* The saved order will always be X.509 first, then PGP */
3753 extract_certs_for_kind (editor
, CERT_KIND_X509
, E_CONTACT_X509_CERT
, model
);
3754 extract_certs_for_kind (editor
, CERT_KIND_PGP
, E_CONTACT_PGP_CERT
, model
);
3758 sensitize_certs (EContactEditor
*editor
)
3762 widget
= e_builder_get_widget (editor
->priv
->builder
, "certs-grid");
3764 gtk_widget_set_sensitive (widget
, editor
->priv
->target_editable
&& (
3765 is_field_supported (editor
, E_CONTACT_X509_CERT
) ||
3766 is_field_supported (editor
, E_CONTACT_PGP_CERT
)));
3768 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-add-pgp-btn");
3769 gtk_widget_set_sensitive (widget
, is_field_supported (editor
, E_CONTACT_PGP_CERT
));
3771 widget
= e_builder_get_widget (editor
->priv
->builder
, "cert-add-x509-btn");
3772 gtk_widget_set_sensitive (widget
, is_field_supported (editor
, E_CONTACT_X509_CERT
));
3774 widget
= e_builder_get_widget (editor
->priv
->builder
, "certs-treeview");
3775 cert_tab_selection_changed_cb (gtk_tree_view_get_selection (GTK_TREE_VIEW (widget
)), editor
);
3779 fill_in_all (EContactEditor
*editor
)
3781 GtkWidget
*focused_widget
;
3782 gpointer weak_pointer
;
3784 /* Widget changes can cause focus widget change, thus remember the current
3785 widget and restore it after the fill is done; some fill operations
3786 can delete widgets, like the dyntable, thus do the weak_pointer as well.
3788 focused_widget
= gtk_window_get_focus (eab_editor_get_window (EAB_EDITOR (editor
)));
3789 weak_pointer
= focused_widget
;
3791 g_object_add_weak_pointer (G_OBJECT (focused_widget
), &weak_pointer
);
3793 fill_in_source_field (editor
);
3794 fill_in_simple (editor
);
3795 fill_in_email (editor
);
3796 fill_in_phone (editor
);
3797 fill_in_sip (editor
);
3798 fill_in_im (editor
);
3799 fill_in_address (editor
);
3800 fill_in_certs (editor
);
3802 /* Visibility of sections and status of menuitems in the config-menu depend on data
3803 * they have to be initialized here instead of init_all() and sensitize_all()
3805 configure_visibility (editor
);
3806 config_sensitize_cb (NULL
, editor
);
3809 g_object_remove_weak_pointer (G_OBJECT (focused_widget
), &weak_pointer
);
3810 gtk_widget_grab_focus (focused_widget
);
3815 extract_all (EContactEditor
*editor
)
3817 extract_simple (editor
);
3818 extract_email (editor
);
3819 extract_phone (editor
);
3820 extract_sip (editor
);
3821 extract_im (editor
);
3822 extract_address (editor
);
3823 extract_certs (editor
);
3827 sensitize_all (EContactEditor
*editor
)
3829 GtkWidget
*focused_widget
;
3830 gpointer weak_pointer
;
3832 /* Widget changes can cause focus widget change, thus remember the current
3833 widget and restore it after the fill is done; some fill operations
3834 can delete widgets, like the dyntable, thus do the weak_pointer as well.
3836 focused_widget
= gtk_window_get_focus (eab_editor_get_window (EAB_EDITOR (editor
)));
3837 weak_pointer
= focused_widget
;
3839 g_object_add_weak_pointer (G_OBJECT (focused_widget
), &weak_pointer
);
3841 sensitize_ok (editor
);
3842 sensitize_simple (editor
);
3843 sensitize_email (editor
);
3844 sensitize_phone (editor
);
3845 sensitize_sip (editor
);
3846 sensitize_im (editor
);
3847 sensitize_address (editor
);
3848 sensitize_certs (editor
);
3851 g_object_remove_weak_pointer (G_OBJECT (focused_widget
), &weak_pointer
);
3852 gtk_widget_grab_focus (focused_widget
);
3857 init_personal (EContactEditor
*editor
)
3859 gtk_expander_set_expanded (
3860 GTK_EXPANDER (e_builder_get_widget (editor
->priv
->builder
, "expander-personal-web")),
3861 !editor
->priv
->compress_ui
);
3862 gtk_expander_set_expanded (
3863 GTK_EXPANDER (e_builder_get_widget (editor
->priv
->builder
, "expander-personal-job")),
3864 !editor
->priv
->compress_ui
);
3865 gtk_expander_set_expanded (
3866 GTK_EXPANDER (e_builder_get_widget (editor
->priv
->builder
, "expander-personal-misc")),
3867 !editor
->priv
->compress_ui
);
3871 init_all (EContactEditor
*editor
)
3873 const gchar
*contents
[] = { "viewport1", "viewport2", "viewport3", "text-comments" };
3875 GtkRequisition tab_req
, requisition
;
3878 init_simple (editor
);
3879 init_email (editor
);
3880 init_phone (editor
);
3883 init_personal (editor
);
3884 init_address (editor
);
3885 init_certs (editor
);
3886 init_config (editor
);
3888 /* with so many scrolled windows, we need to
3889 * do some manual sizing */
3890 requisition
.width
= -1;
3891 requisition
.height
= -1;
3893 for (ii
= 0; ii
< G_N_ELEMENTS (contents
); ii
++) {
3894 widget
= e_builder_get_widget (editor
->priv
->builder
, contents
[ii
]);
3896 gtk_widget_get_preferred_size (widget
, NULL
, &tab_req
);
3898 if (tab_req
.width
> requisition
.width
)
3899 requisition
.width
= tab_req
.width
;
3900 if (tab_req
.height
> requisition
.height
)
3901 requisition
.height
= tab_req
.height
;
3904 if (requisition
.width
> 0 && requisition
.height
> 0) {
3907 GdkRectangle monitor_area
;
3908 gint x
= 0, y
= 0, monitor
, width
, height
;
3910 window
= e_builder_get_widget (
3911 editor
->priv
->builder
, "contact editor");
3913 gtk_widget_get_preferred_size (window
, &tab_req
, NULL
);
3914 width
= tab_req
.width
- 320 + 24;
3915 height
= tab_req
.height
- 240 + 24;
3917 screen
= gtk_window_get_screen (GTK_WINDOW (window
));
3918 gtk_window_get_position (GTK_WINDOW (window
), &x
, &y
);
3920 monitor
= gdk_screen_get_monitor_at_point (screen
, x
, y
);
3925 if (monitor
>= gdk_screen_get_n_monitors (screen
))
3928 gdk_screen_get_monitor_workarea (screen
, monitor
, &monitor_area
);
3930 if (requisition
.width
> monitor_area
.width
- width
)
3931 requisition
.width
= monitor_area
.width
- width
;
3933 if (requisition
.height
> monitor_area
.height
- height
)
3934 requisition
.height
= monitor_area
.height
- height
;
3936 if (requisition
.width
> 0 && requisition
.height
> 0)
3937 gtk_window_set_default_size (
3938 GTK_WINDOW (window
),
3939 width
+ requisition
.width
,
3940 height
+ requisition
.height
);
3943 widget
= e_builder_get_widget (editor
->priv
->builder
, "text-comments");
3945 e_spell_text_view_attach (GTK_TEXT_VIEW (widget
));
3949 contact_editor_get_client_cb (GObject
*source_object
,
3950 GAsyncResult
*result
,
3953 EClientComboBox
*combo_box
;
3954 ConnectClosure
*closure
= user_data
;
3956 GError
*error
= NULL
;
3958 combo_box
= E_CLIENT_COMBO_BOX (source_object
);
3960 client
= e_client_combo_box_get_client_finish (
3961 combo_box
, result
, &error
);
3965 ((client
!= NULL
) && (error
== NULL
)) ||
3966 ((client
== NULL
) && (error
!= NULL
)));
3968 if (g_error_matches (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
)) {
3969 g_warn_if_fail (client
== NULL
);
3970 g_error_free (error
);
3973 } else if (error
!= NULL
) {
3976 parent
= eab_editor_get_window (EAB_EDITOR (closure
->editor
));
3978 eab_load_error_dialog (
3979 GTK_WIDGET (parent
), NULL
,
3980 closure
->source
, error
);
3982 e_source_combo_box_set_active (
3983 E_SOURCE_COMBO_BOX (combo_box
),
3984 e_client_get_source (E_CLIENT (closure
->editor
->priv
->target_client
)));
3986 g_error_free (error
);
3990 /* FIXME Write a private contact_editor_set_target_client(). */
3991 g_object_set (closure
->editor
, "target_client", client
, NULL
);
3993 g_object_unref (client
);
3996 connect_closure_free (closure
);
4000 source_changed (EClientComboBox
*combo_box
,
4001 EContactEditor
*editor
)
4003 ConnectClosure
*closure
;
4004 ESource
*target_source
;
4005 ESource
*source_source
;
4008 source
= e_source_combo_box_ref_active (
4009 E_SOURCE_COMBO_BOX (combo_box
));
4010 g_return_if_fail (source
!= NULL
);
4012 if (editor
->priv
->cancellable
!= NULL
) {
4013 g_cancellable_cancel (editor
->priv
->cancellable
);
4014 g_object_unref (editor
->priv
->cancellable
);
4015 editor
->priv
->cancellable
= NULL
;
4018 target_source
= e_client_get_source (E_CLIENT (editor
->priv
->target_client
));
4019 source_source
= e_client_get_source (E_CLIENT (editor
->priv
->source_client
));
4021 if (e_source_equal (target_source
, source
))
4024 if (e_source_equal (source_source
, source
)) {
4026 editor
, "target_client",
4027 editor
->priv
->source_client
, NULL
);
4031 editor
->priv
->cancellable
= g_cancellable_new ();
4033 closure
= g_slice_new0 (ConnectClosure
);
4034 closure
->editor
= g_object_ref (editor
);
4035 closure
->source
= g_object_ref (source
);
4037 e_client_combo_box_get_client (
4039 editor
->priv
->cancellable
,
4040 contact_editor_get_client_cb
,
4044 g_object_unref (source
);
4048 full_name_editor_closed_cb (GtkWidget
*widget
,
4051 if (GTK_IS_WIDGET (widget
))
4052 gtk_widget_destroy (widget
);
4056 full_name_response (GtkDialog
*dialog
,
4058 EContactEditor
*editor
)
4061 GtkWidget
*fname_widget
;
4063 gboolean editable
= FALSE
;
4065 g_object_get (dialog
, "editable", &editable
, NULL
);
4067 if (editable
&& response
== GTK_RESPONSE_OK
) {
4068 g_object_get (dialog
, "name", &name
, NULL
);
4070 style
= file_as_get_style (editor
);
4072 fname_widget
= e_builder_get_widget (
4073 editor
->priv
->builder
, "entry-fullname");
4075 if (GTK_IS_ENTRY (fname_widget
)) {
4077 gchar
*full_name
= e_contact_name_to_string (name
);
4078 const gchar
*old_full_name
;
4080 entry
= GTK_ENTRY (fname_widget
);
4081 old_full_name
= gtk_entry_get_text (entry
);
4083 if (strcmp (full_name
, old_full_name
))
4084 gtk_entry_set_text (entry
, full_name
);
4088 e_contact_name_free (editor
->priv
->name
);
4089 editor
->priv
->name
= name
;
4091 file_as_set_style (editor
, style
);
4094 g_signal_handlers_disconnect_by_func (editor
, G_CALLBACK (full_name_editor_closed_cb
), dialog
);
4096 gtk_widget_destroy (GTK_WIDGET (dialog
));
4097 editor
->priv
->fullname_dialog
= NULL
;
4101 full_name_clicked (GtkWidget
*button
,
4102 EContactEditor
*editor
)
4106 gboolean fullname_supported
;
4108 if (editor
->priv
->fullname_dialog
) {
4109 gtk_window_present (GTK_WINDOW (editor
->priv
->fullname_dialog
));
4113 parent
= eab_editor_get_window (EAB_EDITOR (editor
));
4114 dialog
= GTK_DIALOG (e_contact_editor_fullname_new (parent
, editor
->priv
->name
));
4115 fullname_supported
= is_field_supported (editor
, E_CONTACT_FULL_NAME
);
4119 fullname_supported
& editor
->priv
->target_editable
, NULL
);
4123 G_CALLBACK (full_name_response
), editor
);
4125 /* Close the fullname dialog if the editor is closed */
4126 g_signal_connect_swapped (
4127 editor
, "editor_closed",
4128 G_CALLBACK (full_name_editor_closed_cb
), dialog
);
4130 gtk_widget_show (GTK_WIDGET (dialog
));
4131 editor
->priv
->fullname_dialog
= GTK_WIDGET (dialog
);
4135 categories_response (GtkDialog
*dialog
,
4137 EContactEditor
*editor
)
4142 entry
= e_builder_get_widget (editor
->priv
->builder
, "entry-categories");
4144 if (response
== GTK_RESPONSE_OK
) {
4145 categories
= e_categories_dialog_get_categories (
4146 E_CATEGORIES_DIALOG (dialog
));
4147 if (GTK_IS_ENTRY (entry
))
4148 gtk_entry_set_text (
4149 GTK_ENTRY (entry
), categories
);
4152 editor
->priv
->contact
,
4153 E_CONTACT_CATEGORIES
,
4155 g_free (categories
);
4158 gtk_widget_destroy (GTK_WIDGET (dialog
));
4159 editor
->priv
->categories_dialog
= NULL
;
4163 categories_clicked (GtkWidget
*button
,
4164 EContactEditor
*editor
)
4166 gchar
*categories
= NULL
;
4169 GtkWidget
*entry
= e_builder_get_widget (editor
->priv
->builder
, "entry-categories");
4171 if (entry
&& GTK_IS_ENTRY (entry
))
4172 categories
= g_strdup (gtk_entry_get_text (GTK_ENTRY (entry
)));
4173 else if (editor
->priv
->contact
)
4174 categories
= e_contact_get (editor
->priv
->contact
, E_CONTACT_CATEGORIES
);
4176 if (editor
->priv
->categories_dialog
!= NULL
) {
4177 gtk_window_present (GTK_WINDOW (editor
->priv
->categories_dialog
));
4178 g_free (categories
);
4180 }else if (!(dialog
= GTK_DIALOG (e_categories_dialog_new (categories
)))) {
4181 e_alert_run_dialog_for_args (
4182 GTK_WINDOW (editor
->priv
->app
),
4183 "addressbook:edit-categories", NULL
);
4184 g_free (categories
);
4190 G_CALLBACK (categories_response
), editor
);
4192 window
= GTK_WINDOW (dialog
);
4194 /* Close the category dialog if the editor is closed */
4195 gtk_window_set_destroy_with_parent (window
, TRUE
);
4196 gtk_window_set_modal (window
, FALSE
);
4197 gtk_window_set_transient_for (window
, eab_editor_get_window (EAB_EDITOR (editor
)));
4199 gtk_widget_show (GTK_WIDGET (dialog
));
4200 g_free (categories
);
4202 editor
->priv
->categories_dialog
= GTK_WIDGET (dialog
);
4206 image_selected (EContactEditor
*editor
)
4209 GtkWidget
*image_chooser
;
4211 file_name
= gtk_file_chooser_get_filename (
4212 GTK_FILE_CHOOSER (editor
->priv
->file_selector
));
4217 image_chooser
= e_builder_get_widget (editor
->priv
->builder
, "image-chooser");
4219 g_signal_handlers_block_by_func (
4220 image_chooser
, image_chooser_changed
, editor
);
4221 e_image_chooser_set_from_file (
4222 E_IMAGE_CHOOSER (image_chooser
), file_name
);
4223 g_signal_handlers_unblock_by_func (
4224 image_chooser
, image_chooser_changed
, editor
);
4226 editor
->priv
->image_set
= TRUE
;
4227 editor
->priv
->image_changed
= TRUE
;
4228 object_changed (G_OBJECT (image_chooser
), editor
);
4232 image_cleared (EContactEditor
*editor
)
4234 GtkWidget
*image_chooser
;
4237 image_chooser
= e_builder_get_widget (
4238 editor
->priv
->builder
, "image-chooser");
4240 file_name
= e_icon_factory_get_icon_filename (
4241 "avatar-default", GTK_ICON_SIZE_DIALOG
);
4243 g_signal_handlers_block_by_func (
4244 image_chooser
, image_chooser_changed
, editor
);
4245 e_image_chooser_set_from_file (
4246 E_IMAGE_CHOOSER (image_chooser
), file_name
);
4247 g_signal_handlers_unblock_by_func (
4248 image_chooser
, image_chooser_changed
, editor
);
4252 editor
->priv
->image_set
= FALSE
;
4253 editor
->priv
->image_changed
= TRUE
;
4254 object_changed (G_OBJECT (image_chooser
), editor
);
4258 file_chooser_response (GtkWidget
*widget
,
4260 EContactEditor
*editor
)
4262 if (response
== GTK_RESPONSE_ACCEPT
)
4263 image_selected (editor
);
4264 else if (response
== GTK_RESPONSE_NO
)
4265 image_cleared (editor
);
4267 gtk_widget_hide (editor
->priv
->file_selector
);
4271 file_selector_deleted (GtkWidget
*widget
)
4273 gtk_widget_hide (widget
);
4278 update_preview_cb (GtkFileChooser
*file_chooser
,
4282 gchar
*filename
= NULL
;
4285 gtk_file_chooser_set_preview_widget_active (file_chooser
, TRUE
);
4286 preview
= GTK_WIDGET (data
);
4287 filename
= gtk_file_chooser_get_preview_filename (file_chooser
);
4288 if (filename
== NULL
)
4291 pixbuf
= gdk_pixbuf_new_from_file_at_size (filename
, 128, 128, NULL
);
4293 gchar
*alternate_file
;
4294 alternate_file
= e_icon_factory_get_icon_filename (
4295 "avatar-default", GTK_ICON_SIZE_DIALOG
);
4296 if (alternate_file
) {
4297 pixbuf
= gdk_pixbuf_new_from_file_at_size (
4298 alternate_file
, 128, 128, NULL
);
4299 g_free (alternate_file
);
4304 gtk_image_set_from_pixbuf (GTK_IMAGE (preview
), pixbuf
);
4306 g_object_unref (pixbuf
);
4310 image_clicked (GtkWidget
*button
,
4311 EContactEditor
*editor
)
4313 if (!editor
->priv
->file_selector
) {
4315 GtkFileFilter
*filter
;
4317 editor
->priv
->file_selector
= gtk_file_chooser_dialog_new (
4318 _("Please select an image for this contact"),
4319 GTK_WINDOW (editor
->priv
->app
),
4320 GTK_FILE_CHOOSER_ACTION_OPEN
,
4321 _("_Cancel"), GTK_RESPONSE_CANCEL
,
4322 _("_Open"), GTK_RESPONSE_ACCEPT
,
4323 _("_No image"), GTK_RESPONSE_NO
,
4326 filter
= gtk_file_filter_new ();
4327 gtk_file_filter_add_mime_type (filter
, "image/*");
4328 gtk_file_chooser_set_filter (
4329 GTK_FILE_CHOOSER (editor
->priv
->file_selector
),
4332 preview
= GTK_IMAGE (gtk_image_new ());
4333 gtk_file_chooser_set_preview_widget (
4334 GTK_FILE_CHOOSER (editor
->priv
->file_selector
),
4335 GTK_WIDGET (preview
));
4337 editor
->priv
->file_selector
, "update-preview",
4338 G_CALLBACK (update_preview_cb
), preview
);
4340 gtk_dialog_set_default_response (
4341 GTK_DIALOG (editor
->priv
->file_selector
),
4342 GTK_RESPONSE_ACCEPT
);
4345 editor
->priv
->file_selector
, "response",
4346 G_CALLBACK (file_chooser_response
), editor
);
4348 g_signal_connect_after (
4349 editor
->priv
->file_selector
, "delete-event",
4350 G_CALLBACK (file_selector_deleted
),
4351 editor
->priv
->file_selector
);
4354 /* Display the dialog */
4356 gtk_window_set_modal (GTK_WINDOW (editor
->priv
->file_selector
), TRUE
);
4357 gtk_window_present (GTK_WINDOW (editor
->priv
->file_selector
));
4362 gboolean should_close
;
4364 } EditorCloseStruct
;
4367 contact_removed_cb (GObject
*source_object
,
4368 GAsyncResult
*result
,
4371 EBookClient
*book_client
= E_BOOK_CLIENT (source_object
);
4372 EditorCloseStruct
*ecs
= user_data
;
4373 EContactEditor
*ce
= ecs
->ce
;
4374 gboolean should_close
= ecs
->should_close
;
4375 GError
*error
= NULL
;
4377 e_book_client_remove_contact_finish (book_client
, result
, &error
);
4379 gtk_widget_set_sensitive (ce
->priv
->app
, TRUE
);
4380 ce
->priv
->in_async_call
= FALSE
;
4382 e_contact_set (ce
->priv
->contact
, E_CONTACT_UID
, ecs
->new_id
);
4384 eab_editor_contact_deleted (EAB_EDITOR (ce
), error
, ce
->priv
->contact
);
4386 ce
->priv
->is_new_contact
= FALSE
;
4389 eab_editor_close (EAB_EDITOR (ce
));
4391 ce
->priv
->changed
= FALSE
;
4393 g_object_ref (ce
->priv
->target_client
);
4394 g_object_unref (ce
->priv
->source_client
);
4395 ce
->priv
->source_client
= ce
->priv
->target_client
;
4401 g_error_free (error
);
4403 g_object_unref (ce
);
4404 g_free (ecs
->new_id
);
4409 contact_added_cb (EBookClient
*book_client
,
4410 const GError
*error
,
4414 EditorCloseStruct
*ecs
= closure
;
4415 EContactEditor
*ce
= ecs
->ce
;
4416 gboolean should_close
= ecs
->should_close
;
4418 if (ce
->priv
->source_client
!= ce
->priv
->target_client
&& !e_client_is_readonly (E_CLIENT (ce
->priv
->source_client
)) &&
4419 !error
&& ce
->priv
->is_new_contact
== FALSE
) {
4420 ecs
->new_id
= g_strdup (id
);
4421 e_book_client_remove_contact (
4422 ce
->priv
->source_client
, ce
->priv
->contact
, NULL
, contact_removed_cb
, ecs
);
4426 gtk_widget_set_sensitive (ce
->priv
->app
, TRUE
);
4427 ce
->priv
->in_async_call
= FALSE
;
4429 e_contact_set (ce
->priv
->contact
, E_CONTACT_UID
, id
);
4431 eab_editor_contact_added (EAB_EDITOR (ce
), error
, ce
->priv
->contact
);
4434 ce
->priv
->is_new_contact
= FALSE
;
4437 eab_editor_close (EAB_EDITOR (ce
));
4439 ce
->priv
->changed
= FALSE
;
4444 g_object_unref (ce
);
4449 contact_modified_cb (EBookClient
*book_client
,
4450 const GError
*error
,
4453 EditorCloseStruct
*ecs
= closure
;
4454 EContactEditor
*ce
= ecs
->ce
;
4455 gboolean should_close
= ecs
->should_close
;
4457 gtk_widget_set_sensitive (ce
->priv
->app
, TRUE
);
4458 ce
->priv
->in_async_call
= FALSE
;
4460 eab_editor_contact_modified (EAB_EDITOR (ce
), error
, ce
->priv
->contact
);
4464 eab_editor_close (EAB_EDITOR (ce
));
4467 ce
->priv
->changed
= FALSE
;
4472 g_object_unref (ce
);
4477 contact_modified_ready_cb (GObject
*source_object
,
4478 GAsyncResult
*result
,
4481 EBookClient
*book_client
= E_BOOK_CLIENT (source_object
);
4482 GError
*error
= NULL
;
4484 e_book_client_modify_contact_finish (book_client
, result
, &error
);
4486 contact_modified_cb (book_client
, error
, user_data
);
4489 g_error_free (error
);
4492 /* Emits the signal to request saving a contact */
4494 real_save_contact (EContactEditor
*ce
,
4495 gboolean should_close
)
4498 EditorCloseStruct
*ecs
;
4499 ESourceRegistry
*registry
;
4501 shell
= eab_editor_get_shell (EAB_EDITOR (ce
));
4502 registry
= e_shell_get_registry (shell
);
4504 ecs
= g_new0 (EditorCloseStruct
, 1);
4506 g_object_ref (ecs
->ce
);
4508 ecs
->should_close
= should_close
;
4510 gtk_widget_set_sensitive (ce
->priv
->app
, FALSE
);
4511 ce
->priv
->in_async_call
= TRUE
;
4513 if (ce
->priv
->source_client
!= ce
->priv
->target_client
) {
4514 /* Two-step move; add to target, then remove from source */
4515 eab_merging_book_add_contact (
4516 registry
, ce
->priv
->target_client
,
4517 ce
->priv
->contact
, contact_added_cb
, ecs
);
4519 if (ce
->priv
->is_new_contact
)
4520 eab_merging_book_add_contact (
4521 registry
, ce
->priv
->target_client
,
4522 ce
->priv
->contact
, contact_added_cb
, ecs
);
4523 else if (ce
->priv
->check_merge
)
4524 eab_merging_book_modify_contact (
4525 registry
, ce
->priv
->target_client
,
4526 ce
->priv
->contact
, contact_modified_cb
, ecs
);
4528 e_book_client_modify_contact (
4529 ce
->priv
->target_client
, ce
->priv
->contact
, NULL
,
4530 contact_modified_ready_cb
, ecs
);
4535 save_contact (EContactEditor
*ce
,
4536 gboolean should_close
)
4539 const gchar
*name_entry_string
;
4540 const gchar
*file_as_entry_string
;
4541 const gchar
*company_name_string
;
4542 GtkWidget
*entry_fullname
, *entry_file_as
, *company_name
, *client_combo_box
;
4543 ESource
*active_source
;
4545 if (!ce
->priv
->target_client
)
4548 client_combo_box
= e_builder_get_widget (ce
->priv
->builder
, "client-combo-box");
4549 active_source
= e_source_combo_box_ref_active (E_SOURCE_COMBO_BOX (client_combo_box
));
4550 g_return_if_fail (active_source
!= NULL
);
4552 if (!e_source_equal (e_client_get_source (E_CLIENT (ce
->priv
->target_client
)), active_source
)) {
4553 e_alert_run_dialog_for_args (
4554 GTK_WINDOW (ce
->priv
->app
),
4555 "addressbook:error-still-opening",
4556 e_source_get_display_name (active_source
),
4558 g_object_unref (active_source
);
4562 g_object_unref (active_source
);
4564 if (ce
->priv
->target_editable
&& e_client_is_readonly (E_CLIENT (ce
->priv
->source_client
))) {
4565 if (e_alert_run_dialog_for_args (
4566 GTK_WINDOW (ce
->priv
->app
),
4567 "addressbook:prompt-move",
4568 NULL
) == GTK_RESPONSE_NO
)
4572 entry_fullname
= e_builder_get_widget (ce
->priv
->builder
, "entry-fullname");
4573 entry_file_as
= gtk_bin_get_child (
4574 GTK_BIN (e_builder_get_widget (ce
->priv
->builder
, "combo-file-as")));
4575 company_name
= e_builder_get_widget (ce
->priv
->builder
, "entry-company");
4576 name_entry_string
= gtk_entry_get_text (GTK_ENTRY (entry_fullname
));
4577 file_as_entry_string
= gtk_entry_get_text (GTK_ENTRY (entry_file_as
));
4578 company_name_string
= gtk_entry_get_text (GTK_ENTRY (company_name
));
4580 if (strcmp (company_name_string
, "")) {
4581 if (!strcmp (name_entry_string
, ""))
4582 gtk_entry_set_text (
4583 GTK_ENTRY (entry_fullname
),
4584 company_name_string
);
4585 if (!strcmp (file_as_entry_string
, ""))
4586 gtk_entry_set_text (
4587 GTK_ENTRY (entry_file_as
),
4588 company_name_string
);
4593 if (!e_contact_editor_is_valid (EAB_EDITOR (ce
))) {
4594 uid
= e_contact_get (ce
->priv
->contact
, E_CONTACT_UID
);
4595 g_object_unref (ce
->priv
->contact
);
4596 ce
->priv
->contact
= e_contact_new ();
4598 e_contact_set (ce
->priv
->contact
, E_CONTACT_UID
, uid
);
4604 real_save_contact (ce
, should_close
);
4608 e_contact_editor_save_contact (EABEditor
*editor
,
4609 gboolean should_close
)
4611 save_contact (E_CONTACT_EDITOR (editor
), should_close
);
4614 /* Closes the dialog box and emits the appropriate signals */
4616 e_contact_editor_close (EABEditor
*editor
)
4618 EContactEditor
*ce
= E_CONTACT_EDITOR (editor
);
4620 if (ce
->priv
->app
!= NULL
) {
4621 gtk_widget_destroy (ce
->priv
->app
);
4622 ce
->priv
->app
= NULL
;
4623 eab_editor_closed (editor
);
4627 static const EContactField non_string_fields
[] = {
4628 E_CONTACT_FULL_NAME
,
4630 E_CONTACT_ADDRESS_HOME
,
4631 E_CONTACT_ADDRESS_WORK
,
4632 E_CONTACT_ADDRESS_OTHER
,
4635 E_CONTACT_IM_GROUPWISE
,
4636 E_CONTACT_IM_JABBER
,
4638 E_CONTACT_IM_GADUGADU
,
4642 E_CONTACT_IM_TWITTER
,
4645 E_CONTACT_X509_CERT
,
4646 E_CONTACT_CATEGORY_LIST
,
4647 E_CONTACT_BIRTH_DATE
,
4648 E_CONTACT_ANNIVERSARY
4653 is_non_string_field (EContactField id
)
4655 gint count
= sizeof (non_string_fields
) / sizeof (EContactField
);
4657 for (i
= 0; i
< count
; i
++)
4658 if (id
== non_string_fields
[i
])
4664 /* insert checks here (date format, for instance, etc.) */
4666 e_contact_editor_is_valid (EABEditor
*editor
)
4668 EContactEditor
*ce
= E_CONTACT_EDITOR (editor
);
4670 gboolean validation_error
= FALSE
;
4672 GString
*errmsg
= g_string_new (_("The contact data is invalid:\n\n"));
4673 time_t bday
, now
= time (NULL
);
4675 widget
= e_builder_get_widget (ce
->priv
->builder
, "dateedit-birthday");
4676 if (!(e_date_edit_date_is_valid (E_DATE_EDIT (widget
)))) {
4677 g_string_append_printf (
4678 errmsg
, _("“%s” has an invalid format"),
4679 e_contact_pretty_name (E_CONTACT_BIRTH_DATE
));
4680 validation_error
= TRUE
;
4682 /* If valid, see if the birthday is a future date */
4683 bday
= e_date_edit_get_time (E_DATE_EDIT (widget
));
4685 g_string_append_printf (
4686 errmsg
, _("“%s” cannot be a future date"),
4687 e_contact_pretty_name (E_CONTACT_BIRTH_DATE
));
4688 validation_error
= TRUE
;
4691 widget
= e_builder_get_widget (ce
->priv
->builder
, "dateedit-anniversary");
4692 if (!(e_date_edit_date_is_valid (E_DATE_EDIT (widget
)))) {
4693 g_string_append_printf (
4694 errmsg
, _("%s“%s” has an invalid format"),
4695 validation_error
? ",\n" : "",
4696 e_contact_pretty_name (E_CONTACT_ANNIVERSARY
));
4697 validation_error
= TRUE
;
4700 for (iter
= ce
->priv
->required_fields
; iter
; iter
= iter
->next
) {
4701 const gchar
*field_name
= iter
->data
;
4702 EContactField field_id
= e_contact_field_id (field_name
);
4704 if (is_non_string_field (field_id
)) {
4705 if (e_contact_get_const (ce
->priv
->contact
, field_id
) == NULL
) {
4706 g_string_append_printf (
4707 errmsg
, _("%s“%s” is empty"),
4708 validation_error
? ",\n" : "",
4709 e_contact_pretty_name (field_id
));
4710 validation_error
= TRUE
;
4717 text
= e_contact_get_const (ce
->priv
->contact
, field_id
);
4719 if (STRING_IS_EMPTY (text
)) {
4720 g_string_append_printf (
4721 errmsg
, _("%s“%s” is empty"),
4722 validation_error
? ",\n" : "",
4723 e_contact_pretty_name (field_id
));
4724 validation_error
= TRUE
;
4731 if (validation_error
) {
4732 g_string_append (errmsg
, ".");
4733 e_alert_run_dialog_for_args (
4734 GTK_WINDOW (ce
->priv
->app
),
4735 "addressbook:generic-error",
4736 _("Invalid contact."), errmsg
->str
, NULL
);
4737 g_string_free (errmsg
, TRUE
);
4741 g_string_free (errmsg
, TRUE
);
4747 e_contact_editor_is_changed (EABEditor
*editor
)
4749 return E_CONTACT_EDITOR (editor
)->priv
->changed
;
4753 e_contact_editor_get_window (EABEditor
*editor
)
4755 return GTK_WINDOW (E_CONTACT_EDITOR (editor
)->priv
->app
);
4759 file_save_and_close_cb (GtkWidget
*widget
,
4762 save_contact (ce
, TRUE
);
4766 file_cancel_cb (GtkWidget
*widget
,
4769 eab_editor_close (EAB_EDITOR (ce
));
4772 /* Callback used when the dialog box is destroyed */
4774 app_delete_event_cb (GtkWidget
*widget
,
4780 ce
= E_CONTACT_EDITOR (data
);
4782 /* if we're saving, don't allow the dialog to close */
4783 if (ce
->priv
->in_async_call
)
4786 if (ce
->priv
->changed
) {
4787 switch (eab_prompt_save_dialog (GTK_WINDOW (ce
->priv
->app
))) {
4788 case GTK_RESPONSE_YES
:
4789 eab_editor_save_contact (EAB_EDITOR (ce
), TRUE
);
4792 case GTK_RESPONSE_NO
:
4795 case GTK_RESPONSE_CANCEL
:
4802 eab_editor_close (EAB_EDITOR (ce
));
4807 show_help_cb (GtkWidget
*widget
,
4810 /* FIXME Pass a proper parent window. */
4811 e_display_help (NULL
, "contacts-usage-add-contact");
4815 add_to_tab_order (GList
*list
,
4816 GtkBuilder
*builder
,
4819 GtkWidget
*widget
= e_builder_get_widget (builder
, name
);
4820 return g_list_prepend (list
, widget
);
4824 setup_tab_order (GtkBuilder
*builder
)
4826 GtkWidget
*container
;
4829 container = e_builder_get_widget (builder, "table-contact-editor-general");
4832 list = add_to_tab_order (list, builder, "entry-fullname");
4833 list = add_to_tab_order (list, builder, "entry-jobtitle");
4834 list = add_to_tab_order (list, builder, "entry-company");
4835 list = add_to_tab_order (list, builder, "combo-file-as");
4836 list = add_to_tab_order (list, builder, "entry-phone-1");
4837 list = add_to_tab_order (list, builder, "entry-phone-2");
4838 list = add_to_tab_order (list, builder, "entry-phone-3");
4839 list = add_to_tab_order (list, builder, "entry-phone-4");
4841 list = add_to_tab_order (list, builder, "entry-email1");
4842 list = add_to_tab_order (list, builder, "alignment-htmlmail");
4843 list = add_to_tab_order (list, builder, "entry-web");
4844 list = add_to_tab_order (list, builder, "entry-homepage");
4845 list = add_to_tab_order (list, builder, "button-fulladdr");
4846 list = add_to_tab_order (list, builder, "text-address");
4847 list = g_list_reverse (list);
4848 e_container_change_tab_order (GTK_CONTAINER (container), list);
4853 container
= e_builder_get_widget (builder
, "table-home-address");
4854 gtk_container_get_focus_chain (GTK_CONTAINER (container
), &list
);
4856 list
= add_to_tab_order (list
, builder
, "scrolledwindow-home-address");
4857 list
= add_to_tab_order (list
, builder
, "entry-home-city");
4858 list
= add_to_tab_order (list
, builder
, "entry-home-zip");
4859 list
= add_to_tab_order (list
, builder
, "entry-home-state");
4860 list
= add_to_tab_order (list
, builder
, "entry-home-pobox");
4861 list
= add_to_tab_order (list
, builder
, "entry-home-country");
4862 list
= g_list_reverse (list
);
4864 gtk_container_set_focus_chain (GTK_CONTAINER (container
), list
);
4867 container
= e_builder_get_widget (builder
, "table-work-address");
4868 gtk_container_get_focus_chain (GTK_CONTAINER (container
), &list
);
4870 list
= add_to_tab_order (list
, builder
, "scrolledwindow-work-address");
4871 list
= add_to_tab_order (list
, builder
, "entry-work-city");
4872 list
= add_to_tab_order (list
, builder
, "entry-work-zip");
4873 list
= add_to_tab_order (list
, builder
, "entry-work-state");
4874 list
= add_to_tab_order (list
, builder
, "entry-work-pobox");
4875 list
= add_to_tab_order (list
, builder
, "entry-work-country");
4876 list
= g_list_reverse (list
);
4878 gtk_container_set_focus_chain (GTK_CONTAINER (container
), list
);
4881 container
= e_builder_get_widget (builder
, "table-other-address");
4882 gtk_container_get_focus_chain (GTK_CONTAINER (container
), &list
);
4884 list
= add_to_tab_order (list
, builder
, "scrolledwindow-other-address");
4885 list
= add_to_tab_order (list
, builder
, "entry-other-city");
4886 list
= add_to_tab_order (list
, builder
, "entry-other-zip");
4887 list
= add_to_tab_order (list
, builder
, "entry-other-state");
4888 list
= add_to_tab_order (list
, builder
, "entry-other-pobox");
4889 list
= add_to_tab_order (list
, builder
, "entry-other-country");
4890 list
= g_list_reverse (list
);
4892 gtk_container_set_focus_chain (GTK_CONTAINER (container
), list
);
4897 expand_dyntable (GtkExpander
*expander
,
4898 EContactEditorDynTable
*dyntable
,
4901 if (gtk_expander_get_expanded (expander
)) {
4902 e_contact_editor_dyntable_set_show_max (dyntable
, max_slots
);
4904 e_contact_editor_dyntable_set_show_max (dyntable
,
4905 SLOTS_IN_COLLAPSED_STATE
);
4910 expander_contact_mail_cb (GObject
*object
,
4911 GParamSpec
*param_spec
,
4914 expand_dyntable (GTK_EXPANDER (object
),
4915 E_CONTACT_EDITOR_DYNTABLE (user_data
),
4920 expander_contact_phone_cb (GObject
*object
,
4921 GParamSpec
*param_spec
,
4924 expand_dyntable (GTK_EXPANDER (object
),
4925 E_CONTACT_EDITOR_DYNTABLE (user_data
),
4930 expander_contact_sip_cb (GObject
*object
,
4931 GParamSpec
*param_spec
,
4934 expand_dyntable (GTK_EXPANDER (object
),
4935 E_CONTACT_EDITOR_DYNTABLE (user_data
),
4940 expander_contact_im_cb (GObject
*object
,
4941 GParamSpec
*param_spec
,
4944 expand_dyntable (GTK_EXPANDER (object
),
4945 E_CONTACT_EDITOR_DYNTABLE (user_data
),
4950 contact_editor_focus_widget_changed_cb (EFocusTracker
*focus_tracker
,
4952 EContactEditor
*editor
)
4956 widget
= e_focus_tracker_get_focus (focus_tracker
);
4958 /* there is no problem to call the attach multiple times */
4960 e_widget_undo_attach (widget
, focus_tracker
);
4964 e_contact_editor_init (EContactEditor
*e_contact_editor
)
4966 GtkBuilder
*builder
;
4968 EClientCache
*client_cache
;
4969 GtkWidget
*container
;
4970 GtkWidget
*widget
, *label
, *dyntable
;
4971 GtkEntryCompletion
*completion
;
4973 e_contact_editor
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (
4974 e_contact_editor
, E_TYPE_CONTACT_EDITOR
, EContactEditorPrivate
);
4976 /* FIXME The shell should be obtained
4977 * through a constructor property. */
4978 shell
= e_shell_get_default ();
4979 client_cache
= e_shell_get_client_cache (shell
);
4981 e_contact_editor
->priv
->name
= e_contact_name_new ();
4983 e_contact_editor
->priv
->contact
= NULL
;
4984 e_contact_editor
->priv
->changed
= FALSE
;
4985 e_contact_editor
->priv
->check_merge
= FALSE
;
4986 e_contact_editor
->priv
->image_set
= FALSE
;
4987 e_contact_editor
->priv
->image_changed
= FALSE
;
4988 e_contact_editor
->priv
->in_async_call
= FALSE
;
4989 e_contact_editor
->priv
->target_editable
= TRUE
;
4990 e_contact_editor
->priv
->fullname_dialog
= NULL
;
4991 e_contact_editor
->priv
->categories_dialog
= NULL
;
4992 e_contact_editor
->priv
->compress_ui
= e_shell_get_express_mode (shell
);
4994 /* Make sure custom widget types are available */
4995 g_type_ensure (E_TYPE_IMAGE_CHOOSER
);
4996 g_type_ensure (E_TYPE_CLIENT_COMBO_BOX
);
4997 g_type_ensure (E_TYPE_CONTACT_EDITOR_DYNTABLE
);
4998 g_type_ensure (E_TYPE_URL_ENTRY
);
4999 g_type_ensure (E_TYPE_DATE_EDIT
);
5001 builder
= gtk_builder_new ();
5002 e_load_ui_builder_definition (builder
, "contact-editor.ui");
5004 e_contact_editor
->priv
->builder
= builder
;
5006 setup_tab_order (builder
);
5008 e_contact_editor
->priv
->app
=
5009 e_builder_get_widget (builder
, "contact editor");
5010 widget
= e_contact_editor
->priv
->app
;
5012 gtk_window_set_type_hint (
5013 GTK_WINDOW (widget
), GDK_WINDOW_TYPE_HINT_NORMAL
);
5014 container
= gtk_dialog_get_action_area (GTK_DIALOG (widget
));
5015 gtk_container_set_border_width (GTK_CONTAINER (container
), 12);
5016 container
= gtk_dialog_get_content_area (GTK_DIALOG (widget
));
5017 gtk_container_set_border_width (GTK_CONTAINER (container
), 0);
5019 init_all (e_contact_editor
);
5021 widget
= e_builder_get_widget (
5022 e_contact_editor
->priv
->builder
, "button-image");
5025 G_CALLBACK (image_clicked
), e_contact_editor
);
5026 widget
= e_builder_get_widget (
5027 e_contact_editor
->priv
->builder
, "button-fullname");
5030 G_CALLBACK (full_name_clicked
), e_contact_editor
);
5031 widget
= e_builder_get_widget (
5032 e_contact_editor
->priv
->builder
, "button-categories");
5035 G_CALLBACK (categories_clicked
), e_contact_editor
);
5036 widget
= e_builder_get_widget (
5037 e_contact_editor
->priv
->builder
, "client-combo-box");
5038 e_client_combo_box_set_client_cache (
5039 E_CLIENT_COMBO_BOX (widget
), client_cache
);
5042 G_CALLBACK (source_changed
), e_contact_editor
);
5043 label
= e_builder_get_widget (
5044 e_contact_editor
->priv
->builder
, "where-label");
5045 gtk_label_set_mnemonic_widget (GTK_LABEL (label
), widget
);
5046 widget
= e_builder_get_widget (
5047 e_contact_editor
->priv
->builder
, "button-ok");
5050 G_CALLBACK (file_save_and_close_cb
), e_contact_editor
);
5051 widget
= e_builder_get_widget (
5052 e_contact_editor
->priv
->builder
, "button-cancel");
5055 G_CALLBACK (file_cancel_cb
), e_contact_editor
);
5056 widget
= e_builder_get_widget (
5057 e_contact_editor
->priv
->builder
, "button-help");
5060 G_CALLBACK (show_help_cb
), e_contact_editor
);
5062 widget
= e_builder_get_widget (
5063 e_contact_editor
->priv
->builder
, "expander-contact-phone");
5064 dyntable
= e_builder_get_widget (
5065 e_contact_editor
->priv
->builder
, "phone-dyntable");
5066 g_signal_connect (widget
, "notify::expanded",
5067 G_CALLBACK (expander_contact_phone_cb
), dyntable
);
5069 widget
= e_builder_get_widget (
5070 e_contact_editor
->priv
->builder
, "expander-contact-sip");
5071 dyntable
= e_builder_get_widget (
5072 e_contact_editor
->priv
->builder
, "sip-dyntable");
5073 g_signal_connect (widget
, "notify::expanded",
5074 G_CALLBACK (expander_contact_sip_cb
), dyntable
);
5076 widget
= e_builder_get_widget (
5077 e_contact_editor
->priv
->builder
, "expander-contact-im");
5078 dyntable
= e_builder_get_widget (
5079 e_contact_editor
->priv
->builder
, "im-dyntable");
5080 g_signal_connect (widget
, "notify::expanded",
5081 G_CALLBACK (expander_contact_im_cb
), dyntable
);
5083 widget
= e_builder_get_widget (
5084 e_contact_editor
->priv
->builder
, "expander-contact-email");
5085 dyntable
= e_builder_get_widget (
5086 e_contact_editor
->priv
->builder
, "mail-dyntable");
5087 g_signal_connect (widget
, "notify::expanded",
5088 G_CALLBACK (expander_contact_mail_cb
), dyntable
);
5090 widget
= e_builder_get_widget (
5091 e_contact_editor
->priv
->builder
, "entry-fullname");
5093 gtk_widget_grab_focus (widget
);
5095 widget
= e_builder_get_widget (
5096 e_contact_editor
->priv
->builder
, "entry-categories");
5097 completion
= e_category_completion_new ();
5098 gtk_entry_set_completion (GTK_ENTRY (widget
), completion
);
5099 g_object_unref (completion
);
5101 /* Connect to the deletion of the dialog */
5104 e_contact_editor
->priv
->app
, "delete_event",
5105 G_CALLBACK (app_delete_event_cb
), e_contact_editor
);
5108 gtk_window_set_icon_name (
5109 GTK_WINDOW (e_contact_editor
->priv
->app
), "contact-editor");
5111 gtk_application_add_window (
5112 GTK_APPLICATION (shell
),
5113 GTK_WINDOW (e_contact_editor
->priv
->app
));
5117 e_contact_editor_constructed (GObject
*object
)
5121 " <menubar name='undo-menubar'>"
5122 " <menu action='undo-menu'>"
5123 " <menuitem action='undo'/>"
5124 " <menuitem action='redo'/>"
5128 EContactEditor
*editor
= E_CONTACT_EDITOR (object
);
5129 GtkActionGroup
*action_group
;
5131 GError
*error
= NULL
;
5133 /* Chain up to parent's method. */
5134 G_OBJECT_CLASS (parent_class
)->constructed (object
);
5136 editor
->priv
->focus_tracker
= e_focus_tracker_new (GTK_WINDOW (editor
->priv
->app
));
5137 editor
->priv
->ui_manager
= gtk_ui_manager_new ();
5139 gtk_window_add_accel_group (
5140 GTK_WINDOW (editor
->priv
->app
),
5141 gtk_ui_manager_get_accel_group (editor
->priv
->ui_manager
));
5143 e_signal_connect_notify (
5144 editor
->priv
->focus_tracker
, "notify::focus",
5145 G_CALLBACK (contact_editor_focus_widget_changed_cb
), editor
);
5147 action_group
= gtk_action_group_new ("undo");
5148 gtk_action_group_set_translation_domain (
5149 action_group
, GETTEXT_PACKAGE
);
5150 gtk_action_group_add_actions (
5151 action_group
, undo_entries
,
5152 G_N_ELEMENTS (undo_entries
), editor
);
5153 gtk_ui_manager_insert_action_group (
5154 editor
->priv
->ui_manager
, action_group
, 0);
5156 action
= gtk_action_group_get_action (action_group
, "undo");
5157 e_focus_tracker_set_undo_action (editor
->priv
->focus_tracker
, action
);
5159 action
= gtk_action_group_get_action (action_group
, "redo");
5160 e_focus_tracker_set_redo_action (editor
->priv
->focus_tracker
, action
);
5162 g_object_unref (action_group
);
5164 gtk_ui_manager_add_ui_from_string (editor
->priv
->ui_manager
, ui
, -1, &error
);
5165 if (error
!= NULL
) {
5166 g_warning ("%s: %s", G_STRFUNC
, error
->message
);
5167 g_error_free (error
);
5172 e_contact_editor_dispose (GObject
*object
)
5174 EContactEditor
*e_contact_editor
= E_CONTACT_EDITOR (object
);
5176 if (e_contact_editor
->priv
->file_selector
!= NULL
) {
5177 gtk_widget_destroy (e_contact_editor
->priv
->file_selector
);
5178 e_contact_editor
->priv
->file_selector
= NULL
;
5182 e_contact_editor
->priv
->writable_fields
,
5183 (GDestroyNotify
) g_free
);
5184 e_contact_editor
->priv
->writable_fields
= NULL
;
5187 e_contact_editor
->priv
->required_fields
,
5188 (GDestroyNotify
) g_free
);
5189 e_contact_editor
->priv
->required_fields
= NULL
;
5191 if (e_contact_editor
->priv
->target_client
) {
5192 g_signal_handler_disconnect (
5193 e_contact_editor
->priv
->target_client
,
5194 e_contact_editor
->priv
->target_editable_id
);
5197 if (e_contact_editor
->priv
->name
) {
5198 e_contact_name_free (e_contact_editor
->priv
->name
);
5199 e_contact_editor
->priv
->name
= NULL
;
5202 if (e_contact_editor
->priv
->focus_tracker
) {
5203 g_signal_handlers_disconnect_by_data (
5204 e_contact_editor
->priv
->focus_tracker
,
5208 g_clear_object (&e_contact_editor
->priv
->contact
);
5209 g_clear_object (&e_contact_editor
->priv
->source_client
);
5210 g_clear_object (&e_contact_editor
->priv
->target_client
);
5211 g_clear_object (&e_contact_editor
->priv
->builder
);
5212 g_clear_object (&e_contact_editor
->priv
->ui_manager
);
5213 g_clear_object (&e_contact_editor
->priv
->cancellable
);
5214 g_clear_object (&e_contact_editor
->priv
->focus_tracker
);
5216 /* Chain up to parent's dispose() method. */
5217 G_OBJECT_CLASS (parent_class
)->dispose (object
);
5221 supported_fields_cb (GObject
*source_object
,
5222 GAsyncResult
*result
,
5225 EBookClient
*book_client
= E_BOOK_CLIENT (source_object
);
5226 EContactEditor
*ce
= user_data
;
5227 gchar
*prop_value
= NULL
;
5230 GError
*error
= NULL
;
5232 success
= e_client_get_backend_property_finish (
5233 E_CLIENT (book_client
), result
, &prop_value
, &error
);
5238 if (error
!= NULL
) {
5240 "%s: Failed to get supported fields: %s",
5241 G_STRFUNC
, error
->message
);
5242 g_error_free (error
);
5245 if (!g_slist_find (eab_editor_get_all_editors (), ce
)) {
5247 "supported_fields_cb called for book that's still "
5248 "around, but contact editor that's been destroyed.");
5249 g_free (prop_value
);
5253 fields
= e_client_util_parse_comma_strings (prop_value
);
5255 g_object_set (ce
, "writable_fields", fields
, NULL
);
5257 g_slist_free_full (fields
, (GDestroyNotify
) g_free
);
5258 g_free (prop_value
);
5260 eab_editor_show (EAB_EDITOR (ce
));
5266 required_fields_cb (GObject
*source_object
,
5267 GAsyncResult
*result
,
5270 EBookClient
*book_client
= E_BOOK_CLIENT (source_object
);
5271 EContactEditor
*ce
= user_data
;
5272 gchar
*prop_value
= NULL
;
5275 GError
*error
= NULL
;
5277 success
= e_client_get_backend_property_finish (
5278 E_CLIENT (book_client
), result
, &prop_value
, &error
);
5283 if (error
!= NULL
) {
5285 "%s: Failed to get supported fields: %s",
5286 G_STRFUNC
, error
->message
);
5287 g_error_free (error
);
5290 if (!g_slist_find (eab_editor_get_all_editors (), ce
)) {
5292 "supported_fields_cb called for book that's still "
5293 "around, but contact editor that's been destroyed.");
5294 g_free (prop_value
);
5298 fields
= e_client_util_parse_comma_strings (prop_value
);
5300 g_object_set (ce
, "required_fields", fields
, NULL
);
5302 g_slist_free_full (fields
, (GDestroyNotify
) g_free
);
5303 g_free (prop_value
);
5307 e_contact_editor_new (EShell
*shell
,
5308 EBookClient
*book_client
,
5310 gboolean is_new_contact
,
5315 g_return_val_if_fail (E_IS_SHELL (shell
), NULL
);
5316 g_return_val_if_fail (E_IS_BOOK_CLIENT (book_client
), NULL
);
5317 g_return_val_if_fail (E_IS_CONTACT (contact
), NULL
);
5319 editor
= g_object_new (E_TYPE_CONTACT_EDITOR
, "shell", shell
, NULL
);
5323 "source_client", book_client
,
5325 "is_new_contact", is_new_contact
,
5326 "editable", editable
,
5333 notify_readonly_cb (EBookClient
*book_client
,
5338 gint new_target_editable
;
5339 gboolean changed
= FALSE
;
5341 client
= E_CLIENT (ce
->priv
->target_client
);
5342 new_target_editable
= !e_client_is_readonly (client
);
5344 if (ce
->priv
->target_editable
!= new_target_editable
)
5347 ce
->priv
->target_editable
= new_target_editable
;
5354 e_contact_editor_set_property (GObject
*object
,
5356 const GValue
*value
,
5359 EContactEditor
*editor
;
5361 editor
= E_CONTACT_EDITOR (object
);
5363 switch (property_id
) {
5364 case PROP_SOURCE_CLIENT
: {
5366 gboolean changed
= FALSE
;
5367 EBookClient
*source_client
;
5369 source_client
= E_BOOK_CLIENT (g_value_get_object (value
));
5371 if (source_client
== editor
->priv
->source_client
)
5374 if (editor
->priv
->source_client
)
5375 g_object_unref (editor
->priv
->source_client
);
5377 editor
->priv
->source_client
= source_client
;
5378 g_object_ref (editor
->priv
->source_client
);
5380 if (!editor
->priv
->target_client
) {
5381 editor
->priv
->target_client
= editor
->priv
->source_client
;
5382 g_object_ref (editor
->priv
->target_client
);
5384 editor
->priv
->target_editable_id
= e_signal_connect_notify (
5385 editor
->priv
->target_client
, "notify::readonly",
5386 G_CALLBACK (notify_readonly_cb
), editor
);
5388 e_client_get_backend_property (
5389 E_CLIENT (editor
->priv
->target_client
),
5390 BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS
,
5391 NULL
, supported_fields_cb
, editor
);
5393 e_client_get_backend_property (
5394 E_CLIENT (editor
->priv
->target_client
),
5395 BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS
,
5396 NULL
, required_fields_cb
, editor
);
5399 writable
= !e_client_is_readonly (E_CLIENT (editor
->priv
->target_client
));
5400 if (writable
!= editor
->priv
->target_editable
) {
5401 editor
->priv
->target_editable
= writable
;
5406 sensitize_all (editor
);
5411 case PROP_TARGET_CLIENT
: {
5413 gboolean changed
= FALSE
;
5414 EBookClient
*target_client
;
5416 target_client
= E_BOOK_CLIENT (g_value_get_object (value
));
5418 if (target_client
== editor
->priv
->target_client
)
5421 if (editor
->priv
->target_client
) {
5422 g_signal_handler_disconnect (
5423 editor
->priv
->target_client
,
5424 editor
->priv
->target_editable_id
);
5425 g_object_unref (editor
->priv
->target_client
);
5428 editor
->priv
->target_client
= target_client
;
5429 g_object_ref (editor
->priv
->target_client
);
5431 editor
->priv
->target_editable_id
= e_signal_connect_notify (
5432 editor
->priv
->target_client
, "notify::readonly",
5433 G_CALLBACK (notify_readonly_cb
), editor
);
5435 e_client_get_backend_property (
5436 E_CLIENT (editor
->priv
->target_client
),
5437 BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS
,
5438 NULL
, supported_fields_cb
, editor
);
5440 e_client_get_backend_property (
5441 E_CLIENT (editor
->priv
->target_client
),
5442 BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS
,
5443 NULL
, required_fields_cb
, editor
);
5445 if (!editor
->priv
->is_new_contact
)
5446 editor
->priv
->changed
= TRUE
;
5448 writable
= !e_client_is_readonly (E_CLIENT (editor
->priv
->target_client
));
5450 if (writable
!= editor
->priv
->target_editable
) {
5451 editor
->priv
->target_editable
= writable
;
5456 sensitize_all (editor
);
5462 if (editor
->priv
->contact
)
5463 g_object_unref (editor
->priv
->contact
);
5464 editor
->priv
->contact
= e_contact_duplicate (
5465 E_CONTACT (g_value_get_object (value
)));
5466 fill_in_all (editor
);
5467 editor
->priv
->changed
= FALSE
;
5470 case PROP_IS_NEW_CONTACT
:
5471 editor
->priv
->is_new_contact
= g_value_get_boolean (value
);
5474 case PROP_EDITABLE
: {
5475 gboolean new_value
= g_value_get_boolean (value
);
5476 gboolean changed
= (editor
->priv
->target_editable
!= new_value
);
5478 editor
->priv
->target_editable
= new_value
;
5481 sensitize_all (editor
);
5485 case PROP_CHANGED
: {
5486 gboolean new_value
= g_value_get_boolean (value
);
5487 gboolean changed
= (editor
->priv
->changed
!= new_value
);
5489 editor
->priv
->changed
= new_value
;
5492 sensitize_ok (editor
);
5495 case PROP_WRITABLE_FIELDS
:
5497 editor
->priv
->writable_fields
,
5498 (GDestroyNotify
) g_free
);
5499 editor
->priv
->writable_fields
= g_slist_copy_deep (
5500 g_value_get_pointer (value
),
5501 (GCopyFunc
) g_strdup
, NULL
);
5503 sensitize_all (editor
);
5505 case PROP_REQUIRED_FIELDS
:
5507 editor
->priv
->required_fields
,
5508 (GDestroyNotify
) g_free
);
5509 editor
->priv
->required_fields
= g_slist_copy_deep (
5510 g_value_get_pointer (value
),
5511 (GCopyFunc
) g_strdup
, NULL
);
5514 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
5520 e_contact_editor_get_property (GObject
*object
,
5525 EContactEditor
*e_contact_editor
;
5527 e_contact_editor
= E_CONTACT_EDITOR (object
);
5529 switch (property_id
) {
5530 case PROP_SOURCE_CLIENT
:
5531 g_value_set_object (value
, e_contact_editor
->priv
->source_client
);
5534 case PROP_TARGET_CLIENT
:
5535 g_value_set_object (value
, e_contact_editor
->priv
->target_client
);
5539 extract_all (e_contact_editor
);
5540 g_value_set_object (value
, e_contact_editor
->priv
->contact
);
5543 case PROP_IS_NEW_CONTACT
:
5544 g_value_set_boolean (
5545 value
, e_contact_editor
->priv
->is_new_contact
);
5549 g_value_set_boolean (
5550 value
, e_contact_editor
->priv
->target_editable
);
5554 g_value_set_boolean (
5555 value
, e_contact_editor
->priv
->changed
);
5558 case PROP_WRITABLE_FIELDS
:
5559 g_value_set_pointer (value
, e_contact_editor
->priv
->writable_fields
);
5561 case PROP_REQUIRED_FIELDS
:
5562 g_value_set_pointer (value
, e_contact_editor
->priv
->required_fields
);
5565 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
5571 * e_contact_editor_raise:
5572 * @config: The %EContactEditor object.
5574 * Raises the dialog associated with this %EContactEditor object.
5577 e_contact_editor_raise (EABEditor
*editor
)
5579 EContactEditor
*ce
= E_CONTACT_EDITOR (editor
);
5582 window
= gtk_widget_get_window (ce
->priv
->app
);
5585 gdk_window_raise (window
);
5589 * e_contact_editor_show:
5590 * @ce: The %EContactEditor object.
5592 * Shows the dialog associated with this %EContactEditor object.
5595 e_contact_editor_show (EABEditor
*editor
)
5597 EContactEditor
*ce
= E_CONTACT_EDITOR (editor
);
5598 gtk_widget_show (ce
->priv
->app
);